1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2009 James Gritton. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/jail.h> 31 #include <sys/linker.h> 32 #include <sys/socket.h> 33 #include <sys/sysctl.h> 34 35 #include <arpa/inet.h> 36 #include <netinet/in.h> 37 38 #include <errno.h> 39 #include <inttypes.h> 40 #include <stdio.h> 41 #include <stdarg.h> 42 #include <stdlib.h> 43 #include <string.h> 44 45 #include "jail.h" 46 47 #define SJPARAM "security.jail.param" 48 49 #define JPS_IN_ADDR 1 50 #define JPS_IN6_ADDR 2 51 52 #define ARRAY_SANITY 5 53 #define ARRAY_SLOP 5 54 55 56 static int jailparam_import_enum(const char **values, int nvalues, 57 const char *valstr, size_t valsize, int *value); 58 static int jailparam_type(struct jailparam *jp); 59 static int kldload_param(const char *name); 60 static char *noname(const char *name); 61 static char *nononame(const char *name); 62 63 char jail_errmsg[JAIL_ERRMSGLEN]; 64 65 static const char *bool_values[] = { "false", "true" }; 66 static const char *jailsys_values[] = { "disable", "new", "inherit" }; 67 68 69 /* 70 * Import a null-terminated parameter list and set a jail with the flags 71 * and parameters. 72 */ 73 int 74 jail_setv(int flags, ...) 75 { 76 va_list ap, tap; 77 struct jailparam *jp; 78 const char *name, *value; 79 int njp, jid; 80 81 /* Create the parameter list and import the parameters. */ 82 va_start(ap, flags); 83 va_copy(tap, ap); 84 for (njp = 0; va_arg(tap, char *) != NULL; njp++) 85 (void)va_arg(tap, char *); 86 va_end(tap); 87 jp = alloca(njp * sizeof(struct jailparam)); 88 for (njp = 0; (name = va_arg(ap, char *)) != NULL;) { 89 value = va_arg(ap, char *); 90 if (jailparam_init(jp + njp, name) < 0) 91 goto error; 92 if (jailparam_import(jp + njp++, value) < 0) 93 goto error; 94 } 95 va_end(ap); 96 jid = jailparam_set(jp, njp, flags); 97 jailparam_free(jp, njp); 98 return (jid); 99 100 error: 101 jailparam_free(jp, njp); 102 va_end(ap); 103 return (-1); 104 } 105 106 /* 107 * Read a null-terminated parameter list, get the referenced jail, and export 108 * the parameters to the list. 109 */ 110 int 111 jail_getv(int flags, ...) 112 { 113 va_list ap, tap; 114 struct jailparam *jp, *jp_lastjid, *jp_jid, *jp_name, *jp_key; 115 char *valarg, *value; 116 const char *name, *key_value, *lastjid_value, *jid_value, *name_value; 117 int njp, i, jid; 118 119 /* Create the parameter list and find the key. */ 120 va_start(ap, flags); 121 va_copy(tap, ap); 122 for (njp = 0; va_arg(tap, char *) != NULL; njp++) 123 (void)va_arg(tap, char *); 124 va_end(tap); 125 126 jp = alloca(njp * sizeof(struct jailparam)); 127 va_copy(tap, ap); 128 jp_lastjid = jp_jid = jp_name = NULL; 129 lastjid_value = jid_value = name_value = NULL; 130 for (njp = 0; (name = va_arg(tap, char *)) != NULL; njp++) { 131 value = va_arg(tap, char *); 132 if (jailparam_init(jp + njp, name) < 0) { 133 va_end(tap); 134 goto error; 135 } 136 if (!strcmp(jp[njp].jp_name, "lastjid")) { 137 jp_lastjid = jp + njp; 138 lastjid_value = value; 139 } else if (!strcmp(jp[njp].jp_name, "jid")) { 140 jp_jid = jp + njp; 141 jid_value = value; 142 } if (!strcmp(jp[njp].jp_name, "name")) { 143 jp_name = jp + njp; 144 name_value = value; 145 } 146 } 147 va_end(tap); 148 /* Import the key parameter. */ 149 if (jp_lastjid != NULL) { 150 jp_key = jp_lastjid; 151 key_value = lastjid_value; 152 } else if (jp_jid != NULL && strtol(jid_value, NULL, 10) != 0) { 153 jp_key = jp_jid; 154 key_value = jid_value; 155 } else if (jp_name != NULL) { 156 jp_key = jp_name; 157 key_value = name_value; 158 } else { 159 strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN); 160 errno = ENOENT; 161 goto error; 162 } 163 if (jailparam_import(jp_key, key_value) < 0) 164 goto error; 165 /* Get the jail and export the parameters. */ 166 jid = jailparam_get(jp, njp, flags); 167 if (jid < 0) 168 goto error; 169 for (i = 0; i < njp; i++) { 170 (void)va_arg(ap, char *); 171 valarg = va_arg(ap, char *); 172 if (jp + i != jp_key) { 173 /* It's up to the caller to ensure there's room. */ 174 if ((jp[i].jp_ctltype & CTLTYPE) == CTLTYPE_STRING) 175 strcpy(valarg, jp[i].jp_value); 176 else { 177 value = jailparam_export(jp + i); 178 if (value == NULL) 179 goto error; 180 strcpy(valarg, value); 181 free(value); 182 } 183 } 184 } 185 jailparam_free(jp, njp); 186 va_end(ap); 187 return (jid); 188 189 error: 190 jailparam_free(jp, njp); 191 va_end(ap); 192 return (-1); 193 } 194 195 /* 196 * Return a list of all known parameters. 197 */ 198 int 199 jailparam_all(struct jailparam **jpp) 200 { 201 struct jailparam *jp, *tjp; 202 size_t mlen1, mlen2, buflen; 203 unsigned njp, nlist; 204 int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2]; 205 char buf[MAXPATHLEN]; 206 207 njp = 0; 208 nlist = 32; 209 jp = malloc(nlist * sizeof(*jp)); 210 if (jp == NULL) { 211 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 212 return (-1); 213 } 214 mib1[0] = 0; 215 mib1[1] = 2; 216 mlen1 = CTL_MAXNAME - 2; 217 if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0) { 218 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 219 "sysctlnametomib(" SJPARAM "): %s", strerror(errno)); 220 goto error; 221 } 222 for (;; njp++) { 223 /* Get the next parameter. */ 224 mlen2 = sizeof(mib2); 225 if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0) { 226 if (errno == ENOENT) { 227 /* No more entries. */ 228 break; 229 } 230 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 231 "sysctl(0.2): %s", strerror(errno)); 232 goto error; 233 } 234 if (mib2[0] != mib1[2] || 235 mib2[1] != mib1[3] || 236 mib2[2] != mib1[4]) 237 break; 238 /* Convert it to an ascii name. */ 239 memcpy(mib1 + 2, mib2, mlen2); 240 mlen1 = mlen2 / sizeof(int); 241 mib1[1] = 1; 242 buflen = sizeof(buf); 243 if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0) { 244 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 245 "sysctl(0.1): %s", strerror(errno)); 246 goto error; 247 } 248 if (buf[buflen - 2] == '.') 249 buf[buflen - 2] = '\0'; 250 /* Add the parameter to the list */ 251 if (njp >= nlist) { 252 nlist *= 2; 253 tjp = reallocarray(jp, nlist, sizeof(*jp)); 254 if (tjp == NULL) 255 goto error; 256 jp = tjp; 257 } 258 if (jailparam_init(jp + njp, buf + sizeof(SJPARAM)) < 0) 259 goto error; 260 mib1[1] = 2; 261 } 262 /* Just return the untrimmed buffer if reallocarray() somehow fails. */ 263 tjp = reallocarray(jp, njp, sizeof(*jp)); 264 if (tjp != NULL) 265 jp = tjp; 266 *jpp = jp; 267 return (njp); 268 269 error: 270 jailparam_free(jp, njp); 271 free(jp); 272 return (-1); 273 } 274 275 /* 276 * Clear a jail parameter and copy in its name. 277 */ 278 int 279 jailparam_init(struct jailparam *jp, const char *name) 280 { 281 282 memset(jp, 0, sizeof(*jp)); 283 jp->jp_name = strdup(name); 284 if (jp->jp_name == NULL) { 285 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 286 return (-1); 287 } 288 if (jailparam_type(jp) < 0) { 289 jailparam_free(jp, 1); 290 jp->jp_name = NULL; 291 jp->jp_value = NULL; 292 return (-1); 293 } 294 return (0); 295 } 296 297 /* 298 * Put a name and value into a jail parameter element, converting the value 299 * to internal form. 300 */ 301 int 302 jailparam_import(struct jailparam *jp, const char *value) 303 { 304 char *p, *ep, *tvalue; 305 const char *avalue; 306 int i, nval, fw; 307 308 if (value == NULL) 309 return (0); 310 if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) { 311 jp->jp_value = strdup(value); 312 if (jp->jp_value == NULL) { 313 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 314 return (-1); 315 } 316 return (0); 317 } 318 nval = 1; 319 if (jp->jp_elemlen) { 320 if (value[0] == '\0' || (value[0] == '-' && value[1] == '\0')) { 321 jp->jp_value = strdup(""); 322 if (jp->jp_value == NULL) { 323 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 324 return (-1); 325 } 326 jp->jp_valuelen = 0; 327 return (0); 328 } 329 for (p = strchr(value, ','); p; p = strchr(p + 1, ',')) 330 nval++; 331 jp->jp_valuelen = jp->jp_elemlen * nval; 332 } 333 jp->jp_value = malloc(jp->jp_valuelen); 334 if (jp->jp_value == NULL) { 335 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 336 return (-1); 337 } 338 avalue = value; 339 for (i = 0; i < nval; i++) { 340 fw = nval == 1 ? strlen(avalue) : strcspn(avalue, ","); 341 switch (jp->jp_ctltype & CTLTYPE) { 342 case CTLTYPE_INT: 343 if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) { 344 if (!jailparam_import_enum(bool_values, 2, 345 avalue, fw, &((int *)jp->jp_value)[i])) { 346 snprintf(jail_errmsg, 347 JAIL_ERRMSGLEN, "%s: " 348 "unknown boolean value \"%.*s\"", 349 jp->jp_name, fw, avalue); 350 errno = EINVAL; 351 goto error; 352 } 353 break; 354 } 355 if (jp->jp_flags & JP_JAILSYS) { 356 /* 357 * Allow setting a jailsys parameter to "new" 358 * in a booleanesque fashion. 359 */ 360 if (value[0] == '\0') 361 ((int *)jp->jp_value)[i] = JAIL_SYS_NEW; 362 else if (!jailparam_import_enum(jailsys_values, 363 sizeof(jailsys_values) / 364 sizeof(jailsys_values[0]), avalue, fw, 365 &((int *)jp->jp_value)[i])) { 366 snprintf(jail_errmsg, 367 JAIL_ERRMSGLEN, "%s: " 368 "unknown jailsys value \"%.*s\"", 369 jp->jp_name, fw, avalue); 370 errno = EINVAL; 371 goto error; 372 } 373 break; 374 } 375 ((int *)jp->jp_value)[i] = strtol(avalue, &ep, 10); 376 integer_test: 377 if (ep != avalue + fw) { 378 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 379 "%s: non-integer value \"%.*s\"", 380 jp->jp_name, fw, avalue); 381 errno = EINVAL; 382 goto error; 383 } 384 break; 385 case CTLTYPE_UINT: 386 ((unsigned *)jp->jp_value)[i] = 387 strtoul(avalue, &ep, 10); 388 goto integer_test; 389 case CTLTYPE_LONG: 390 ((long *)jp->jp_value)[i] = strtol(avalue, &ep, 10); 391 goto integer_test; 392 case CTLTYPE_ULONG: 393 ((unsigned long *)jp->jp_value)[i] = 394 strtoul(avalue, &ep, 10); 395 goto integer_test; 396 case CTLTYPE_S64: 397 ((int64_t *)jp->jp_value)[i] = 398 strtoimax(avalue, &ep, 10); 399 goto integer_test; 400 case CTLTYPE_U64: 401 ((uint64_t *)jp->jp_value)[i] = 402 strtoumax(avalue, &ep, 10); 403 goto integer_test; 404 case CTLTYPE_STRUCT: 405 tvalue = alloca(fw + 1); 406 strlcpy(tvalue, avalue, fw + 1); 407 switch (jp->jp_structtype) { 408 case JPS_IN_ADDR: 409 if (inet_pton(AF_INET, tvalue, 410 &((struct in_addr *)jp->jp_value)[i]) != 1) 411 { 412 snprintf(jail_errmsg, 413 JAIL_ERRMSGLEN, 414 "%s: not an IPv4 address: %s", 415 jp->jp_name, tvalue); 416 errno = EINVAL; 417 goto error; 418 } 419 break; 420 case JPS_IN6_ADDR: 421 if (inet_pton(AF_INET6, tvalue, 422 &((struct in6_addr *)jp->jp_value)[i]) != 1) 423 { 424 snprintf(jail_errmsg, 425 JAIL_ERRMSGLEN, 426 "%s: not an IPv6 address: %s", 427 jp->jp_name, tvalue); 428 errno = EINVAL; 429 goto error; 430 } 431 break; 432 default: 433 goto unknown_type; 434 } 435 break; 436 default: 437 unknown_type: 438 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 439 "unknown type for %s", jp->jp_name); 440 errno = ENOENT; 441 goto error; 442 } 443 avalue += fw + 1; 444 } 445 return (0); 446 447 error: 448 free(jp->jp_value); 449 jp->jp_value = NULL; 450 return (-1); 451 } 452 453 static int 454 jailparam_import_enum(const char **values, int nvalues, const char *valstr, 455 size_t valsize, int *value) 456 { 457 char *ep; 458 int i; 459 460 for (i = 0; i < nvalues; i++) 461 if (valsize == strlen(values[i]) && 462 !strncasecmp(valstr, values[i], valsize)) { 463 *value = i; 464 return 1; 465 } 466 *value = strtol(valstr, &ep, 10); 467 return (ep == valstr + valsize); 468 } 469 470 /* 471 * Put a name and value into a jail parameter element, copying the value 472 * but not altering it. 473 */ 474 int 475 jailparam_import_raw(struct jailparam *jp, void *value, size_t valuelen) 476 { 477 478 jp->jp_value = value; 479 jp->jp_valuelen = valuelen; 480 jp->jp_flags |= JP_RAWVALUE; 481 return (0); 482 } 483 484 /* 485 * Run the jail_set and jail_get system calls on a parameter list. 486 */ 487 int 488 jailparam_set(struct jailparam *jp, unsigned njp, int flags) 489 { 490 struct iovec *jiov; 491 char *nname; 492 int i, jid, bool0; 493 unsigned j; 494 495 jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1)); 496 bool0 = 0; 497 for (i = j = 0; j < njp; j++) { 498 jiov[i].iov_base = jp[j].jp_name; 499 jiov[i].iov_len = strlen(jp[j].jp_name) + 1; 500 i++; 501 if (jp[j].jp_flags & (JP_BOOL | JP_NOBOOL)) { 502 /* 503 * Set booleans without values. If one has a value of 504 * zero, change it to (or from) its "no" counterpart. 505 */ 506 jiov[i].iov_base = NULL; 507 jiov[i].iov_len = 0; 508 if (jp[j].jp_value != NULL && 509 jp[j].jp_valuelen == sizeof(int) && 510 !*(int *)jp[j].jp_value) { 511 bool0 = 1; 512 nname = jp[j].jp_flags & JP_BOOL 513 ? noname(jp[j].jp_name) 514 : nononame(jp[j].jp_name); 515 if (nname == NULL) { 516 njp = j; 517 jid = -1; 518 goto done; 519 } 520 jiov[i - 1].iov_base = nname; 521 jiov[i - 1].iov_len = strlen(nname) + 1; 522 523 } 524 } else { 525 /* 526 * Try to fill in missing values with an empty string. 527 */ 528 if (jp[j].jp_value == NULL && jp[j].jp_valuelen > 0 && 529 jailparam_import(jp + j, "") < 0) { 530 njp = j; 531 jid = -1; 532 goto done; 533 } 534 jiov[i].iov_base = jp[j].jp_value; 535 jiov[i].iov_len = 536 (jp[j].jp_ctltype & CTLTYPE) == CTLTYPE_STRING 537 ? strlen(jp[j].jp_value) + 1 538 : jp[j].jp_valuelen; 539 } 540 i++; 541 } 542 jiov[i].iov_base = __DECONST(char *, "errmsg"); 543 jiov[i].iov_len = sizeof("errmsg"); 544 i++; 545 jiov[i].iov_base = jail_errmsg; 546 jiov[i].iov_len = JAIL_ERRMSGLEN; 547 i++; 548 jail_errmsg[0] = 0; 549 jid = jail_set(jiov, i, flags); 550 if (jid < 0 && !jail_errmsg[0]) 551 snprintf(jail_errmsg, sizeof(jail_errmsg), "jail_set: %s", 552 strerror(errno)); 553 done: 554 if (bool0) 555 for (j = 0; j < njp; j++) 556 if ((jp[j].jp_flags & (JP_BOOL | JP_NOBOOL)) && 557 jp[j].jp_value != NULL && 558 jp[j].jp_valuelen == sizeof(int) && 559 !*(int *)jp[j].jp_value) 560 free(jiov[j * 2].iov_base); 561 return (jid); 562 } 563 564 int 565 jailparam_get(struct jailparam *jp, unsigned njp, int flags) 566 { 567 struct iovec *jiov; 568 struct jailparam *jp_lastjid, *jp_jid, *jp_name, *jp_key; 569 int i, ai, ki, jid, arrays, sanity; 570 unsigned j; 571 572 /* 573 * Get the types for all parameters. 574 * Find the key and any array parameters. 575 */ 576 jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1)); 577 jp_lastjid = jp_jid = jp_name = NULL; 578 arrays = 0; 579 for (ai = j = 0; j < njp; j++) { 580 if (!strcmp(jp[j].jp_name, "lastjid")) 581 jp_lastjid = jp + j; 582 else if (!strcmp(jp[j].jp_name, "jid")) 583 jp_jid = jp + j; 584 else if (!strcmp(jp[j].jp_name, "name")) 585 jp_name = jp + j; 586 else if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) { 587 arrays = 1; 588 jiov[ai].iov_base = jp[j].jp_name; 589 jiov[ai].iov_len = strlen(jp[j].jp_name) + 1; 590 ai++; 591 jiov[ai].iov_base = NULL; 592 jiov[ai].iov_len = 0; 593 ai++; 594 } 595 } 596 jp_key = jp_lastjid ? jp_lastjid : 597 jp_jid && jp_jid->jp_valuelen == sizeof(int) && 598 jp_jid->jp_value && *(int *)jp_jid->jp_value ? jp_jid : jp_name; 599 if (jp_key == NULL || jp_key->jp_value == NULL) { 600 strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN); 601 errno = ENOENT; 602 return (-1); 603 } 604 ki = ai; 605 jiov[ki].iov_base = jp_key->jp_name; 606 jiov[ki].iov_len = strlen(jp_key->jp_name) + 1; 607 ki++; 608 jiov[ki].iov_base = jp_key->jp_value; 609 jiov[ki].iov_len = (jp_key->jp_ctltype & CTLTYPE) == CTLTYPE_STRING 610 ? strlen(jp_key->jp_value) + 1 : jp_key->jp_valuelen; 611 ki++; 612 jiov[ki].iov_base = __DECONST(char *, "errmsg"); 613 jiov[ki].iov_len = sizeof("errmsg"); 614 ki++; 615 jiov[ki].iov_base = jail_errmsg; 616 jiov[ki].iov_len = JAIL_ERRMSGLEN; 617 ki++; 618 jail_errmsg[0] = 0; 619 if (arrays && jail_get(jiov, ki, flags) < 0) { 620 if (!jail_errmsg[0]) 621 snprintf(jail_errmsg, sizeof(jail_errmsg), 622 "jail_get: %s", strerror(errno)); 623 return (-1); 624 } 625 /* Allocate storage for all parameters. */ 626 for (ai = j = 0, i = ki; j < njp; j++) { 627 if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) { 628 ai++; 629 jiov[ai].iov_len += jp[j].jp_elemlen * ARRAY_SLOP; 630 if (jp[j].jp_valuelen >= jiov[ai].iov_len) 631 jiov[ai].iov_len = jp[j].jp_valuelen; 632 else { 633 jp[j].jp_valuelen = jiov[ai].iov_len; 634 if (jp[j].jp_value != NULL) 635 free(jp[j].jp_value); 636 jp[j].jp_value = malloc(jp[j].jp_valuelen); 637 if (jp[j].jp_value == NULL) { 638 strerror_r(errno, jail_errmsg, 639 JAIL_ERRMSGLEN); 640 return (-1); 641 } 642 } 643 jiov[ai].iov_base = jp[j].jp_value; 644 memset(jiov[ai].iov_base, 0, jiov[ai].iov_len); 645 ai++; 646 } else if (jp + j != jp_key) { 647 jiov[i].iov_base = jp[j].jp_name; 648 jiov[i].iov_len = strlen(jp[j].jp_name) + 1; 649 i++; 650 if (jp[j].jp_value == NULL && 651 !(jp[j].jp_flags & JP_RAWVALUE)) { 652 jp[j].jp_value = malloc(jp[j].jp_valuelen); 653 if (jp[j].jp_value == NULL) { 654 strerror_r(errno, jail_errmsg, 655 JAIL_ERRMSGLEN); 656 return (-1); 657 } 658 } 659 jiov[i].iov_base = jp[j].jp_value; 660 jiov[i].iov_len = jp[j].jp_valuelen; 661 memset(jiov[i].iov_base, 0, jiov[i].iov_len); 662 i++; 663 } 664 } 665 /* 666 * Get the prison. If there are array elements, retry a few times 667 * in case their sizes changed from under us. 668 */ 669 for (sanity = 0;; sanity++) { 670 jid = jail_get(jiov, i, flags); 671 if (jid >= 0 || !arrays || sanity == ARRAY_SANITY || 672 errno != EINVAL || jail_errmsg[0]) 673 break; 674 for (ai = j = 0; j < njp; j++) { 675 if (jp[j].jp_elemlen && 676 !(jp[j].jp_flags & JP_RAWVALUE)) { 677 ai++; 678 jiov[ai].iov_base = NULL; 679 jiov[ai].iov_len = 0; 680 ai++; 681 } 682 } 683 if (jail_get(jiov, ki, flags) < 0) 684 break; 685 for (ai = j = 0; j < njp; j++) { 686 if (jp[j].jp_elemlen && 687 !(jp[j].jp_flags & JP_RAWVALUE)) { 688 ai++; 689 jiov[ai].iov_len += 690 jp[j].jp_elemlen * ARRAY_SLOP; 691 if (jp[j].jp_valuelen >= jiov[ai].iov_len) 692 jiov[ai].iov_len = jp[j].jp_valuelen; 693 else { 694 jp[j].jp_valuelen = jiov[ai].iov_len; 695 if (jp[j].jp_value != NULL) 696 free(jp[j].jp_value); 697 jp[j].jp_value = 698 malloc(jiov[ai].iov_len); 699 if (jp[j].jp_value == NULL) { 700 strerror_r(errno, jail_errmsg, 701 JAIL_ERRMSGLEN); 702 return (-1); 703 } 704 } 705 jiov[ai].iov_base = jp[j].jp_value; 706 memset(jiov[ai].iov_base, 0, jiov[ai].iov_len); 707 ai++; 708 } 709 } 710 } 711 if (jid < 0 && !jail_errmsg[0]) 712 snprintf(jail_errmsg, sizeof(jail_errmsg), 713 "jail_get: %s", strerror(errno)); 714 for (ai = j = 0, i = ki; j < njp; j++) { 715 if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) { 716 ai++; 717 jp[j].jp_valuelen = jiov[ai].iov_len; 718 ai++; 719 } else if (jp + j != jp_key) { 720 i++; 721 jp[j].jp_valuelen = jiov[i].iov_len; 722 i++; 723 } 724 } 725 return (jid); 726 } 727 728 /* 729 * Convert a jail parameter's value to external form. 730 */ 731 char * 732 jailparam_export(struct jailparam *jp) 733 { 734 size_t *valuelens; 735 char *value, *tvalue, **values; 736 size_t valuelen; 737 int i, nval, ival; 738 char valbuf[INET6_ADDRSTRLEN]; 739 740 if (jp->jp_value == NULL) { 741 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 742 "parameter %s was not imported", jp->jp_name); 743 errno = EINVAL; 744 return (NULL); 745 } 746 if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) { 747 value = strdup(jp->jp_value); 748 if (value == NULL) 749 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 750 return (value); 751 } 752 nval = jp->jp_elemlen ? jp->jp_valuelen / jp->jp_elemlen : 1; 753 if (nval == 0) { 754 value = strdup(""); 755 if (value == NULL) 756 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 757 return (value); 758 } 759 values = alloca(nval * sizeof(char *)); 760 valuelens = alloca(nval * sizeof(size_t)); 761 valuelen = 0; 762 for (i = 0; i < nval; i++) { 763 switch (jp->jp_ctltype & CTLTYPE) { 764 case CTLTYPE_INT: 765 ival = ((int *)jp->jp_value)[i]; 766 if ((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) && 767 (unsigned)ival < 2) { 768 strlcpy(valbuf, bool_values[ival], 769 sizeof(valbuf)); 770 break; 771 } 772 if ((jp->jp_flags & JP_JAILSYS) && 773 (unsigned)ival < sizeof(jailsys_values) / 774 sizeof(jailsys_values[0])) { 775 strlcpy(valbuf, jailsys_values[ival], 776 sizeof(valbuf)); 777 break; 778 } 779 snprintf(valbuf, sizeof(valbuf), "%d", ival); 780 break; 781 case CTLTYPE_UINT: 782 snprintf(valbuf, sizeof(valbuf), "%u", 783 ((unsigned *)jp->jp_value)[i]); 784 break; 785 case CTLTYPE_LONG: 786 snprintf(valbuf, sizeof(valbuf), "%ld", 787 ((long *)jp->jp_value)[i]); 788 break; 789 case CTLTYPE_ULONG: 790 snprintf(valbuf, sizeof(valbuf), "%lu", 791 ((unsigned long *)jp->jp_value)[i]); 792 break; 793 case CTLTYPE_S64: 794 snprintf(valbuf, sizeof(valbuf), "%jd", 795 (intmax_t)((int64_t *)jp->jp_value)[i]); 796 break; 797 case CTLTYPE_U64: 798 snprintf(valbuf, sizeof(valbuf), "%ju", 799 (uintmax_t)((uint64_t *)jp->jp_value)[i]); 800 break; 801 case CTLTYPE_STRUCT: 802 switch (jp->jp_structtype) { 803 case JPS_IN_ADDR: 804 if (inet_ntop(AF_INET, 805 &((struct in_addr *)jp->jp_value)[i], 806 valbuf, sizeof(valbuf)) == NULL) { 807 strerror_r(errno, jail_errmsg, 808 JAIL_ERRMSGLEN); 809 return (NULL); 810 } 811 break; 812 case JPS_IN6_ADDR: 813 if (inet_ntop(AF_INET6, 814 &((struct in6_addr *)jp->jp_value)[i], 815 valbuf, sizeof(valbuf)) == NULL) { 816 strerror_r(errno, jail_errmsg, 817 JAIL_ERRMSGLEN); 818 return (NULL); 819 } 820 break; 821 default: 822 goto unknown_type; 823 } 824 break; 825 default: 826 unknown_type: 827 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 828 "unknown type for %s", jp->jp_name); 829 errno = ENOENT; 830 return (NULL); 831 } 832 valuelens[i] = strlen(valbuf) + 1; 833 valuelen += valuelens[i]; 834 values[i] = alloca(valuelens[i]); 835 strcpy(values[i], valbuf); 836 } 837 value = malloc(valuelen); 838 if (value == NULL) 839 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 840 else { 841 tvalue = value; 842 for (i = 0; i < nval; i++) { 843 strcpy(tvalue, values[i]); 844 if (i < nval - 1) { 845 tvalue += valuelens[i]; 846 tvalue[-1] = ','; 847 } 848 } 849 } 850 return (value); 851 } 852 853 /* 854 * Free the contents of a jail parameter list (but not the list itself). 855 */ 856 void 857 jailparam_free(struct jailparam *jp, unsigned njp) 858 { 859 unsigned j; 860 861 for (j = 0; j < njp; j++) { 862 free(jp[j].jp_name); 863 if (!(jp[j].jp_flags & JP_RAWVALUE)) 864 free(jp[j].jp_value); 865 } 866 } 867 868 /* 869 * Find a parameter's type and size from its MIB. 870 */ 871 static int 872 jailparam_type(struct jailparam *jp) 873 { 874 char *p, *name, *nname; 875 size_t miblen, desclen; 876 int i, isarray; 877 struct { 878 int i; 879 char s[MAXPATHLEN]; 880 } desc; 881 int mib[CTL_MAXNAME]; 882 883 /* The "lastjid" parameter isn't real. */ 884 name = jp->jp_name; 885 if (!strcmp(name, "lastjid")) { 886 jp->jp_valuelen = sizeof(int); 887 jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR; 888 return (0); 889 } 890 891 /* Find the sysctl that describes the parameter. */ 892 mib[0] = 0; 893 mib[1] = 3; 894 snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", name); 895 miblen = sizeof(mib) - 2 * sizeof(int); 896 if (sysctl(mib, 2, mib + 2, &miblen, desc.s, strlen(desc.s)) < 0) { 897 if (errno != ENOENT) { 898 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 899 "sysctl(0.3.%s): %s", name, strerror(errno)); 900 return (-1); 901 } 902 if (kldload_param(name) >= 0 && sysctl(mib, 2, mib + 2, &miblen, 903 desc.s, strlen(desc.s)) >= 0) 904 goto mib_desc; 905 /* 906 * The parameter probably doesn't exist. But it might be 907 * the "no" counterpart to a boolean. 908 */ 909 nname = nononame(name); 910 if (nname == NULL) { 911 unknown_parameter: 912 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 913 "unknown parameter: %s", jp->jp_name); 914 errno = ENOENT; 915 return (-1); 916 } 917 name = alloca(strlen(nname) + 1); 918 strcpy(name, nname); 919 free(nname); 920 snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", name); 921 miblen = sizeof(mib) - 2 * sizeof(int); 922 if (sysctl(mib, 2, mib + 2, &miblen, desc.s, 923 strlen(desc.s)) < 0) 924 goto unknown_parameter; 925 jp->jp_flags |= JP_NOBOOL; 926 } 927 mib_desc: 928 mib[1] = 4; 929 desclen = sizeof(desc); 930 if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen, 931 NULL, 0) < 0) { 932 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 933 "sysctl(0.4.%s): %s", name, strerror(errno)); 934 return (-1); 935 } 936 jp->jp_ctltype = desc.i; 937 /* If this came from removing a "no", it better be a boolean. */ 938 if (jp->jp_flags & JP_NOBOOL) { 939 if ((desc.i & CTLTYPE) == CTLTYPE_INT && desc.s[0] == 'B') { 940 jp->jp_valuelen = sizeof(int); 941 return (0); 942 } 943 else if ((desc.i & CTLTYPE) != CTLTYPE_NODE) 944 goto unknown_parameter; 945 } 946 /* See if this is an array type. */ 947 p = strchr(desc.s, '\0'); 948 isarray = 0; 949 if (p - 2 < desc.s || strcmp(p - 2, ",a")) 950 isarray = 0; 951 else { 952 isarray = 1; 953 p[-2] = 0; 954 } 955 /* Look for types we understand. */ 956 switch (desc.i & CTLTYPE) { 957 case CTLTYPE_INT: 958 if (desc.s[0] == 'B') 959 jp->jp_flags |= JP_BOOL; 960 else if (!strcmp(desc.s, "E,jailsys")) 961 jp->jp_flags |= JP_JAILSYS; 962 case CTLTYPE_UINT: 963 jp->jp_valuelen = sizeof(int); 964 break; 965 case CTLTYPE_LONG: 966 case CTLTYPE_ULONG: 967 jp->jp_valuelen = sizeof(long); 968 break; 969 case CTLTYPE_S64: 970 case CTLTYPE_U64: 971 jp->jp_valuelen = sizeof(int64_t); 972 break; 973 case CTLTYPE_STRING: 974 desc.s[0] = 0; 975 desclen = sizeof(desc.s); 976 if (sysctl(mib + 2, miblen / sizeof(int), desc.s, &desclen, 977 NULL, 0) < 0) { 978 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 979 "sysctl(" SJPARAM ".%s): %s", name, 980 strerror(errno)); 981 return (-1); 982 } 983 jp->jp_valuelen = strtoul(desc.s, NULL, 10); 984 break; 985 case CTLTYPE_STRUCT: 986 if (!strcmp(desc.s, "S,in_addr")) { 987 jp->jp_structtype = JPS_IN_ADDR; 988 jp->jp_valuelen = sizeof(struct in_addr); 989 } else if (!strcmp(desc.s, "S,in6_addr")) { 990 jp->jp_structtype = JPS_IN6_ADDR; 991 jp->jp_valuelen = sizeof(struct in6_addr); 992 } else { 993 desclen = 0; 994 if (sysctl(mib + 2, miblen / sizeof(int), 995 NULL, &jp->jp_valuelen, NULL, 0) < 0) { 996 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 997 "sysctl(" SJPARAM ".%s): %s", name, 998 strerror(errno)); 999 return (-1); 1000 } 1001 } 1002 break; 1003 case CTLTYPE_NODE: 1004 /* 1005 * A node might be described by an empty-named child, 1006 * which would be immediately before or after the node itself. 1007 */ 1008 mib[1] = 1; 1009 miblen += sizeof(int); 1010 for (i = -1; i <= 1; i += 2) { 1011 mib[(miblen / sizeof(int)) + 1] = 1012 mib[(miblen / sizeof(int))] + i; 1013 desclen = sizeof(desc.s); 1014 if (sysctl(mib, (miblen / sizeof(int)) + 2, desc.s, 1015 &desclen, NULL, 0) < 0) { 1016 if (errno == ENOENT) 1017 continue; 1018 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1019 "sysctl(0.1): %s", strerror(errno)); 1020 return (-1); 1021 } 1022 if (desclen == sizeof(SJPARAM) + strlen(name) + 2 && 1023 memcmp(SJPARAM ".", desc.s, sizeof(SJPARAM)) == 0 && 1024 memcmp(name, desc.s + sizeof(SJPARAM), 1025 desclen - sizeof(SJPARAM) - 2) == 0 && 1026 desc.s[desclen - 2] == '.') 1027 goto mib_desc; 1028 } 1029 goto unknown_parameter; 1030 default: 1031 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1032 "unknown type for %s", jp->jp_name); 1033 errno = ENOENT; 1034 return (-1); 1035 } 1036 if (isarray) { 1037 jp->jp_elemlen = jp->jp_valuelen; 1038 jp->jp_valuelen = 0; 1039 } 1040 return (0); 1041 } 1042 1043 /* 1044 * Attempt to load a kernel module matching an otherwise nonexistent parameter. 1045 */ 1046 static int 1047 kldload_param(const char *name) 1048 { 1049 int kl; 1050 1051 if (strcmp(name, "linux") == 0 || strncmp(name, "linux.", 6) == 0) 1052 kl = kldload("linux"); 1053 else if (strcmp(name, "sysvmsg") == 0 || strcmp(name, "sysvsem") == 0 || 1054 strcmp(name, "sysvshm") == 0) 1055 kl = kldload(name); 1056 else if (strncmp(name, "allow.mount.", 12) == 0) { 1057 /* Load the matching filesystem */ 1058 const char *modname = name + 12; 1059 1060 kl = kldload(modname); 1061 if (kl < 0 && errno == ENOENT && 1062 strncmp(modname, "no", 2) == 0) 1063 kl = kldload(modname + 2); 1064 } else { 1065 errno = ENOENT; 1066 return (-1); 1067 } 1068 if (kl < 0 && errno == EEXIST) { 1069 /* 1070 * In the module is already loaded, then it must not contain 1071 * the parameter. 1072 */ 1073 errno = ENOENT; 1074 } 1075 return kl; 1076 } 1077 1078 /* 1079 * Change a boolean parameter name into its "no" counterpart or vice versa. 1080 */ 1081 static char * 1082 noname(const char *name) 1083 { 1084 char *nname, *p; 1085 1086 nname = malloc(strlen(name) + 3); 1087 if (nname == NULL) { 1088 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 1089 return (NULL); 1090 } 1091 p = strrchr(name, '.'); 1092 if (p != NULL) 1093 sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1); 1094 else 1095 sprintf(nname, "no%s", name); 1096 return (nname); 1097 } 1098 1099 static char * 1100 nononame(const char *name) 1101 { 1102 char *p, *nname; 1103 1104 p = strrchr(name, '.'); 1105 if (strncmp(p ? p + 1 : name, "no", 2)) { 1106 snprintf(jail_errmsg, sizeof(jail_errmsg), 1107 "mismatched boolean: %s", name); 1108 errno = EINVAL; 1109 return (NULL); 1110 } 1111 nname = malloc(strlen(name) - 1); 1112 if (nname == NULL) { 1113 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 1114 return (NULL); 1115 } 1116 if (p != NULL) 1117 sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3); 1118 else 1119 strcpy(nname, name + 2); 1120 return (nname); 1121 } 1122