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