jail.c (194708) | jail.c (194869) |
---|---|
1/*- 2 * Copyright (c) 1999 Poul-Henning Kamp. 3 * Copyright (c) 2009 James Gritton 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1999 Poul-Henning Kamp. 3 * Copyright (c) 2009 James Gritton 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/usr.sbin/jail/jail.c 194708 2009-06-23 14:39:51Z jamie $"); | 29__FBSDID("$FreeBSD: head/usr.sbin/jail/jail.c 194869 2009-06-24 18:18:35Z jamie $"); |
30 31#include <sys/param.h> 32#include <sys/jail.h> 33#include <sys/socket.h> 34#include <sys/sysctl.h> | 30 31#include <sys/param.h> 32#include <sys/jail.h> 33#include <sys/socket.h> 34#include <sys/sysctl.h> |
35#include <sys/uio.h> | |
36 37#include <arpa/inet.h> 38#include <netinet/in.h> 39 40#include <ctype.h> 41#include <err.h> 42#include <errno.h> 43#include <grp.h> | 35 36#include <arpa/inet.h> 37#include <netinet/in.h> 38 39#include <ctype.h> 40#include <err.h> 41#include <errno.h> 42#include <grp.h> |
43#include <jail.h> |
|
44#include <login_cap.h> 45#include <netdb.h> 46#include <paths.h> 47#include <pwd.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <unistd.h> 52 | 44#include <login_cap.h> 45#include <netdb.h> 46#include <paths.h> 47#include <pwd.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <unistd.h> 52 |
53#define SJPARAM "security.jail.param" 54#define ERRMSG_SIZE 256 55 56struct param { 57 struct iovec name; 58 struct iovec value; 59}; 60 61static struct param *params; | 53static struct jailparam *params; |
62static char **param_values; 63static int nparams; 64 65static char *ip4_addr; 66#ifdef INET6 67static char *ip6_addr; 68#endif 69 --- 38 unchanged lines hidden (view full) --- 108 if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \ 109 err(1, "getgrouplist: %s", username); \ 110} while (0) 111 112int 113main(int argc, char **argv) 114{ 115 login_cap_t *lcap = NULL; | 54static char **param_values; 55static int nparams; 56 57static char *ip4_addr; 58#ifdef INET6 59static char *ip6_addr; 60#endif 61 --- 38 unchanged lines hidden (view full) --- 100 if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \ 101 err(1, "getgrouplist: %s", username); \ 102} while (0) 103 104int 105main(int argc, char **argv) 106{ 107 login_cap_t *lcap = NULL; |
116 struct iovec rparams[2]; | |
117 struct passwd *pwd = NULL; 118 gid_t *groups; 119 size_t sysvallen; 120 int ch, cmdarg, i, jail_set_flags, jid, ngroups, sysval; 121 int hflag, iflag, Jflag, lflag, rflag, uflag, Uflag; 122 long ngroups_max; 123 unsigned pi; | 108 struct passwd *pwd = NULL; 109 gid_t *groups; 110 size_t sysvallen; 111 int ch, cmdarg, i, jail_set_flags, jid, ngroups, sysval; 112 int hflag, iflag, Jflag, lflag, rflag, uflag, Uflag; 113 long ngroups_max; 114 unsigned pi; |
124 char *ep, *jailname, *securelevel, *username, *JidFile; 125 char errmsg[ERRMSG_SIZE], enforce_statfs[4]; | 115 char *jailname, *securelevel, *username, *JidFile; 116 char enforce_statfs[4]; |
126 static char *cleanenv; 127 const char *shell, *p = NULL; 128 FILE *fp; 129 130 hflag = iflag = Jflag = lflag = rflag = uflag = Uflag = 131 jail_set_flags = 0; 132 cmdarg = jid = -1; 133 jailname = securelevel = username = JidFile = cleanenv = NULL; --- 37 unchanged lines hidden (view full) --- 171 break; 172 case 'c': 173 jail_set_flags |= JAIL_CREATE; 174 break; 175 case 'm': 176 jail_set_flags |= JAIL_UPDATE; 177 break; 178 case 'r': | 117 static char *cleanenv; 118 const char *shell, *p = NULL; 119 FILE *fp; 120 121 hflag = iflag = Jflag = lflag = rflag = uflag = Uflag = 122 jail_set_flags = 0; 123 cmdarg = jid = -1; 124 jailname = securelevel = username = JidFile = cleanenv = NULL; --- 37 unchanged lines hidden (view full) --- 162 break; 163 case 'c': 164 jail_set_flags |= JAIL_CREATE; 165 break; 166 case 'm': 167 jail_set_flags |= JAIL_UPDATE; 168 break; 169 case 'r': |
179 jid = strtoul(optarg, &ep, 10); 180 if (!*optarg || *ep) { 181 *(const void **)&rparams[0].iov_base = "name"; 182 rparams[0].iov_len = sizeof("name"); 183 rparams[1].iov_base = optarg; 184 rparams[1].iov_len = strlen(optarg) + 1; 185 jid = jail_get(rparams, 2, 0); 186 if (jid < 0) 187 errx(1, "unknown jail: %s", optarg); 188 } | 170 jid = jail_getid(optarg); 171 if (jid < 0) 172 errx(1, "%s", jail_errmsg); |
189 rflag = 1; 190 break; 191 default: 192 usage(); 193 } 194 } 195 argc -= optind; 196 argv += optind; --- 78 unchanged lines hidden (view full) --- 275 } 276 } 277 if (ip4_addr != NULL) 278 set_param("ip4.addr", ip4_addr); 279#ifdef INET6 280 if (ip6_addr != NULL) 281 set_param("ip6.addr", ip6_addr); 282#endif | 173 rflag = 1; 174 break; 175 default: 176 usage(); 177 } 178 } 179 argc -= optind; 180 argv += optind; --- 78 unchanged lines hidden (view full) --- 259 } 260 } 261 if (ip4_addr != NULL) 262 set_param("ip4.addr", ip4_addr); 263#ifdef INET6 264 if (ip6_addr != NULL) 265 set_param("ip6.addr", ip6_addr); 266#endif |
283 errmsg[0] = 0; 284 set_param("errmsg", errmsg); | |
285 286 if (Jflag) { 287 fp = fopen(JidFile, "w"); 288 if (fp == NULL) 289 errx(1, "Could not create JidFile: %s", JidFile); 290 } | 267 268 if (Jflag) { 269 fp = fopen(JidFile, "w"); 270 if (fp == NULL) 271 errx(1, "Could not create JidFile: %s", JidFile); 272 } |
291 jid = jail_set(¶ms->name, 2 * nparams, | 273 jid = jailparam_set(params, nparams, |
292 jail_set_flags ? jail_set_flags : JAIL_CREATE | JAIL_ATTACH); | 274 jail_set_flags ? jail_set_flags : JAIL_CREATE | JAIL_ATTACH); |
293 if (jid < 0) { 294 if (errmsg[0] != '\0') 295 errx(1, "%s", errmsg); 296 err(1, "jail_set"); 297 } | 275 if (jid < 0) 276 errx(1, "%s", jail_errmsg); |
298 if (iflag) { 299 printf("%d\n", jid); 300 fflush(stdout); 301 } 302 if (Jflag) { 303 if (jail_set_flags) { 304 fprintf(fp, "jid=%d", jid); 305 for (i = 0; i < nparams; i++) | 277 if (iflag) { 278 printf("%d\n", jid); 279 fflush(stdout); 280 } 281 if (Jflag) { 282 if (jail_set_flags) { 283 fprintf(fp, "jid=%d", jid); 284 for (i = 0; i < nparams; i++) |
306 if (strcmp(params[i].name.iov_base, "jid") && 307 strcmp(params[i].name.iov_base, "errmsg")) { | 285 if (strcmp(params[i].jp_name, "jid")) { |
308 fprintf(fp, " %s", | 286 fprintf(fp, " %s", |
309 (char *)params[i].name.iov_base); | 287 (char *)params[i].jp_name); |
310 if (param_values[i]) { 311 putc('=', fp); 312 quoted_print(fp, 313 param_values[i]); 314 } 315 } 316 fprintf(fp, "\n"); 317 } else { 318 for (i = 0; i < nparams; i++) | 288 if (param_values[i]) { 289 putc('=', fp); 290 quoted_print(fp, 291 param_values[i]); 292 } 293 } 294 fprintf(fp, "\n"); 295 } else { 296 for (i = 0; i < nparams; i++) |
319 if (!strcmp(params[i].name.iov_base, "path")) | 297 if (!strcmp(params[i].jp_name, "path")) |
320 break; 321#ifdef INET6 322 fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n", 323 jid, i < nparams | 298 break; 299#ifdef INET6 300 fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n", 301 jid, i < nparams |
324 ? (char *)params[i].value.iov_base : argv[0], | 302 ? (char *)params[i].jp_value : argv[0], |
325 argv[1], ip4_addr ? ip4_addr : "", 326 ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0] 327 ? "," : "", ip6_addr ? ip6_addr : "", argv[3]); 328#else 329 fprintf(fp, "%d\t%s\t%s\t%s\t%s\n", 330 jid, i < nparams | 303 argv[1], ip4_addr ? ip4_addr : "", 304 ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0] 305 ? "," : "", ip6_addr ? ip6_addr : "", argv[3]); 306#else 307 fprintf(fp, "%d\t%s\t%s\t%s\t%s\n", 308 jid, i < nparams |
331 ? (char *)params[i].value.iov_base : argv[0], | 309 ? (char *)params[i].jp_value : argv[0], |
332 argv[1], ip4_addr ? ip4_addr : "", argv[3]); 333#endif 334 } 335 (void)fclose(fp); 336 } 337 if (cmdarg < 0) 338 exit(0); 339 if (username != NULL) { --- 152 unchanged lines hidden (view full) --- 492 } 493 if (qc) 494 putc(qc, fp); 495} 496 497static void 498set_param(const char *name, char *value) 499{ | 310 argv[1], ip4_addr ? ip4_addr : "", argv[3]); 311#endif 312 } 313 (void)fclose(fp); 314 } 315 if (cmdarg < 0) 316 exit(0); 317 if (username != NULL) { --- 152 unchanged lines hidden (view full) --- 470 } 471 if (qc) 472 putc(qc, fp); 473} 474 475static void 476set_param(const char *name, char *value) 477{ |
500 struct param *param; 501 char *ep, *p; 502 size_t buflen, mlen; 503 int i, nval, mib[CTL_MAXNAME]; 504 struct { 505 int i; 506 char s[MAXPATHLEN]; 507 } buf; | 478 struct jailparam *param; 479 int i; |
508 509 static int paramlistsize; 510 511 /* Separate the name from the value, if not done already. */ 512 if (name == NULL) { 513 name = value; 514 if ((value = strchr(value, '='))) 515 *value++ = '\0'; 516 } 517 518 /* Check for repeat parameters */ 519 for (i = 0; i < nparams; i++) | 480 481 static int paramlistsize; 482 483 /* Separate the name from the value, if not done already. */ 484 if (name == NULL) { 485 name = value; 486 if ((value = strchr(value, '='))) 487 *value++ = '\0'; 488 } 489 490 /* Check for repeat parameters */ 491 for (i = 0; i < nparams; i++) |
520 if (!strcmp(name, params[i].name.iov_base)) { | 492 if (!strcmp(name, params[i].jp_name)) { 493 jailparam_free(params + i, 1); |
521 memcpy(params + i, params + i + 1, | 494 memcpy(params + i, params + i + 1, |
522 (--nparams - i) * sizeof(struct param)); | 495 (--nparams - i) * sizeof(struct jailparam)); |
523 break; 524 } 525 526 /* Make sure there is room for the new param record. */ 527 if (!nparams) { 528 paramlistsize = 32; 529 params = malloc(paramlistsize * sizeof(*params)); 530 param_values = malloc(paramlistsize * sizeof(*param_values)); --- 6 unchanged lines hidden (view full) --- 537 paramlistsize * sizeof(*param_values)); 538 if (params == NULL) 539 err(1, "realloc"); 540 } 541 542 /* Look up the paramter. */ 543 param_values[nparams] = value; 544 param = params + nparams++; | 496 break; 497 } 498 499 /* Make sure there is room for the new param record. */ 500 if (!nparams) { 501 paramlistsize = 32; 502 params = malloc(paramlistsize * sizeof(*params)); 503 param_values = malloc(paramlistsize * sizeof(*param_values)); --- 6 unchanged lines hidden (view full) --- 510 paramlistsize * sizeof(*param_values)); 511 if (params == NULL) 512 err(1, "realloc"); 513 } 514 515 /* Look up the paramter. */ 516 param_values[nparams] = value; 517 param = params + nparams++; |
545 *(const void **)¶m->name.iov_base = name; 546 param->name.iov_len = strlen(name) + 1; 547 /* Trivial values - no value or errmsg. */ 548 if (value == NULL) { 549 param->value.iov_base = NULL; 550 param->value.iov_len = 0; 551 return; 552 } 553 if (!strcmp(name, "errmsg")) { 554 param->value.iov_base = value; 555 param->value.iov_len = ERRMSG_SIZE; 556 return; 557 } 558 mib[0] = 0; 559 mib[1] = 3; 560 snprintf(buf.s, sizeof(buf.s), SJPARAM ".%s", name); 561 mlen = sizeof(mib) - 2 * sizeof(int); 562 if (sysctl(mib, 2, mib + 2, &mlen, buf.s, strlen(buf.s)) < 0) 563 errx(1, "unknown parameter: %s", name); 564 mib[1] = 4; 565 buflen = sizeof(buf); 566 if (sysctl(mib, (mlen / sizeof(int)) + 2, &buf, &buflen, NULL, 0) < 0) 567 err(1, "sysctl(0.4.%s)", name); 568 /* 569 * See if this is an array type. 570 * Treat non-arrays as an array of one. 571 */ 572 p = strchr(buf.s, '\0'); 573 nval = 1; 574 if (p - 2 >= buf.s && !strcmp(p - 2, ",a")) { 575 if (value[0] == '\0' || 576 (value[0] == '-' && value[1] == '\0')) { 577 param->value.iov_base = value; 578 param->value.iov_len = 0; 579 return; 580 } 581 p[-2] = 0; 582 for (p = strchr(value, ','); p; p = strchr(p + 1, ',')) { 583 *p = '\0'; 584 nval++; 585 } 586 } 587 588 /* Set the values according to the parameter type. */ 589 switch (buf.i & CTLTYPE) { 590 case CTLTYPE_INT: 591 case CTLTYPE_UINT: 592 param->value.iov_len = nval * sizeof(int); 593 break; 594 case CTLTYPE_LONG: 595 case CTLTYPE_ULONG: 596 param->value.iov_len = nval * sizeof(long); 597 break; 598 case CTLTYPE_STRUCT: 599 if (!strcmp(buf.s, "S,in_addr")) 600 param->value.iov_len = nval * sizeof(struct in_addr); 601#ifdef INET6 602 else if (!strcmp(buf.s, "S,in6_addr")) 603 param->value.iov_len = nval * sizeof(struct in6_addr); 604#endif 605 else 606 errx(1, "%s: unknown parameter structure (%s)", 607 name, buf.s); 608 break; 609 case CTLTYPE_STRING: 610 if (!strcmp(name, "path")) { 611 param->value.iov_base = malloc(MAXPATHLEN); 612 if (param->value.iov_base == NULL) 613 err(1, "malloc"); 614 if (realpath(value, param->value.iov_base) == NULL) 615 err(1, "%s: realpath(%s)", name, value); 616 if (chdir(param->value.iov_base) != 0) 617 err(1, "chdir: %s", 618 (char *)param->value.iov_base); 619 } else 620 param->value.iov_base = value; 621 param->value.iov_len = strlen(param->value.iov_base) + 1; 622 return; 623 default: 624 errx(1, "%s: unknown parameter type %d (%s)", 625 name, buf.i, buf.s); 626 } 627 param->value.iov_base = malloc(param->value.iov_len); 628 for (i = 0; i < nval; i++) { 629 switch (buf.i & CTLTYPE) { 630 case CTLTYPE_INT: 631 ((int *)param->value.iov_base)[i] = 632 strtol(value, &ep, 10); 633 if (ep[0] != '\0') 634 errx(1, "%s: non-integer value \"%s\"", 635 name, value); 636 break; 637 case CTLTYPE_UINT: 638 ((unsigned *)param->value.iov_base)[i] = 639 strtoul(value, &ep, 10); 640 if (ep[0] != '\0') 641 errx(1, "%s: non-integer value \"%s\"", 642 name, value); 643 break; 644 case CTLTYPE_LONG: 645 ((long *)param->value.iov_base)[i] = 646 strtol(value, &ep, 10); 647 if (ep[0] != '\0') 648 errx(1, "%s: non-integer value \"%s\"", 649 name, value); 650 break; 651 case CTLTYPE_ULONG: 652 ((unsigned long *)param->value.iov_base)[i] = 653 strtoul(value, &ep, 10); 654 if (ep[0] != '\0') 655 errx(1, "%s: non-integer value \"%s\"", 656 name, value); 657 break; 658 case CTLTYPE_STRUCT: 659 if (!strcmp(buf.s, "S,in_addr")) { 660 if (inet_pton(AF_INET, value, 661 &((struct in_addr *) 662 param->value.iov_base)[i]) != 1) 663 errx(1, "%s: not an IPv4 address: %s", 664 name, value); 665 } 666#ifdef INET6 667 else if (!strcmp(buf.s, "S,in6_addr")) { 668 if (inet_pton(AF_INET6, value, 669 &((struct in6_addr *) 670 param->value.iov_base)[i]) != 1) 671 errx(1, "%s: not an IPv6 address: %s", 672 name, value); 673 } 674#endif 675 } 676 if (i > 0) 677 value[-1] = ','; 678 value = strchr(value, '\0') + 1; 679 } | 518 if (jailparam_init(param, name) < 0 || 519 jailparam_import(param, value) < 0) 520 errx(1, "%s", jail_errmsg); |
680} 681 682static void 683usage(void) 684{ 685 686 (void)fprintf(stderr, 687 "usage: jail [-d] [-h] [-i] [-J jid_file] " 688 "[-l -u username | -U username]\n" 689 " [-c | -m] param=value ... [command=command ...]\n" 690 " jail [-r jail]\n"); 691 exit(1); 692} | 521} 522 523static void 524usage(void) 525{ 526 527 (void)fprintf(stderr, 528 "usage: jail [-d] [-h] [-i] [-J jid_file] " 529 "[-l -u username | -U username]\n" 530 " [-c | -m] param=value ... [command=command ...]\n" 531 " jail [-r jail]\n"); 532 exit(1); 533} |