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/mac.h> 33 #include <sys/socket.h> 34 #include <sys/sysctl.h> 35 36 #include <arpa/inet.h> 37 #include <netinet/in.h> 38 39 #include <assert.h> 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 JPSDEF_OF(jp) \ 52 ((jp)->jp_structtype >= 0 ? &jp_structdefs[(jp)->jp_structtype] : NULL) 53 54 static int jps_get(struct jailparam *, struct iovec *); 55 static int jps_set(const struct jailparam *, struct iovec *); 56 static void jps_free(struct jailparam *); 57 58 typedef int (jps_import_t)(const struct jailparam *, int, const char *); 59 typedef char *(jps_export_t)(const struct jailparam *, int); 60 typedef int (jps_get_t)(struct jailparam *, struct iovec *); 61 typedef int (jps_set_t)(const struct jailparam *, struct iovec *); 62 typedef void (jps_free_t)(struct jailparam *); 63 64 static jps_import_t jps_import_in_addr; 65 static jps_import_t jps_import_in6_addr; 66 static jps_import_t jps_import_mac_label; 67 68 static jps_export_t jps_export_in_addr; 69 static jps_export_t jps_export_in6_addr; 70 static jps_export_t jps_export_mac_label; 71 72 static jps_get_t jps_get_mac_label; 73 74 static jps_set_t jps_set_mac_label; 75 76 static jps_free_t jps_free_mac_label; 77 78 static const struct jp_structdef { 79 const char *jps_type; /* sysctl type */ 80 size_t jps_valuelen; /* value size */ 81 jps_import_t *jps_import; /* jailparam_import() */ 82 jps_export_t *jps_export; /* jailparam_export() */ 83 jps_get_t *jps_get; /* jailparam_get() */ 84 jps_set_t *jps_set; /* jailparam_set() */ 85 jps_free_t *jps_free; /* jailparam_free() */ 86 } jp_structdefs[] = { 87 { 88 .jps_type = "S,in_addr", 89 .jps_valuelen = sizeof(struct in_addr), 90 .jps_import = jps_import_in_addr, 91 .jps_export = jps_export_in_addr, 92 }, 93 { 94 .jps_type = "S,in6_addr", 95 .jps_valuelen = sizeof(struct in6_addr), 96 .jps_import = jps_import_in6_addr, 97 .jps_export = jps_export_in6_addr, 98 }, 99 { 100 .jps_type = "S,mac", 101 .jps_valuelen = sizeof(mac_t *), 102 .jps_import = jps_import_mac_label, 103 .jps_export = jps_export_mac_label, 104 .jps_get = jps_get_mac_label, 105 .jps_set = jps_set_mac_label, 106 .jps_free = jps_free_mac_label, 107 }, 108 }; 109 110 _Static_assert(nitems(jp_structdefs) <= INT_MAX, 111 "Too many struct definitions requires an ABI break in struct jailparam"); 112 113 #define ARRAY_SANITY 5 114 #define ARRAY_SLOP 5 115 116 static const struct jp_structdef *jp_structinfo(const char *type, int *); 117 118 static int jailparam_import_enum(const char **values, int nvalues, 119 const char *valstr, size_t valsize, int *value); 120 static int jailparam_type(struct jailparam *jp); 121 static int kldload_param(const char *name); 122 static char *noname(const char *name); 123 static char *nononame(const char *name); 124 static char *kvname(const char *name); 125 126 char jail_errmsg[JAIL_ERRMSGLEN]; 127 128 static const char *bool_values[] = { "false", "true" }; 129 static const char *jailsys_values[] = { "disable", "new", "inherit" }; 130 131 static const struct jp_structdef * 132 jp_structinfo(const char *type, int *oidx) 133 { 134 const struct jp_structdef *jpsdef; 135 136 for (size_t idx = 0; idx < nitems(jp_structdefs); idx++) { 137 jpsdef = &jp_structdefs[idx]; 138 139 if (strcmp(jpsdef->jps_type, type) == 0) { 140 *oidx = (int)idx; 141 return (jpsdef); 142 } 143 } 144 145 *oidx = -1; 146 return (NULL); 147 } 148 149 /* 150 * Import a null-terminated parameter list and set a jail with the flags 151 * and parameters. 152 */ 153 int 154 jail_setv(int flags, ...) 155 { 156 va_list ap, tap; 157 struct jailparam *jp, *jp_desc; 158 const char *name; 159 char *value, *desc_value; 160 int njp, jid; 161 162 /* Create the parameter list and import the parameters. */ 163 va_start(ap, flags); 164 va_copy(tap, ap); 165 for (njp = 0; va_arg(tap, char *) != NULL; njp++) 166 (void)va_arg(tap, char *); 167 va_end(tap); 168 jp = alloca(njp * sizeof(struct jailparam)); 169 jp_desc = NULL; 170 desc_value = NULL; 171 for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) { 172 value = va_arg(ap, char *); 173 if (jailparam_init(jp + njp, name) < 0) 174 goto error; 175 if (jailparam_import(jp + njp, value) < 0) 176 goto error; 177 if (!strcmp(name, "desc") && 178 (flags & (JAIL_GET_DESC | JAIL_OWN_DESC))) { 179 jp_desc = jp + njp; 180 desc_value = value; 181 } 182 } 183 va_end(ap); 184 jid = jailparam_set(jp, njp, flags); 185 if (jid > 0 && jp_desc != NULL) 186 sprintf(desc_value, "%d", *(int *)jp_desc->jp_value); 187 jailparam_free(jp, njp); 188 return (jid); 189 190 error: 191 jailparam_free(jp, njp); 192 va_end(ap); 193 return (-1); 194 } 195 196 /* 197 * Read a null-terminated parameter list, get the referenced jail, and export 198 * the parameters to the list. 199 */ 200 int 201 jail_getv(int flags, ...) 202 { 203 va_list ap, tap; 204 struct jailparam *jp, *jp_desc, *jp_lastjid, *jp_jid, *jp_name, *jp_key; 205 char *valarg, *value; 206 const char *name, *key_value, *desc_value, *lastjid_value, *jid_value; 207 const char *name_value; 208 int njp, i, jid; 209 210 /* Create the parameter list and find the key. */ 211 va_start(ap, flags); 212 va_copy(tap, ap); 213 for (njp = 0; va_arg(tap, char *) != NULL; njp++) 214 (void)va_arg(tap, char *); 215 va_end(tap); 216 217 jp = alloca(njp * sizeof(struct jailparam)); 218 va_copy(tap, ap); 219 jp_desc = jp_lastjid = jp_jid = jp_name = NULL; 220 desc_value = lastjid_value = jid_value = name_value = NULL; 221 for (njp = 0; (name = va_arg(tap, char *)) != NULL; njp++) { 222 value = va_arg(tap, char *); 223 if (jailparam_init(jp + njp, name) < 0) { 224 va_end(tap); 225 goto error; 226 } 227 if (!strcmp(jp[njp].jp_name, "desc") && 228 (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) { 229 jp_desc = jp + njp; 230 desc_value = value; 231 } else if (!strcmp(jp[njp].jp_name, "lastjid")) { 232 jp_lastjid = jp + njp; 233 lastjid_value = value; 234 } else if (!strcmp(jp[njp].jp_name, "jid")) { 235 jp_jid = jp + njp; 236 jid_value = value; 237 } if (!strcmp(jp[njp].jp_name, "name")) { 238 jp_name = jp + njp; 239 name_value = value; 240 } 241 } 242 va_end(tap); 243 /* Import the key parameter. */ 244 if (jp_desc != NULL && (flags & JAIL_USE_DESC)) { 245 jp_key = jp_desc; 246 key_value = desc_value; 247 } else if (jp_lastjid != NULL) { 248 jp_key = jp_lastjid; 249 key_value = lastjid_value; 250 } else if (jp_jid != NULL && strtol(jid_value, NULL, 10) != 0) { 251 jp_key = jp_jid; 252 key_value = jid_value; 253 } else if (jp_name != NULL) { 254 jp_key = jp_name; 255 key_value = name_value; 256 } else { 257 strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN); 258 errno = ENOENT; 259 goto error; 260 } 261 if (jailparam_import(jp_key, key_value) < 0) 262 goto error; 263 if (jp_desc != NULL && jp_desc != jp_key && 264 jailparam_import(jp_desc, desc_value) < 0) 265 goto error; 266 /* Get the jail and export the parameters. */ 267 jid = jailparam_get(jp, njp, flags); 268 if (jid < 0) 269 goto error; 270 for (i = 0; i < njp; i++) { 271 (void)va_arg(ap, char *); 272 valarg = va_arg(ap, char *); 273 if (jp + i != jp_key) { 274 /* It's up to the caller to ensure there's room. */ 275 if ((jp[i].jp_ctltype & CTLTYPE) == CTLTYPE_STRING) 276 strcpy(valarg, jp[i].jp_value); 277 else { 278 value = jailparam_export(jp + i); 279 if (value == NULL) 280 goto error; 281 strcpy(valarg, value); 282 free(value); 283 } 284 } 285 } 286 jailparam_free(jp, njp); 287 va_end(ap); 288 return (jid); 289 290 error: 291 jailparam_free(jp, njp); 292 va_end(ap); 293 return (-1); 294 } 295 296 /* 297 * Return a list of all known parameters. 298 */ 299 int 300 jailparam_all(struct jailparam **jpp) 301 { 302 struct jailparam *jp, *tjp; 303 size_t mlen1, mlen2, buflen; 304 unsigned njp, nlist; 305 int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2]; 306 char buf[MAXPATHLEN]; 307 308 njp = 0; 309 nlist = 32; 310 jp = malloc(nlist * sizeof(*jp)); 311 if (jp == NULL) { 312 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 313 return (-1); 314 } 315 mib1[0] = 0; 316 mib1[1] = 2; 317 mlen1 = CTL_MAXNAME - 2; 318 if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0) { 319 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 320 "sysctlnametomib(" SJPARAM "): %s", strerror(errno)); 321 goto error; 322 } 323 for (;; njp++) { 324 /* Get the next parameter. */ 325 mlen2 = sizeof(mib2); 326 if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0) { 327 if (errno == ENOENT) { 328 /* No more entries. */ 329 break; 330 } 331 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 332 "sysctl(0.2): %s", strerror(errno)); 333 goto error; 334 } 335 if (mib2[0] != mib1[2] || 336 mib2[1] != mib1[3] || 337 mib2[2] != mib1[4]) 338 break; 339 /* Convert it to an ascii name. */ 340 memcpy(mib1 + 2, mib2, mlen2); 341 mlen1 = mlen2 / sizeof(int); 342 mib1[1] = 1; 343 buflen = sizeof(buf); 344 if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0) { 345 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 346 "sysctl(0.1): %s", strerror(errno)); 347 goto error; 348 } 349 if (buf[buflen - 2] == '.') 350 buf[buflen - 2] = '\0'; 351 /* Add the parameter to the list */ 352 if (njp >= nlist) { 353 nlist *= 2; 354 tjp = reallocarray(jp, nlist, sizeof(*jp)); 355 if (tjp == NULL) 356 goto error; 357 jp = tjp; 358 } 359 if (jailparam_init(jp + njp, buf + sizeof(SJPARAM)) < 0) 360 goto error; 361 mib1[1] = 2; 362 } 363 /* Just return the untrimmed buffer if reallocarray() somehow fails. */ 364 tjp = reallocarray(jp, njp, sizeof(*jp)); 365 if (tjp != NULL) 366 jp = tjp; 367 *jpp = jp; 368 return (njp); 369 370 error: 371 jailparam_free(jp, njp); 372 free(jp); 373 return (-1); 374 } 375 376 /* 377 * Clear a jail parameter and copy in its name. 378 */ 379 int 380 jailparam_init(struct jailparam *jp, const char *name) 381 { 382 383 memset(jp, 0, sizeof(*jp)); 384 jp->jp_name = strdup(name); 385 if (jp->jp_name == NULL) { 386 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 387 return (-1); 388 } 389 if (jailparam_type(jp) < 0) { 390 jailparam_free(jp, 1); 391 jp->jp_name = NULL; 392 jp->jp_value = NULL; 393 return (-1); 394 } 395 return (0); 396 } 397 398 /* 399 * Put a name and value into a jail parameter element, converting the value 400 * to internal form. 401 */ 402 int 403 jailparam_import(struct jailparam *jp, const char *value) 404 { 405 char *p, *ep, *tvalue; 406 const char *avalue; 407 const struct jp_structdef *jpsdef; 408 int i, nval, fw; 409 410 if (value == NULL) 411 return (0); 412 if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) { 413 jp->jp_value = strdup(value); 414 if (jp->jp_value == NULL) { 415 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 416 return (-1); 417 } 418 return (0); 419 } 420 nval = 1; 421 if (jp->jp_elemlen) { 422 if (value[0] == '\0' || (value[0] == '-' && value[1] == '\0')) { 423 jp->jp_value = strdup(""); 424 if (jp->jp_value == NULL) { 425 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 426 return (-1); 427 } 428 jp->jp_valuelen = 0; 429 return (0); 430 } 431 for (p = strchr(value, ','); p; p = strchr(p + 1, ',')) 432 nval++; 433 jp->jp_valuelen = jp->jp_elemlen * nval; 434 } 435 jp->jp_value = malloc(jp->jp_valuelen); 436 if (jp->jp_value == NULL) { 437 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 438 return (-1); 439 } 440 avalue = value; 441 for (i = 0; i < nval; i++) { 442 fw = nval == 1 ? strlen(avalue) : strcspn(avalue, ","); 443 switch (jp->jp_ctltype & CTLTYPE) { 444 case CTLTYPE_INT: 445 if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) { 446 if (!jailparam_import_enum(bool_values, 2, 447 avalue, fw, &((int *)jp->jp_value)[i])) { 448 snprintf(jail_errmsg, 449 JAIL_ERRMSGLEN, "%s: " 450 "unknown boolean value \"%.*s\"", 451 jp->jp_name, fw, avalue); 452 errno = EINVAL; 453 goto error; 454 } 455 break; 456 } 457 if (jp->jp_flags & JP_JAILSYS) { 458 /* 459 * Allow setting a jailsys parameter to "new" 460 * in a booleanesque fashion. 461 */ 462 if (value[0] == '\0') 463 ((int *)jp->jp_value)[i] = JAIL_SYS_NEW; 464 else if (!jailparam_import_enum(jailsys_values, 465 sizeof(jailsys_values) / 466 sizeof(jailsys_values[0]), avalue, fw, 467 &((int *)jp->jp_value)[i])) { 468 snprintf(jail_errmsg, 469 JAIL_ERRMSGLEN, "%s: " 470 "unknown jailsys value \"%.*s\"", 471 jp->jp_name, fw, avalue); 472 errno = EINVAL; 473 goto error; 474 } 475 break; 476 } 477 ((int *)jp->jp_value)[i] = strtol(avalue, &ep, 10); 478 integer_test: 479 if (ep != avalue + fw) { 480 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 481 "%s: non-integer value \"%.*s\"", 482 jp->jp_name, fw, avalue); 483 errno = EINVAL; 484 goto error; 485 } 486 break; 487 case CTLTYPE_UINT: 488 ((unsigned *)jp->jp_value)[i] = 489 strtoul(avalue, &ep, 10); 490 goto integer_test; 491 case CTLTYPE_LONG: 492 ((long *)jp->jp_value)[i] = strtol(avalue, &ep, 10); 493 goto integer_test; 494 case CTLTYPE_ULONG: 495 ((unsigned long *)jp->jp_value)[i] = 496 strtoul(avalue, &ep, 10); 497 goto integer_test; 498 case CTLTYPE_S64: 499 ((int64_t *)jp->jp_value)[i] = 500 strtoimax(avalue, &ep, 10); 501 goto integer_test; 502 case CTLTYPE_U64: 503 ((uint64_t *)jp->jp_value)[i] = 504 strtoumax(avalue, &ep, 10); 505 goto integer_test; 506 case CTLTYPE_STRUCT: 507 tvalue = alloca(fw + 1); 508 strlcpy(tvalue, avalue, fw + 1); 509 510 if (jp->jp_structtype == -1) 511 goto unknown_type; 512 513 jpsdef = &jp_structdefs[jp->jp_structtype]; 514 if ((*jpsdef->jps_import)(jp, i, tvalue) != 0) 515 goto error; 516 break; 517 default: 518 unknown_type: 519 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 520 "unknown type for %s", jp->jp_name); 521 errno = ENOENT; 522 goto error; 523 } 524 avalue += fw + 1; 525 } 526 return (0); 527 528 error: 529 free(jp->jp_value); 530 jp->jp_value = NULL; 531 return (-1); 532 } 533 534 static int 535 jailparam_import_enum(const char **values, int nvalues, const char *valstr, 536 size_t valsize, int *value) 537 { 538 char *ep; 539 int i; 540 541 for (i = 0; i < nvalues; i++) 542 if (valsize == strlen(values[i]) && 543 !strncasecmp(valstr, values[i], valsize)) { 544 *value = i; 545 return 1; 546 } 547 *value = strtol(valstr, &ep, 10); 548 return (ep == valstr + valsize); 549 } 550 551 /* 552 * Put a name and value into a jail parameter element, copying the value 553 * but not altering it. 554 */ 555 int 556 jailparam_import_raw(struct jailparam *jp, void *value, size_t valuelen) 557 { 558 559 jp->jp_value = value; 560 jp->jp_valuelen = valuelen; 561 jp->jp_flags |= JP_RAWVALUE; 562 return (0); 563 } 564 565 /* 566 * Run the jail_set and jail_get system calls on a parameter list. 567 */ 568 int 569 jailparam_set(struct jailparam *jp, unsigned njp, int flags) 570 { 571 struct iovec *jiov; 572 char *nname; 573 int i, jid, bool0; 574 unsigned j; 575 576 jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1)); 577 bool0 = 0; 578 for (i = j = 0; j < njp; j++) { 579 jiov[i].iov_base = jp[j].jp_name; 580 jiov[i].iov_len = strlen(jp[j].jp_name) + 1; 581 i++; 582 if (jp[j].jp_flags & (JP_BOOL | JP_NOBOOL)) { 583 /* 584 * Set booleans without values. If one has a value of 585 * zero, change it to (or from) its "no" counterpart. 586 */ 587 jiov[i].iov_base = NULL; 588 jiov[i].iov_len = 0; 589 if (jp[j].jp_value != NULL && 590 jp[j].jp_valuelen == sizeof(int) && 591 !*(int *)jp[j].jp_value) { 592 bool0 = 1; 593 nname = jp[j].jp_flags & JP_BOOL 594 ? noname(jp[j].jp_name) 595 : nononame(jp[j].jp_name); 596 if (nname == NULL) { 597 njp = j; 598 jid = -1; 599 goto done; 600 } 601 jiov[i - 1].iov_base = nname; 602 jiov[i - 1].iov_len = strlen(nname) + 1; 603 604 } 605 } else if (jp[j].jp_flags & JP_KEYVALUE && 606 jp[j].jp_value == NULL) { 607 /* No value means key removal. */ 608 jiov[i].iov_base = NULL; 609 jiov[i].iov_len = 0; 610 } else if (jps_set(&jp[j], &jiov[i]) != 0) { 611 /* 612 * Try to fill in missing values with an empty string. 613 */ 614 if (jp[j].jp_value == NULL && jp[j].jp_valuelen > 0 && 615 jailparam_import(jp + j, "") < 0) { 616 njp = j; 617 jid = -1; 618 goto done; 619 } 620 jiov[i].iov_base = jp[j].jp_value; 621 jiov[i].iov_len = 622 (jp[j].jp_ctltype & CTLTYPE) == CTLTYPE_STRING 623 ? strlen(jp[j].jp_value) + 1 624 : jp[j].jp_valuelen; 625 } 626 i++; 627 } 628 jiov[i].iov_base = __DECONST(char *, "errmsg"); 629 jiov[i].iov_len = sizeof("errmsg"); 630 i++; 631 jiov[i].iov_base = jail_errmsg; 632 jiov[i].iov_len = JAIL_ERRMSGLEN; 633 i++; 634 jail_errmsg[0] = 0; 635 jid = jail_set(jiov, i, flags); 636 if (jid < 0 && !jail_errmsg[0]) 637 snprintf(jail_errmsg, sizeof(jail_errmsg), "jail_set: %s", 638 strerror(errno)); 639 done: 640 if (bool0) 641 for (j = 0; j < njp; j++) 642 if ((jp[j].jp_flags & (JP_BOOL | JP_NOBOOL)) && 643 jp[j].jp_value != NULL && 644 jp[j].jp_valuelen == sizeof(int) && 645 !*(int *)jp[j].jp_value) 646 free(jiov[j * 2].iov_base); 647 return (jid); 648 } 649 650 int 651 jailparam_get(struct jailparam *jp, unsigned njp, int flags) 652 { 653 struct iovec *jiov; 654 struct jailparam *jp_desc, *jp_lastjid, *jp_jid, *jp_name, *jp_key; 655 int i, ai, ki, jid, arrays, processed, sanity; 656 unsigned j; 657 658 /* 659 * Get the types for all parameters. 660 * Find the key and any array parameters. 661 */ 662 jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1)); 663 jp_desc = jp_lastjid = jp_jid = jp_name = NULL; 664 arrays = 0; 665 for (ai = j = 0; j < njp; j++) { 666 if (!strcmp(jp[j].jp_name, "desc") && 667 (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) 668 jp_desc = jp + j; 669 else if (!strcmp(jp[j].jp_name, "lastjid")) 670 jp_lastjid = jp + j; 671 else if (!strcmp(jp[j].jp_name, "jid")) 672 jp_jid = jp + j; 673 else if (!strcmp(jp[j].jp_name, "name")) 674 jp_name = jp + j; 675 else if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) { 676 arrays = 1; 677 jiov[ai].iov_base = jp[j].jp_name; 678 jiov[ai].iov_len = strlen(jp[j].jp_name) + 1; 679 ai++; 680 jiov[ai].iov_base = NULL; 681 jiov[ai].iov_len = 0; 682 ai++; 683 } 684 } 685 jp_key = jp_desc && jp_desc->jp_valuelen == sizeof(int) && 686 jp_desc->jp_value && (flags & JAIL_USE_DESC) ? jp_desc : 687 jp_lastjid ? jp_lastjid : 688 jp_jid && jp_jid->jp_valuelen == sizeof(int) && 689 jp_jid->jp_value && *(int *)jp_jid->jp_value ? jp_jid : jp_name; 690 if (jp_key == NULL || jp_key->jp_value == NULL) { 691 strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN); 692 errno = ENOENT; 693 return (-1); 694 } 695 ki = ai; 696 jiov[ki].iov_base = jp_key->jp_name; 697 jiov[ki].iov_len = strlen(jp_key->jp_name) + 1; 698 ki++; 699 jiov[ki].iov_base = jp_key->jp_value; 700 jiov[ki].iov_len = (jp_key->jp_ctltype & CTLTYPE) == CTLTYPE_STRING 701 ? strlen(jp_key->jp_value) + 1 : jp_key->jp_valuelen; 702 ki++; 703 jiov[ki].iov_base = __DECONST(char *, "errmsg"); 704 jiov[ki].iov_len = sizeof("errmsg"); 705 ki++; 706 jiov[ki].iov_base = jail_errmsg; 707 jiov[ki].iov_len = JAIL_ERRMSGLEN; 708 ki++; 709 jail_errmsg[0] = 0; 710 if (jp_desc != NULL && jp_desc != jp_key) { 711 jiov[ki].iov_base = jp_desc->jp_name; 712 jiov[ki].iov_len = strlen(jp_desc->jp_name) + 1; 713 ki++; 714 jiov[ki].iov_base = jp_desc->jp_value; 715 jiov[ki].iov_len = jp_desc->jp_valuelen; 716 ki++; 717 } 718 if (arrays && jail_get(jiov, ki, flags) < 0) { 719 if (!jail_errmsg[0]) 720 snprintf(jail_errmsg, sizeof(jail_errmsg), 721 "jail_get: %s", strerror(errno)); 722 return (-1); 723 } 724 /* Allocate storage for all parameters. */ 725 for (ai = j = 0, i = ki; j < njp; j++) { 726 if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) { 727 ai++; 728 jiov[ai].iov_len += jp[j].jp_elemlen * ARRAY_SLOP; 729 if (jp[j].jp_valuelen >= jiov[ai].iov_len) 730 jiov[ai].iov_len = jp[j].jp_valuelen; 731 else { 732 jp[j].jp_valuelen = jiov[ai].iov_len; 733 if (jp[j].jp_value != NULL) 734 free(jp[j].jp_value); 735 jp[j].jp_value = malloc(jp[j].jp_valuelen); 736 if (jp[j].jp_value == NULL) { 737 strerror_r(errno, jail_errmsg, 738 JAIL_ERRMSGLEN); 739 return (-1); 740 } 741 } 742 jiov[ai].iov_base = jp[j].jp_value; 743 memset(jiov[ai].iov_base, 0, jiov[ai].iov_len); 744 ai++; 745 } else if (jp + j != jp_key && jp + j != jp_desc) { 746 jiov[i].iov_base = jp[j].jp_name; 747 jiov[i].iov_len = strlen(jp[j].jp_name) + 1; 748 i++; 749 if (jp[j].jp_value == NULL && 750 !(jp[j].jp_flags & JP_RAWVALUE)) { 751 jp[j].jp_value = malloc(jp[j].jp_valuelen); 752 if (jp[j].jp_value == NULL) { 753 strerror_r(errno, jail_errmsg, 754 JAIL_ERRMSGLEN); 755 return (-1); 756 } 757 758 /* 759 * Returns -1 on error, or # index populated on 760 * success. 0 is perfectly valid for a type 761 * that may want to simply initialize the value 762 * as needed. 763 */ 764 processed = jps_get(&jp[j], &jiov[i]); 765 if (processed == -1) { 766 return (-1); 767 } else if (processed > 0) { 768 /* 769 * The above math for jiov sizing does 770 * not really account for one param 771 * expanding to multiple entries. 772 */ 773 assert(processed == 1); 774 i += processed; 775 continue; 776 } 777 } 778 jiov[i].iov_base = jp[j].jp_value; 779 jiov[i].iov_len = jp[j].jp_valuelen; 780 memset(jiov[i].iov_base, 0, jiov[i].iov_len); 781 i++; 782 } 783 } 784 /* 785 * Get the prison. If there are array elements, retry a few times 786 * in case their sizes changed from under us. 787 */ 788 for (sanity = 0;; sanity++) { 789 jid = jail_get(jiov, i, flags); 790 if (jid >= 0 || !arrays || sanity == ARRAY_SANITY || 791 errno != EINVAL || jail_errmsg[0]) 792 break; 793 for (ai = j = 0; j < njp; j++) { 794 if (jp[j].jp_elemlen && 795 !(jp[j].jp_flags & JP_RAWVALUE)) { 796 ai++; 797 jiov[ai].iov_base = NULL; 798 jiov[ai].iov_len = 0; 799 ai++; 800 } 801 } 802 if (jail_get(jiov, ki, flags) < 0) 803 break; 804 for (ai = j = 0; j < njp; j++) { 805 if (jp[j].jp_elemlen && 806 !(jp[j].jp_flags & JP_RAWVALUE)) { 807 ai++; 808 jiov[ai].iov_len += 809 jp[j].jp_elemlen * ARRAY_SLOP; 810 if (jp[j].jp_valuelen >= jiov[ai].iov_len) 811 jiov[ai].iov_len = jp[j].jp_valuelen; 812 else { 813 jp[j].jp_valuelen = jiov[ai].iov_len; 814 if (jp[j].jp_value != NULL) 815 free(jp[j].jp_value); 816 jp[j].jp_value = 817 malloc(jiov[ai].iov_len); 818 if (jp[j].jp_value == NULL) { 819 strerror_r(errno, jail_errmsg, 820 JAIL_ERRMSGLEN); 821 return (-1); 822 } 823 } 824 jiov[ai].iov_base = jp[j].jp_value; 825 memset(jiov[ai].iov_base, 0, jiov[ai].iov_len); 826 ai++; 827 } 828 } 829 } 830 if (jid < 0 && !jail_errmsg[0]) 831 snprintf(jail_errmsg, sizeof(jail_errmsg), 832 "jail_get: %s", strerror(errno)); 833 for (ai = j = 0, i = ki; j < njp; j++) { 834 if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) { 835 ai++; 836 jp[j].jp_valuelen = jiov[ai].iov_len; 837 ai++; 838 } else if (jp + j != jp_key) { 839 i++; 840 jp[j].jp_valuelen = jiov[i].iov_len; 841 i++; 842 } 843 } 844 return (jid); 845 } 846 847 /* 848 * Convert a jail parameter's value to external form. 849 */ 850 char * 851 jailparam_export(struct jailparam *jp) 852 { 853 size_t *valuelens; 854 char *value, *tvalue, **values; 855 const struct jp_structdef *jpsdef; 856 size_t valuelen; 857 int i, nval, ival; 858 char valbuf[INET6_ADDRSTRLEN]; 859 860 if (jp->jp_value == NULL) { 861 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 862 "parameter %s was not imported", jp->jp_name); 863 errno = EINVAL; 864 return (NULL); 865 } 866 if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) { 867 value = strdup(jp->jp_value); 868 if (value == NULL) 869 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 870 return (value); 871 } 872 nval = jp->jp_elemlen ? jp->jp_valuelen / jp->jp_elemlen : 1; 873 if (nval == 0) { 874 value = strdup(""); 875 if (value == NULL) 876 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 877 return (value); 878 } 879 values = alloca(nval * sizeof(char *)); 880 valuelens = alloca(nval * sizeof(size_t)); 881 valuelen = 0; 882 for (i = 0; i < nval; i++) { 883 switch (jp->jp_ctltype & CTLTYPE) { 884 case CTLTYPE_INT: 885 ival = ((int *)jp->jp_value)[i]; 886 if ((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) && 887 (unsigned)ival < 2) { 888 strlcpy(valbuf, bool_values[ival], 889 sizeof(valbuf)); 890 break; 891 } 892 if ((jp->jp_flags & JP_JAILSYS) && 893 (unsigned)ival < sizeof(jailsys_values) / 894 sizeof(jailsys_values[0])) { 895 strlcpy(valbuf, jailsys_values[ival], 896 sizeof(valbuf)); 897 break; 898 } 899 snprintf(valbuf, sizeof(valbuf), "%d", ival); 900 break; 901 case CTLTYPE_UINT: 902 snprintf(valbuf, sizeof(valbuf), "%u", 903 ((unsigned *)jp->jp_value)[i]); 904 break; 905 case CTLTYPE_LONG: 906 snprintf(valbuf, sizeof(valbuf), "%ld", 907 ((long *)jp->jp_value)[i]); 908 break; 909 case CTLTYPE_ULONG: 910 snprintf(valbuf, sizeof(valbuf), "%lu", 911 ((unsigned long *)jp->jp_value)[i]); 912 break; 913 case CTLTYPE_S64: 914 snprintf(valbuf, sizeof(valbuf), "%jd", 915 (intmax_t)((int64_t *)jp->jp_value)[i]); 916 break; 917 case CTLTYPE_U64: 918 snprintf(valbuf, sizeof(valbuf), "%ju", 919 (uintmax_t)((uint64_t *)jp->jp_value)[i]); 920 break; 921 case CTLTYPE_STRUCT: 922 if (jp->jp_structtype == -1) 923 goto unknown_type; 924 925 jpsdef = &jp_structdefs[jp->jp_structtype]; 926 value = (*jpsdef->jps_export)(jp, i); 927 if (value == NULL) { 928 strerror_r(errno, jail_errmsg, 929 JAIL_ERRMSGLEN); 930 return (NULL); 931 } 932 933 valuelens[i] = strlen(value) + 1; 934 valuelen += valuelens[i]; 935 values[i] = alloca(valuelens[i]); 936 strcpy(values[i], value); 937 938 free(value); 939 value = NULL; 940 continue; /* Value already added to values[] */ 941 default: 942 unknown_type: 943 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 944 "unknown type for %s", jp->jp_name); 945 errno = ENOENT; 946 return (NULL); 947 } 948 valuelens[i] = strlen(valbuf) + 1; 949 valuelen += valuelens[i]; 950 values[i] = alloca(valuelens[i]); 951 strcpy(values[i], valbuf); 952 } 953 value = malloc(valuelen); 954 if (value == NULL) 955 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 956 else { 957 tvalue = value; 958 for (i = 0; i < nval; i++) { 959 strcpy(tvalue, values[i]); 960 if (i < nval - 1) { 961 tvalue += valuelens[i]; 962 tvalue[-1] = ','; 963 } 964 } 965 } 966 return (value); 967 } 968 969 /* 970 * Free the contents of a jail parameter list (but not the list itself). 971 */ 972 void 973 jailparam_free(struct jailparam *jp, unsigned njp) 974 { 975 976 unsigned j; 977 978 for (j = 0; j < njp; j++) { 979 free(jp[j].jp_name); 980 if (!(jp[j].jp_flags & JP_RAWVALUE)) { 981 jps_free(jp); 982 free(jp[j].jp_value); 983 } 984 } 985 } 986 987 /* 988 * Find a parameter's type and size from its MIB. 989 */ 990 static int 991 jailparam_type(struct jailparam *jp) 992 { 993 char *p, *name, *nname; 994 size_t miblen, desclen; 995 int i, isarray; 996 struct { 997 int i; 998 char s[MAXPATHLEN]; 999 } desc; 1000 int mib[CTL_MAXNAME]; 1001 1002 /* 1003 * Some pseudo-parameters don't show up in the sysctl 1004 * parameter list. 1005 */ 1006 name = jp->jp_name; 1007 if (!strcmp(name, "lastjid")) { 1008 jp->jp_valuelen = sizeof(int); 1009 jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR; 1010 return (0); 1011 } 1012 if (!strcmp(name, "desc")) { 1013 jp->jp_valuelen = sizeof(int); 1014 jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_RW; 1015 return (0); 1016 } 1017 1018 /* Find the sysctl that describes the parameter. */ 1019 mib[0] = 0; 1020 mib[1] = 3; 1021 snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", name); 1022 miblen = sizeof(mib) - 2 * sizeof(int); 1023 if (sysctl(mib, 2, mib + 2, &miblen, desc.s, strlen(desc.s)) < 0) { 1024 if (errno != ENOENT) { 1025 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1026 "sysctl(0.3.%s): %s", name, strerror(errno)); 1027 return (-1); 1028 } 1029 if (kldload_param(name) >= 0 && sysctl(mib, 2, mib + 2, &miblen, 1030 desc.s, strlen(desc.s)) >= 0) 1031 goto mib_desc; 1032 /* 1033 * The parameter probably doesn't exist. But it might be 1034 * the "no" counterpart to a boolean. 1035 */ 1036 nname = nononame(name); 1037 if (nname != NULL) { 1038 snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname); 1039 miblen = sizeof(mib) - 2 * sizeof(int); 1040 if (sysctl(mib, 2, mib + 2, &miblen, desc.s, 1041 strlen(desc.s)) >= 0) { 1042 name = alloca(strlen(nname) + 1); 1043 strcpy(name, nname); 1044 free(nname); 1045 jp->jp_flags |= JP_NOBOOL; 1046 goto mib_desc; 1047 } 1048 free(nname); 1049 } 1050 /* 1051 * It might be an assumed sub-node of a fmt='A,keyvalue' sysctl. 1052 */ 1053 nname = kvname(name); 1054 if (nname != NULL) { 1055 snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname); 1056 miblen = sizeof(mib) - 2 * sizeof(int); 1057 if (sysctl(mib, 2, mib + 2, &miblen, desc.s, 1058 strlen(desc.s)) >= 0) { 1059 name = alloca(strlen(nname) + 1); 1060 strcpy(name, nname); 1061 free(nname); 1062 jp->jp_flags |= JP_KEYVALUE; 1063 goto mib_desc; 1064 } 1065 free(nname); 1066 } 1067 unknown_parameter: 1068 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1069 "unknown parameter: %s", jp->jp_name); 1070 errno = ENOENT; 1071 return (-1); 1072 } 1073 mib_desc: 1074 mib[1] = 4; 1075 desclen = sizeof(desc); 1076 if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen, 1077 NULL, 0) < 0) { 1078 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1079 "sysctl(0.4.%s): %s", name, strerror(errno)); 1080 return (-1); 1081 } 1082 jp->jp_ctltype = desc.i; 1083 /* If this came from removing a "no", it better be a boolean. */ 1084 if (jp->jp_flags & JP_NOBOOL) { 1085 if ((desc.i & CTLTYPE) == CTLTYPE_INT && desc.s[0] == 'B') { 1086 jp->jp_valuelen = sizeof(int); 1087 return (0); 1088 } 1089 else if ((desc.i & CTLTYPE) != CTLTYPE_NODE) 1090 goto unknown_parameter; 1091 } 1092 /* Make sure it is a valid keyvalue param. */ 1093 if (jp->jp_flags & JP_KEYVALUE) { 1094 if ((desc.i & CTLTYPE) != CTLTYPE_STRING || 1095 strcmp(desc.s, "A,keyvalue") != 0) 1096 goto unknown_parameter; 1097 } 1098 /* See if this is an array type. */ 1099 p = strchr(desc.s, '\0'); 1100 isarray = 0; 1101 if (p - 2 < desc.s || strcmp(p - 2, ",a")) 1102 isarray = 0; 1103 else { 1104 isarray = 1; 1105 p[-2] = 0; 1106 } 1107 /* Look for types we understand. */ 1108 switch (desc.i & CTLTYPE) { 1109 case CTLTYPE_INT: 1110 if (desc.s[0] == 'B') 1111 jp->jp_flags |= JP_BOOL; 1112 else if (!strcmp(desc.s, "E,jailsys")) 1113 jp->jp_flags |= JP_JAILSYS; 1114 case CTLTYPE_UINT: 1115 jp->jp_valuelen = sizeof(int); 1116 break; 1117 case CTLTYPE_LONG: 1118 case CTLTYPE_ULONG: 1119 jp->jp_valuelen = sizeof(long); 1120 break; 1121 case CTLTYPE_S64: 1122 case CTLTYPE_U64: 1123 jp->jp_valuelen = sizeof(int64_t); 1124 break; 1125 case CTLTYPE_STRING: 1126 desc.s[0] = 0; 1127 desclen = sizeof(desc.s); 1128 if (sysctl(mib + 2, miblen / sizeof(int), desc.s, &desclen, 1129 NULL, 0) < 0) { 1130 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1131 "sysctl(" SJPARAM ".%s): %s", name, 1132 strerror(errno)); 1133 return (-1); 1134 } 1135 jp->jp_valuelen = strtoul(desc.s, NULL, 10); 1136 break; 1137 case CTLTYPE_STRUCT: { 1138 const struct jp_structdef *jpsdef; 1139 1140 jpsdef = jp_structinfo(desc.s, &jp->jp_structtype); 1141 if (jpsdef != NULL) { 1142 assert(jp->jp_structtype >= 0); 1143 1144 jp->jp_valuelen = jpsdef->jps_valuelen; 1145 } else { 1146 assert(jp->jp_structtype == -1); 1147 1148 desclen = 0; 1149 if (sysctl(mib + 2, miblen / sizeof(int), 1150 NULL, &jp->jp_valuelen, NULL, 0) < 0) { 1151 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1152 "sysctl(" SJPARAM ".%s): %s", name, 1153 strerror(errno)); 1154 return (-1); 1155 } 1156 } 1157 break; 1158 } 1159 case CTLTYPE_NODE: 1160 /* 1161 * A node might be described by an empty-named child, 1162 * which would be immediately before or after the node itself. 1163 */ 1164 mib[1] = 1; 1165 miblen += sizeof(int); 1166 for (i = -1; i <= 1; i += 2) { 1167 mib[(miblen / sizeof(int)) + 1] = 1168 mib[(miblen / sizeof(int))] + i; 1169 desclen = sizeof(desc.s); 1170 if (sysctl(mib, (miblen / sizeof(int)) + 2, desc.s, 1171 &desclen, NULL, 0) < 0) { 1172 if (errno == ENOENT) 1173 continue; 1174 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1175 "sysctl(0.1): %s", strerror(errno)); 1176 return (-1); 1177 } 1178 if (desclen == sizeof(SJPARAM) + strlen(name) + 2 && 1179 memcmp(SJPARAM ".", desc.s, sizeof(SJPARAM)) == 0 && 1180 memcmp(name, desc.s + sizeof(SJPARAM), 1181 desclen - sizeof(SJPARAM) - 2) == 0 && 1182 desc.s[desclen - 2] == '.') 1183 goto mib_desc; 1184 } 1185 goto unknown_parameter; 1186 default: 1187 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1188 "unknown type for %s", jp->jp_name); 1189 errno = ENOENT; 1190 return (-1); 1191 } 1192 if (isarray) { 1193 jp->jp_elemlen = jp->jp_valuelen; 1194 jp->jp_valuelen = 0; 1195 } 1196 return (0); 1197 } 1198 1199 /* 1200 * Attempt to load a kernel module matching an otherwise nonexistent parameter. 1201 */ 1202 static int 1203 kldload_param(const char *name) 1204 { 1205 int kl; 1206 1207 if (strcmp(name, "linux") == 0 || strncmp(name, "linux.", 6) == 0) 1208 kl = kldload("linux"); 1209 else if (strcmp(name, "sysvmsg") == 0 || strcmp(name, "sysvsem") == 0 || 1210 strcmp(name, "sysvshm") == 0) 1211 kl = kldload(name); 1212 else if (strncmp(name, "allow.mount.", 12) == 0) { 1213 /* Load the matching filesystem */ 1214 const char *modname = name + 12; 1215 1216 kl = kldload(modname); 1217 if (kl < 0 && errno == ENOENT && 1218 strncmp(modname, "no", 2) == 0) 1219 kl = kldload(modname + 2); 1220 } else { 1221 errno = ENOENT; 1222 return (-1); 1223 } 1224 if (kl < 0 && errno == EEXIST) { 1225 /* 1226 * In the module is already loaded, then it must not contain 1227 * the parameter. 1228 */ 1229 errno = ENOENT; 1230 } 1231 return kl; 1232 } 1233 1234 /* 1235 * Change a boolean parameter name into its "no" counterpart or vice versa. 1236 */ 1237 static char * 1238 noname(const char *name) 1239 { 1240 char *nname, *p; 1241 1242 nname = malloc(strlen(name) + 3); 1243 if (nname == NULL) { 1244 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 1245 return (NULL); 1246 } 1247 p = strrchr(name, '.'); 1248 if (p != NULL) 1249 sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1); 1250 else 1251 sprintf(nname, "no%s", name); 1252 return (nname); 1253 } 1254 1255 static char * 1256 nononame(const char *name) 1257 { 1258 char *p, *nname; 1259 1260 p = strrchr(name, '.'); 1261 if (strncmp(p ? p + 1 : name, "no", 2)) { 1262 snprintf(jail_errmsg, sizeof(jail_errmsg), 1263 "mismatched boolean: %s", name); 1264 errno = EINVAL; 1265 return (NULL); 1266 } 1267 nname = malloc(strlen(name) - 1); 1268 if (nname == NULL) { 1269 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 1270 return (NULL); 1271 } 1272 if (p != NULL) 1273 sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3); 1274 else 1275 strcpy(nname, name + 2); 1276 return (nname); 1277 } 1278 1279 static char * 1280 kvname(const char *name) 1281 { 1282 const char *p; 1283 char *kvname; 1284 size_t len; 1285 1286 p = strchr(name, '.'); 1287 if (p == NULL) 1288 return (NULL); 1289 1290 len = p - name; 1291 kvname = malloc(len + 1); 1292 if (kvname == NULL) { 1293 strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); 1294 return (NULL); 1295 } 1296 strncpy(kvname, name, len); 1297 kvname[len] = '\0'; 1298 1299 return (kvname); 1300 } 1301 1302 static int 1303 jps_get(struct jailparam *jp, struct iovec *jiov) 1304 { 1305 const struct jp_structdef *jpsdef; 1306 1307 jpsdef = JPSDEF_OF(jp); 1308 if (jpsdef == NULL || jpsdef->jps_get == NULL) 1309 return (0); /* Nop, but not an error. */ 1310 1311 return ((jpsdef->jps_get)(jp, jiov)); 1312 } 1313 1314 static int 1315 jps_set(const struct jailparam *jp, struct iovec *jiov) 1316 { 1317 const struct jp_structdef *jpsdef; 1318 1319 jpsdef = JPSDEF_OF(jp); 1320 if (jpsdef == NULL || jpsdef->jps_set == NULL) 1321 return (EINVAL); /* Unhandled */ 1322 1323 return ((jpsdef->jps_set)(jp, jiov)); 1324 } 1325 1326 static void 1327 jps_free(struct jailparam *jp) 1328 { 1329 const struct jp_structdef *jpsdef; 1330 1331 jpsdef = JPSDEF_OF(jp); 1332 if (jpsdef == NULL) 1333 return; 1334 1335 if (jpsdef->jps_free != NULL) 1336 jpsdef->jps_free(jp); 1337 } 1338 1339 static int 1340 jps_import_in_addr(const struct jailparam *jp, int i, const char *value) 1341 { 1342 struct in_addr *addr; 1343 1344 addr = &((struct in_addr *)jp->jp_value)[i]; 1345 if (inet_pton(AF_INET, value, addr) != 1) { 1346 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1347 "%s: not an IPv4 address: %s", jp->jp_name, value); 1348 errno = EINVAL; 1349 return (-1); 1350 } 1351 1352 return (0); 1353 } 1354 1355 static int 1356 jps_import_in6_addr(const struct jailparam *jp, int i, const char *value) 1357 { 1358 struct in6_addr *addr6; 1359 1360 addr6 = &((struct in6_addr *)jp->jp_value)[i]; 1361 if (inet_pton(AF_INET6, value, addr6) != 1) { 1362 snprintf(jail_errmsg, JAIL_ERRMSGLEN, 1363 "%s: not an IPv6 address: %s", jp->jp_name, value); 1364 errno = EINVAL; 1365 return (-1); 1366 } 1367 1368 return (0); 1369 } 1370 1371 static int 1372 jps_import_mac_label(const struct jailparam *jp, int i, const char *value) 1373 { 1374 mac_t *pmac; 1375 1376 pmac = &((mac_t *)jp->jp_value)[i]; 1377 if (mac_from_text(pmac, value) != 0) { 1378 int serrno = errno; 1379 1380 snprintf(jail_errmsg, JAIL_ERRMSGLEN, "%s: mac_from_text: %s", 1381 jp->jp_name, strerror(errno)); 1382 errno = serrno; 1383 return (-1); 1384 } 1385 1386 return (0); 1387 } 1388 1389 static char * 1390 jps_export_in_addr(const struct jailparam *jp, int i) 1391 { 1392 struct in_addr *addr; 1393 char valbuf[INET_ADDRSTRLEN]; 1394 1395 addr = &((struct in_addr *)jp->jp_value)[i]; 1396 if (inet_ntop(AF_INET, addr, valbuf, sizeof(valbuf)) == NULL) 1397 return (NULL); 1398 1399 /* Error checked by caller. */ 1400 return (strdup(valbuf)); 1401 } 1402 1403 static char * 1404 jps_export_in6_addr(const struct jailparam *jp, int i) 1405 { 1406 struct in6_addr *addr6; 1407 char valbuf[INET6_ADDRSTRLEN]; 1408 1409 addr6 = &((struct in6_addr *)jp->jp_value)[i]; 1410 if (inet_ntop(AF_INET6, addr6, valbuf, sizeof(valbuf)) == NULL) 1411 return (NULL); 1412 1413 /* Error checked by caller. */ 1414 return (strdup(valbuf)); 1415 } 1416 1417 static char * 1418 jps_export_mac_label(const struct jailparam *jp, int i) 1419 { 1420 mac_t *macp; 1421 char *labelbuf; 1422 int error; 1423 1424 macp = &((mac_t *)jp->jp_value)[i]; 1425 error = mac_to_text(*macp, &labelbuf); 1426 if (error != 0) 1427 return (NULL); 1428 1429 return (labelbuf); 1430 } 1431 1432 static int 1433 jps_get_mac_label(struct jailparam *jp, struct iovec *jiov) 1434 { 1435 mac_t *pmac = jp->jp_value; 1436 int error; 1437 1438 error = mac_prepare_type(pmac, "jail"); 1439 if (error != 0 && errno == ENOENT) { 1440 /* 1441 * We special-case the scenario where a system has a custom 1442 * mac.conf(5) that doesn't include a jail entry -- just let 1443 * an empty label slide. 1444 */ 1445 error = mac_prepare(pmac, "?"); 1446 } 1447 if (error != 0) { 1448 int serrno = errno; 1449 1450 free(jp->jp_value); 1451 jp->jp_value = NULL; 1452 1453 strerror_r(serrno, jail_errmsg, JAIL_ERRMSGLEN); 1454 errno = serrno; 1455 return (-1); 1456 } 1457 1458 /* 1459 * MAC label gets special handling because libjail internally maintains 1460 * it as a pointer to a mac_t, but we actually want to pass the mac_t 1461 * itself. We don't want the jailparam_get() zeroing behavior, as it's 1462 * initialized by us. 1463 */ 1464 jiov->iov_base = *pmac; 1465 jiov->iov_len = sizeof(**pmac); 1466 return (1); 1467 } 1468 1469 static int 1470 jps_set_mac_label(const struct jailparam *jp, struct iovec *jiov) 1471 { 1472 mac_t *pmac; 1473 1474 /* 1475 * MAC label gets special handling because libjail internally 1476 * maintains it as a pointer to a mac_t, but we actually want to 1477 * pass the mac_t itself. 1478 */ 1479 pmac = jp->jp_value; 1480 if (pmac != NULL) { 1481 jiov->iov_base = *pmac; 1482 jiov->iov_len = sizeof(**pmac); 1483 } else { 1484 jiov->iov_base = NULL; 1485 jiov->iov_len = 0; 1486 } 1487 1488 return (0); 1489 } 1490 1491 static void 1492 jps_free_mac_label(struct jailparam *jp) 1493 { 1494 mac_t *pmac = jp->jp_value; 1495 1496 if (pmac != NULL) 1497 mac_free(*pmac); 1498 } 1499