1 /* 2 * Copyright (C) 2015 John Crispin <blogic@openwrt.org> 3 * Copyright (C) 2020 Daniel Golle <daniel@makrotopia.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #define _GNU_SOURCE 16 #include <sys/mount.h> 17 #include <sys/prctl.h> 18 #include <sys/wait.h> 19 #include <sys/types.h> 20 #include <sys/time.h> 21 #include <sys/resource.h> 22 #include <sys/stat.h> 23 #include <sys/sysmacros.h> 24 #include <sys/ioctl.h> 25 #include <sys/mman.h> 26 #include <sys/personality.h> 27 #include <sys/syscall.h> 28 #include <sys/socket.h> 29 #include <sys/un.h> 30 #include <poll.h> 31 #include <linux/rtnetlink.h> 32 #include <net/if.h> 33 #include <arpa/inet.h> 34 35 /* musl only defined 15 limit types, make sure all 16 are supported */ 36 #ifndef RLIMIT_RTTIME 37 #define RLIMIT_RTTIME 15 38 #undef RLIMIT_NLIMITS 39 #define RLIMIT_NLIMITS 16 40 #undef RLIM_NLIMITS 41 #define RLIM_NLIMITS 16 42 #endif 43 44 #include <assert.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <errno.h> 48 #include <pwd.h> 49 #include <grp.h> 50 #include <string.h> 51 #include <fcntl.h> 52 #include <sched.h> 53 #include <limits.h> 54 #include <linux/close_range.h> 55 #include <linux/filter.h> 56 #include <linux/landlock.h> 57 #include <linux/limits.h> 58 #include <linux/nsfs.h> 59 #include <linux/sched.h> 60 #include <linux/securebits.h> 61 #include <signal.h> 62 #include <inttypes.h> 63 #include <limits.h> 64 #include <sys/ptrace.h> 65 66 #include "capabilities.h" 67 #include "elf.h" 68 #include "fs.h" 69 #include "jail.h" 70 #include "landlock.h" 71 #include "log.h" 72 #include "seccomp-oci.h" 73 #include "seccomp-inject.h" 74 #include "seccomp-trace.h" 75 #include "cgroups.h" 76 #include "netifd.h" 77 #include "../stdio-fds.h" 78 79 #include <libubox/blobmsg.h> 80 #include <libubox/blobmsg_json.h> 81 #include <libubox/list.h> 82 #include <libubox/vlist.h> 83 #include <libubox/uloop.h> 84 #include <libubox/utils.h> 85 #include <libubus.h> 86 87 #ifndef CLONE_NEWCGROUP 88 #define CLONE_NEWCGROUP 0x02000000 89 #endif 90 91 #ifndef CLONE_NEWTIME 92 #define CLONE_NEWTIME 0x00000080 93 #endif 94 95 #ifndef PR_SET_MDWE 96 #define PR_SET_MDWE 65 97 #endif 98 #ifndef PR_MDWE_REFUSE_EXEC_GAIN 99 #define PR_MDWE_REFUSE_EXEC_GAIN (1UL << 0) 100 #endif 101 #ifndef PR_MDWE_NO_INHERIT 102 #define PR_MDWE_NO_INHERIT (1UL << 1) 103 #endif 104 105 #define OPT_ARGS "a:A:b:cC:d:De:EfFG:h:iI:j:J:k:lm:M:n:NoO:pP:r:R:sS:uU:V:w:x:t:T:yY:Z" 106 107 #define JAIL_MAX_CREDENTIALS 16 108 static const char *cred_targets[JAIL_MAX_CREDENTIALS]; 109 static int n_cred_targets; 110 111 struct hook_execvpe { 112 char *file; 113 char **argv; 114 char **envp; 115 int timeout; 116 }; 117 118 struct sysctl_val { 119 char *entry; 120 char *value; 121 }; 122 123 struct mknod_args { 124 char *path; 125 mode_t mode; 126 dev_t dev; 127 uid_t uid; 128 gid_t gid; 129 }; 130 131 static struct { 132 char *name; 133 char *hostname; 134 char *domainname; 135 char **jail_argv; 136 char *cwd; 137 char *seccomp; 138 struct sock_fprog *ociseccomp; 139 struct sock_fprog *ociseccomp_linker; 140 struct sock_fprog *ociseccomp_init; 141 struct sock_fprog *ociseccomp_delta_entry; 142 struct sock_fprog *ociseccomp_delta_main; 143 enum seccomp_mode seccomp_mode; 144 char *seccomp_log; 145 char *capabilities; 146 struct jail_capset capset; 147 char *user; 148 char *group; 149 char *extroot; 150 char *overlaydir; 151 char *tmpoverlaysize; 152 char **envp; 153 char *envfile; 154 char *uidmap; 155 char *gidmap; 156 struct blob_attr *uidmappings; 157 struct blob_attr *gidmappings; 158 unsigned int idmap_offset; 159 char *pidfile; 160 int notify_fd; 161 uint64_t incarnation; 162 struct sysctl_val **sysctl; 163 int no_new_privs; 164 int namespace; 165 struct { 166 int pid; 167 int net; 168 int ns; 169 int ipc; 170 int uts; 171 int user; 172 int cgroup; 173 int time; 174 } setns; 175 int procfs; 176 int ronly; 177 int sysfs; 178 int console; 179 char *console_socket; 180 bool systemd_cgroup; 181 unsigned short console_height; 182 unsigned short console_width; 183 int pw_uid; 184 int pw_gid; 185 int gr_gid; 186 int root_map_uid; 187 gid_t *additional_gids; 188 size_t num_additional_gids; 189 mode_t umask; 190 bool set_umask; 191 int require_jail; 192 struct { 193 struct hook_execvpe **prestart; 194 struct hook_execvpe **createRuntime; 195 struct hook_execvpe **createContainer; 196 struct hook_execvpe **startContainer; 197 struct hook_execvpe **poststart; 198 struct hook_execvpe **poststop; 199 } hooks; 200 struct rlimit *rlimits[RLIM_NLIMITS]; 201 int oom_score_adj; 202 bool set_oom_score_adj; 203 struct mknod_args **devices; 204 char *ocibundle; 205 char **oci_deferred_masked; 206 char **oci_deferred_readonly; 207 bool immediately; 208 struct blob_attr *annotations; 209 struct blob_attr *netdevices; 210 int term_timeout; 211 struct { 212 bool set; 213 uint32_t policy; 214 uint64_t flags; 215 int32_t nice; 216 uint32_t priority; 217 uint64_t runtime; 218 uint64_t deadline; 219 uint64_t period; 220 } scheduler; 221 struct { 222 bool set; 223 int class; 224 int priority; 225 } ioprio; 226 unsigned long mdwe_flags; 227 unsigned long rootfs_propagation; 228 struct landlock_config landlock; 229 bool private_ubus; 230 bool private_netifd; 231 bool jail_network_started; 232 } opts; 233 234 static struct blob_buf ocibuf; 235 static struct blob_buf notify_buf; 236 237 static char **volume_sources; 238 static int num_volume_sources; 239 240 #define EXEC_ACK_EXEC 'X' 241 static int exec_ack[2] = { -1, -1 }; 242 static char exec_ack_buf[1 + sizeof(int)]; 243 static size_t exec_ack_len; 244 static void exec_ack_cb(struct uloop_fd *fd, unsigned int events); 245 static struct uloop_fd exec_ack_uloop = { 246 .cb = exec_ack_cb, 247 }; 248 249 extern int pivot_root(const char *new_root, const char *put_old); 250 251 int debug = 0; 252 253 static long jail_clone3(struct clone_args *args) 254 { 255 return syscall(SYS_clone3, args, sizeof(*args)); 256 } 257 258 static int jail_process_pidfd = -1; 259 260 static struct ubus_context *parent_ctx; 261 static volatile sig_atomic_t jail_stop_requested; 262 static bool netifd_restart_pending; 263 static bool container_registered; 264 static bool stop_announced; 265 static volatile sig_atomic_t delete_requested; 266 static bool delete_awaited; 267 static bool delete_deferred; 268 static struct ubus_request_data delete_request; 269 static char **restart_argv; 270 271 static const char *jail_reason; 272 static char jail_reason_owned[64]; 273 static int jail_reason_errno; 274 275 /* 276 * The deepest field the runtime spec defines is four levels below the 277 * root, linux.resources.blockIO.weightDevice[0].leafWeight. 278 */ 279 #define OCI_PATH_MAX_DEPTH 16 280 #define OCI_PATH_INDEX_LEN sizeof("[4294967295]") 281 282 struct oci_path { 283 const char *seg[OCI_PATH_MAX_DEPTH]; 284 char index[OCI_PATH_MAX_DEPTH][OCI_PATH_INDEX_LEN]; 285 int depth; 286 }; 287 288 static const struct blob_attr *jail_oci_root; 289 290 const struct blob_attr *jail_oci_root_get(void) 291 { 292 return jail_oci_root; 293 } 294 295 void jail_oci_root_restore(const struct blob_attr *root) 296 { 297 jail_oci_root = root; 298 } 299 300 static bool oci_attr_contains(const struct blob_attr *outer, 301 const struct blob_attr *inner) 302 { 303 const char *p = (const char *)inner; 304 const char *base; 305 size_t len; 306 307 base = blobmsg_data(outer); 308 len = blobmsg_data_len(outer); 309 310 return p >= base && p < base + len; 311 } 312 313 static bool oci_path_push(struct oci_path *path, const char *name, 314 unsigned int index) 315 { 316 if (path->depth >= OCI_PATH_MAX_DEPTH) 317 return false; 318 319 if (name) { 320 path->seg[path->depth++] = name; 321 return true; 322 } 323 324 snprintf(path->index[path->depth], OCI_PATH_INDEX_LEN, "[%u]", index); 325 path->seg[path->depth] = path->index[path->depth]; 326 ++path->depth; 327 328 return true; 329 } 330 331 /* Siblings hold disjoint ranges, so the first match is the only one. */ 332 static bool oci_path_walk(const struct blob_attr *node, 333 const struct blob_attr *leaf, struct oci_path *path) 334 { 335 struct blob_attr *cur; 336 unsigned int i = 0; 337 size_t rem; 338 bool array; 339 340 if (node == leaf) 341 return true; 342 343 switch (blobmsg_type(node)) { 344 case BLOBMSG_TYPE_TABLE: 345 array = false; 346 break; 347 case BLOBMSG_TYPE_ARRAY: 348 array = true; 349 break; 350 default: 351 return false; 352 } 353 354 blobmsg_for_each_attr(cur, node, rem) { 355 if (cur != leaf && !oci_attr_contains(cur, leaf)) { 356 ++i; 357 continue; 358 } 359 360 if (!oci_path_push(path, array ? NULL : blobmsg_name(cur), i)) 361 return false; 362 363 return oci_path_walk(cur, leaf, path); 364 } 365 366 return false; 367 } 368 369 static bool oci_path_walk_root(const struct blob_attr *root, 370 const struct blob_attr *leaf, 371 struct oci_path *path) 372 { 373 struct blob_attr *cur; 374 size_t rem; 375 376 blob_for_each_attr(cur, root, rem) { 377 if (cur != leaf && !oci_attr_contains(cur, leaf)) 378 continue; 379 380 if (!oci_path_push(path, blobmsg_name(cur), 0)) 381 return false; 382 383 return oci_path_walk(cur, leaf, path); 384 } 385 386 return false; 387 } 388 389 static bool oci_path_resolve(const struct blob_attr *leaf, char *buf, 390 size_t len) 391 { 392 struct oci_path path = { .depth = 0 }; 393 size_t pos = 0; 394 int i; 395 396 if (!jail_oci_root || !leaf) 397 return false; 398 399 if (blobmsg_type(jail_oci_root) == BLOBMSG_TYPE_TABLE) { 400 if (!oci_path_walk(jail_oci_root, leaf, &path)) 401 return false; 402 } else if (!oci_path_walk_root(jail_oci_root, leaf, &path)) { 403 return false; 404 } 405 406 for (i = 0; i < path.depth && pos < len; i++) 407 pos += snprintf(buf + pos, len - pos, "%s%s", 408 (i && path.seg[i][0] != '[') ? "." : "", 409 path.seg[i]); 410 411 return true; 412 } 413 414 static const char *oci_field_name(const struct blob_attr *attr, char *buf, 415 size_t len) 416 { 417 if (oci_path_resolve(attr, buf, len)) 418 return buf; 419 420 return blobmsg_name(attr); 421 } 422 423 static void jail_reason_restore(const char *reason, int err) 424 { 425 jail_reason = reason; 426 jail_reason_errno = err; 427 } 428 429 static void jail_reason_set(const char *reason, int err) 430 { 431 if (jail_reason) 432 return; 433 434 jail_reason_restore(reason, err); 435 } 436 437 /* The bundle is parsed and freed long before the reason is reported. */ 438 static void jail_reason_own(const char *reason, int err) 439 { 440 if (jail_reason) 441 return; 442 443 snprintf(jail_reason_owned, sizeof(jail_reason_owned), "%s", reason); 444 jail_reason_set(jail_reason_owned, err); 445 } 446 447 int jail_unsupported(const struct blob_attr *attr) 448 { 449 char path[sizeof(jail_reason_owned)]; 450 const char *field; 451 452 field = oci_field_name(attr, path, sizeof(path)); 453 ERROR("%s is not supported\n", field); 454 jail_reason_own(field, ENOTSUP); 455 456 return ENOTSUP; 457 } 458 459 void jail_cgroup_refused(const char *attr) 460 { 461 jail_reason_own(attr, ENOTSUP); 462 } 463 464 int console_fd; 465 static int console_slave_fd = -1; 466 static char console_slave_name[64]; 467 468 469 /* 470 * Joining a namespace by path needs privilege in the user namespace owning it, 471 * which our own user namespace would take away, so in that case it is created 472 * after the joins instead of by clone(). crun makes the same distinction. 473 * 474 * A userns joined with -j (opts.setns.user) drops privilege the same way and 475 * never owns the pidns clone() created, so procfs must be mounted before 476 * entering it. Both cases are entered in enter_userns(), after build_jail_fs(). 477 */ 478 static inline bool userns_deferred(void) 479 { 480 if (opts.setns.user != -1) 481 return true; 482 483 if (!(opts.namespace & CLONE_NEWUSER)) 484 return false; 485 486 return (opts.setns.pid != -1) || 487 (opts.setns.net != -1) || 488 (opts.setns.ns != -1) || 489 (opts.setns.ipc != -1) || 490 (opts.setns.uts != -1) || 491 (opts.setns.cgroup != -1) || 492 #ifdef CLONE_NEWTIME 493 (opts.setns.time != -1) || 494 #endif 495 false; 496 } 497 498 /* 499 * The jail's root maps to a host uid we know: our own user namespace, or a 500 * joined one whose map we managed to read. Without the map the ownership 501 * decisions below would act on a guess, so they stay as they were. 502 */ 503 static bool joined_userns_mapped; 504 505 static inline bool jail_has_userns(void) 506 { 507 return (opts.namespace & CLONE_NEWUSER) || joined_userns_mapped; 508 } 509 510 static inline bool jail_in_userns(void) 511 { 512 return (opts.namespace & CLONE_NEWUSER) || opts.setns.user != -1; 513 } 514 515 static inline bool has_namespaces(void) 516 { 517 return ((opts.setns.pid != -1) || 518 (opts.setns.net != -1) || 519 (opts.setns.ns != -1) || 520 (opts.setns.ipc != -1) || 521 (opts.setns.uts != -1) || 522 (opts.setns.user != -1) || 523 (opts.setns.cgroup != -1) || 524 (opts.setns.time != -1) || 525 opts.namespace); 526 } 527 528 static void free_oci_envp(char **p) { 529 char **tmp; 530 531 if (p) { 532 tmp = p; 533 while (*tmp) 534 free(*(tmp++)); 535 536 free(p); 537 } 538 } 539 540 static void free_hooklist(struct hook_execvpe **hooklist) 541 { 542 struct hook_execvpe **cur; 543 544 if (!hooklist) 545 return; 546 547 cur = hooklist; 548 while (*cur) { 549 free_oci_envp((*cur)->argv); 550 free_oci_envp((*cur)->envp); 551 free((*cur)->file); 552 free(*(cur++)); 553 } 554 free(hooklist); 555 } 556 557 static void free_sysctl(void) { 558 struct sysctl_val **cur; 559 560 if (!opts.sysctl) 561 return; 562 563 cur = opts.sysctl; 564 565 while (*cur) { 566 free((*cur)->entry); 567 free((*cur)->value); 568 free(*(cur++)); 569 } 570 free(opts.sysctl); 571 } 572 573 static void free_devices(void) { 574 struct mknod_args **cur; 575 576 if (!opts.devices) 577 return; 578 579 cur = opts.devices; 580 581 while (*cur) { 582 free((*cur)->path); 583 free(*(cur++)); 584 } 585 free(opts.devices); 586 } 587 588 static void free_rlimits(void) { 589 int type; 590 591 for (type = 0; type < RLIM_NLIMITS; ++type) 592 free(opts.rlimits[type]); 593 } 594 595 static void free_opts(bool parent) { 596 597 free_library_search(); 598 mount_free(); 599 cgroups_free(); 600 601 /* we need to keep argv, envp and seccomp filter in child */ 602 if (parent) { /* parent-only */ 603 if (opts.ociseccomp) { 604 free(opts.ociseccomp->filter); 605 free(opts.ociseccomp); 606 } 607 608 if (opts.ociseccomp_linker) { 609 free(opts.ociseccomp_linker->filter); 610 free(opts.ociseccomp_linker); 611 } 612 613 if (opts.ociseccomp_init) { 614 free(opts.ociseccomp_init->filter); 615 free(opts.ociseccomp_init); 616 } 617 618 if (opts.ociseccomp_delta_entry) { 619 free(opts.ociseccomp_delta_entry->filter); 620 free(opts.ociseccomp_delta_entry); 621 } 622 623 if (opts.ociseccomp_delta_main) { 624 free(opts.ociseccomp_delta_main->filter); 625 free(opts.ociseccomp_delta_main); 626 } 627 628 free_oci_envp(opts.jail_argv); 629 free_oci_envp(opts.envp); 630 } 631 632 free_rlimits(); 633 free_sysctl(); 634 free_devices(); 635 free(opts.hostname); 636 free(opts.domainname); 637 free(opts.cwd); 638 free(opts.uidmap); 639 free(opts.gidmap); 640 free(opts.uidmappings); 641 free(opts.gidmappings); 642 free(opts.annotations); 643 landlock_config_free(&opts.landlock); 644 free(opts.netdevices); 645 free(opts.extroot); 646 free(opts.overlaydir); 647 free_hooklist(opts.hooks.prestart); 648 free_hooklist(opts.hooks.createRuntime); 649 free_hooklist(opts.hooks.createContainer); 650 free_hooklist(opts.hooks.startContainer); 651 free_hooklist(opts.hooks.poststart); 652 free_hooklist(opts.hooks.poststop); 653 654 if (opts.oci_deferred_masked) { 655 char **p; 656 for (p = opts.oci_deferred_masked; *p; p++) 657 free(*p); 658 free(opts.oci_deferred_masked); 659 } 660 if (opts.oci_deferred_readonly) { 661 char **p; 662 for (p = opts.oci_deferred_readonly; *p; p++) 663 free(*p); 664 free(opts.oci_deferred_readonly); 665 } 666 } 667 668 static int mount_overlay(char *jail_root, char *overlaydir) { 669 char *upperdir, *workdir, *optsstr, *upperetc, *upperresolvconf; 670 const char mountoptsformat[] = "lowerdir=%s,upperdir=%s,workdir=%s"; 671 const char mountoptsformat_userns[] = "lowerdir=%s,upperdir=%s,workdir=%s,userxattr"; 672 int ret = -1, fd; 673 674 if (asprintf(&upperdir, "%s%s", overlaydir, "/upper") < 0) 675 goto out; 676 677 if (asprintf(&workdir, "%s%s", overlaydir, "/work") < 0) 678 goto upper_printf; 679 680 if (asprintf(&optsstr, 681 (opts.namespace & CLONE_NEWUSER) ? mountoptsformat_userns : mountoptsformat, 682 jail_root, upperdir, workdir) < 0) 683 goto work_printf; 684 685 if (mkdir_p(upperdir, 0755) || mkdir_p(workdir, 0755)) 686 goto opts_printf; 687 688 /* 689 * make sure /etc/resolv.conf exists in overlay and is owned by jail userns root 690 * this is to work-around a bug in overlayfs described in the overlayfs-userns 691 * patch: 692 * 3. modification of a file 'hithere' which is in l but not yet 693 * in u, and which is not owned by T, is not allowed, even if 694 * writes to u are allowed. This may be a bug in overlayfs, 695 * but it is safe behavior. 696 */ 697 if (asprintf(&upperetc, "%s/etc", upperdir) < 0) 698 goto opts_printf; 699 700 if (mkdir_p(upperetc, 0755)) 701 goto upper_etc_printf; 702 703 if (asprintf(&upperresolvconf, "%s/resolv.conf", upperetc) < 0) 704 goto upper_etc_printf; 705 706 fd = creat(upperresolvconf, 0644); 707 if (fd < 0) { 708 if (errno != EEXIST) 709 ERROR("creat(%s) failed: %m\n", upperresolvconf); 710 } else { 711 close(fd); 712 } 713 DEBUG("mount -t overlay %s %s (%s)\n", jail_root, jail_root, optsstr); 714 715 if (mount(jail_root, jail_root, "overlay", MS_NOATIME, optsstr)) 716 goto upper_resolvconf_printf; 717 718 ret = 0; 719 720 upper_resolvconf_printf: 721 free(upperresolvconf); 722 upper_etc_printf: 723 free(upperetc); 724 opts_printf: 725 free(optsstr); 726 work_printf: 727 free(workdir); 728 upper_printf: 729 free(upperdir); 730 out: 731 return ret; 732 } 733 734 static void pass_console(int console_fd) 735 { 736 struct ubus_context *child_ctx = ubus_connect(NULL); 737 static struct blob_buf req; 738 uint32_t id; 739 740 if (!child_ctx) 741 return; 742 743 blob_buf_init(&req, 0); 744 blobmsg_add_string(&req, "name", opts.name); 745 746 if (ubus_lookup_id(child_ctx, "container", &id) || 747 ubus_invoke_fd(child_ctx, id, "console_set", req.head, NULL, NULL, 3000, console_fd)) 748 INFO("ubus request failed\n"); 749 else 750 close(console_fd); 751 752 blob_buf_free(&req); 753 ubus_free(child_ctx); 754 } 755 756 static int parse_inherited_console_fd(const char *spec) 757 { 758 char *endptr; 759 long fd; 760 761 if (!spec || !*spec) 762 return -1; 763 764 errno = 0; 765 fd = strtol(spec, &endptr, 10); 766 if (errno || *endptr || endptr == spec || fd < 0 || fd > INT_MAX) 767 return -1; 768 769 if (fcntl((int)fd, F_GETFD) == -1) 770 return -1; 771 772 return (int)fd; 773 } 774 775 static int open_console_sock(const char *spec, bool *owned, bool path_only) 776 { 777 int sock; 778 struct sockaddr_un addr = { .sun_family = AF_UNIX }; 779 780 *owned = false; 781 if (!path_only) { 782 sock = parse_inherited_console_fd(spec); 783 if (sock >= 0) { 784 int dom = 0, typ = 0; 785 socklen_t slen = sizeof(dom); 786 787 if (getsockopt(sock, SOL_SOCKET, SO_DOMAIN, &dom, &slen) < 0 || 788 dom != AF_UNIX) { 789 ERROR("console-socket: inherited fd %d is not AF_UNIX\n", sock); 790 return -1; 791 } 792 slen = sizeof(typ); 793 if (getsockopt(sock, SOL_SOCKET, SO_TYPE, &typ, &slen) < 0 || 794 typ != SOCK_STREAM) { 795 ERROR("console-socket: inherited fd %d is not SOCK_STREAM\n", sock); 796 return -1; 797 } 798 return sock; 799 } 800 } 801 802 if (strlen(spec) >= sizeof(addr.sun_path)) { 803 ERROR("console-socket path too long: %s\n", spec); 804 return -1; 805 } 806 memcpy(addr.sun_path, spec, strlen(spec) + 1); 807 808 sock = socket(AF_UNIX, SOCK_STREAM, 0); 809 if (sock < 0) { 810 ERROR("console-socket: socket(): %m\n"); 811 return -1; 812 } 813 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 814 ERROR("console-socket: connect(%s): %m\n", spec); 815 close(sock); 816 return -1; 817 } 818 *owned = true; 819 return sock; 820 } 821 822 static int sendmsg_console_fd(int sock, int console_fd, const char *slave_name) 823 { 824 struct msghdr msg = { 0 }; 825 struct cmsghdr *cmsg; 826 struct iovec iov; 827 char cbuf[CMSG_SPACE(sizeof(int))] = { 0 }; 828 829 iov.iov_base = (void *)slave_name; 830 iov.iov_len = strlen(slave_name); 831 msg.msg_iov = &iov; 832 msg.msg_iovlen = 1; 833 msg.msg_control = cbuf; 834 msg.msg_controllen = sizeof(cbuf); 835 836 cmsg = CMSG_FIRSTHDR(&msg); 837 cmsg->cmsg_level = SOL_SOCKET; 838 cmsg->cmsg_type = SCM_RIGHTS; 839 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 840 memcpy(CMSG_DATA(cmsg), &console_fd, sizeof(int)); 841 842 if (sendmsg(sock, &msg, 0) < 0) { 843 ERROR("console-socket: sendmsg: %m\n"); 844 return -1; 845 } 846 return 0; 847 } 848 849 static int send_console_fd(const char *spec, int console_fd, const char *slave_name) 850 { 851 bool owned; 852 int sock, ret; 853 854 sock = open_console_sock(spec, &owned, false); 855 if (sock < 0) 856 return -1; 857 ret = sendmsg_console_fd(sock, console_fd, slave_name); 858 if (owned) 859 close(sock); 860 return ret; 861 } 862 863 static int create_dev_console(const char *jail_root) 864 { 865 char dev_console_path[PATH_MAX]; 866 char fdpath[64]; 867 int dev_console_dummy; 868 869 if (console_slave_fd < 0) 870 return 1; 871 872 snprintf(dev_console_path, sizeof(dev_console_path), "%s/dev/console", jail_root); 873 dev_console_dummy = creat(dev_console_path, 0620); 874 if (dev_console_dummy >= 0) 875 close(dev_console_dummy); 876 877 snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", console_slave_fd); 878 if (mount(fdpath, dev_console_path, "bind", MS_BIND, NULL)) 879 return 1; 880 881 setsid(); 882 if (ioctl(console_slave_fd, TIOCSCTTY, 0) < 0) 883 WARNING("TIOCSCTTY on guest console failed: %m\n"); 884 885 dup2(console_slave_fd, 0); 886 dup2(console_slave_fd, 1); 887 dup2(console_slave_fd, 2); 888 if (console_slave_fd > 2) 889 close(console_slave_fd); 890 891 return 0; 892 } 893 894 static int hook_running = 0; 895 static int hook_return_code = 0; 896 static bool hook_chain_failed = false; 897 static struct hook_execvpe **current_hook = NULL; 898 typedef void (*hook_return_handler)(void); 899 static hook_return_handler hook_return_cb = NULL; 900 901 static void hook_process_timeout_cb(struct uloop_timeout *t); 902 static struct uloop_timeout hook_process_timeout = { 903 .cb = hook_process_timeout_cb, 904 }; 905 906 static void run_hooklist(void); 907 static void oci_state_fill(struct blob_buf *b); 908 static void hook_process_handler(struct uloop_process *c, int ret) 909 { 910 uloop_timeout_cancel(&hook_process_timeout); 911 912 if (WIFEXITED(ret)) { 913 hook_return_code = WEXITSTATUS(ret); 914 if (hook_return_code) 915 ERROR("hook (%d) exited with exit: %d\n", c->pid, hook_return_code); 916 else 917 DEBUG("hook (%d) exited with exit: %d\n", c->pid, hook_return_code); 918 919 } else { 920 hook_return_code = WTERMSIG(ret); 921 ERROR("hook (%d) exited with signal: %d\n", c->pid, hook_return_code); 922 } 923 if (hook_return_code) 924 hook_chain_failed = true; 925 hook_running = 0; 926 ++current_hook; 927 run_hooklist(); 928 } 929 930 static struct uloop_process hook_process = { 931 .cb = hook_process_handler, 932 }; 933 934 static void hook_process_timeout_cb(struct uloop_timeout *t) 935 { 936 DEBUG("hook process failed to stop, sending SIGKILL\n"); 937 kill(hook_process.pid, SIGKILL); 938 } 939 940 static int hook_state_fd(void) 941 { 942 static struct blob_buf sb; 943 char *state; 944 size_t len; 945 int fd; 946 947 blob_buf_init(&sb, 0); 948 oci_state_fill(&sb); 949 state = blobmsg_format_json(sb.head, true); 950 if (!state) 951 return -1; 952 953 fd = memfd_create("oci-state", MFD_CLOEXEC); 954 if (fd < 0) { 955 free(state); 956 return -1; 957 } 958 959 len = strlen(state); 960 if (write(fd, state, len) != (ssize_t)len || 961 lseek(fd, 0, SEEK_SET) == (off_t)-1) { 962 WARNING("cannot pass the container state to the hook: %m\n"); 963 free(state); 964 close(fd); 965 return -1; 966 } 967 968 free(state); 969 970 return fd; 971 } 972 973 static void run_hooklist(void) 974 { 975 struct hook_execvpe *hook = *current_hook; 976 int state_fd; 977 struct stat s; 978 979 if (!hook) 980 return hook_return_cb(); 981 982 DEBUG("executing hook %s\n", hook->file); 983 984 if (stat(hook->file, &s)) { 985 hook_process_handler(&hook_process, ENOENT); 986 return; 987 } 988 989 if (!((unsigned long)s.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { 990 hook_process_handler(&hook_process, EPERM); 991 return; 992 } 993 994 state_fd = hook_state_fd(); 995 996 hook_running = 1; 997 hook_process.pid = fork(); 998 if (hook_process.pid == 0) { 999 /* child */ 1000 if (state_fd > -1) { 1001 dup2(state_fd, STDIN_FILENO); 1002 close(state_fd); 1003 } 1004 execve(hook->file, hook->argv, hook->envp); 1005 ERROR("execve error %m\n"); 1006 _exit(errno); 1007 } else if (hook_process.pid < 0) { 1008 /* fork error */ 1009 ERROR("hook fork error\n"); 1010 hook_running = 0; 1011 if (state_fd > -1) 1012 close(state_fd); 1013 hook_process_handler(&hook_process, errno); 1014 return; 1015 } 1016 1017 /* parent */ 1018 if (state_fd > -1) 1019 close(state_fd); 1020 1021 uloop_process_add(&hook_process); 1022 1023 if (hook->timeout > 0) 1024 uloop_timeout_set(&hook_process_timeout, 1000 * hook->timeout); 1025 1026 uloop_run(); 1027 if (hook_running) { 1028 DEBUG("uloop interrupted, killing jail process\n"); 1029 kill(hook_process.pid, SIGTERM); 1030 uloop_timeout_set(&hook_process_timeout, 1000); 1031 uloop_run(); 1032 } 1033 } 1034 1035 static void run_hooks(struct hook_execvpe **hooklist, hook_return_handler return_cb) 1036 { 1037 hook_chain_failed = false; 1038 1039 if (!hooklist) { 1040 return_cb(); 1041 return; 1042 } 1043 1044 current_hook = hooklist; 1045 hook_return_cb = return_cb; 1046 1047 run_hooklist(); 1048 } 1049 1050 static int apply_sysctl(const char *jail_root) 1051 { 1052 struct sysctl_val **cur; 1053 char *procdir, *fname; 1054 int f; 1055 1056 if (!opts.sysctl) 1057 return 0; 1058 1059 if (asprintf(&procdir, "%s/proc", jail_root) < 0) 1060 return ENOMEM; 1061 1062 if (mkdir(procdir, 0700)) 1063 return errno; 1064 1065 if (mount("proc", procdir, "proc", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0)) 1066 return EPERM; 1067 1068 cur = opts.sysctl; 1069 1070 while (*cur) { 1071 if (asprintf(&fname, "%s/sys/%s", procdir, (*cur)->entry) < 0) 1072 return ENOMEM; 1073 1074 DEBUG("sysctl: writing '%s' to %s\n", (*cur)->value, fname); 1075 1076 f = open(fname, O_WRONLY); 1077 if (f < 0) { 1078 ERROR("sysctl: can't open %s\n", fname); 1079 free(fname); 1080 return errno; 1081 } 1082 if (write(f, (*cur)->value, strlen((*cur)->value)) < 0) { 1083 ERROR("sysctl: write to %s\n", fname); 1084 free(fname); 1085 close(f); 1086 return errno; 1087 } 1088 1089 free(fname); 1090 close(f); 1091 ++cur; 1092 } 1093 umount(procdir); 1094 rmdir(procdir); 1095 free(procdir); 1096 1097 return 0; 1098 } 1099 1100 /* glibc defines makedev calling a function. make sure it's a pure macro */ 1101 #if defined(__GLIBC__) 1102 #undef makedev 1103 /* from musl's sys/sysmacros.h */ 1104 #define makedev(x,y) ( \ 1105 (((x)&0xfffff000ULL) << 32) | \ 1106 (((x)&0x00000fffULL) << 8) | \ 1107 (((y)&0xffffff00ULL) << 12) | \ 1108 (((y)&0x000000ffULL)) ) 1109 #endif 1110 1111 static char jail_dev[] = "/tmp/ujail-dev-XXXXXX"; 1112 static bool jail_dev_staged; 1113 1114 static struct mknod_args default_devices[] = { 1115 { .path = "/dev/null", .mode = (S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH), .dev = makedev(1, 3) }, 1116 { .path = "/dev/zero", .mode = (S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH), .dev = makedev(1, 5) }, 1117 { .path = "/dev/full", .mode = (S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH), .dev = makedev(1, 7) }, 1118 { .path = "/dev/random", .mode = (S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH), .dev = makedev(1, 8) }, 1119 { .path = "/dev/urandom", .mode = (S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH), .dev = makedev(1, 9) }, 1120 { .path = "/dev/tty", .mode = (S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH), .dev = makedev(5, 0), .gid = 5 }, 1121 { 0 }, 1122 }; 1123 1124 static int prepare_jail_dev(void) 1125 { 1126 struct mknod_args **cur, *curdef; 1127 uid_t base = jail_has_userns() ? opts.root_map_uid : 0; 1128 mode_t oldmask = umask(0); 1129 char path[PATH_MAX], *tmp; 1130 int consfd; 1131 1132 if (mkdtemp(jail_dev) == NULL) { 1133 ERROR("mkdtemp(%s) failed: %m\n", jail_dev); 1134 return errno; 1135 } 1136 jail_dev_staged = true; 1137 1138 if (mount("tmpfs", jail_dev, "tmpfs", MS_NOSUID | MS_NOATIME, 1139 "mode=0755,size=1M")) { 1140 ERROR("tmpfs mount for /dev failed: %m\n"); 1141 return errno; 1142 } 1143 1144 if (mount(NULL, jail_dev, NULL, MS_PRIVATE, NULL)) { 1145 ERROR("making /dev tmpfs private failed: %m\n"); 1146 return errno; 1147 } 1148 1149 for (cur = opts.devices; cur && *cur; ++cur) { 1150 /* don't allow devices outside of /dev */ 1151 if (strncmp((*cur)->path, "/dev", 4)) 1152 return EPERM; 1153 1154 snprintf(path, sizeof(path), "%s%s", jail_dev, (*cur)->path + 4); 1155 1156 /* make sure parent folder exists */ 1157 tmp = strrchr(path, '/'); 1158 if (!tmp) 1159 return EINVAL; 1160 *tmp = '\0'; 1161 if (strcmp(path, jail_dev) && mkdir_p(path, 0755)) 1162 return errno; 1163 *tmp = '/'; 1164 1165 if (mknod(path, (*cur)->mode, (*cur)->dev)) 1166 return errno; 1167 if (chown(path, base + (*cur)->uid, base + (*cur)->gid)) 1168 return errno; 1169 } 1170 1171 for (curdef = default_devices; curdef->path; ++curdef) { 1172 snprintf(path, sizeof(path), "%s%s", jail_dev, curdef->path + 4); 1173 if (mknod(path, curdef->mode, curdef->dev)) 1174 return errno; 1175 if (chown(path, base + curdef->uid, base + curdef->gid)) 1176 return errno; 1177 } 1178 1179 /* Dev symbolic links as defined in OCI spec */ 1180 snprintf(path, sizeof(path), "%s/ptmx", jail_dev); 1181 if (symlink("pts/ptmx", path)) 1182 WARNING("symlink() failed to create link to pts/ptmx"); 1183 1184 snprintf(path, sizeof(path), "%s/fd", jail_dev); 1185 if (symlink("/proc/self/fd", path)) 1186 WARNING("symlink() failed to create link to /proc/self/fd"); 1187 1188 snprintf(path, sizeof(path), "%s/stdin", jail_dev); 1189 if (symlink("/proc/self/fd/0", path)) 1190 WARNING("symlink() failed to create link to /proc/self/fd/0"); 1191 1192 snprintf(path, sizeof(path), "%s/stdout", jail_dev); 1193 if (symlink("/proc/self/fd/1", path)) 1194 WARNING("symlink() failed to create link to /proc/self/fd/1"); 1195 1196 snprintf(path, sizeof(path), "%s/stderr", jail_dev); 1197 if (symlink("/proc/self/fd/2", path)) 1198 WARNING("symlink() failed to create link to /proc/self/fd/2"); 1199 1200 snprintf(path, sizeof(path), "%s/pts", jail_dev); 1201 mkdir(path, 0755); 1202 snprintf(path, sizeof(path), "%s/shm", jail_dev); 1203 mkdir(path, 0755); 1204 snprintf(path, sizeof(path), "%s/mqueue", jail_dev); 1205 mkdir(path, 0755); 1206 1207 if ((opts.namespace & CLONE_NEWNET) && opts.private_netifd) { 1208 snprintf(path, sizeof(path), "%s/resolv.conf.d", jail_dev); 1209 mkdir(path, 0755); 1210 snprintf(path, sizeof(path), "%s/resolv.conf", jail_dev); 1211 if (symlink("/dev/resolv.conf.d/resolv.conf.auto", path)) 1212 WARNING("symlink() failed to create /dev/resolv.conf: %m\n"); 1213 } 1214 1215 if (opts.console) { 1216 snprintf(path, sizeof(path), "%s/console", jail_dev); 1217 consfd = creat(path, 0620); 1218 if (consfd < 0) 1219 WARNING("creat() failed to stage /dev/console: %m\n"); 1220 else 1221 close(consfd); 1222 } 1223 1224 mount_stage_dev(jail_dev); 1225 1226 if (mount(NULL, jail_dev, NULL, MS_REMOUNT | MS_RDONLY | MS_NOSUID | MS_NOATIME, NULL)) { 1227 ERROR("read-only remount of /dev staging failed: %m\n"); 1228 return errno; 1229 } 1230 1231 umask(oldmask); 1232 return 0; 1233 } 1234 1235 static char jail_root[] = "/tmp/ujail-XXXXXX"; 1236 /* Handshake for the deferred CLONE_NEWUSER creation in enter_userns(). */ 1237 int userns_pipe[4]; 1238 1239 /* single-byte read()/write(), retrying on EINTR */ 1240 static ssize_t xread_byte(int fd, char *buf) 1241 { 1242 ssize_t n; 1243 1244 do { 1245 n = read(fd, buf, 1); 1246 } while (n < 0 && errno == EINTR); 1247 1248 return n; 1249 } 1250 1251 static ssize_t xwrite_byte(int fd, char byte) 1252 { 1253 ssize_t n; 1254 1255 do { 1256 n = write(fd, &byte, 1); 1257 } while (n < 0 && errno == EINTR); 1258 1259 return n; 1260 } 1261 1262 static char tmpovdir[] = "/tmp/ujail-overlay-XXXXXX"; 1263 static mode_t old_umask; 1264 static int jail_tmp_dirfd = -1; 1265 #define JAIL_IDMAP_MAX_FDS 64 1266 1267 static int idmap_fds[JAIL_IDMAP_MAX_FDS]; 1268 static int num_idmap_fds; 1269 static int extroot_idmap_fd = -1; 1270 static int overlay_idmap_fd = -1; 1271 1272 static bool jail_idmap_active(void) 1273 { 1274 return (opts.namespace & CLONE_NEWUSER) && opts.uidmap; 1275 } 1276 1277 static int sock_send_fds(int sock, char tag, const int *fds, int nfds) 1278 { 1279 struct msghdr msg = { 0 }; 1280 struct iovec iov; 1281 char cmsgbuf[CMSG_SPACE(JAIL_IDMAP_MAX_FDS * sizeof(int))]; 1282 struct cmsghdr *cmsg; 1283 char data[1]; 1284 ssize_t n; 1285 1286 data[0] = tag; 1287 iov.iov_base = data; 1288 iov.iov_len = 1; 1289 msg.msg_iov = &iov; 1290 msg.msg_iovlen = 1; 1291 1292 if (nfds > 0) { 1293 msg.msg_control = cmsgbuf; 1294 msg.msg_controllen = CMSG_SPACE(nfds * sizeof(int)); 1295 cmsg = CMSG_FIRSTHDR(&msg); 1296 cmsg->cmsg_level = SOL_SOCKET; 1297 cmsg->cmsg_type = SCM_RIGHTS; 1298 cmsg->cmsg_len = CMSG_LEN(nfds * sizeof(int)); 1299 memcpy(CMSG_DATA(cmsg), fds, nfds * sizeof(int)); 1300 } 1301 1302 do { 1303 n = sendmsg(sock, &msg, MSG_NOSIGNAL); 1304 } while (n < 0 && errno == EINTR); 1305 1306 return (n == 1) ? 0 : -1; 1307 } 1308 1309 static int sock_recv_fds(int sock, char *tag, int *fds, int maxfds) 1310 { 1311 struct msghdr msg = { 0 }; 1312 struct iovec iov; 1313 char cmsgbuf[CMSG_SPACE(JAIL_IDMAP_MAX_FDS * sizeof(int))]; 1314 struct cmsghdr *cmsg; 1315 char data[1]; 1316 ssize_t n; 1317 int nfds = 0; 1318 1319 iov.iov_base = data; 1320 iov.iov_len = 1; 1321 msg.msg_iov = &iov; 1322 msg.msg_iovlen = 1; 1323 msg.msg_control = cmsgbuf; 1324 msg.msg_controllen = sizeof(cmsgbuf); 1325 1326 do { 1327 n = recvmsg(sock, &msg, MSG_CMSG_CLOEXEC); 1328 } while (n < 0 && errno == EINTR); 1329 1330 if (n < 1) 1331 return -1; 1332 1333 *tag = data[0]; 1334 1335 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 1336 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) 1337 continue; 1338 nfds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); 1339 if (nfds > maxfds) 1340 nfds = maxfds; 1341 memcpy(fds, CMSG_DATA(cmsg), nfds * sizeof(int)); 1342 break; 1343 } 1344 1345 return nfds; 1346 } 1347 1348 static void enter_jail_fs(void); 1349 1350 static size_t path_depth(const char *path) 1351 { 1352 size_t depth = 0; 1353 1354 for (; *path; path++) 1355 if (*path == '/') 1356 depth++; 1357 1358 return depth; 1359 } 1360 1361 static void mountinfo_unescape(char *s) 1362 { 1363 char *r = s, *w = s; 1364 1365 while (*r) { 1366 if (r[0] == '\\' && r[1] >= '' && r[1] <= '7' && 1367 r[2] >= '' && r[2] <= '7' && r[3] >= '' && r[3] <= '7') { 1368 *w++ = (char)(((r[1] - '') << 6) | ((r[2] - '') << 3) | (r[3] - '')); 1369 r += 4; 1370 } else { 1371 *w++ = *r++; 1372 } 1373 } 1374 *w = '\0'; 1375 } 1376 1377 static int mountinfo_detach_children(const char *prefix) 1378 { 1379 size_t prefixlen = strlen(prefix); 1380 int pass; 1381 1382 for (pass = 0; pass < 16; pass++) { 1383 FILE *f; 1384 char *line = NULL; 1385 size_t linecap = 0; 1386 char *paths[128]; 1387 size_t n = 0, dropped = 0, i, j; 1388 bool progress = false; 1389 1390 f = fopen("/proc/self/mountinfo", "re"); 1391 if (!f) { 1392 ERROR("mountinfo_detach_children(%s): fopen(/proc/self/mountinfo) " 1393 "failed: %m\n", prefix); 1394 return -1; 1395 } 1396 1397 while (getline(&line, &linecap, f) >= 0) { 1398 char *mp, *save = NULL; 1399 1400 strtok_r(line, " ", &save); 1401 strtok_r(NULL, " ", &save); 1402 strtok_r(NULL, " ", &save); 1403 strtok_r(NULL, " ", &save); 1404 mp = strtok_r(NULL, " ", &save); 1405 if (!mp) 1406 continue; 1407 mountinfo_unescape(mp); 1408 1409 if (strncmp(mp, prefix, prefixlen) || mp[prefixlen] != '/') 1410 continue; 1411 1412 if (n < ARRAY_SIZE(paths)) { 1413 char *dup = strdup(mp); 1414 1415 if (dup) 1416 paths[n++] = dup; 1417 else 1418 dropped++; 1419 } else { 1420 dropped++; 1421 } 1422 } 1423 free(line); 1424 fclose(f); 1425 1426 if (dropped) 1427 WARNING("mountinfo_detach_children(%s): %zu nested mount(s) " 1428 "exceeded the %zu-entry per-pass limit or could not " 1429 "be recorded (out of memory); retrying over further " 1430 "passes\n", prefix, dropped, ARRAY_SIZE(paths)); 1431 1432 if (n == 0 && dropped == 0) 1433 return 0; 1434 1435 for (i = 0; i < n; i++) { 1436 size_t deepest = i; 1437 1438 for (j = i + 1; j < n; j++) 1439 if (path_depth(paths[j]) > path_depth(paths[deepest])) 1440 deepest = j; 1441 if (deepest != i) { 1442 char *tmp = paths[i]; 1443 paths[i] = paths[deepest]; 1444 paths[deepest] = tmp; 1445 } 1446 } 1447 1448 for (i = 0; i < n; i++) { 1449 if (!umount2(paths[i], MNT_DETACH)) 1450 progress = true; 1451 free(paths[i]); 1452 } 1453 1454 if (!progress && !dropped) { 1455 ERROR("mountinfo_detach_children(%s): %zu nested mount(s) could " 1456 "not be detached; refusing to continue\n", prefix, n); 1457 return -1; 1458 } 1459 } 1460 1461 ERROR("mountinfo_detach_children(%s): nested mounts remained attached " 1462 "after %d passes; refusing to continue\n", prefix, pass); 1463 return -1; 1464 } 1465 1466 static unsigned long mountns_propagation(void) 1467 { 1468 if (opts.rootfs_propagation & MS_SLAVE) 1469 return MS_REC | MS_SLAVE; 1470 1471 return MS_REC | MS_PRIVATE; 1472 } 1473 1474 /* enter_jail_fs() detaches the old root, which propagates to every peer */ 1475 static int isolate_mountns(void) 1476 { 1477 return mount("none", "/", "none", mountns_propagation(), NULL); 1478 } 1479 1480 static int detach_inherited_mounts(void) 1481 { 1482 if ((opts.procfs || opts.ocibundle) && mountinfo_detach_children("/proc")) 1483 return -1; 1484 if ((opts.sysfs || opts.ocibundle) && mountinfo_detach_children("/sys")) 1485 return -1; 1486 1487 return 0; 1488 } 1489 1490 static void jail_tmpdir_remove(const char *dir) 1491 { 1492 const char *base; 1493 1494 if (jail_tmp_dirfd < 0) 1495 return; 1496 1497 base = strrchr(dir, '/'); 1498 unlinkat(jail_tmp_dirfd, base ? base + 1 : dir, AT_REMOVEDIR); 1499 } 1500 1501 static int build_jail_fs(void) 1502 { 1503 char *overlaydir = NULL; 1504 int ret; 1505 1506 old_umask = umask(0); 1507 1508 if (opts.console && console_slave_name[0]) { 1509 console_slave_fd = open(console_slave_name, O_RDWR | O_NOCTTY); 1510 if (console_slave_fd < 0) 1511 WARNING("open guest console slave %s: %m\n", console_slave_name); 1512 } 1513 1514 jail_tmp_dirfd = open("/tmp", O_PATH | O_DIRECTORY | O_CLOEXEC); 1515 1516 if (mkdtemp(jail_root) == NULL) { 1517 ERROR("mkdtemp(%s) failed: %m\n", jail_root); 1518 return -1; 1519 } 1520 1521 if (apply_sysctl(jail_root)) { 1522 ERROR("failed to apply sysctl values\n"); 1523 return -1; 1524 } 1525 1526 if (opts.extroot) { 1527 if (extroot_idmap_fd >= 0) { 1528 if (sys_move_mount(extroot_idmap_fd, "", AT_FDCWD, jail_root, MOVE_MOUNT_F_EMPTY_PATH)) { 1529 ERROR("move_mount(idmapped extroot) failed: %m\n"); 1530 return -1; 1531 } 1532 close(extroot_idmap_fd); 1533 extroot_idmap_fd = -1; 1534 } else if (mount(opts.extroot, jail_root, "bind", MS_BIND, NULL)) { 1535 ERROR("extroot mount failed %m\n"); 1536 return -1; 1537 } 1538 } else { 1539 if (mount("tmpfs", jail_root, "tmpfs", MS_NOATIME, "mode=0755")) { 1540 ERROR("tmpfs mount failed %m\n"); 1541 return -1; 1542 } 1543 } 1544 1545 if (opts.tmpoverlaysize) { 1546 char mountoptsstr[] = "mode=0755,size=XXXXXXXX"; 1547 1548 snprintf(mountoptsstr, sizeof(mountoptsstr), 1549 "mode=0755,size=%s", opts.tmpoverlaysize); 1550 if (mkdtemp(tmpovdir) == NULL) { 1551 ERROR("mkdtemp(%s) failed: %m\n", jail_root); 1552 return -1; 1553 } 1554 if (mount("tmpfs", tmpovdir, "tmpfs", MS_NOATIME | MS_NOEXEC | MS_NOSUID | MS_NODEV, 1555 mountoptsstr)) { 1556 ERROR("failed to mount tmpfs for overlay (size=%s)\n", opts.tmpoverlaysize); 1557 return -1; 1558 } 1559 overlaydir = tmpovdir; 1560 } 1561 1562 if (opts.overlaydir) 1563 overlaydir = opts.overlaydir; 1564 1565 if (overlaydir) { 1566 if (overlay_idmap_fd >= 0) { 1567 if (sys_move_mount(overlay_idmap_fd, "", AT_FDCWD, overlaydir, MOVE_MOUNT_F_EMPTY_PATH)) { 1568 ERROR("move_mount(idmapped overlay upper) failed: %m\n"); 1569 return -1; 1570 } 1571 close(overlay_idmap_fd); 1572 overlay_idmap_fd = -1; 1573 } else if (mount(NULL, overlaydir, NULL, 1574 MS_BIND | MS_REMOUNT | MS_NOEXEC | MS_NOSUID | MS_NODEV, NULL)) { 1575 WARNING("failed to harden overlay upper %s: %m\n", overlaydir); 1576 } 1577 1578 ret = mount_overlay(jail_root, overlaydir); 1579 if (ret) 1580 return ret; 1581 } 1582 1583 if (chdir(jail_root)) { 1584 ERROR("chdir(%s) (jail_root) failed: %m\n", jail_root); 1585 return -1; 1586 } 1587 1588 jail_fs_set_userns(jail_has_userns()); 1589 1590 if (mount_all(jail_root, jail_dev)) { 1591 ERROR("mount_all() failed\n"); 1592 return -1; 1593 } 1594 1595 if (opts.console) 1596 create_dev_console(jail_root); 1597 1598 if ((opts.namespace & CLONE_NEWNET) && opts.private_netifd) { 1599 char jailetc[PATH_MAX], devresolv[PATH_MAX], etcresolv[PATH_MAX]; 1600 struct stat rcst; 1601 int treefd; 1602 1603 snprintf(devresolv, PATH_MAX, "%s/dev/resolv.conf", jail_root); 1604 snprintf(etcresolv, PATH_MAX, "%s/etc/resolv.conf", jail_root); 1605 if (stat(etcresolv, &rcst) && (overlaydir || !opts.ronly)) { 1606 snprintf(jailetc, PATH_MAX, "%s/etc", jail_root); 1607 mkdir_p(jailetc, 0755); 1608 close(creat(etcresolv, 0644)); 1609 } 1610 if (!stat(etcresolv, &rcst)) { 1611 treefd = sys_open_tree(AT_FDCWD, devresolv, 1612 OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | AT_SYMLINK_NOFOLLOW); 1613 if (treefd < 0) { 1614 WARNING("open_tree(/dev/resolv.conf) failed: %m\n"); 1615 } else { 1616 if (sys_move_mount(treefd, "", AT_FDCWD, etcresolv, MOVE_MOUNT_F_EMPTY_PATH)) 1617 WARNING("move_mount onto /etc/resolv.conf failed: %m\n"); 1618 close(treefd); 1619 } 1620 } 1621 } 1622 1623 run_hooks(opts.hooks.createContainer, enter_jail_fs); 1624 1625 return 0; 1626 } 1627 1628 static bool exit_from_child; 1629 static void emit_instance_event(const char *event); 1630 static bool pidfile_sibling(const char *pidfile, const char *name, char *path, size_t len) 1631 { 1632 char *slash; 1633 1634 if (!pidfile) 1635 return false; 1636 1637 if (snprintf(path, len, "%s", pidfile) >= (int)len) 1638 return false; 1639 1640 slash = strrchr(path, '/'); 1641 if (!slash) 1642 return false; 1643 1644 if ((size_t)(slash - path) + strlen(name) + 1 >= len) 1645 return false; 1646 1647 strcpy(slash, name); 1648 1649 return true; 1650 } 1651 1652 static void jail_write_exit_status(const char *pidfile, int status) 1653 { 1654 char path[PATH_MAX], tmp[PATH_MAX]; 1655 char buf[12]; 1656 int fd, len; 1657 1658 if (!pidfile_sibling(pidfile, "/exit_status", path, sizeof(path))) 1659 return; 1660 1661 if (snprintf(tmp, sizeof(tmp), "%s.tmp", path) >= (int)sizeof(tmp)) 1662 return; 1663 1664 len = snprintf(buf, sizeof(buf), "%d", status); 1665 if (len < 0 || len >= (int)sizeof(buf)) 1666 return; 1667 1668 fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); 1669 if (fd < 0) 1670 return; 1671 1672 if (write(fd, buf, len) != len) { 1673 close(fd); 1674 unlink(tmp); 1675 return; 1676 } 1677 1678 if (close(fd)) { 1679 unlink(tmp); 1680 return; 1681 } 1682 1683 if (rename(tmp, path)) 1684 unlink(tmp); 1685 } 1686 1687 static void jail_clear_exit_status(const char *pidfile) 1688 { 1689 char path[PATH_MAX]; 1690 1691 if (pidfile_sibling(pidfile, "/exit_status", path, sizeof(path))) 1692 unlink(path); 1693 } 1694 1695 static void notify_signal(int fd) 1696 { 1697 struct pollfd pfd = { .fd = fd, .events = POLLIN }; 1698 1699 if (fd < 0) 1700 return; 1701 1702 if (poll(&pfd, 1, 0) > 0) 1703 return; 1704 1705 syscall(SYS_pidfd_send_signal, fd, SIGCHLD, NULL, 0); 1706 } 1707 1708 static bool jail_ptrace_seccomp(void); 1709 static bool jail_inproc_seccomp(void); 1710 1711 static int restart_argv_save(int argc, char **argv) 1712 { 1713 int i; 1714 1715 restart_argv = calloc(argc + 1, sizeof(*restart_argv)); 1716 if (!restart_argv) 1717 return ENOMEM; 1718 1719 for (i = 0; i < argc; i++) { 1720 restart_argv[i] = strdup(argv[i]); 1721 if (!restart_argv[i]) 1722 return ENOMEM; 1723 } 1724 1725 return 0; 1726 } 1727 1728 static bool jail_restarting(void) 1729 { 1730 return !exit_from_child && netifd_restart_pending && !jail_stop_requested; 1731 } 1732 1733 static void jail_restart_exec(void) 1734 { 1735 char **argv; 1736 int argc, n, i; 1737 1738 for (argc = 0; restart_argv[argc]; argc++); 1739 1740 argv = calloc(argc + 2, sizeof(*argv)); 1741 if (!argv) 1742 return; 1743 1744 n = 0; 1745 argv[n++] = restart_argv[0]; 1746 argv[n++] = "-i"; 1747 for (i = 1; i < argc; i++) { 1748 if (!strcmp(restart_argv[i], "-a") && i + 1 < argc) { 1749 i++; 1750 continue; 1751 } 1752 argv[n++] = restart_argv[i]; 1753 } 1754 1755 INFO("restarting the container\n"); 1756 syscall(SYS_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC); 1757 execv("/proc/self/exe", argv); 1758 ERROR("failed to re-execute for the restart: %m\n"); 1759 free(argv); 1760 } 1761 1762 static void free_and_exit(int ret) 1763 { 1764 if (!exit_from_child && !stop_announced && !jail_restarting()) 1765 notify_signal(opts.notify_fd); 1766 1767 if (!exit_from_child && opts.jail_network_started) { 1768 jail_network_teardown(); 1769 opts.jail_network_started = false; 1770 } 1771 1772 if (!exit_from_child && opts.ocibundle && container_registered) 1773 cgroups_destroy(); 1774 1775 if (!exit_from_child && opts.ocibundle) 1776 cgroups_free(); 1777 1778 if (!exit_from_child && jail_dev_staged) { 1779 umount2(jail_dev, MNT_DETACH); 1780 rmdir(jail_dev); 1781 jail_dev_staged = false; 1782 } 1783 1784 if (!exit_from_child && !stop_announced && opts.ocibundle && parent_ctx && 1785 opts.name) { 1786 if (jail_restarting()) 1787 jail_reason_set("jail.restart", 0); 1788 1789 emit_instance_event(container_registered ? "instance.stopped" : 1790 "instance.create_failed"); 1791 } 1792 1793 if (!exit_from_child && parent_ctx && delete_deferred) 1794 ubus_complete_deferred_request(parent_ctx, &delete_request, 0); 1795 1796 if (!exit_from_child && parent_ctx) 1797 ubus_free(parent_ctx); 1798 1799 free_opts(!exit_from_child); 1800 1801 if (jail_restarting()) 1802 jail_restart_exec(); 1803 1804 exit(ret); 1805 } 1806 1807 static int setns_open(unsigned long nstype); 1808 static void post_jail_fs(void); 1809 static void enter_userns(void); 1810 static int userns_wait_idmaps(void); 1811 #ifdef CLONE_NEWTIME 1812 static int timens_create(void); 1813 #endif 1814 static int remask_after_unshare(void); 1815 static void remount_proc_sys_after_unshare(void); 1816 static void enter_jail_fs(void) 1817 { 1818 if (chdir(jail_root)) { 1819 ERROR("chdir(%s) (jail_root) failed: %m\n", jail_root); 1820 free_and_exit(-1); 1821 } 1822 if (pivot_root(".", ".") == -1) { 1823 ERROR("pivot_root(%s) failed: %m\n", jail_root); 1824 free_and_exit(-1); 1825 } 1826 if (umount2(".", MNT_DETACH)) { 1827 ERROR("umount2() of the old root failed: %m\n"); 1828 free_and_exit(-1); 1829 } 1830 1831 jail_tmpdir_remove(jail_root); 1832 if (opts.tmpoverlaysize) 1833 jail_tmpdir_remove(tmpovdir); 1834 if (jail_tmp_dirfd >= 0) { 1835 close(jail_tmp_dirfd); 1836 jail_tmp_dirfd = -1; 1837 } 1838 1839 if (chdir("/")) { 1840 ERROR("chdir(/) (after pivot_root) failed: %m\n"); 1841 free_and_exit(-1); 1842 } 1843 1844 if (opts.ronly) 1845 mount(NULL, "/", "bind", MS_REMOUNT | MS_BIND | MS_RDONLY, 0); 1846 1847 umask(old_umask); 1848 enter_userns(); 1849 } 1850 1851 static int userns_wait_idmaps(void) 1852 { 1853 char buf[1]; 1854 1855 buf[0] = 'i'; 1856 if (xwrite_byte(userns_pipe[1], buf[0]) < 1) { 1857 ERROR("can't write to parent\n"); 1858 return -1; 1859 } 1860 close(userns_pipe[1]); 1861 1862 if (xread_byte(userns_pipe[2], buf) < 1) { 1863 ERROR("can't read from parent\n"); 1864 return -1; 1865 } 1866 close(userns_pipe[2]); 1867 if (buf[0] != 'O') { 1868 ERROR("parent had an error, child exiting\n"); 1869 return -1; 1870 } 1871 1872 return 0; 1873 } 1874 1875 /* become root in the userns just entered */ 1876 static int userns_become_root(void) 1877 { 1878 if (setregid(0, 0) < 0 || setreuid(0, 0) < 0) { 1879 ERROR("cannot become root in the user namespace: %m\n"); 1880 return -1; 1881 } 1882 1883 if (setgroups(0, NULL) < 0) { 1884 /* setgroups=deny is permanent once gid_map is written; only a 1885 * joined userns can have it */ 1886 if (errno != EPERM || opts.setns.user == -1) { 1887 ERROR("setgroups: %m\n"); 1888 return -1; 1889 } 1890 WARNING("setgroups(0, NULL) denied by the joined userns; " 1891 "continuing without dropping supplementary groups\n"); 1892 } 1893 1894 return 0; 1895 } 1896 1897 static void enter_userns(void) 1898 { 1899 int ret; 1900 1901 if (!userns_deferred()) { 1902 post_jail_fs(); 1903 return; 1904 } 1905 1906 if (opts.setns.user != -1) { 1907 /* maps exist already, no handshake */ 1908 ret = setns_open(CLONE_NEWUSER); 1909 if (ret) { 1910 ERROR("failed to join user namespace: %s\n", strerror(ret)); 1911 free_and_exit(-1); 1912 } 1913 } else { 1914 if (unshare(CLONE_NEWUSER)) { 1915 ERROR("unshare(CLONE_NEWUSER) failed: %m\n"); 1916 free_and_exit(-1); 1917 } 1918 1919 if (userns_wait_idmaps()) 1920 free_and_exit(-1); 1921 } 1922 1923 if (userns_become_root()) 1924 free_and_exit(-1); 1925 1926 #ifdef CLONE_NEWTIME 1927 if ((opts.namespace & CLONE_NEWTIME) && opts.setns.time == -1 && 1928 timens_create()) 1929 free_and_exit(-1); 1930 #endif 1931 1932 if ((opts.namespace & CLONE_NEWNS) && unshare(CLONE_NEWNS)) { 1933 ERROR("unshare(CLONE_NEWNS) failed: %m\n"); 1934 free_and_exit(-1); 1935 } 1936 if (opts.namespace & CLONE_NEWNS) { 1937 if (remask_after_unshare()) 1938 free_and_exit(-1); 1939 1940 remount_proc_sys_after_unshare(); 1941 } 1942 1943 post_jail_fs(); 1944 } 1945 1946 static int write_uid_gid_map(pid_t child_pid, bool gidmap, char *mapstr) 1947 { 1948 int map_file; 1949 char map_path[64]; 1950 1951 if (snprintf(map_path, sizeof(map_path), "/proc/%d/%s", 1952 child_pid, gidmap?"gid_map":"uid_map") < 0) 1953 return -1; 1954 1955 if ((map_file = open(map_path, O_WRONLY | O_CLOEXEC)) < 0) 1956 return -1; 1957 1958 if (dprintf(map_file, "%s", mapstr) < 0) { 1959 close(map_file); 1960 return -1; 1961 } 1962 1963 close(map_file); 1964 return 0; 1965 } 1966 1967 static int write_single_uid_gid_map(pid_t child_pid, bool gidmap, int id) 1968 { 1969 int map_file; 1970 char map_path[64]; 1971 const char *map_format = "%d %d %d\n"; 1972 if (snprintf(map_path, sizeof(map_path), "/proc/%d/%s", 1973 child_pid, gidmap?"gid_map":"uid_map") < 0) 1974 return -1; 1975 1976 if ((map_file = open(map_path, O_WRONLY | O_CLOEXEC)) < 0) 1977 return -1; 1978 1979 if (dprintf(map_file, map_format, 0, id, 1) < 0) { 1980 close(map_file); 1981 return -1; 1982 } 1983 1984 close(map_file); 1985 return 0; 1986 } 1987 1988 static int write_setgroups(pid_t child_pid, bool allow) 1989 { 1990 int setgroups_file; 1991 char setgroups_path[64]; 1992 1993 if (snprintf(setgroups_path, sizeof(setgroups_path), "/proc/%d/setgroups", 1994 child_pid) < 0) { 1995 return -1; 1996 } 1997 1998 if ((setgroups_file = open(setgroups_path, O_WRONLY | O_CLOEXEC)) < 0) { 1999 return -1; 2000 } 2001 2002 if (dprintf(setgroups_file, "%s", allow?"allow":"deny") == -1) { 2003 close(setgroups_file); 2004 return -1; 2005 } 2006 2007 close(setgroups_file); 2008 return 0; 2009 } 2010 2011 static void get_jail_user(int *user, int *user_gid, int *gr_gid) 2012 { 2013 struct passwd pwd, *p = NULL; 2014 struct group grp, *g = NULL; 2015 char *buf = NULL; 2016 size_t bufsize; 2017 long sc; 2018 int ret = 0, attempt; 2019 2020 if (opts.user) { 2021 sc = sysconf(_SC_GETPW_R_SIZE_MAX); 2022 bufsize = (sc > 0) ? (size_t)sc : 16384; 2023 2024 for (attempt = 0; attempt < 8; attempt++) { 2025 buf = malloc(bufsize); 2026 if (!buf) { 2027 ERROR("out of memory resolving user %s\n", opts.user); 2028 free_and_exit(EXIT_FAILURE); 2029 } 2030 2031 ret = getpwnam_r(opts.user, &pwd, buf, bufsize, &p); 2032 if (ret != ERANGE) 2033 break; 2034 2035 free(buf); 2036 buf = NULL; 2037 bufsize *= 2; 2038 } 2039 2040 if (ret || !p) { 2041 free(buf); 2042 if (!ret) 2043 ERROR("failed to get uid/gid for user %s: " 2044 "no such user\n", opts.user); 2045 else 2046 ERROR("failed to get uid/gid for user %s: %d (%s)\n", 2047 opts.user, ret, strerror(ret)); 2048 free_and_exit(EXIT_FAILURE); 2049 } 2050 2051 *user = p->pw_uid; 2052 *user_gid = p->pw_gid; 2053 free(buf); 2054 } else { 2055 *user = -1; 2056 *user_gid = -1; 2057 } 2058 2059 if (opts.group) { 2060 sc = sysconf(_SC_GETGR_R_SIZE_MAX); 2061 bufsize = (sc > 0) ? (size_t)sc : 16384; 2062 2063 for (attempt = 0; attempt < 8; attempt++) { 2064 buf = malloc(bufsize); 2065 if (!buf) { 2066 ERROR("out of memory resolving group %s\n", opts.group); 2067 free_and_exit(EXIT_FAILURE); 2068 } 2069 2070 ret = getgrnam_r(opts.group, &grp, buf, bufsize, &g); 2071 if (ret != ERANGE) 2072 break; 2073 2074 free(buf); 2075 buf = NULL; 2076 bufsize *= 2; 2077 } 2078 2079 if (ret || !g) { 2080 free(buf); 2081 if (!ret) 2082 ERROR("failed to get gid for group %s: " 2083 "no such group\n", opts.group); 2084 else 2085 ERROR("failed to get gid for group %s: %d (%s)\n", 2086 opts.group, ret, strerror(ret)); 2087 free_and_exit(EXIT_FAILURE); 2088 } 2089 2090 *gr_gid = g->gr_gid; 2091 free(buf); 2092 } else { 2093 *gr_gid = -1; 2094 } 2095 }; 2096 2097 static void set_jail_user(int pw_uid, int user_gid, int gr_gid) 2098 { 2099 if (opts.user && (user_gid != -1) && initgroups(opts.user, user_gid)) { 2100 ERROR("failed to initgroups() for user %s: %m\n", opts.user); 2101 free_and_exit(EXIT_FAILURE); 2102 } 2103 2104 if ((gr_gid != -1) && setregid(gr_gid, gr_gid)) { 2105 ERROR("failed to set group id %d: %m\n", gr_gid); 2106 free_and_exit(EXIT_FAILURE); 2107 } 2108 2109 if ((pw_uid != -1) && setreuid(pw_uid, pw_uid)) { 2110 ERROR("failed to set user id %d: %m\n", pw_uid); 2111 free_and_exit(EXIT_FAILURE); 2112 } 2113 } 2114 2115 static const char *proc_mask_critical[] = { 2116 "/proc/kcore", 2117 "/proc/sysrq-trigger", 2118 NULL, 2119 }; 2120 2121 static const char *proc_mask_optional[] = { 2122 "/proc/latency_stats", 2123 "/proc/timer_list", 2124 "/proc/timer_stats", 2125 "/proc/sched_debug", 2126 "/proc/scsi", 2127 NULL, 2128 }; 2129 2130 static const char *sys_mask_critical[] = { 2131 "/sys/firmware", 2132 NULL, 2133 }; 2134 2135 static int mask_default_paths(const char **paths, bool critical) 2136 { 2137 const char **p; 2138 2139 for (p = paths; *p; p++) { 2140 if (add_mount((void *)(-1), *p, NULL, 0, 0, NULL, critical ? -1 : 0)) { 2141 if (critical) { 2142 ERROR("failed to mask sensitive path %s\n", *p); 2143 return -1; 2144 } 2145 WARNING("could not mask optional path %s; it may not " 2146 "exist on this kernel/config\n", *p); 2147 } 2148 } 2149 2150 return 0; 2151 } 2152 2153 /* deferred like mask_path_now(): locking a readonlyPath in phase 1 2154 * would stay locked past the jail's own unshare(CLONE_NEWNS). */ 2155 static int remount_readonly_now(const char *path) 2156 { 2157 struct stat s; 2158 2159 if (stat(path, &s)) 2160 return 0; /* doesn't exist, nothing to restrict */ 2161 2162 if (bind_remount_readonly(path, MS_REC)) 2163 return -1; 2164 2165 DEBUG("read-only path %s\n", path); 2166 return 0; 2167 } 2168 2169 /* re-apply masks inside the container's own mntns: the first pass is 2170 * locked once copied in after unshare(CLONE_NEWNS); best-effort */ 2171 static int mask_paths_now(const char **paths, bool critical) 2172 { 2173 const char **p; 2174 2175 for (p = paths; *p; p++) { 2176 if (!mask_path_now(*p)) 2177 continue; 2178 2179 if (critical) { 2180 ERROR("failed to mask sensitive path %s: %m\n", *p); 2181 return -1; 2182 } 2183 2184 WARNING("could not mask optional path %s: %m\n", *p); 2185 } 2186 2187 return 0; 2188 } 2189 2190 static int remask_after_unshare(void) 2191 { 2192 char **dp; 2193 2194 if (!opts.ocibundle) { 2195 if (opts.procfs && 2196 (mask_paths_now(proc_mask_critical, true) || 2197 mask_paths_now(proc_mask_optional, false))) 2198 return -1; 2199 2200 if (opts.sysfs && mask_paths_now(sys_mask_critical, true)) 2201 return -1; 2202 } 2203 2204 /* same reason as the default masks above: locked in phase 1, an 2205 * OCI bundle's own masks would outlive its unshare(CLONE_NEWNS). */ 2206 if (opts.oci_deferred_masked) 2207 for (dp = opts.oci_deferred_masked; *dp; dp++) 2208 if (mask_path_now(*dp)) 2209 WARNING("could not mask %s: %m\n", *dp); 2210 2211 if (opts.oci_deferred_readonly) 2212 for (dp = opts.oci_deferred_readonly; *dp; dp++) 2213 if (remount_readonly_now(*dp)) 2214 WARNING("could not make %s read-only: %m\n", *dp); 2215 2216 return 0; 2217 } 2218 2219 /* /proc/sys is locked read-only for every procfs jail via a self-bind, 2220 * separately from the mask_default_paths() lists above; a deferred- 2221 * userns jail skips it in phase 1 for the same reason it skips the 2222 * masks (see the call site in post_main()), so re-apply it here. */ 2223 static void remount_proc_sys_after_unshare(void) 2224 { 2225 struct stat s; 2226 2227 if (!(opts.procfs || opts.ocibundle)) 2228 return; 2229 if (mount_is_defined("/proc/sys")) 2230 return; 2231 if (stat("/proc/sys", &s)) 2232 return; 2233 2234 /* the MS_MOVE below needs a mountpoint to move from, or it's a 2235 * silent EINVAL. */ 2236 if ((opts.namespace & CLONE_NEWNET) && 2237 mount("/proc/sys/net", "/proc/self/net", "bind", MS_BIND, NULL)) { 2238 ERROR("failed to stash /proc/sys/net: %m\n"); 2239 free_and_exit(-1); 2240 } 2241 2242 if (bind_remount_readonly("/proc/sys", 0)) { 2243 ERROR("failed to remount /proc/sys read-only: %m\n"); 2244 free_and_exit(-1); 2245 } 2246 2247 if ((opts.namespace & CLONE_NEWNET) && 2248 mount("/proc/self/net", "/proc/sys/net", "bind", MS_MOVE, NULL)) { 2249 ERROR("failed to restore /proc/sys/net: %m\n"); 2250 free_and_exit(-1); 2251 } 2252 } 2253 2254 static bool resolve_jail_user_gids(int primary_gid) 2255 { 2256 gid_t *groups = NULL; 2257 int ngroups = 16; 2258 int ret = -1; 2259 int attempt, i, n; 2260 2261 if (!opts.user || primary_gid == -1) 2262 return false; 2263 2264 for (attempt = 0; attempt < 16; attempt++) { 2265 gid_t *tmp = realloc(groups, ngroups * sizeof(gid_t)); 2266 if (!tmp) { 2267 free(groups); 2268 ERROR("out of memory resolving groups for %s\n", opts.user); 2269 return false; 2270 } 2271 groups = tmp; 2272 2273 ret = getgrouplist(opts.user, primary_gid, groups, &ngroups); 2274 if (ret >= 0) 2275 break; 2276 } 2277 2278 if (ret < 0) { 2279 free(groups); 2280 ERROR("could not resolve groups for %s\n", opts.user); 2281 return false; 2282 } 2283 2284 for (n = 0, i = 0; i < ret; i++) { 2285 if ((int)groups[i] == primary_gid) 2286 continue; 2287 groups[n++] = groups[i]; 2288 } 2289 2290 opts.additional_gids = groups; 2291 opts.num_additional_gids = n; 2292 2293 return true; 2294 } 2295 2296 /* deterministic: parent and child (across fork) compute the same ids */ 2297 static int *compute_inner_gids(int primary_gid) 2298 { 2299 size_t i; 2300 int *inner_id; 2301 int next_id = 1; 2302 2303 inner_id = calloc(opts.num_additional_gids ?: 1, sizeof(int)); 2304 if (!inner_id) 2305 return NULL; 2306 2307 for (i = 0; i < opts.num_additional_gids; i++) { 2308 int gid = (int)opts.additional_gids[i]; 2309 int candidate = gid; 2310 bool used; 2311 2312 if (gid == 0) { 2313 do { 2314 used = (candidate == 0 || candidate == primary_gid); 2315 for (size_t j = 0; !used && j < opts.num_additional_gids; j++) 2316 if ((int)opts.additional_gids[j] == candidate) 2317 used = true; 2318 for (size_t j = 0; !used && j < i; j++) 2319 if (inner_id[j] == candidate) 2320 used = true; 2321 if (used) 2322 candidate = next_id++; 2323 } while (used); 2324 } 2325 2326 inner_id[i] = candidate; 2327 } 2328 2329 return inner_id; 2330 } 2331 2332 static char *build_group_gidmap(int primary_gid) 2333 { 2334 size_t i, len = 0, pos = 0; 2335 char *map; 2336 int *inner_id; 2337 2338 inner_id = compute_inner_gids(primary_gid); 2339 if (!inner_id) 2340 return NULL; 2341 2342 len += snprintf(NULL, 0, "%d %d %d\n", 0, primary_gid, 1); 2343 for (i = 0; i < opts.num_additional_gids; i++) 2344 len += snprintf(NULL, 0, "%d %d %d\n", 2345 inner_id[i], opts.additional_gids[i], 1); 2346 2347 map = malloc(len + 1); 2348 if (!map) { 2349 free(inner_id); 2350 return NULL; 2351 } 2352 2353 pos += snprintf(&map[pos], len + 1 - pos, "%d %d %d\n", 0, primary_gid, 1); 2354 for (i = 0; i < opts.num_additional_gids; i++) 2355 pos += snprintf(&map[pos], len + 1 - pos, "%d %d %d\n", 2356 inner_id[i], opts.additional_gids[i], 1); 2357 2358 free(inner_id); 2359 return map; 2360 } 2361 2362 static int apply_rlimits(void) 2363 { 2364 int resource; 2365 2366 for (resource = 0; resource < RLIM_NLIMITS; ++resource) { 2367 if (opts.rlimits[resource]) 2368 DEBUG("applying limits to resource %u\n", resource); 2369 2370 if (opts.rlimits[resource] && 2371 setrlimit(resource, opts.rlimits[resource])) 2372 return errno; 2373 } 2374 2375 return 0; 2376 } 2377 2378 #define MAX_ENVP 64 2379 static char** build_envp(char **ocienvp) 2380 { 2381 static char *envp[MAX_ENVP]; 2382 static char debug_var[] = "LD_DEBUG=all"; 2383 static char container_var[] = "container=ujail"; 2384 char **addenv; 2385 2386 int count = 0; 2387 2388 envp[count++] = container_var; 2389 2390 if (debug > 1) 2391 envp[count++] = debug_var; 2392 2393 addenv = ocienvp; 2394 while (addenv && *addenv) { 2395 envp[count++] = *(addenv++); 2396 if (count >= MAX_ENVP) { 2397 ERROR("environment limited to %d extra records, truncating\n", MAX_ENVP); 2398 break; 2399 } 2400 } 2401 return envp; 2402 } 2403 2404 static int build_oci_seccomp(struct blob_attr *msg) 2405 { 2406 opts.ociseccomp = parseOCIlinuxseccomp(msg, NULL); 2407 if (!opts.ociseccomp) 2408 return -1; 2409 2410 if (!seccomp_profile_covers(opts.ociseccomp, seccomp_init_base)) { 2411 opts.ociseccomp_init = parseOCIlinuxseccomp(msg, seccomp_init_base); 2412 if (!opts.ociseccomp_init) 2413 return -1; 2414 } 2415 2416 if (!seccomp_profile_covers(opts.ociseccomp, seccomp_linker_base)) { 2417 opts.ociseccomp_linker = parseOCIlinuxseccomp(msg, seccomp_linker_base); 2418 if (!opts.ociseccomp_linker) 2419 return -1; 2420 2421 opts.ociseccomp_delta_entry = seccomp_deny_delta(seccomp_loader_files, 2422 opts.ociseccomp); 2423 opts.ociseccomp_delta_main = seccomp_deny_delta(seccomp_init_base, 2424 opts.ociseccomp); 2425 } 2426 2427 return 0; 2428 } 2429 2430 static int seccomp_compile_file(const char *json_path) 2431 { 2432 const struct blob_attr *prev_root = jail_oci_root_get(); 2433 struct blob_buf b = { 0 }; 2434 int rc; 2435 2436 blob_buf_init(&b, 0); 2437 if (!blobmsg_add_json_from_file(&b, json_path)) { 2438 ERROR("seccomp: failed to load %s\n", json_path); 2439 blob_buf_free(&b); 2440 return -1; 2441 } 2442 2443 jail_oci_root_restore(b.head); 2444 rc = build_oci_seccomp(b.head); 2445 jail_oci_root_restore(prev_root); 2446 blob_buf_free(&b); 2447 if (rc) { 2448 ERROR("seccomp: failed to parse %s\n", json_path); 2449 return -1; 2450 } 2451 2452 return 0; 2453 } 2454 2455 static void usage(void) 2456 { 2457 fprintf(stderr, "ujail <options> -- <binary> <params ...>\n"); 2458 fprintf(stderr, " -d <num>\tshow debug log (increase num to increase verbosity)\n"); 2459 fprintf(stderr, " -S <file>\tseccomp filter config\n"); 2460 fprintf(stderr, " -m <mode>\tseccomp mode: enforce (default), trace, audit or complain\n"); 2461 fprintf(stderr, " -M <file>\tseccomp trace log (NDJSON) output path\n"); 2462 fprintf(stderr, " -C <file>\tcapabilities drop config\n"); 2463 fprintf(stderr, " -c\t\tset PR_SET_NO_NEW_PRIVS\n"); 2464 fprintf(stderr, " -n <name>\tthe name of the jail\n"); 2465 fprintf(stderr, " -e <var>\timport environment variable\n"); 2466 fprintf(stderr, " -x <file>\tappend KEY=VALUE lines from <file> to the container env\n"); 2467 fprintf(stderr, "namespace jail options:\n"); 2468 fprintf(stderr, " -h <hostname>\tchange the hostname of the jail\n"); 2469 fprintf(stderr, " -N\t\tjail has network namespace\n"); 2470 fprintf(stderr, " -f\t\tjail has user namespace\n"); 2471 fprintf(stderr, " -F\t\tjail has cgroups namespace\n"); 2472 fprintf(stderr, " -r <file>\treadonly files that should be staged\n"); 2473 fprintf(stderr, " -w <file>\twriteable files that should be staged\n"); 2474 fprintf(stderr, " -V <src:dest>\tbind <src> at <dest> as a noexec,nosuid,nodev volume\n"); 2475 fprintf(stderr, " -p\t\tjail has /proc\n"); 2476 fprintf(stderr, " -s\t\tjail has /sys\n"); 2477 fprintf(stderr, " -l\t\tjail has /dev/log\n"); 2478 fprintf(stderr, " -u\t\tjail has a ubus socket\n"); 2479 fprintf(stderr, " -D\t\tjail has a udebug socket\n"); 2480 fprintf(stderr, " -U <name>\tuser to run jailed process\n"); 2481 fprintf(stderr, " -G <name>\tgroup to run jailed process\n"); 2482 fprintf(stderr, " -o\t\tremont jail root (/) read only\n"); 2483 fprintf(stderr, " -R <dir>\texternal jail rootfs (system container)\n"); 2484 fprintf(stderr, " -O <dir>\tdirectory for r/w overlayfs\n"); 2485 fprintf(stderr, " -T <size>\tuse tmpfs r/w overlayfs with <size>\n"); 2486 fprintf(stderr, " -E\t\tfail if jail cannot be setup\n"); 2487 fprintf(stderr, " -y\t\tprovide jail console\n"); 2488 fprintf(stderr, " -Y <spec>\tsend PTY master fd via inherited fd or AF_UNIX path\n"); 2489 fprintf(stderr, " -J <dir>\tcreate container from OCI bundle\n"); 2490 fprintf(stderr, " -i\t\tstart container immediately\n"); 2491 fprintf(stderr, " -P <pidfile>\tcreate <pidfile>\n"); 2492 fprintf(stderr, " -a <fd>\tsend SIGCHLD through inherited pidfd <fd> once the container is gone\n"); 2493 fprintf(stderr, " -A <num>\ttag the lifecycle events of this run with incarnation <num>\n"); 2494 fprintf(stderr, "\nWarning: by default root inside the jail is the same\n\ 2495 and he has the same powers as root outside the jail,\n\ 2496 thus he can escape the jail and/or break stuff.\n\ 2497 Please use seccomp/capabilities (-S/-C) to restrict his powers\n\n\ 2498 If you use none of the namespace jail options,\n\ 2499 ujail will not use namespace/build a jail,\n\ 2500 and will only drop capabilities/apply seccomp filter.\n\n"); 2501 } 2502 2503 static int* get_namespace_fd(const unsigned int nstype) 2504 { 2505 switch (nstype) { 2506 case CLONE_NEWPID: 2507 return &opts.setns.pid; 2508 case CLONE_NEWNET: 2509 return &opts.setns.net; 2510 case CLONE_NEWNS: 2511 return &opts.setns.ns; 2512 case CLONE_NEWIPC: 2513 return &opts.setns.ipc; 2514 case CLONE_NEWUTS: 2515 return &opts.setns.uts; 2516 case CLONE_NEWUSER: 2517 return &opts.setns.user; 2518 case CLONE_NEWCGROUP: 2519 return &opts.setns.cgroup; 2520 case CLONE_NEWTIME: 2521 return &opts.setns.time; 2522 default: 2523 return NULL; 2524 } 2525 } 2526 2527 static int setns_open(unsigned long nstype) 2528 { 2529 int *fd = get_namespace_fd(nstype); 2530 2531 assert(fd != NULL); 2532 2533 if (*fd < 0) 2534 return 0; 2535 2536 if (setns(*fd, nstype) == -1) { 2537 close(*fd); 2538 return errno; 2539 } 2540 2541 close(*fd); 2542 return 0; 2543 } 2544 2545 static int jail_running = 0; 2546 static int jail_return_code = 0; 2547 static bool jail_reaped; 2548 static bool poststart_pending; 2549 2550 static void post_poststop(void) 2551 { 2552 if (jail_process_pidfd >= 0) { 2553 close(jail_process_pidfd); 2554 jail_process_pidfd = -1; 2555 } 2556 free_and_exit(jail_return_code); 2557 } 2558 2559 static void poststop_hooks(void) 2560 { 2561 run_hooks(opts.hooks.poststop, post_poststop); 2562 } 2563 2564 static void jail_process_timeout_cb(struct uloop_timeout *t); 2565 static struct uloop_timeout jail_process_timeout = { 2566 .cb = jail_process_timeout_cb, 2567 }; 2568 static void poststop(void); 2569 static void jail_process_handler(struct uloop_process *c, int ret) 2570 { 2571 uloop_timeout_cancel(&jail_process_timeout); 2572 jail_reaped = true; 2573 if (WIFEXITED(ret)) { 2574 jail_return_code = WEXITSTATUS(ret); 2575 INFO("jail (%d) exited with exit: %d\n", c->pid, jail_return_code); 2576 } else { 2577 jail_return_code = 128 + WTERMSIG(ret); 2578 INFO("jail (%d) exited with signal: %d\n", c->pid, WTERMSIG(ret)); 2579 } 2580 jail_write_exit_status(opts.pidfile, jail_return_code); 2581 jail_running = 0; 2582 2583 if (hook_running || poststart_pending) 2584 return; 2585 2586 poststop(); 2587 } 2588 2589 static struct uloop_process jail_process = { 2590 .cb = jail_process_handler, 2591 }; 2592 2593 static int jail_pidfd_send_signal(int sig) 2594 { 2595 if (jail_process_pidfd < 0) 2596 return kill(jail_process.pid, sig); 2597 return syscall(SYS_pidfd_send_signal, jail_process_pidfd, sig, NULL, 0); 2598 } 2599 2600 static void jail_process_timeout_cb(struct uloop_timeout *t) 2601 { 2602 DEBUG("jail process failed to stop, sending SIGKILL\n"); 2603 jail_pidfd_send_signal(SIGKILL); 2604 } 2605 2606 static void container_delete_cb(struct uloop_timeout *t) 2607 { 2608 if (!delete_awaited) 2609 return; 2610 2611 delete_awaited = false; 2612 poststop_hooks(); 2613 } 2614 2615 static struct uloop_timeout container_delete_timeout = { 2616 .cb = container_delete_cb, 2617 }; 2618 2619 static void jail_handle_signal(int signo) 2620 { 2621 if (signo == SIGTERM) { 2622 jail_stop_requested = true; 2623 delete_requested = true; 2624 } 2625 2626 if (hook_running) { 2627 DEBUG("forwarding signal %d to the hook process\n", signo); 2628 kill(hook_process.pid, signo); 2629 /* set timeout to send SIGKILL hook process in case SIGTERM doesn't succeed */ 2630 if (signo == SIGTERM) 2631 uloop_timeout_set(&hook_process_timeout, opts.term_timeout * 1000); 2632 } 2633 2634 if (jail_running) { 2635 DEBUG("forwarding signal %d to the jailed process\n", signo); 2636 jail_pidfd_send_signal(signo); 2637 /* set timeout to send SIGKILL jail process in case SIGTERM doesn't succeed */ 2638 if (signo == SIGTERM) 2639 uloop_timeout_set(&jail_process_timeout, opts.term_timeout * 1000); 2640 } 2641 2642 if (signo == SIGTERM && delete_awaited) 2643 uloop_timeout_add(&container_delete_timeout); 2644 } 2645 2646 static void signals_init(void) 2647 { 2648 int i; 2649 sigset_t sigmask; 2650 2651 sigfillset(&sigmask); 2652 for (i = 0; i < _NSIG; i++) { 2653 struct sigaction s = { 0 }; 2654 2655 if (!sigismember(&sigmask, i)) 2656 continue; 2657 switch (i) { 2658 case SIGCHLD: 2659 case SIGPIPE: 2660 case SIGKILL: 2661 case SIGSTOP: 2662 case SIGSEGV: 2663 case SIGBUS: 2664 case SIGFPE: 2665 case SIGILL: 2666 case SIGSYS: 2667 case SIGABRT: 2668 case SIGTRAP: 2669 continue; 2670 default: 2671 break; 2672 } 2673 2674 s.sa_handler = jail_handle_signal; 2675 sigaction(i, &s, NULL); 2676 } 2677 } 2678 2679 enum { 2680 OCI_PROCESS_SCHEDULER_POLICY, 2681 OCI_PROCESS_SCHEDULER_NICE, 2682 OCI_PROCESS_SCHEDULER_PRIORITY, 2683 OCI_PROCESS_SCHEDULER_FLAGS, 2684 OCI_PROCESS_SCHEDULER_RUNTIME, 2685 OCI_PROCESS_SCHEDULER_DEADLINE, 2686 OCI_PROCESS_SCHEDULER_PERIOD, 2687 __OCI_PROCESS_SCHEDULER_MAX, 2688 }; 2689 2690 static const struct blobmsg_policy oci_process_scheduler_policy[] = { 2691 [OCI_PROCESS_SCHEDULER_POLICY] = { "policy", BLOBMSG_TYPE_STRING }, 2692 [OCI_PROCESS_SCHEDULER_NICE] = { "nice", BLOBMSG_TYPE_INT32 }, 2693 [OCI_PROCESS_SCHEDULER_PRIORITY] = { "priority", BLOBMSG_TYPE_INT32 }, 2694 [OCI_PROCESS_SCHEDULER_FLAGS] = { "flags", BLOBMSG_TYPE_ARRAY }, 2695 [OCI_PROCESS_SCHEDULER_RUNTIME] = { "runtime", BLOBMSG_CAST_INT64 }, 2696 [OCI_PROCESS_SCHEDULER_DEADLINE] = { "deadline", BLOBMSG_CAST_INT64 }, 2697 [OCI_PROCESS_SCHEDULER_PERIOD] = { "period", BLOBMSG_CAST_INT64 }, 2698 }; 2699 2700 #ifndef SCHED_DEADLINE 2701 #define SCHED_DEADLINE 6 2702 #endif 2703 2704 #ifndef SCHED_FLAG_RESET_ON_FORK 2705 #define SCHED_FLAG_RESET_ON_FORK 0x01 2706 #endif 2707 2708 #ifndef SCHED_FLAG_RECLAIM 2709 #define SCHED_FLAG_RECLAIM 0x02 2710 #endif 2711 2712 #ifndef SCHED_FLAG_DL_OVERRUN 2713 #define SCHED_FLAG_DL_OVERRUN 0x04 2714 #endif 2715 2716 struct procd_sched_attr { 2717 uint32_t size; 2718 uint32_t sched_policy; 2719 uint64_t sched_flags; 2720 int32_t sched_nice; 2721 uint32_t sched_priority; 2722 uint64_t sched_runtime; 2723 uint64_t sched_deadline; 2724 uint64_t sched_period; 2725 }; 2726 2727 static int parseOCIprocessscheduler(struct blob_attr *msg) 2728 { 2729 struct blob_attr *tb[__OCI_PROCESS_SCHEDULER_MAX]; 2730 struct blob_attr *cur; 2731 const char *policy; 2732 int rem; 2733 2734 blobmsg_parse(oci_process_scheduler_policy, __OCI_PROCESS_SCHEDULER_MAX, tb, 2735 blobmsg_data(msg), blobmsg_len(msg)); 2736 2737 if (!tb[OCI_PROCESS_SCHEDULER_POLICY]) 2738 return ENODATA; 2739 2740 policy = blobmsg_get_string(tb[OCI_PROCESS_SCHEDULER_POLICY]); 2741 if (!strcmp(policy, "SCHED_OTHER")) 2742 opts.scheduler.policy = SCHED_OTHER; 2743 else if (!strcmp(policy, "SCHED_FIFO")) 2744 opts.scheduler.policy = SCHED_FIFO; 2745 else if (!strcmp(policy, "SCHED_RR")) 2746 opts.scheduler.policy = SCHED_RR; 2747 else if (!strcmp(policy, "SCHED_BATCH")) 2748 opts.scheduler.policy = SCHED_BATCH; 2749 else if (!strcmp(policy, "SCHED_IDLE")) 2750 opts.scheduler.policy = SCHED_IDLE; 2751 else if (!strcmp(policy, "SCHED_DEADLINE")) 2752 opts.scheduler.policy = SCHED_DEADLINE; 2753 else 2754 return EINVAL; 2755 2756 if (tb[OCI_PROCESS_SCHEDULER_NICE]) 2757 opts.scheduler.nice = blobmsg_get_u32(tb[OCI_PROCESS_SCHEDULER_NICE]); 2758 2759 if (tb[OCI_PROCESS_SCHEDULER_PRIORITY]) { 2760 int32_t prio = (int32_t)blobmsg_get_u32(tb[OCI_PROCESS_SCHEDULER_PRIORITY]); 2761 2762 if (prio < 0) { 2763 ERROR("scheduler: priority %d out of range\n", prio); 2764 return EINVAL; 2765 } 2766 if ((opts.scheduler.policy == SCHED_FIFO || opts.scheduler.policy == SCHED_RR) && 2767 (prio < 1 || prio > 99)) { 2768 ERROR("scheduler: priority %d outside 1..99 for FIFO/RR\n", prio); 2769 return EINVAL; 2770 } 2771 opts.scheduler.priority = prio; 2772 } 2773 2774 if (tb[OCI_PROCESS_SCHEDULER_RUNTIME]) 2775 opts.scheduler.runtime = blobmsg_cast_u64(tb[OCI_PROCESS_SCHEDULER_RUNTIME]); 2776 2777 if (tb[OCI_PROCESS_SCHEDULER_DEADLINE]) 2778 opts.scheduler.deadline = blobmsg_cast_u64(tb[OCI_PROCESS_SCHEDULER_DEADLINE]); 2779 2780 if (tb[OCI_PROCESS_SCHEDULER_PERIOD]) 2781 opts.scheduler.period = blobmsg_cast_u64(tb[OCI_PROCESS_SCHEDULER_PERIOD]); 2782 2783 if (tb[OCI_PROCESS_SCHEDULER_FLAGS]) { 2784 if (blobmsg_check_array(tb[OCI_PROCESS_SCHEDULER_FLAGS], BLOBMSG_TYPE_STRING) < 0) 2785 return EINVAL; 2786 blobmsg_for_each_attr(cur, tb[OCI_PROCESS_SCHEDULER_FLAGS], rem) { 2787 const char *flag = blobmsg_get_string(cur); 2788 if (!strcmp(flag, "SCHED_FLAG_RESET_ON_FORK")) 2789 opts.scheduler.flags |= SCHED_FLAG_RESET_ON_FORK; 2790 else if (!strcmp(flag, "SCHED_FLAG_RECLAIM")) 2791 opts.scheduler.flags |= SCHED_FLAG_RECLAIM; 2792 else if (!strcmp(flag, "SCHED_FLAG_DL_OVERRUN")) 2793 opts.scheduler.flags |= SCHED_FLAG_DL_OVERRUN; 2794 else 2795 return EINVAL; 2796 } 2797 } 2798 2799 opts.scheduler.set = true; 2800 return 0; 2801 } 2802 2803 static int applyOCIprocessscheduler(void) 2804 { 2805 struct procd_sched_attr attr = { 2806 .size = sizeof(attr), 2807 .sched_policy = opts.scheduler.policy, 2808 .sched_flags = opts.scheduler.flags, 2809 .sched_nice = opts.scheduler.nice, 2810 .sched_priority = opts.scheduler.priority, 2811 .sched_runtime = opts.scheduler.runtime, 2812 .sched_deadline = opts.scheduler.deadline, 2813 .sched_period = opts.scheduler.period, 2814 }; 2815 2816 if (syscall(SYS_sched_setattr, 0, &attr, 0)) { 2817 ERROR("sched_setattr: %m\n"); 2818 return errno; 2819 } 2820 2821 return 0; 2822 } 2823 2824 enum { 2825 OCI_PROCESS_IOPRIORITY_CLASS, 2826 OCI_PROCESS_IOPRIORITY_PRIORITY, 2827 __OCI_PROCESS_IOPRIORITY_MAX, 2828 }; 2829 2830 static const struct blobmsg_policy oci_process_iopriority_policy[] = { 2831 [OCI_PROCESS_IOPRIORITY_CLASS] = { "class", BLOBMSG_TYPE_STRING }, 2832 [OCI_PROCESS_IOPRIORITY_PRIORITY] = { "priority", BLOBMSG_TYPE_INT32 }, 2833 }; 2834 2835 #ifndef IOPRIO_WHO_PROCESS 2836 #define IOPRIO_WHO_PROCESS 1 2837 #endif 2838 2839 #ifndef IOPRIO_CLASS_RT 2840 #define IOPRIO_CLASS_RT 1 2841 #endif 2842 2843 #ifndef IOPRIO_CLASS_BE 2844 #define IOPRIO_CLASS_BE 2 2845 #endif 2846 2847 #ifndef IOPRIO_CLASS_SHIFT 2848 #define IOPRIO_CLASS_SHIFT 13 2849 #endif 2850 2851 #ifndef IOPRIO_CLASS_IDLE 2852 #define IOPRIO_CLASS_IDLE 3 2853 #endif 2854 2855 static int parseOCIprocessiopriority(struct blob_attr *msg) 2856 { 2857 struct blob_attr *tb[__OCI_PROCESS_IOPRIORITY_MAX]; 2858 const char *class; 2859 int priority; 2860 2861 blobmsg_parse(oci_process_iopriority_policy, __OCI_PROCESS_IOPRIORITY_MAX, tb, 2862 blobmsg_data(msg), blobmsg_len(msg)); 2863 2864 if (!tb[OCI_PROCESS_IOPRIORITY_CLASS] || !tb[OCI_PROCESS_IOPRIORITY_PRIORITY]) 2865 return ENODATA; 2866 2867 class = blobmsg_get_string(tb[OCI_PROCESS_IOPRIORITY_CLASS]); 2868 if (!strcmp(class, "IOPRIO_CLASS_RT")) 2869 opts.ioprio.class = IOPRIO_CLASS_RT; 2870 else if (!strcmp(class, "IOPRIO_CLASS_BE")) 2871 opts.ioprio.class = IOPRIO_CLASS_BE; 2872 else if (!strcmp(class, "IOPRIO_CLASS_IDLE")) 2873 opts.ioprio.class = IOPRIO_CLASS_IDLE; 2874 else 2875 return EINVAL; 2876 2877 priority = blobmsg_get_u32(tb[OCI_PROCESS_IOPRIORITY_PRIORITY]); 2878 if (priority < 0 || priority > 7) 2879 return EINVAL; 2880 2881 opts.ioprio.priority = priority; 2882 opts.ioprio.set = true; 2883 return 0; 2884 } 2885 2886 static int applyOCIprocessiopriority(void) 2887 { 2888 int ioprio = (opts.ioprio.class << IOPRIO_CLASS_SHIFT) | opts.ioprio.priority; 2889 2890 if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0, ioprio)) { 2891 ERROR("ioprio_set: %m\n"); 2892 return errno; 2893 } 2894 2895 return 0; 2896 } 2897 2898 static int move_netdev_to_ns(int netns_fd, const char *host_name, const char *new_name) 2899 { 2900 struct { 2901 struct nlmsghdr hdr; 2902 struct ifinfomsg ifi; 2903 char attrbuf[256]; 2904 } req = { 0 }; 2905 struct sockaddr_nl sa = { .nl_family = AF_NETLINK }; 2906 struct rtattr *rta; 2907 int sock, ifindex; 2908 char buf[4096]; 2909 ssize_t n; 2910 2911 int saved_err; 2912 2913 ifindex = if_nametoindex(host_name); 2914 if (!ifindex) { 2915 ERROR("netDevices: interface %s not found\n", host_name); 2916 return ENODEV; 2917 } 2918 2919 sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); 2920 if (sock < 0) { 2921 ERROR("netDevices: socket(AF_NETLINK): %m\n"); 2922 return errno; 2923 } 2924 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 2925 saved_err = errno; 2926 ERROR("netDevices: bind: %m\n"); 2927 close(sock); 2928 errno = saved_err; 2929 return saved_err; 2930 } 2931 2932 req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifi)); 2933 req.hdr.nlmsg_type = RTM_NEWLINK; 2934 req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 2935 req.hdr.nlmsg_seq = 1; 2936 req.ifi.ifi_family = AF_UNSPEC; 2937 req.ifi.ifi_index = ifindex; 2938 2939 rta = (struct rtattr *)((char *)&req + NLMSG_ALIGN(req.hdr.nlmsg_len)); 2940 rta->rta_type = IFLA_NET_NS_FD; 2941 rta->rta_len = RTA_LENGTH(sizeof(int)); 2942 memcpy(RTA_DATA(rta), &netns_fd, sizeof(int)); 2943 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + RTA_ALIGN(rta->rta_len); 2944 2945 if (new_name) { 2946 size_t namelen = strlen(new_name) + 1; 2947 rta = (struct rtattr *)((char *)&req + NLMSG_ALIGN(req.hdr.nlmsg_len)); 2948 rta->rta_type = IFLA_IFNAME; 2949 rta->rta_len = RTA_LENGTH(namelen); 2950 memcpy(RTA_DATA(rta), new_name, namelen); 2951 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + RTA_ALIGN(rta->rta_len); 2952 } 2953 2954 if (send(sock, &req, req.hdr.nlmsg_len, 0) < 0) { 2955 saved_err = errno; 2956 ERROR("netDevices: send: %m\n"); 2957 close(sock); 2958 errno = saved_err; 2959 return saved_err; 2960 } 2961 2962 n = recv(sock, buf, sizeof(buf), 0); 2963 saved_err = (n < 0) ? errno : 0; 2964 close(sock); 2965 if (n < 0) { 2966 errno = saved_err; 2967 ERROR("netDevices: recv: %m\n"); 2968 return saved_err; 2969 } 2970 2971 if (n < (ssize_t)NLMSG_HDRLEN || 2972 !NLMSG_OK((struct nlmsghdr *)buf, (size_t)n)) { 2973 ERROR("netDevices: short or malformed nlmsg (%zd bytes)\n", n); 2974 return EIO; 2975 } 2976 2977 struct nlmsghdr *nh = (struct nlmsghdr *)buf; 2978 if (nh->nlmsg_type == NLMSG_ERROR) { 2979 struct nlmsgerr *err = NLMSG_DATA(nh); 2980 if (err->error) { 2981 ERROR("netDevices: kernel rejected move of %s: %s\n", 2982 host_name, strerror(-err->error)); 2983 return -err->error; 2984 } 2985 } 2986 2987 return 0; 2988 } 2989 2990 static int move_netdevs_into_jail(pid_t pid) 2991 { 2992 enum { 2993 OCI_LINUX_NETDEVICES_NAME, 2994 __OCI_LINUX_NETDEVICES_MAX, 2995 }; 2996 static const struct blobmsg_policy policy[] = { 2997 [OCI_LINUX_NETDEVICES_NAME] = { "name", BLOBMSG_TYPE_STRING }, 2998 }; 2999 struct blob_attr *cur, *tb[__OCI_LINUX_NETDEVICES_MAX]; 3000 char path[64]; 3001 int rem, netns_fd, ret = 0; 3002 3003 if (!opts.netdevices) 3004 return 0; 3005 3006 snprintf(path, sizeof(path), "/proc/%d/ns/net", pid); 3007 netns_fd = open(path, O_RDONLY | O_CLOEXEC); 3008 if (netns_fd < 0) { 3009 ERROR("netDevices: open(%s): %m\n", path); 3010 return errno; 3011 } 3012 3013 blobmsg_for_each_attr(cur, opts.netdevices, rem) { 3014 const char *host_name = blobmsg_name(cur); 3015 const char *new_name = NULL; 3016 3017 blobmsg_parse(policy, __OCI_LINUX_NETDEVICES_MAX, tb, 3018 blobmsg_data(cur), blobmsg_len(cur)); 3019 if (tb[OCI_LINUX_NETDEVICES_NAME]) 3020 new_name = blobmsg_get_string(tb[OCI_LINUX_NETDEVICES_NAME]); 3021 3022 ret = move_netdev_to_ns(netns_fd, host_name, new_name); 3023 if (ret) 3024 break; 3025 } 3026 3027 close(netns_fd); 3028 return ret; 3029 } 3030 3031 enum { 3032 OCI_LINUX_TIMEOFFSETS_SECS, 3033 OCI_LINUX_TIMEOFFSETS_NANOSECS, 3034 __OCI_LINUX_TIMEOFFSETS_CLOCK_MAX, 3035 }; 3036 3037 static const struct blobmsg_policy oci_linux_timeoffsets_clock_policy[] = { 3038 [OCI_LINUX_TIMEOFFSETS_SECS] = { "secs", BLOBMSG_CAST_INT64 }, 3039 [OCI_LINUX_TIMEOFFSETS_NANOSECS] = { "nanosecs", BLOBMSG_TYPE_INT32 }, 3040 }; 3041 3042 struct procd_timens_offset { 3043 bool set; 3044 int64_t secs; 3045 uint32_t nanosecs; 3046 }; 3047 3048 static struct { 3049 struct procd_timens_offset monotonic; 3050 struct procd_timens_offset boottime; 3051 } timens_offsets; 3052 3053 enum { 3054 OCI_LINUX_TIMEOFFSETS_MONOTONIC, 3055 OCI_LINUX_TIMEOFFSETS_BOOTTIME, 3056 __OCI_LINUX_TIMEOFFSETS_MAX, 3057 }; 3058 3059 static const struct blobmsg_policy oci_linux_timeoffsets_policy[] = { 3060 [OCI_LINUX_TIMEOFFSETS_MONOTONIC] = { "monotonic", BLOBMSG_TYPE_TABLE }, 3061 [OCI_LINUX_TIMEOFFSETS_BOOTTIME] = { "boottime", BLOBMSG_TYPE_TABLE }, 3062 }; 3063 3064 static int parseOCItimensclock(struct blob_attr *msg, struct procd_timens_offset *off) 3065 { 3066 struct blob_attr *tb[__OCI_LINUX_TIMEOFFSETS_CLOCK_MAX]; 3067 3068 blobmsg_parse(oci_linux_timeoffsets_clock_policy, __OCI_LINUX_TIMEOFFSETS_CLOCK_MAX, tb, 3069 blobmsg_data(msg), blobmsg_len(msg)); 3070 3071 if (tb[OCI_LINUX_TIMEOFFSETS_SECS]) 3072 off->secs = blobmsg_cast_s64(tb[OCI_LINUX_TIMEOFFSETS_SECS]); 3073 3074 if (tb[OCI_LINUX_TIMEOFFSETS_NANOSECS]) { 3075 uint32_t ns = blobmsg_get_u32(tb[OCI_LINUX_TIMEOFFSETS_NANOSECS]); 3076 3077 if (ns > 999999999) { 3078 ERROR("timeOffsets: nanosecs %u out of range\n", ns); 3079 return EINVAL; 3080 } 3081 off->nanosecs = ns; 3082 } 3083 3084 off->set = true; 3085 return 0; 3086 } 3087 3088 static int parseOCIlinuxtimeoffsets(struct blob_attr *msg) 3089 { 3090 struct blob_attr *tb[__OCI_LINUX_TIMEOFFSETS_MAX]; 3091 int res; 3092 3093 blobmsg_parse(oci_linux_timeoffsets_policy, __OCI_LINUX_TIMEOFFSETS_MAX, tb, 3094 blobmsg_data(msg), blobmsg_len(msg)); 3095 3096 if (tb[OCI_LINUX_TIMEOFFSETS_MONOTONIC]) { 3097 res = parseOCItimensclock(tb[OCI_LINUX_TIMEOFFSETS_MONOTONIC], &timens_offsets.monotonic); 3098 if (res) 3099 return res; 3100 } 3101 3102 if (tb[OCI_LINUX_TIMEOFFSETS_BOOTTIME]) { 3103 res = parseOCItimensclock(tb[OCI_LINUX_TIMEOFFSETS_BOOTTIME], &timens_offsets.boottime); 3104 if (res) 3105 return res; 3106 } 3107 3108 return 0; 3109 } 3110 3111 static int applyOCIlinuxtimeoffsets(void) 3112 { 3113 int fd = open("/proc/self/timens_offsets", O_WRONLY | O_CLOEXEC); 3114 int saved_errno; 3115 3116 if (fd < 0) { 3117 ERROR("open(/proc/self/timens_offsets): %m\n"); 3118 return errno; 3119 } 3120 3121 if (timens_offsets.monotonic.set && 3122 dprintf(fd, "%d %" PRId64 " %" PRIu32 "\n", CLOCK_MONOTONIC, 3123 timens_offsets.monotonic.secs, timens_offsets.monotonic.nanosecs) < 0) { 3124 saved_errno = errno; 3125 ERROR("timens_offsets monotonic: %m\n"); 3126 close(fd); 3127 return saved_errno; 3128 } 3129 3130 if (timens_offsets.boottime.set && 3131 dprintf(fd, "%d %" PRId64 " %" PRIu32 "\n", CLOCK_BOOTTIME, 3132 timens_offsets.boottime.secs, timens_offsets.boottime.nanosecs) < 0) { 3133 saved_errno = errno; 3134 ERROR("timens_offsets boottime: %m\n"); 3135 close(fd); 3136 return saved_errno; 3137 } 3138 3139 close(fd); 3140 return 0; 3141 } 3142 3143 static int timens_create(void) 3144 { 3145 int fd; 3146 3147 if (unshare(CLONE_NEWTIME)) { 3148 ERROR("unshare(CLONE_NEWTIME) failed: %m\n"); 3149 return -1; 3150 } 3151 3152 if ((timens_offsets.monotonic.set || timens_offsets.boottime.set) && 3153 applyOCIlinuxtimeoffsets()) 3154 return -1; 3155 3156 fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC); 3157 if (fd < 0) { 3158 ERROR("open(/proc/self/ns/time_for_children): %m\n"); 3159 return -1; 3160 } 3161 3162 if (setns(fd, CLONE_NEWTIME)) { 3163 ERROR("setns(CLONE_NEWTIME): %m\n"); 3164 close(fd); 3165 return -1; 3166 } 3167 3168 close(fd); 3169 return 0; 3170 } 3171 3172 static void pre_exec_jail(struct uloop_timeout *t); 3173 static struct uloop_timeout pre_exec_timeout = { 3174 .cb = pre_exec_jail, 3175 }; 3176 3177 int pipes[4]; 3178 static int parent_pidfd = -1; 3179 3180 static bool jail_has_utsns(void) 3181 { 3182 return (opts.namespace & CLONE_NEWUTS) || opts.setns.uts != -1; 3183 } 3184 3185 static int exec_jail(void *arg) 3186 { 3187 char buf[1]; 3188 char tag; 3189 int recv_fds[JAIL_IDMAP_MAX_FDS]; 3190 int nrecv; 3191 int ret; 3192 3193 exit_from_child = true; 3194 prctl(PR_SET_SECUREBITS, 0); 3195 3196 uloop_init(); 3197 signals_init(); 3198 3199 close(pipes[0]); 3200 close(pipes[3]); 3201 3202 if ((opts.namespace & CLONE_NEWUSER) && opts.setns.user == -1) { 3203 close(userns_pipe[0]); 3204 close(userns_pipe[3]); 3205 } else { 3206 /* Not deferring anything: this handshake isn't used at all. */ 3207 close(userns_pipe[0]); 3208 close(userns_pipe[1]); 3209 close(userns_pipe[2]); 3210 close(userns_pipe[3]); 3211 } 3212 3213 ret = setns_open(CLONE_NEWNET); 3214 if (!ret) 3215 ret = setns_open(CLONE_NEWNS); 3216 if (!ret) 3217 ret = setns_open(CLONE_NEWIPC); 3218 if (!ret) 3219 ret = setns_open(CLONE_NEWUTS); 3220 #ifdef CLONE_NEWTIME 3221 if (!ret) 3222 ret = setns_open(CLONE_NEWTIME); 3223 #endif 3224 if (ret) { 3225 ERROR("failed to join namespace: %s\n", strerror(ret)); 3226 return EXIT_FAILURE; 3227 } 3228 3229 if ((opts.namespace & CLONE_NEWNS) && isolate_mountns()) { 3230 ERROR("mount propagation failed: %m\n"); 3231 return EXIT_FAILURE; 3232 } 3233 3234 /* 3235 * Must run before enter_userns() drops privilege over the inherited 3236 * mounts. A userns from clone() owns its mntns and has everything 3237 * inherited MNT_LOCKED, so there the detach is neither possible nor 3238 * needed. 3239 */ 3240 if ((opts.namespace & CLONE_NEWNS) && userns_deferred() && 3241 detach_inherited_mounts()) { 3242 ERROR("failed to detach inherited mounts\n"); 3243 return EXIT_FAILURE; 3244 } 3245 3246 buf[0] = 'i'; 3247 if (write(pipes[1], buf, 1) < 1) { 3248 ERROR("can't write to parent\n"); 3249 return EXIT_FAILURE; 3250 } 3251 close(pipes[1]); 3252 3253 nrecv = sock_recv_fds(pipes[2], &tag, recv_fds, JAIL_IDMAP_MAX_FDS); 3254 if (nrecv < 0) { 3255 ERROR("can't read from parent\n"); 3256 return EXIT_FAILURE; 3257 } 3258 if (tag != 'O') { 3259 ERROR("parent had an error, child exiting\n"); 3260 return EXIT_FAILURE; 3261 } 3262 if (nrecv > 0) 3263 jail_idmap_assign(jail_idmap_active() && opts.extroot, 3264 false, 3265 recv_fds, nrecv, &extroot_idmap_fd, &overlay_idmap_fd); 3266 3267 if ((opts.namespace & CLONE_NEWUSER) && !userns_deferred()) { 3268 if (userns_wait_idmaps() || userns_become_root()) 3269 return EXIT_FAILURE; 3270 } 3271 3272 if (opts.namespace & CLONE_NEWCGROUP) 3273 unshare(CLONE_NEWCGROUP); 3274 3275 ret = setns_open(CLONE_NEWCGROUP); 3276 if (ret) { 3277 ERROR("failed to join cgroup namespace: %s\n", strerror(ret)); 3278 free_and_exit(EXIT_FAILURE); 3279 } 3280 3281 #ifdef CLONE_NEWTIME 3282 if ((opts.namespace & CLONE_NEWTIME) && opts.setns.time == -1 && 3283 !userns_deferred() && timens_create()) 3284 free_and_exit(EXIT_FAILURE); 3285 #endif 3286 3287 if (jail_has_utsns() 3288 && opts.hostname && strlen(opts.hostname) > 0 3289 && sethostname(opts.hostname, strlen(opts.hostname))) { 3290 ERROR("sethostname(%s) failed: %m\n", opts.hostname); 3291 free_and_exit(EXIT_FAILURE); 3292 } 3293 3294 if (jail_has_utsns() 3295 && opts.domainname && strlen(opts.domainname) > 0 3296 && setdomainname(opts.domainname, strlen(opts.domainname))) { 3297 ERROR("setdomainname(%s) failed: %m\n", opts.domainname); 3298 free_and_exit(EXIT_FAILURE); 3299 } 3300 3301 uloop_timeout_add(&pre_exec_timeout); 3302 uloop_run(); 3303 3304 free_and_exit(-1); 3305 return -1; 3306 } 3307 3308 static void pre_exec_jail(struct uloop_timeout *t) 3309 { 3310 if ((opts.namespace & CLONE_NEWNS) && build_jail_fs()) { 3311 ERROR("failed to build jail fs\n"); 3312 free_and_exit(EXIT_FAILURE); 3313 } else if (!(opts.namespace & CLONE_NEWNS)) { 3314 /* 3315 * No mount namespace to build (plain "-f"): build_jail_fs() 3316 * is skipped, so reach enter_userns() directly here instead. 3317 */ 3318 run_hooks(opts.hooks.createContainer, enter_userns); 3319 } 3320 } 3321 3322 static void post_start_hook(void); 3323 static void post_jail_fs(void) 3324 { 3325 char buf[1]; 3326 ssize_t n; 3327 3328 if (opts.rootfs_propagation && !(opts.rootfs_propagation & MS_SLAVE) && 3329 (opts.namespace & CLONE_NEWNS) && 3330 mount(NULL, "/", NULL, opts.rootfs_propagation, NULL)) { 3331 ERROR("rootfsPropagation: %m\n"); 3332 free_and_exit(EXIT_FAILURE); 3333 } 3334 3335 do { 3336 if (jail_stop_requested) 3337 free_and_exit(128 + SIGTERM); 3338 3339 n = read(pipes[2], buf, 1); 3340 } while (n < 0 && errno == EINTR); 3341 if (n < 1) { 3342 ERROR("can't read from parent\n"); 3343 free_and_exit(EXIT_FAILURE); 3344 } 3345 if (buf[0] != '!') { 3346 ERROR("parent had an error, child exiting\n"); 3347 free_and_exit(EXIT_FAILURE); 3348 } 3349 close(pipes[2]); 3350 3351 run_hooks(opts.hooks.startContainer, post_start_hook); 3352 } 3353 3354 static void parent_pidfd_check(void) 3355 { 3356 struct pollfd pfd = { .fd = parent_pidfd, .events = POLLIN }; 3357 3358 if (poll(&pfd, 1, 0) > 0) { 3359 ERROR("parent died before PR_SET_PDEATHSIG\n"); 3360 free_and_exit(EXIT_FAILURE); 3361 } 3362 3363 close(parent_pidfd); 3364 } 3365 3366 static void post_start_hook(void) 3367 { 3368 struct sock_fprog *seccomp_prog = opts.ociseccomp_linker ?: opts.ociseccomp; 3369 int pw_uid, pw_gid, gr_gid; 3370 int exec_errno; 3371 3372 if (opts.scheduler.set && applyOCIprocessscheduler()) 3373 free_and_exit(EXIT_FAILURE); 3374 3375 if (opts.ioprio.set && applyOCIprocessiopriority()) 3376 free_and_exit(EXIT_FAILURE); 3377 3378 syscall(SYS_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC); 3379 3380 if (seccomp_prog && jail_inproc_seccomp() && !opts.no_new_privs && 3381 applyOCIlinuxseccomp(seccomp_prog, opts.name, opts.ocibundle)) 3382 free_and_exit(EXIT_FAILURE); 3383 3384 /* 3385 * make sure setuid/setgid won't drop capabilities in case capabilities 3386 * have been specified explicitely. 3387 */ 3388 if (opts.capset.apply) { 3389 if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP)) { 3390 ERROR("prctl(PR_SET_SECUREBITS) failed: %m\n"); 3391 free_and_exit(EXIT_FAILURE); 3392 } 3393 } 3394 3395 /* drop capabilities, retain those still needed to further setup jail */ 3396 if (applyOCIcapabilities(opts.capset, (1LLU << CAP_SETGID) | (1LLU << CAP_SETUID) | (1LLU << CAP_SETPCAP))) 3397 free_and_exit(EXIT_FAILURE); 3398 3399 /* use either cmdline-supplied user/group or uid/gid from OCI spec */ 3400 if (opts.ocibundle || opts.uidmap || !(opts.namespace & CLONE_NEWUSER)) { 3401 get_jail_user(&pw_uid, &pw_gid, &gr_gid); 3402 set_jail_user(opts.pw_uid?:pw_uid, opts.pw_gid?:pw_gid, opts.gr_gid?:gr_gid); 3403 } else if (opts.user || opts.group || opts.pw_uid != -1 || opts.pw_gid != -1 || opts.gr_gid != -1) { 3404 WARNING("user/group identity switch (-U/-G) is not re-applied under " 3405 "CLONE_NEWUSER without an OCI bundle or explicit uidmap; the " 3406 "process already has the correct identity via the uid_map\n"); 3407 } 3408 3409 if (opts.additional_gids) { 3410 bool default_own_userns_map = !opts.uidmap && 3411 (opts.namespace & CLONE_NEWUSER) && opts.setns.user == -1; 3412 3413 if (default_own_userns_map) { 3414 bool has_gr = (opts.gr_gid != -1); 3415 int primary_gid = has_gr ? opts.gr_gid : 3416 ((opts.pw_uid != -1) ? opts.pw_gid : 65534); 3417 int *inner_id = compute_inner_gids(primary_gid); 3418 3419 if (inner_id) { 3420 gid_t *mapped = calloc(opts.num_additional_gids ?: 1, sizeof(gid_t)); 3421 size_t i; 3422 3423 if (mapped) { 3424 for (i = 0; i < opts.num_additional_gids; i++) 3425 mapped[i] = (gid_t)inner_id[i]; 3426 if (setgroups(opts.num_additional_gids, mapped) < 0) { 3427 ERROR("setgroups failed: %m\n"); 3428 free(mapped); 3429 free(inner_id); 3430 free_and_exit(EXIT_FAILURE); 3431 } 3432 free(mapped); 3433 } else { 3434 ERROR("out of memory computing setgroups() list\n"); 3435 free(inner_id); 3436 free_and_exit(EXIT_FAILURE); 3437 } 3438 free(inner_id); 3439 } else { 3440 ERROR("out of memory computing setgroups() list\n"); 3441 free_and_exit(EXIT_FAILURE); 3442 } 3443 } else if (setgroups(opts.num_additional_gids, opts.additional_gids) < 0) { 3444 ERROR("setgroups failed: %m\n"); 3445 free_and_exit(EXIT_FAILURE); 3446 } 3447 } 3448 3449 if (opts.set_umask) 3450 umask(opts.umask); 3451 3452 /* restore securebits back to normal (and lock them if not in userns) */ 3453 if (opts.capset.apply) { 3454 if (prctl(PR_SET_SECUREBITS, jail_in_userns() ? 0 : 3455 SECBIT_KEEP_CAPS_LOCKED|SECBIT_NO_SETUID_FIXUP_LOCKED|SECBIT_NOROOT_LOCKED)) { 3456 ERROR("prctl(PR_SET_SECUREBITS) failed: %m\n"); 3457 free_and_exit(EXIT_FAILURE); 3458 } 3459 } 3460 3461 /* drop remaining capabilities to end up with specified sets */ 3462 if (applyOCIcapabilities(opts.capset, 0)) 3463 free_and_exit(EXIT_FAILURE); 3464 3465 if (opts.no_new_privs && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 3466 ERROR("prctl(PR_SET_NO_NEW_PRIVS) failed: %m\n"); 3467 free_and_exit(EXIT_FAILURE); 3468 } 3469 3470 /* the supervisor can SIGKILL ujail on its own death (netifd on exit, 3471 * procd's instance_timeout() escalation); die with it, otherwise the 3472 * jailed process keeps running and the supervisor's supervisor starts 3473 * a second instance. Placed after set_jail_user() and the capability 3474 * transitions, whose commit_creds() would zero pdeath_signal, but before 3475 * the seccomp filter, which need not permit prctl() to reach execve(). */ 3476 if (prctl(PR_SET_PDEATHSIG, SIGKILL)) { 3477 ERROR("prctl(PR_SET_PDEATHSIG) failed: %m\n"); 3478 free_and_exit(EXIT_FAILURE); 3479 } 3480 3481 /* the parent can die between the fork() and the prctl above; the death 3482 * signal is then bound to the process we are reparented to and never 3483 * delivered, so detect the exit on the inherited pidfd and die ourselves. 3484 * getppid() == 1 cannot serve here: in a new PID namespace the parent is 3485 * not visible and getppid() reads 0 either way. */ 3486 parent_pidfd_check(); 3487 3488 if (opts.mdwe_flags && prctl(PR_SET_MDWE, opts.mdwe_flags, 0, 0, 0)) { 3489 ERROR("prctl(PR_SET_MDWE, 0x%lx) failed: %m\n", opts.mdwe_flags); 3490 free_and_exit(EXIT_FAILURE); 3491 } 3492 3493 char **envp = build_envp(opts.envp); 3494 if (!envp) 3495 free_and_exit(EXIT_FAILURE); 3496 3497 if (opts.cwd && chdir(opts.cwd)) { 3498 ERROR("chdir(cwd=%s) failed: %m\n", opts.cwd); 3499 free_and_exit(EXIT_FAILURE); 3500 } 3501 3502 if (opts.landlock.n > 0 && landlock_apply(&opts.landlock)) { 3503 ERROR("landlock_apply failed\n"); 3504 free_and_exit(EXIT_FAILURE); 3505 } 3506 3507 if (seccomp_prog && jail_inproc_seccomp() && opts.no_new_privs && 3508 applyOCIlinuxseccomp(seccomp_prog, opts.name, opts.ocibundle)) 3509 free_and_exit(EXIT_FAILURE); 3510 3511 uloop_end(); 3512 free_opts(false); 3513 if (jail_ptrace_seccomp() && ptrace(PTRACE_TRACEME, 0, 0, 0)) { 3514 ERROR("PTRACE_TRACEME failed: %m\n"); 3515 exit(EXIT_FAILURE); 3516 } 3517 DEBUG("exec-ing %s\n", *opts.jail_argv); 3518 if (xwrite_byte(exec_ack[1], EXEC_ACK_EXEC) < 1) { 3519 ERROR("cannot announce the exec to the parent: %m\n"); 3520 exit(EXIT_FAILURE); 3521 } 3522 3523 if (opts.envp) { /* respect PATH if potentially set in ENV */ 3524 environ = envp; 3525 execvpe(*opts.jail_argv, opts.jail_argv, envp); 3526 } else { 3527 execve(*opts.jail_argv, opts.jail_argv, envp); 3528 } 3529 3530 /* we get there only if execve fails */ 3531 exec_errno = errno; 3532 ERROR("failed to execve %s: %m\n", *opts.jail_argv); 3533 if (write(exec_ack[1], &exec_errno, sizeof(exec_errno)) != 3534 sizeof(exec_errno)) 3535 ERROR("cannot report the exec failure to the parent: %m\n"); 3536 exit(EXIT_FAILURE); 3537 } 3538 3539 int ns_open_pid(const char *nstype, const pid_t target_ns) 3540 { 3541 char pid_pid_path[PATH_MAX]; 3542 3543 snprintf(pid_pid_path, sizeof(pid_pid_path), "/proc/%u/ns/%s", target_ns, nstype); 3544 3545 return open(pid_pid_path, O_RDONLY); 3546 } 3547 3548 static int parseOCIenvarray(struct blob_attr *msg, char ***envp) 3549 { 3550 struct blob_attr *cur; 3551 int sz = 0, rem; 3552 3553 blobmsg_for_each_attr(cur, msg, rem) 3554 ++sz; 3555 3556 if (sz > 0) { 3557 *envp = calloc(1 + sz, sizeof(char*)); 3558 if (!(*envp)) 3559 return ENOMEM; 3560 } else { 3561 *envp = NULL; 3562 return 0; 3563 } 3564 3565 sz = 0; 3566 blobmsg_for_each_attr(cur, msg, rem) 3567 (*envp)[sz++] = strdup(blobmsg_get_string(cur)); 3568 3569 if (sz) 3570 (*envp)[sz] = NULL; 3571 3572 return 0; 3573 } 3574 3575 static int append_envfile(char ***envp, const char *path) 3576 { 3577 char line[4096]; 3578 char **arr = *envp; 3579 char *nl; 3580 int n = 0; 3581 FILE *f; 3582 3583 f = fopen(path, "r"); 3584 if (!f) 3585 return 0; 3586 3587 while (arr && arr[n]) 3588 ++n; 3589 3590 while (fgets(line, sizeof(line), f)) { 3591 nl = strchr(line, '\n'); 3592 if (nl) 3593 *nl = '\0'; 3594 3595 if (line[0] == '\0' || line[0] == '#' || !strchr(line, '=')) 3596 continue; 3597 3598 arr = realloc(arr, (n + 2) * sizeof(char *)); 3599 if (!arr) { 3600 fclose(f); 3601 return ENOMEM; 3602 } 3603 3604 arr[n++] = strdup(line); 3605 arr[n] = NULL; 3606 } 3607 3608 fclose(f); 3609 *envp = arr; 3610 return 0; 3611 } 3612 3613 enum { 3614 OCI_ROOT_PATH, 3615 OCI_ROOT_READONLY, 3616 __OCI_ROOT_MAX, 3617 }; 3618 3619 static const struct blobmsg_policy oci_root_policy[] = { 3620 [OCI_ROOT_PATH] = { "path", BLOBMSG_TYPE_STRING }, 3621 [OCI_ROOT_READONLY] = { "readonly", BLOBMSG_TYPE_BOOL }, 3622 }; 3623 3624 static int parseOCIroot(const char *jsonfile, struct blob_attr *msg) 3625 { 3626 char extroot[PATH_MAX] = { 0 }; 3627 struct blob_attr *tb[__OCI_ROOT_MAX]; 3628 char *cur; 3629 char *root_path; 3630 3631 blobmsg_parse(oci_root_policy, __OCI_ROOT_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 3632 3633 if (!tb[OCI_ROOT_PATH]) 3634 return ENODATA; 3635 3636 root_path = blobmsg_get_string(tb[OCI_ROOT_PATH]); 3637 3638 /* prepend bundle directory in case of relative paths */ 3639 if (root_path[0] != '/') { 3640 strncpy(extroot, jsonfile, PATH_MAX - 1); 3641 3642 cur = strrchr(extroot, '/'); 3643 3644 if (!cur) 3645 return ENOTDIR; 3646 3647 *(++cur) = '\0'; 3648 } 3649 3650 strncat(extroot, root_path, PATH_MAX - (strlen(extroot) + 1)); 3651 3652 /* follow symbolic link(s) */ 3653 opts.extroot = realpath(extroot, NULL); 3654 if (!opts.extroot) 3655 return errno; 3656 3657 if (tb[OCI_ROOT_READONLY]) 3658 opts.ronly = blobmsg_get_bool(tb[OCI_ROOT_READONLY]); 3659 3660 return 0; 3661 } 3662 3663 3664 enum { 3665 OCI_HOOK_PATH, 3666 OCI_HOOK_ARGS, 3667 OCI_HOOK_ENV, 3668 OCI_HOOK_TIMEOUT, 3669 __OCI_HOOK_MAX, 3670 }; 3671 3672 static const struct blobmsg_policy oci_hook_policy[] = { 3673 [OCI_HOOK_PATH] = { "path", BLOBMSG_TYPE_STRING }, 3674 [OCI_HOOK_ARGS] = { "args", BLOBMSG_TYPE_ARRAY }, 3675 [OCI_HOOK_ENV] = { "env", BLOBMSG_TYPE_ARRAY }, 3676 [OCI_HOOK_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 }, 3677 }; 3678 3679 3680 static int parseOCIhook(struct hook_execvpe ***hooklist, struct blob_attr *msg) 3681 { 3682 struct blob_attr *tb[__OCI_HOOK_MAX]; 3683 struct blob_attr *cur; 3684 int rem, ret = 0; 3685 int idx = 0; 3686 3687 blobmsg_for_each_attr(cur, msg, rem) 3688 ++idx; 3689 3690 if (!idx) 3691 return 0; 3692 3693 *hooklist = calloc(idx + 1, sizeof(struct hook_execvpe *)); 3694 idx = 0; 3695 3696 if (!(*hooklist)) 3697 return ENOMEM; 3698 3699 blobmsg_for_each_attr(cur, msg, rem) { 3700 blobmsg_parse(oci_hook_policy, __OCI_HOOK_MAX, tb, blobmsg_data(cur), blobmsg_len(cur)); 3701 3702 if (!tb[OCI_HOOK_PATH]) { 3703 ret = EINVAL; 3704 goto errout; 3705 } 3706 3707 (*hooklist)[idx] = calloc(1, sizeof(struct hook_execvpe)); 3708 if (tb[OCI_HOOK_ARGS]) { 3709 ret = parseOCIenvarray(tb[OCI_HOOK_ARGS], &((*hooklist)[idx]->argv)); 3710 if (ret) 3711 goto errout; 3712 } else { 3713 (*hooklist)[idx]->argv = calloc(2, sizeof(char *)); 3714 ((*hooklist)[idx]->argv)[0] = strdup(blobmsg_get_string(tb[OCI_HOOK_PATH])); 3715 ((*hooklist)[idx]->argv)[1] = NULL; 3716 }; 3717 3718 3719 if (tb[OCI_HOOK_ENV]) { 3720 ret = parseOCIenvarray(tb[OCI_HOOK_ENV], &((*hooklist)[idx]->envp)); 3721 if (ret) 3722 goto errout; 3723 } 3724 3725 if (tb[OCI_HOOK_TIMEOUT]) 3726 (*hooklist)[idx]->timeout = blobmsg_get_u32(tb[OCI_HOOK_TIMEOUT]); 3727 3728 (*hooklist)[idx]->file = strdup(blobmsg_get_string(tb[OCI_HOOK_PATH])); 3729 3730 ++idx; 3731 } 3732 3733 (*hooklist)[idx] = NULL; 3734 3735 DEBUG("added %d hooks\n", idx); 3736 3737 return 0; 3738 3739 errout: 3740 free_hooklist(*hooklist); 3741 *hooklist = NULL; 3742 3743 return ret; 3744 }; 3745 3746 3747 enum { 3748 OCI_HOOKS_PRESTART, 3749 OCI_HOOKS_CREATERUNTIME, 3750 OCI_HOOKS_CREATECONTAINER, 3751 OCI_HOOKS_STARTCONTAINER, 3752 OCI_HOOKS_POSTSTART, 3753 OCI_HOOKS_POSTSTOP, 3754 __OCI_HOOKS_MAX, 3755 }; 3756 3757 static const struct blobmsg_policy oci_hooks_policy[] = { 3758 [OCI_HOOKS_PRESTART] = { "prestart", BLOBMSG_TYPE_ARRAY }, 3759 [OCI_HOOKS_CREATERUNTIME] = { "createRuntime", BLOBMSG_TYPE_ARRAY }, 3760 [OCI_HOOKS_CREATECONTAINER] = { "createContainer", BLOBMSG_TYPE_ARRAY }, 3761 [OCI_HOOKS_STARTCONTAINER] = { "startContainer", BLOBMSG_TYPE_ARRAY }, 3762 [OCI_HOOKS_POSTSTART] = { "poststart", BLOBMSG_TYPE_ARRAY }, 3763 [OCI_HOOKS_POSTSTOP] = { "poststop", BLOBMSG_TYPE_ARRAY }, 3764 }; 3765 3766 static int parseOCIhooks(struct blob_attr *msg) 3767 { 3768 struct blob_attr *tb[__OCI_HOOKS_MAX]; 3769 int ret; 3770 3771 blobmsg_parse(oci_hooks_policy, __OCI_HOOKS_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 3772 3773 if (tb[OCI_HOOKS_PRESTART]) { 3774 INFO("notice: deprecated prestart hook present; running it before createRuntime\n"); 3775 ret = parseOCIhook(&opts.hooks.prestart, tb[OCI_HOOKS_PRESTART]); 3776 if (ret) 3777 return ret; 3778 } 3779 3780 if (tb[OCI_HOOKS_CREATERUNTIME]) { 3781 ret = parseOCIhook(&opts.hooks.createRuntime, tb[OCI_HOOKS_CREATERUNTIME]); 3782 if (ret) 3783 goto out_prestart; 3784 } 3785 3786 if (tb[OCI_HOOKS_CREATECONTAINER]) { 3787 ret = parseOCIhook(&opts.hooks.createContainer, tb[OCI_HOOKS_CREATECONTAINER]); 3788 if (ret) 3789 goto out_createruntime; 3790 } 3791 3792 if (tb[OCI_HOOKS_STARTCONTAINER]) { 3793 ret = parseOCIhook(&opts.hooks.startContainer, tb[OCI_HOOKS_STARTCONTAINER]); 3794 if (ret) 3795 goto out_createcontainer; 3796 } 3797 3798 if (tb[OCI_HOOKS_POSTSTART]) { 3799 ret = parseOCIhook(&opts.hooks.poststart, tb[OCI_HOOKS_POSTSTART]); 3800 if (ret) 3801 goto out_startcontainer; 3802 } 3803 3804 if (tb[OCI_HOOKS_POSTSTOP]) { 3805 ret = parseOCIhook(&opts.hooks.poststop, tb[OCI_HOOKS_POSTSTOP]); 3806 if (ret) 3807 goto out_poststart; 3808 } 3809 3810 return 0; 3811 3812 out_poststart: 3813 free_hooklist(opts.hooks.poststart); 3814 out_startcontainer: 3815 free_hooklist(opts.hooks.startContainer); 3816 out_createcontainer: 3817 free_hooklist(opts.hooks.createContainer); 3818 out_createruntime: 3819 free_hooklist(opts.hooks.createRuntime); 3820 out_prestart: 3821 free_hooklist(opts.hooks.prestart); 3822 3823 return ret; 3824 }; 3825 3826 3827 enum { 3828 OCI_PROCESS_USER_UID, 3829 OCI_PROCESS_USER_GID, 3830 OCI_PROCESS_USER_UMASK, 3831 OCI_PROCESS_USER_ADDITIONALGIDS, 3832 __OCI_PROCESS_USER_MAX, 3833 }; 3834 3835 static const struct blobmsg_policy oci_process_user_policy[] = { 3836 [OCI_PROCESS_USER_UID] = { "uid", BLOBMSG_TYPE_INT32 }, 3837 [OCI_PROCESS_USER_GID] = { "gid", BLOBMSG_TYPE_INT32 }, 3838 [OCI_PROCESS_USER_UMASK] = { "umask", BLOBMSG_TYPE_INT32 }, 3839 [OCI_PROCESS_USER_ADDITIONALGIDS] = { "additionalGids", BLOBMSG_TYPE_ARRAY }, 3840 }; 3841 3842 static int parseOCIprocessuser(struct blob_attr *msg) { 3843 struct blob_attr *tb[__OCI_PROCESS_USER_MAX]; 3844 struct blob_attr *cur; 3845 int rem; 3846 int has_gid = 0; 3847 3848 blobmsg_parse(oci_process_user_policy, __OCI_PROCESS_USER_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 3849 3850 if (tb[OCI_PROCESS_USER_UID]) 3851 opts.pw_uid = blobmsg_get_u32(tb[OCI_PROCESS_USER_UID]); 3852 3853 if (tb[OCI_PROCESS_USER_GID]) { 3854 opts.pw_gid = blobmsg_get_u32(tb[OCI_PROCESS_USER_GID]); 3855 opts.gr_gid = blobmsg_get_u32(tb[OCI_PROCESS_USER_GID]); 3856 has_gid = 1; 3857 } 3858 3859 if (tb[OCI_PROCESS_USER_ADDITIONALGIDS]) { 3860 size_t gidcnt = 0; 3861 3862 blobmsg_for_each_attr(cur, tb[OCI_PROCESS_USER_ADDITIONALGIDS], rem) { 3863 ++gidcnt; 3864 if (has_gid && (blobmsg_get_u32(cur) == opts.gr_gid)) 3865 continue; 3866 } 3867 3868 if (gidcnt) { 3869 opts.additional_gids = calloc(gidcnt + has_gid, sizeof(gid_t)); 3870 gidcnt = 0; 3871 3872 /* always add primary GID to set of GIDs if set */ 3873 if (has_gid) 3874 opts.additional_gids[gidcnt++] = opts.gr_gid; 3875 3876 blobmsg_for_each_attr(cur, tb[OCI_PROCESS_USER_ADDITIONALGIDS], rem) { 3877 if (has_gid && (blobmsg_get_u32(cur) == opts.gr_gid)) 3878 continue; 3879 opts.additional_gids[gidcnt++] = blobmsg_get_u32(cur); 3880 } 3881 opts.num_additional_gids = gidcnt; 3882 } 3883 DEBUG("read %zu additional groups\n", gidcnt); 3884 } 3885 3886 if (tb[OCI_PROCESS_USER_UMASK]) { 3887 opts.umask = blobmsg_get_u32(tb[OCI_PROCESS_USER_UMASK]); 3888 opts.set_umask = true; 3889 } 3890 3891 return 0; 3892 } 3893 3894 enum { 3895 OCI_PROCESS_RLIMIT_TYPE, 3896 OCI_PROCESS_RLIMIT_SOFT, 3897 OCI_PROCESS_RLIMIT_HARD, 3898 __OCI_PROCESS_RLIMIT_MAX, 3899 }; 3900 3901 static const struct blobmsg_policy oci_process_rlimit_policy[] = { 3902 [OCI_PROCESS_RLIMIT_TYPE] = { "type", BLOBMSG_TYPE_STRING }, 3903 [OCI_PROCESS_RLIMIT_SOFT] = { "soft", BLOBMSG_CAST_INT64 }, 3904 [OCI_PROCESS_RLIMIT_HARD] = { "hard", BLOBMSG_CAST_INT64 }, 3905 }; 3906 3907 /* from manpage GETRLIMIT(2) */ 3908 static const char* const rlimit_names[RLIM_NLIMITS] = { 3909 [RLIMIT_AS] = "AS", 3910 [RLIMIT_CORE] = "CORE", 3911 [RLIMIT_CPU] = "CPU", 3912 [RLIMIT_DATA] = "DATA", 3913 [RLIMIT_FSIZE] = "FSIZE", 3914 [RLIMIT_LOCKS] = "LOCKS", 3915 [RLIMIT_MEMLOCK] = "MEMLOCK", 3916 [RLIMIT_MSGQUEUE] = "MSGQUEUE", 3917 [RLIMIT_NICE] = "NICE", 3918 [RLIMIT_NOFILE] = "NOFILE", 3919 [RLIMIT_NPROC] = "NPROC", 3920 [RLIMIT_RSS] = "RSS", 3921 [RLIMIT_RTPRIO] = "RTPRIO", 3922 [RLIMIT_RTTIME] = "RTTIME", 3923 [RLIMIT_SIGPENDING] = "SIGPENDING", 3924 [RLIMIT_STACK] = "STACK", 3925 }; 3926 3927 static int resolve_rlimit(char *type) { 3928 unsigned int rltype; 3929 3930 for (rltype = 0; rltype < RLIM_NLIMITS; ++rltype) 3931 if (rlimit_names[rltype] && 3932 !strncmp("RLIMIT_", type, 7) && 3933 !strcmp(rlimit_names[rltype], type + 7)) 3934 return rltype; 3935 3936 return -1; 3937 } 3938 3939 3940 static int parseOCIrlimit(struct blob_attr *msg) 3941 { 3942 struct blob_attr *tb[__OCI_PROCESS_RLIMIT_MAX]; 3943 int limtype = -1; 3944 struct rlimit *curlim; 3945 3946 blobmsg_parse(oci_process_rlimit_policy, __OCI_PROCESS_RLIMIT_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 3947 3948 if (!tb[OCI_PROCESS_RLIMIT_TYPE] || 3949 !tb[OCI_PROCESS_RLIMIT_SOFT] || 3950 !tb[OCI_PROCESS_RLIMIT_HARD]) 3951 return ENODATA; 3952 3953 limtype = resolve_rlimit(blobmsg_get_string(tb[OCI_PROCESS_RLIMIT_TYPE])); 3954 3955 if (limtype < 0) 3956 return EINVAL; 3957 3958 if (opts.rlimits[limtype]) 3959 return ENOTUNIQ; 3960 3961 curlim = malloc(sizeof(struct rlimit)); 3962 curlim->rlim_cur = blobmsg_cast_u64(tb[OCI_PROCESS_RLIMIT_SOFT]); 3963 curlim->rlim_max = blobmsg_cast_u64(tb[OCI_PROCESS_RLIMIT_HARD]); 3964 3965 opts.rlimits[limtype] = curlim; 3966 3967 return 0; 3968 }; 3969 3970 enum { 3971 OCI_PROCESS_APPARMORPROFILE, 3972 OCI_PROCESS_ARGS, 3973 OCI_PROCESS_CAPABILITIES, 3974 OCI_PROCESS_CONSOLESIZE, 3975 OCI_PROCESS_CWD, 3976 OCI_PROCESS_ENV, 3977 OCI_PROCESS_EXECCPUAFFINITY, 3978 OCI_PROCESS_IOPRIORITY, 3979 OCI_PROCESS_OOMSCOREADJ, 3980 OCI_PROCESS_NONEWPRIVILEGES, 3981 OCI_PROCESS_RLIMITS, 3982 OCI_PROCESS_SCHEDULER, 3983 OCI_PROCESS_SELINUXLABEL, 3984 OCI_PROCESS_TERMINAL, 3985 OCI_PROCESS_USER, 3986 __OCI_PROCESS_MAX, 3987 }; 3988 3989 static const struct blobmsg_policy oci_process_policy[] = { 3990 [OCI_PROCESS_APPARMORPROFILE] = { "apparmorProfile", BLOBMSG_TYPE_STRING }, 3991 [OCI_PROCESS_ARGS] = { "args", BLOBMSG_TYPE_ARRAY }, 3992 [OCI_PROCESS_CAPABILITIES] = { "capabilities", BLOBMSG_TYPE_TABLE }, 3993 [OCI_PROCESS_CONSOLESIZE] = { "consoleSize", BLOBMSG_TYPE_TABLE }, 3994 [OCI_PROCESS_CWD] = { "cwd", BLOBMSG_TYPE_STRING }, 3995 [OCI_PROCESS_ENV] = { "env", BLOBMSG_TYPE_ARRAY }, 3996 [OCI_PROCESS_EXECCPUAFFINITY] = { "execCPUAffinity", BLOBMSG_TYPE_TABLE }, 3997 [OCI_PROCESS_IOPRIORITY] = { "ioPriority", BLOBMSG_TYPE_TABLE }, 3998 [OCI_PROCESS_OOMSCOREADJ] = { "oomScoreAdj", BLOBMSG_TYPE_INT32 }, 3999 [OCI_PROCESS_NONEWPRIVILEGES] = { "noNewPrivileges", BLOBMSG_TYPE_BOOL }, 4000 [OCI_PROCESS_RLIMITS] = { "rlimits", BLOBMSG_TYPE_ARRAY }, 4001 [OCI_PROCESS_SCHEDULER] = { "scheduler", BLOBMSG_TYPE_TABLE }, 4002 [OCI_PROCESS_SELINUXLABEL] = { "selinuxLabel", BLOBMSG_TYPE_STRING }, 4003 [OCI_PROCESS_TERMINAL] = { "terminal", BLOBMSG_TYPE_BOOL }, 4004 [OCI_PROCESS_USER] = { "user", BLOBMSG_TYPE_TABLE }, 4005 }; 4006 4007 enum { 4008 OCI_PROCESS_CONSOLESIZE_HEIGHT, 4009 OCI_PROCESS_CONSOLESIZE_WIDTH, 4010 __OCI_PROCESS_CONSOLESIZE_MAX, 4011 }; 4012 4013 static const struct blobmsg_policy oci_process_consolesize_policy[] = { 4014 [OCI_PROCESS_CONSOLESIZE_HEIGHT] = { "height", BLOBMSG_TYPE_INT32 }, 4015 [OCI_PROCESS_CONSOLESIZE_WIDTH] = { "width", BLOBMSG_TYPE_INT32 }, 4016 }; 4017 4018 static int parseOCIprocessconsolesize(struct blob_attr *msg) 4019 { 4020 struct blob_attr *tb[__OCI_PROCESS_CONSOLESIZE_MAX]; 4021 uint32_t height, width; 4022 4023 blobmsg_parse(oci_process_consolesize_policy, __OCI_PROCESS_CONSOLESIZE_MAX, tb, 4024 blobmsg_data(msg), blobmsg_len(msg)); 4025 4026 if (!tb[OCI_PROCESS_CONSOLESIZE_HEIGHT] || !tb[OCI_PROCESS_CONSOLESIZE_WIDTH]) 4027 return ENODATA; 4028 4029 height = blobmsg_get_u32(tb[OCI_PROCESS_CONSOLESIZE_HEIGHT]); 4030 width = blobmsg_get_u32(tb[OCI_PROCESS_CONSOLESIZE_WIDTH]); 4031 if (!height || !width || height > USHRT_MAX || width > USHRT_MAX) { 4032 ERROR("consoleSize: %u x %u out of range\n", height, width); 4033 return EINVAL; 4034 } 4035 4036 opts.console_height = height; 4037 opts.console_width = width; 4038 4039 return 0; 4040 } 4041 4042 4043 static int parseOCIprocess(struct blob_attr *msg) 4044 { 4045 struct blob_attr *tb[__OCI_PROCESS_MAX], *cur; 4046 int rem, res; 4047 4048 blobmsg_parse(oci_process_policy, __OCI_PROCESS_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 4049 4050 if (tb[OCI_PROCESS_APPARMORPROFILE]) 4051 return jail_unsupported(tb[OCI_PROCESS_APPARMORPROFILE]); 4052 4053 if (tb[OCI_PROCESS_SELINUXLABEL]) 4054 return jail_unsupported(tb[OCI_PROCESS_SELINUXLABEL]); 4055 4056 if (!tb[OCI_PROCESS_ARGS]) 4057 return ENOENT; 4058 4059 res = parseOCIenvarray(tb[OCI_PROCESS_ARGS], &opts.jail_argv); 4060 if (res) 4061 return res; 4062 4063 if (tb[OCI_PROCESS_TERMINAL]) 4064 opts.console = blobmsg_get_bool(tb[OCI_PROCESS_TERMINAL]); 4065 4066 if (opts.console && tb[OCI_PROCESS_CONSOLESIZE]) { 4067 res = parseOCIprocessconsolesize(tb[OCI_PROCESS_CONSOLESIZE]); 4068 if (res) 4069 return res; 4070 } 4071 4072 if (tb[OCI_PROCESS_SCHEDULER]) { 4073 res = parseOCIprocessscheduler(tb[OCI_PROCESS_SCHEDULER]); 4074 if (res) 4075 return res; 4076 } 4077 4078 if (tb[OCI_PROCESS_IOPRIORITY]) { 4079 res = parseOCIprocessiopriority(tb[OCI_PROCESS_IOPRIORITY]); 4080 if (res) 4081 return res; 4082 } 4083 4084 if (tb[OCI_PROCESS_NONEWPRIVILEGES]) 4085 opts.no_new_privs = blobmsg_get_bool(tb[OCI_PROCESS_NONEWPRIVILEGES]); 4086 4087 if (tb[OCI_PROCESS_CWD]) 4088 opts.cwd = strdup(blobmsg_get_string(tb[OCI_PROCESS_CWD])); 4089 4090 if (tb[OCI_PROCESS_ENV]) { 4091 res = parseOCIenvarray(tb[OCI_PROCESS_ENV], &opts.envp); 4092 if (res) 4093 return res; 4094 } 4095 4096 if (opts.envfile && (res = append_envfile(&opts.envp, opts.envfile))) 4097 return res; 4098 4099 if (tb[OCI_PROCESS_USER] && (res = parseOCIprocessuser(tb[OCI_PROCESS_USER]))) 4100 return res; 4101 4102 if (tb[OCI_PROCESS_CAPABILITIES] && 4103 (res = parseOCIcapabilities(&opts.capset, tb[OCI_PROCESS_CAPABILITIES]))) 4104 return res; 4105 4106 if (tb[OCI_PROCESS_RLIMITS]) { 4107 blobmsg_for_each_attr(cur, tb[OCI_PROCESS_RLIMITS], rem) { 4108 res = parseOCIrlimit(cur); 4109 if (res) 4110 return res; 4111 } 4112 } 4113 4114 if (tb[OCI_PROCESS_OOMSCOREADJ]) { 4115 opts.oom_score_adj = blobmsg_get_u32(tb[OCI_PROCESS_OOMSCOREADJ]); 4116 opts.set_oom_score_adj = true; 4117 } 4118 4119 return 0; 4120 } 4121 4122 enum { 4123 OCI_LINUX_NAMESPACE_TYPE, 4124 OCI_LINUX_NAMESPACE_PATH, 4125 __OCI_LINUX_NAMESPACE_MAX, 4126 }; 4127 4128 static const struct blobmsg_policy oci_linux_namespace_policy[] = { 4129 [OCI_LINUX_NAMESPACE_TYPE] = { "type", BLOBMSG_TYPE_STRING }, 4130 [OCI_LINUX_NAMESPACE_PATH] = { "path", BLOBMSG_TYPE_STRING }, 4131 }; 4132 4133 /* the name -j accepts, and the /proc/<pid>/ns/ link it actually lives under */ 4134 static const struct { 4135 const char *name; 4136 const char *link; 4137 int nstype; 4138 } ns_types[] = { 4139 { "pid", "pid", CLONE_NEWPID }, 4140 { "net", "net", CLONE_NEWNET }, 4141 { "network", "net", CLONE_NEWNET }, 4142 { "mnt", "mnt", CLONE_NEWNS }, 4143 { "mount", "mnt", CLONE_NEWNS }, 4144 { "ipc", "ipc", CLONE_NEWIPC }, 4145 { "uts", "uts", CLONE_NEWUTS }, 4146 { "user", "user", CLONE_NEWUSER }, 4147 { "cgroup", "cgroup", CLONE_NEWCGROUP }, 4148 { "time", "time", CLONE_NEWTIME }, 4149 { NULL, NULL, 0 }, 4150 }; 4151 4152 static int resolve_nstype(const char *type) 4153 { 4154 int i; 4155 4156 for (i = 0; ns_types[i].name; i++) 4157 if (!strcmp(ns_types[i].name, type)) 4158 return ns_types[i].nstype; 4159 4160 return 0; 4161 } 4162 4163 static const char *nstype_link(int nstype) 4164 { 4165 int i; 4166 4167 for (i = 0; ns_types[i].name; i++) 4168 if (ns_types[i].nstype == nstype) 4169 return ns_types[i].link; 4170 4171 return NULL; 4172 } 4173 4174 /* linux.namespaces entries are unique by type */ 4175 static int oci_ns_seen; 4176 4177 static int parseOCIlinuxns(struct blob_attr *msg) 4178 { 4179 struct blob_attr *tb[__OCI_LINUX_NAMESPACE_MAX]; 4180 int nstype; 4181 int *setns; 4182 int fd; 4183 4184 blobmsg_parse(oci_linux_namespace_policy, __OCI_LINUX_NAMESPACE_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 4185 4186 if (!tb[OCI_LINUX_NAMESPACE_TYPE]) 4187 return EINVAL; 4188 4189 nstype = resolve_nstype(blobmsg_get_string(tb[OCI_LINUX_NAMESPACE_TYPE])); 4190 if (!nstype) 4191 return EINVAL; 4192 4193 setns = get_namespace_fd(nstype); 4194 4195 if (!setns) 4196 return EFAULT; 4197 4198 if (oci_ns_seen & nstype) 4199 return ENOTUNIQ; 4200 4201 oci_ns_seen |= nstype; 4202 4203 if (tb[OCI_LINUX_NAMESPACE_PATH]) { 4204 if (*setns != -1) 4205 return ENOTUNIQ; 4206 4207 DEBUG("opening existing %s namespace from path %s\n", 4208 blobmsg_get_string(tb[OCI_LINUX_NAMESPACE_TYPE]), 4209 blobmsg_get_string(tb[OCI_LINUX_NAMESPACE_PATH])); 4210 4211 fd = open(blobmsg_get_string(tb[OCI_LINUX_NAMESPACE_PATH]), O_RDONLY); 4212 if (fd < 0) 4213 return errno?:ESTALE; 4214 4215 if (ioctl(fd, NS_GET_NSTYPE) != nstype) { 4216 close(fd); 4217 return EINVAL; 4218 } 4219 4220 DEBUG("opened existing %s namespace got filehandler %u\n", 4221 blobmsg_get_string(tb[OCI_LINUX_NAMESPACE_TYPE]), 4222 fd); 4223 4224 *setns = fd; 4225 } else { 4226 opts.namespace |= nstype; 4227 } 4228 4229 return 0; 4230 } 4231 4232 /* 4233 * join namespace of existing PID 4234 * The string argument is the reference PID followed by ':' and a 4235 * ',' separated list of namespaces to to join. 4236 */ 4237 /* the pid -j resolved the user namespace from, for uid_map_root_read() */ 4238 static pid_t setns_user_pid = -1; 4239 4240 static int jail_join_ns(char *arg) 4241 { 4242 pid_t pid; 4243 int fd; 4244 int nstype; 4245 char *tmp, *etmp, *nspath; 4246 int *setns; 4247 4248 tmp = strchr(arg, ':'); 4249 if (!tmp) 4250 return EINVAL; 4251 4252 *tmp = '\0'; 4253 pid = atoi(arg); 4254 4255 do { 4256 ++tmp; 4257 etmp = strchr(tmp, ','); 4258 if (etmp) 4259 *etmp = '\0'; 4260 4261 nstype = resolve_nstype(tmp); 4262 if (!nstype) 4263 return EINVAL; 4264 4265 setns = get_namespace_fd(nstype); 4266 4267 if (!setns) 4268 return EFAULT; 4269 4270 if (*setns != -1) 4271 return ENOTUNIQ; 4272 4273 if (asprintf(&nspath, "/proc/%d/ns/%s", pid, nstype_link(nstype)) < 0) 4274 return ENOMEM; 4275 4276 fd = open(nspath, O_RDONLY); 4277 free(nspath); 4278 4279 if (fd < 0) 4280 return errno?:ESTALE; 4281 4282 *setns = fd; 4283 if (nstype == CLONE_NEWUSER) 4284 setns_user_pid = pid; 4285 4286 if (etmp) 4287 tmp = etmp; 4288 else 4289 tmp = NULL; 4290 } while (tmp); 4291 4292 return 0; 4293 } 4294 4295 /* 4296 * What uid 0 of the joined user namespace maps to on the host. Read from 4297 * here rather than from inside: uid_m_show() renders the outside column 4298 * through the reader's user namespace, so ours gives a host uid at any 4299 * nesting depth, and no process of ours has to enter a namespace the 4300 * caller controls. 4301 */ 4302 static bool uid_map_root_read(pid_t pid, uid_t *host_uid) 4303 { 4304 uint32_t inside, outside, count; 4305 bool found = false; 4306 char path[32]; 4307 FILE *f; 4308 4309 snprintf(path, sizeof(path), "/proc/%d/uid_map", pid); 4310 f = fopen(path, "re"); 4311 if (!f) 4312 return false; 4313 4314 while (fscanf(f, "%u %u %u", &inside, &outside, &count) == 3) { 4315 if (inside || count < 1 || outside >= (uint32_t)-1) 4316 continue; 4317 4318 *host_uid = outside; 4319 found = true; 4320 break; 4321 } 4322 4323 fclose(f); 4324 4325 return found; 4326 } 4327 4328 /* the pid is not pinned by the namespace fd we hold, so it can be recycled */ 4329 static bool userns_pid_valid(pid_t pid) 4330 { 4331 struct stat nsst, pidst; 4332 char path[32]; 4333 4334 if (fstat(opts.setns.user, &nsst)) 4335 return false; 4336 4337 snprintf(path, sizeof(path), "/proc/%d/ns/user", pid); 4338 if (stat(path, &pidst)) 4339 return false; 4340 4341 return nsst.st_dev == pidst.st_dev && nsst.st_ino == pidst.st_ino; 4342 } 4343 4344 static bool userns_root_map(void) 4345 { 4346 uid_t host_uid; 4347 4348 if (setns_user_pid < 0) { 4349 WARNING("the joined user namespace was given as a path, so its " 4350 "root uid cannot be determined; keeping the ownership " 4351 "the jail would have had without it\n"); 4352 return false; 4353 } 4354 4355 if (!uid_map_root_read(setns_user_pid, &host_uid)) { 4356 ERROR("cannot read the uid map of the joined user namespace\n"); 4357 return false; 4358 } 4359 4360 if (!userns_pid_valid(setns_user_pid)) { 4361 ERROR("pid %d no longer names the joined user namespace\n", 4362 setns_user_pid); 4363 return false; 4364 } 4365 4366 opts.root_map_uid = host_uid; 4367 DEBUG("root of the joined user namespace is uid %d\n", host_uid); 4368 4369 return true; 4370 } 4371 4372 static void get_jail_root_user(bool is_gidmap, uint32_t container_id, uint32_t host_id, uint32_t size) 4373 { 4374 if (container_id == 0 && size >= 1) 4375 if (!is_gidmap) 4376 opts.root_map_uid = host_id; 4377 } 4378 4379 enum { 4380 OCI_LINUX_UIDGIDMAP_CONTAINERID, 4381 OCI_LINUX_UIDGIDMAP_HOSTID, 4382 OCI_LINUX_UIDGIDMAP_SIZE, 4383 __OCI_LINUX_UIDGIDMAP_MAX, 4384 }; 4385 4386 static const struct blobmsg_policy oci_linux_uidgidmap_policy[] = { 4387 [OCI_LINUX_UIDGIDMAP_CONTAINERID] = { "containerID", BLOBMSG_TYPE_INT32 }, 4388 [OCI_LINUX_UIDGIDMAP_HOSTID] = { "hostID", BLOBMSG_TYPE_INT32 }, 4389 [OCI_LINUX_UIDGIDMAP_SIZE] = { "size", BLOBMSG_TYPE_INT32 }, 4390 }; 4391 4392 static int parseOCIuidgidmappings(struct blob_attr *msg, bool is_gidmap) 4393 { 4394 struct blob_attr *tb[__OCI_LINUX_UIDGIDMAP_MAX]; 4395 struct blob_attr *cur; 4396 int rem; 4397 char *map; 4398 size_t len, pos, totallen = 0; 4399 4400 blobmsg_for_each_attr(cur, msg, rem) { 4401 blobmsg_parse(oci_linux_uidgidmap_policy, __OCI_LINUX_UIDGIDMAP_MAX, tb, blobmsg_data(cur), blobmsg_len(cur)); 4402 4403 if (!tb[OCI_LINUX_UIDGIDMAP_CONTAINERID] || 4404 !tb[OCI_LINUX_UIDGIDMAP_HOSTID] || 4405 !tb[OCI_LINUX_UIDGIDMAP_SIZE]) 4406 return EINVAL; 4407 4408 /* count length */ 4409 totallen += snprintf(NULL, 0, "%d %d %d\n", 4410 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_CONTAINERID]), 4411 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_HOSTID]) + opts.idmap_offset, 4412 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_SIZE])); 4413 } 4414 4415 /* allocate combined mapping string */ 4416 map = malloc(totallen + 1); 4417 if (!map) 4418 return ENOMEM; 4419 4420 pos = 0; 4421 blobmsg_for_each_attr(cur, msg, rem) { 4422 blobmsg_parse(oci_linux_uidgidmap_policy, __OCI_LINUX_UIDGIDMAP_MAX, tb, blobmsg_data(cur), blobmsg_len(cur)); 4423 4424 get_jail_root_user(is_gidmap, blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_CONTAINERID]), 4425 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_HOSTID]) + opts.idmap_offset, 4426 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_SIZE])); 4427 4428 /* write mapping line into pre-allocated string */ 4429 len = snprintf(&map[pos], totallen + 1, "%d %d %d\n", 4430 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_CONTAINERID]), 4431 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_HOSTID]) + opts.idmap_offset, 4432 blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_SIZE])); 4433 pos += len; 4434 totallen -= len; 4435 } 4436 4437 assert(totallen == 0); 4438 4439 if (is_gidmap) { 4440 opts.gidmap = map; 4441 free(opts.gidmappings); 4442 opts.gidmappings = blob_memdup(msg); 4443 if (!opts.gidmappings) 4444 return ENOMEM; 4445 } else { 4446 opts.uidmap = map; 4447 free(opts.uidmappings); 4448 opts.uidmappings = blob_memdup(msg); 4449 if (!opts.uidmappings) 4450 return ENOMEM; 4451 } 4452 4453 return 0; 4454 } 4455 4456 static unsigned int host_id_for(struct blob_attr *mappings, unsigned int cid) 4457 { 4458 struct blob_attr *tb[__OCI_LINUX_UIDGIDMAP_MAX]; 4459 struct blob_attr *cur; 4460 unsigned int base, host, size; 4461 int rem; 4462 4463 if (!mappings) 4464 return (unsigned int)-1; 4465 4466 blobmsg_for_each_attr(cur, mappings, rem) { 4467 blobmsg_parse(oci_linux_uidgidmap_policy, __OCI_LINUX_UIDGIDMAP_MAX, tb, 4468 blobmsg_data(cur), blobmsg_len(cur)); 4469 if (!tb[OCI_LINUX_UIDGIDMAP_CONTAINERID] || 4470 !tb[OCI_LINUX_UIDGIDMAP_HOSTID] || 4471 !tb[OCI_LINUX_UIDGIDMAP_SIZE]) 4472 continue; 4473 base = blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_CONTAINERID]); 4474 host = blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_HOSTID]); 4475 size = blobmsg_get_u32(tb[OCI_LINUX_UIDGIDMAP_SIZE]); 4476 if (cid >= base && cid < base + size) 4477 return host + (cid - base) + opts.idmap_offset; 4478 } 4479 4480 return (unsigned int)-1; 4481 } 4482 4483 static void jail_chown_writable_surfaces(void) 4484 { 4485 unsigned int vuid, vgid, ouid, ogid; 4486 4487 vuid = host_id_for(opts.uidmappings, opts.pw_uid); 4488 vgid = host_id_for(opts.gidmappings, opts.pw_gid); 4489 if (vuid != (unsigned int)-1 && vgid != (unsigned int)-1) 4490 jail_chown_fresh_volumes(vuid, vgid); 4491 4492 if (!opts.overlaydir) 4493 return; 4494 4495 ouid = host_id_for(opts.uidmappings, 0); 4496 ogid = host_id_for(opts.gidmappings, 0); 4497 if (ouid != (unsigned int)-1 && ogid != (unsigned int)-1 && 4498 jail_dir_is_fresh(opts.overlaydir) && 4499 chown(opts.overlaydir, ouid, ogid)) 4500 ERROR("chown(fresh overlay %s -> %u:%u): %m\n", opts.overlaydir, ouid, ogid); 4501 } 4502 4503 enum { 4504 OCI_DEVICES_TYPE, 4505 OCI_DEVICES_PATH, 4506 OCI_DEVICES_MAJOR, 4507 OCI_DEVICES_MINOR, 4508 OCI_DEVICES_FILEMODE, 4509 OCI_DEVICES_UID, 4510 OCI_DEVICES_GID, 4511 __OCI_DEVICES_MAX, 4512 }; 4513 4514 static const struct blobmsg_policy oci_devices_policy[] = { 4515 [OCI_DEVICES_TYPE] = { "type", BLOBMSG_TYPE_STRING }, 4516 [OCI_DEVICES_PATH] = { "path", BLOBMSG_TYPE_STRING }, 4517 [OCI_DEVICES_MAJOR] = { "major", BLOBMSG_TYPE_INT32 }, 4518 [OCI_DEVICES_MINOR] = { "minor", BLOBMSG_TYPE_INT32 }, 4519 [OCI_DEVICES_FILEMODE] = { "fileMode", BLOBMSG_TYPE_INT32 }, 4520 [OCI_DEVICES_UID] = { "uid", BLOBMSG_TYPE_INT32 }, 4521 [OCI_DEVICES_GID] = { "gid", BLOBMSG_TYPE_INT32 }, 4522 }; 4523 4524 static mode_t resolve_devtype(char *tstr) 4525 { 4526 if (!strcmp("c", tstr) || 4527 !strcmp("u", tstr)) 4528 return S_IFCHR; 4529 else if (!strcmp("b", tstr)) 4530 return S_IFBLK; 4531 else if (!strcmp("p", tstr)) 4532 return S_IFIFO; 4533 else 4534 return 0; 4535 } 4536 4537 static int parseOCIdevices(struct blob_attr *msg) 4538 { 4539 struct blob_attr *tb[__OCI_DEVICES_MAX]; 4540 struct blob_attr *cur; 4541 int rem; 4542 size_t cnt = 0; 4543 struct mknod_args *tmp; 4544 4545 blobmsg_for_each_attr(cur, msg, rem) 4546 ++cnt; 4547 4548 opts.devices = calloc(cnt + 1, sizeof(struct mknod_args *)); 4549 4550 cnt = 0; 4551 blobmsg_for_each_attr(cur, msg, rem) { 4552 blobmsg_parse(oci_devices_policy, __OCI_DEVICES_MAX, tb, blobmsg_data(cur), blobmsg_len(cur)); 4553 if (!tb[OCI_DEVICES_TYPE] || 4554 !tb[OCI_DEVICES_PATH]) 4555 return ENODATA; 4556 4557 tmp = calloc(1, sizeof(struct mknod_args)); 4558 if (!tmp) 4559 return ENOMEM; 4560 4561 tmp->mode = resolve_devtype(blobmsg_get_string(tb[OCI_DEVICES_TYPE])); 4562 if (!tmp->mode) { 4563 free(tmp); 4564 return EINVAL; 4565 } 4566 4567 if (tmp->mode != S_IFIFO) { 4568 if (!tb[OCI_DEVICES_MAJOR] || !tb[OCI_DEVICES_MINOR]) { 4569 free(tmp); 4570 return ENODATA; 4571 } 4572 4573 tmp->dev = makedev(blobmsg_get_u32(tb[OCI_DEVICES_MAJOR]), 4574 blobmsg_get_u32(tb[OCI_DEVICES_MINOR])); 4575 } 4576 4577 if (tb[OCI_DEVICES_FILEMODE]) { 4578 if (~(S_IRWXU|S_IRWXG|S_IRWXO) & blobmsg_get_u32(tb[OCI_DEVICES_FILEMODE])) { 4579 free(tmp); 4580 return EINVAL; 4581 } 4582 4583 tmp->mode |= blobmsg_get_u32(tb[OCI_DEVICES_FILEMODE]); 4584 } else { 4585 tmp->mode |= (S_IRUSR|S_IWUSR); /* 0600 */ 4586 } 4587 4588 tmp->path = strdup(blobmsg_get_string(tb[OCI_DEVICES_PATH])); 4589 4590 if (tb[OCI_DEVICES_UID]) 4591 tmp->uid = blobmsg_get_u32(tb[OCI_DEVICES_UID]); 4592 else 4593 tmp->uid = -1; 4594 4595 if (tb[OCI_DEVICES_GID]) 4596 tmp->gid = blobmsg_get_u32(tb[OCI_DEVICES_GID]); 4597 else 4598 tmp->gid = -1; 4599 4600 DEBUG("read device %s (%s)\n", blobmsg_get_string(tb[OCI_DEVICES_PATH]), blobmsg_get_string(tb[OCI_DEVICES_TYPE])); 4601 opts.devices[cnt++] = tmp; 4602 } 4603 4604 opts.devices[cnt] = NULL; 4605 4606 return 0; 4607 } 4608 4609 static int parseOCIsysctl(struct blob_attr *msg) 4610 { 4611 struct blob_attr *cur; 4612 int rem; 4613 char *tmp, *tc; 4614 size_t cnt = 0; 4615 4616 blobmsg_for_each_attr(cur, msg, rem) { 4617 if (!blobmsg_name(cur) || !blobmsg_get_string(cur)) 4618 return EINVAL; 4619 4620 ++cnt; 4621 } 4622 4623 if (!cnt) 4624 return 0; 4625 4626 opts.sysctl = calloc(cnt + 1, sizeof(struct sysctl_val *)); 4627 if (!opts.sysctl) 4628 return ENOMEM; 4629 4630 cnt = 0; 4631 blobmsg_for_each_attr(cur, msg, rem) { 4632 opts.sysctl[cnt] = malloc(sizeof(struct sysctl_val)); 4633 if (!opts.sysctl[cnt]) 4634 return ENOMEM; 4635 4636 /* replace '.' with '/' in entry name */ 4637 tc = tmp = strdup(blobmsg_name(cur)); 4638 while ((tc = strchr(tc, '.'))) 4639 *tc = '/'; 4640 4641 opts.sysctl[cnt]->value = strdup(blobmsg_get_string(cur)); 4642 opts.sysctl[cnt]->entry = tmp; 4643 4644 ++cnt; 4645 } 4646 4647 opts.sysctl[cnt] = NULL; 4648 4649 return 0; 4650 } 4651 4652 4653 enum { 4654 OCI_LINUX_CGROUPSPATH, 4655 OCI_LINUX_RESOURCES, 4656 OCI_LINUX_SECCOMP, 4657 OCI_LINUX_SYSCTL, 4658 OCI_LINUX_NAMESPACES, 4659 OCI_LINUX_DEVICES, 4660 OCI_LINUX_UIDMAPPINGS, 4661 OCI_LINUX_GIDMAPPINGS, 4662 OCI_LINUX_MASKEDPATHS, 4663 OCI_LINUX_READONLYPATHS, 4664 OCI_LINUX_ROOTFSPROPAGATION, 4665 OCI_LINUX_PERSONALITY, 4666 OCI_LINUX_TIMEOFFSETS, 4667 OCI_LINUX_NETDEVICES, 4668 OCI_LINUX_MEMORYPOLICY, 4669 OCI_LINUX_MOUNTLABEL, 4670 __OCI_LINUX_MAX, 4671 }; 4672 4673 static const struct blobmsg_policy oci_linux_policy[] = { 4674 [OCI_LINUX_CGROUPSPATH] = { "cgroupsPath", BLOBMSG_TYPE_STRING }, 4675 [OCI_LINUX_RESOURCES] = { "resources", BLOBMSG_TYPE_TABLE }, 4676 [OCI_LINUX_SECCOMP] = { "seccomp", BLOBMSG_TYPE_TABLE }, 4677 [OCI_LINUX_SYSCTL] = { "sysctl", BLOBMSG_TYPE_TABLE }, 4678 [OCI_LINUX_NAMESPACES] = { "namespaces", BLOBMSG_TYPE_ARRAY }, 4679 [OCI_LINUX_DEVICES] = { "devices", BLOBMSG_TYPE_ARRAY }, 4680 [OCI_LINUX_UIDMAPPINGS] = { "uidMappings", BLOBMSG_TYPE_ARRAY }, 4681 [OCI_LINUX_GIDMAPPINGS] = { "gidMappings", BLOBMSG_TYPE_ARRAY }, 4682 [OCI_LINUX_MASKEDPATHS] = { "maskedPaths", BLOBMSG_TYPE_ARRAY }, 4683 [OCI_LINUX_READONLYPATHS] = { "readonlyPaths", BLOBMSG_TYPE_ARRAY }, 4684 [OCI_LINUX_ROOTFSPROPAGATION] = { "rootfsPropagation", BLOBMSG_TYPE_STRING }, 4685 [OCI_LINUX_PERSONALITY] = { "personality", BLOBMSG_TYPE_TABLE }, 4686 [OCI_LINUX_TIMEOFFSETS] = { "timeOffsets", BLOBMSG_TYPE_TABLE }, 4687 [OCI_LINUX_NETDEVICES] = { "netDevices", BLOBMSG_TYPE_TABLE }, 4688 [OCI_LINUX_MEMORYPOLICY] = { "memoryPolicy", BLOBMSG_TYPE_TABLE }, 4689 [OCI_LINUX_MOUNTLABEL] = { "mountLabel", BLOBMSG_TYPE_STRING }, 4690 }; 4691 4692 static int append_deferred_path(char ***list, const char *path) 4693 { 4694 size_t n = 0; 4695 char **newlist; 4696 4697 if (*list) 4698 while ((*list)[n]) 4699 n++; 4700 4701 newlist = realloc(*list, (n + 2) * sizeof(char *)); 4702 if (!newlist) 4703 return ENOMEM; 4704 4705 newlist[n] = strdup(path); 4706 if (!newlist[n]) { 4707 *list = newlist; 4708 return ENOMEM; 4709 } 4710 newlist[n + 1] = NULL; 4711 *list = newlist; 4712 4713 return 0; 4714 } 4715 4716 enum { 4717 OCI_LINUX_PERSONALITY_DOMAIN, 4718 OCI_LINUX_PERSONALITY_FLAGS, 4719 __OCI_LINUX_PERSONALITY_MAX, 4720 }; 4721 4722 static const struct blobmsg_policy oci_linux_personality_policy[] = { 4723 [OCI_LINUX_PERSONALITY_DOMAIN] = { "domain", BLOBMSG_TYPE_STRING }, 4724 [OCI_LINUX_PERSONALITY_FLAGS] = { "flags", BLOBMSG_TYPE_ARRAY }, 4725 }; 4726 4727 static int parseOCIlinuxpersonality(struct blob_attr *msg) 4728 { 4729 struct blob_attr *tb[__OCI_LINUX_PERSONALITY_MAX]; 4730 char field[sizeof(jail_reason_owned)]; 4731 unsigned long requested, current; 4732 const char *domain; 4733 4734 blobmsg_parse(oci_linux_personality_policy, __OCI_LINUX_PERSONALITY_MAX, tb, 4735 blobmsg_data(msg), blobmsg_len(msg)); 4736 4737 if (tb[OCI_LINUX_PERSONALITY_FLAGS] && 4738 blobmsg_len(tb[OCI_LINUX_PERSONALITY_FLAGS])) 4739 return jail_unsupported(tb[OCI_LINUX_PERSONALITY_FLAGS]); 4740 4741 if (!tb[OCI_LINUX_PERSONALITY_DOMAIN]) 4742 return ENODATA; 4743 4744 domain = blobmsg_get_string(tb[OCI_LINUX_PERSONALITY_DOMAIN]); 4745 if (!strcmp(domain, "LINUX")) 4746 requested = PER_LINUX; 4747 else if (!strcmp(domain, "LINUX32")) 4748 requested = PER_LINUX32; 4749 else 4750 return EINVAL; 4751 4752 current = personality(0xFFFFFFFF) & PER_MASK; 4753 if (requested != current) { 4754 ERROR("linux.personality '%s' differs from current; cross-personality execution is not supported\n", 4755 domain); 4756 jail_reason_own(oci_field_name(msg, field, sizeof(field)), 4757 ENOTSUP); 4758 return ENOTSUP; 4759 } 4760 4761 return 0; 4762 } 4763 4764 static int parseOCIrootfspropagation(const char *mode) 4765 { 4766 if (!*mode) 4767 return 0; 4768 4769 if (!jail_propagation_flags_add(mode, &opts.rootfs_propagation)) { 4770 ERROR("unknown linux.rootfsPropagation %s\n", mode); 4771 return EINVAL; 4772 } 4773 4774 return 0; 4775 } 4776 4777 static int parseOCIlinux(struct blob_attr *msg) 4778 { 4779 struct blob_attr *tb[__OCI_LINUX_MAX]; 4780 struct blob_attr *cur; 4781 int rem; 4782 int res = 0; 4783 char *cgpath; 4784 char cgfullpath[256] = "/sys/fs/cgroup"; 4785 char cgleaf[200]; 4786 char *cgsep; 4787 4788 blobmsg_parse(oci_linux_policy, __OCI_LINUX_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); 4789 4790 if (tb[OCI_LINUX_ROOTFSPROPAGATION]) { 4791 res = parseOCIrootfspropagation(blobmsg_get_string(tb[OCI_LINUX_ROOTFSPROPAGATION])); 4792 if (res) 4793 return res; 4794 } 4795 4796 if (tb[OCI_LINUX_PERSONALITY]) { 4797 res = parseOCIlinuxpersonality(tb[OCI_LINUX_PERSONALITY]); 4798 if (res) 4799 return res; 4800 } 4801 4802 if (tb[OCI_LINUX_TIMEOFFSETS]) { 4803 res = parseOCIlinuxtimeoffsets(tb[OCI_LINUX_TIMEOFFSETS]); 4804 if (res) 4805 return res; 4806 } 4807 4808 if (tb[OCI_LINUX_NETDEVICES]) 4809 opts.netdevices = blob_memdup(tb[OCI_LINUX_NETDEVICES]); 4810 4811 if (tb[OCI_LINUX_MEMORYPOLICY]) 4812 return jail_unsupported(tb[OCI_LINUX_MEMORYPOLICY]); 4813 4814 if (tb[OCI_LINUX_MOUNTLABEL]) 4815 return jail_unsupported(tb[OCI_LINUX_MOUNTLABEL]); 4816 4817 if (tb[OCI_LINUX_NAMESPACES]) { 4818 blobmsg_for_each_attr(cur, tb[OCI_LINUX_NAMESPACES], rem) { 4819 res = parseOCIlinuxns(cur); 4820 if (res) 4821 return res; 4822 } 4823 } 4824 4825 if (tb[OCI_LINUX_UIDMAPPINGS]) { 4826 res = parseOCIuidgidmappings(tb[OCI_LINUX_UIDMAPPINGS], 0); 4827 if (res) 4828 return res; 4829 } 4830 4831 if (tb[OCI_LINUX_GIDMAPPINGS]) { 4832 res = parseOCIuidgidmappings(tb[OCI_LINUX_GIDMAPPINGS], 1); 4833 if (res) 4834 return res; 4835 } 4836 4837 { 4838 bool defer_userns = userns_deferred(); 4839 4840 if (tb[OCI_LINUX_READONLYPATHS]) { 4841 blobmsg_for_each_attr(cur, tb[OCI_LINUX_READONLYPATHS], rem) { 4842 if (defer_userns) { 4843 res = append_deferred_path(&opts.oci_deferred_readonly, blobmsg_get_string(cur)); 4844 if (res) 4845 return res; 4846 continue; 4847 } 4848 res = add_mount(NULL, blobmsg_get_string(cur), NULL, MS_BIND | MS_REC | MS_RDONLY, 0, NULL, 0); 4849 if (res) 4850 return res; 4851 } 4852 } 4853 4854 if (tb[OCI_LINUX_MASKEDPATHS]) { 4855 blobmsg_for_each_attr(cur, tb[OCI_LINUX_MASKEDPATHS], rem) { 4856 if (defer_userns) { 4857 res = append_deferred_path(&opts.oci_deferred_masked, blobmsg_get_string(cur)); 4858 if (res) 4859 return res; 4860 continue; 4861 } 4862 res = add_mount((void *)(-1), blobmsg_get_string(cur), NULL, 0, 0, NULL, 0); 4863 if (res) 4864 return res; 4865 } 4866 } 4867 } 4868 4869 if (tb[OCI_LINUX_SYSCTL]) { 4870 res = parseOCIsysctl(tb[OCI_LINUX_SYSCTL]); 4871 if (res) 4872 return res; 4873 } 4874 4875 if (tb[OCI_LINUX_SECCOMP]) { 4876 if (build_oci_seccomp(tb[OCI_LINUX_SECCOMP])) 4877 return EINVAL; 4878 } 4879 4880 if (tb[OCI_LINUX_DEVICES]) { 4881 res = parseOCIdevices(tb[OCI_LINUX_DEVICES]); 4882 if (res) 4883 return res; 4884 } 4885 4886 if (tb[OCI_LINUX_CGROUPSPATH]) { 4887 cgpath = blobmsg_get_string(tb[OCI_LINUX_CGROUPSPATH]); 4888 if (opts.systemd_cgroup) { 4889 char *orig = strdupa(cgpath); 4890 char *slice = cgpath; 4891 char *prefix = strchr(slice, ':'); 4892 char *id; 4893 4894 if (!prefix || prefix == slice) { 4895 ERROR("--systemd-cgroup: cgroupsPath %s is not slice:prefix:name\n", orig); 4896 return EINVAL; 4897 } 4898 *prefix++ = '\0'; 4899 id = strchr(prefix, ':'); 4900 if (!id || id == prefix || !id[1]) { 4901 ERROR("--systemd-cgroup: cgroupsPath %s is not slice:prefix:name\n", orig); 4902 return EINVAL; 4903 } 4904 *id++ = '\0'; 4905 4906 if (strlen(slice) + strlen(prefix) + strlen(id) + 9 4907 >= (sizeof(cgfullpath) - strlen(cgfullpath))) 4908 return E2BIG; 4909 4910 strcat(cgfullpath, "/"); 4911 strcat(cgfullpath, slice); 4912 strcat(cgfullpath, "/"); 4913 strcat(cgfullpath, prefix); 4914 strcat(cgfullpath, "-"); 4915 strcat(cgfullpath, id); 4916 strcat(cgfullpath, ".scope"); 4917 } else if (cgpath[0] == '/') { 4918 if (strlen(cgpath) + 1 >= (sizeof(cgfullpath) - strlen(cgfullpath))) 4919 return E2BIG; 4920 4921 strcat(cgfullpath, cgpath); 4922 } else { 4923 strcat(cgfullpath, "/containers/"); 4924 if (strlen(opts.name) + strlen(cgpath) + 2 >= (sizeof(cgfullpath) - strlen(cgfullpath))) 4925 return E2BIG; 4926 4927 strcat(cgfullpath, opts.name); /* should be container name rather than jail name */ 4928 strcat(cgfullpath, "/"); 4929 strcat(cgfullpath, cgpath); 4930 } 4931 } else { 4932 cgsep = strchr(opts.name, '.'); 4933 if (cgsep) 4934 snprintf(cgleaf, sizeof(cgleaf), "/containers/%.*s/%s.%d", 4935 (int)(cgsep - opts.name), opts.name, cgsep + 1, (int)getpid()); 4936 else 4937 snprintf(cgleaf, sizeof(cgleaf), "/containers/%s/%s.%d", 4938 opts.name, opts.name, (int)getpid()); 4939 4940 if (strlen(cgleaf) >= sizeof(cgfullpath) - strlen(cgfullpath)) 4941 return E2BIG; 4942 4943 strcat(cgfullpath, cgleaf); 4944 } 4945 4946 cgroups_init(cgfullpath); 4947 4948 if (tb[OCI_LINUX_RESOURCES]) { 4949 res = parseOCIlinuxcgroups(tb[OCI_LINUX_RESOURCES], false); 4950 if (res) 4951 return res; 4952 } 4953 4954 return 0; 4955 } 4956 4957 enum { 4958 OCI_VERSION, 4959 OCI_HOSTNAME, 4960 OCI_DOMAINNAME, 4961 OCI_PROCESS, 4962 OCI_ROOT, 4963 OCI_MOUNTS, 4964 OCI_HOOKS, 4965 OCI_LINUX, 4966 OCI_ANNOTATIONS, 4967 __OCI_MAX, 4968 }; 4969 4970 static const struct blobmsg_policy oci_policy[] = { 4971 [OCI_VERSION] = { "ociVersion", BLOBMSG_TYPE_STRING }, 4972 [OCI_HOSTNAME] = { "hostname", BLOBMSG_TYPE_STRING }, 4973 [OCI_DOMAINNAME] = { "domainname", BLOBMSG_TYPE_STRING }, 4974 [OCI_PROCESS] = { "process", BLOBMSG_TYPE_TABLE }, 4975 [OCI_ROOT] = { "root", BLOBMSG_TYPE_TABLE }, 4976 [OCI_MOUNTS] = { "mounts", BLOBMSG_TYPE_ARRAY }, 4977 [OCI_HOOKS] = { "hooks", BLOBMSG_TYPE_TABLE }, 4978 [OCI_LINUX] = { "linux", BLOBMSG_TYPE_TABLE }, 4979 [OCI_ANNOTATIONS] = { "annotations", BLOBMSG_TYPE_TABLE }, 4980 }; 4981 4982 static int64_t read_memtotal_bytes(void) 4983 { 4984 char buf[512]; 4985 char *p; 4986 char *end; 4987 int64_t kb; 4988 int fd; 4989 ssize_t n; 4990 4991 fd = open("/proc/meminfo", O_RDONLY | O_CLOEXEC); 4992 if (fd < 0) 4993 return -1; 4994 do { 4995 n = read(fd, buf, sizeof(buf) - 1); 4996 } while (n < 0 && errno == EINTR); 4997 close(fd); 4998 if (n <= 0) 4999 return -1; 5000 buf[n] = '\0'; 5001 p = strstr(buf, "MemTotal:"); 5002 if (!p) 5003 return -1; 5004 p += strlen("MemTotal:"); 5005 while (*p == ' ' || *p == '\t') 5006 p++; 5007 kb = strtoll(p, &end, 10); 5008 if (end == p || kb <= 0) 5009 return -1; 5010 return kb * 1024; 5011 } 5012 5013 static int parseOCI(const char *jsonfile) 5014 { 5015 const struct blob_attr *prev_root = jail_oci_root_get(); 5016 struct blob_attr *tb[__OCI_MAX]; 5017 struct blob_attr *cur; 5018 int rem; 5019 int arem; 5020 struct blob_attr *acur; 5021 int res; 5022 long pct; 5023 char *pct_end; 5024 int64_t memtotal; 5025 5026 blob_buf_init(&ocibuf, 0); 5027 5028 if (!blobmsg_add_json_from_file(&ocibuf, jsonfile)) { 5029 res=ENOENT; 5030 goto errout; 5031 } 5032 5033 jail_oci_root_restore(ocibuf.head); 5034 5035 blobmsg_parse(oci_policy, __OCI_MAX, tb, blob_data(ocibuf.head), blob_len(ocibuf.head)); 5036 5037 if (!tb[OCI_VERSION]) { 5038 res=ENOMSG; 5039 goto errout; 5040 } 5041 5042 const char *ociver = blobmsg_get_string(tb[OCI_VERSION]); 5043 if (strncmp("1.", ociver, 2) || ociver[2] < '1' || ociver[2] > '3') { 5044 ERROR("unsupported ociVersion %s\n", ociver); 5045 jail_reason_set("ociVersion", ENOTSUP); 5046 res=ENOTSUP; 5047 goto errout; 5048 } 5049 5050 if (tb[OCI_HOSTNAME]) 5051 opts.hostname = strdup(blobmsg_get_string(tb[OCI_HOSTNAME])); 5052 5053 if (tb[OCI_DOMAINNAME]) 5054 opts.domainname = strdup(blobmsg_get_string(tb[OCI_DOMAINNAME])); 5055 5056 if (!tb[OCI_PROCESS] && opts.immediately) { 5057 res=ENODATA; 5058 goto errout; 5059 } 5060 5061 if (tb[OCI_PROCESS] && (res = parseOCIprocess(tb[OCI_PROCESS]))) 5062 goto errout; 5063 5064 if (!tb[OCI_ROOT]) { 5065 res=ENODATA; 5066 goto errout; 5067 } 5068 if ((res = parseOCIroot(jsonfile, tb[OCI_ROOT]))) 5069 goto errout; 5070 5071 if (!tb[OCI_MOUNTS]) { 5072 res=ENODATA; 5073 goto errout; 5074 } 5075 5076 blobmsg_for_each_attr(cur, tb[OCI_MOUNTS], rem) 5077 if ((res = parseOCImount(cur))) 5078 goto errout; 5079 5080 if (tb[OCI_LINUX] && (res = parseOCIlinux(tb[OCI_LINUX]))) 5081 goto errout; 5082 5083 if (tb[OCI_HOOKS] && (res = parseOCIhooks(tb[OCI_HOOKS]))) 5084 goto errout; 5085 5086 if (tb[OCI_ANNOTATIONS]) { 5087 opts.annotations = blob_memdup(tb[OCI_ANNOTATIONS]); 5088 5089 blobmsg_for_each_attr(acur, tb[OCI_ANNOTATIONS], arem) { 5090 const char *name = blobmsg_name(acur); 5091 const char *val; 5092 5093 if (!name || blobmsg_type(acur) != BLOBMSG_TYPE_STRING) 5094 continue; 5095 5096 val = blobmsg_get_string(acur); 5097 5098 if (!strcmp(name, "org.openwrt.ujail.mdwe")) { 5099 while (val && *val) { 5100 size_t tlen; 5101 const char *comma = strchr(val, ','); 5102 5103 tlen = comma ? (size_t)(comma - val) : strlen(val); 5104 if (tlen == strlen("refuse_exec_gain") && 5105 !strncmp(val, "refuse_exec_gain", tlen)) 5106 opts.mdwe_flags |= PR_MDWE_REFUSE_EXEC_GAIN; 5107 else if (tlen == strlen("no_inherit") && 5108 !strncmp(val, "no_inherit", tlen)) 5109 opts.mdwe_flags |= PR_MDWE_NO_INHERIT; 5110 val = comma ? comma + 1 : NULL; 5111 } 5112 } else if (!strcmp(name, "org.openwrt.ujail.landlock.ro")) { 5113 res = landlock_config_add_paths(&opts.landlock, val, 5114 LANDLOCK_ACCESS_FS_READ_FILE | 5115 LANDLOCK_ACCESS_FS_READ_DIR); 5116 if (res) 5117 goto errout; 5118 } else if (!strcmp(name, "org.openwrt.ujail.landlock.rx")) { 5119 res = landlock_config_add_paths(&opts.landlock, val, 5120 LANDLOCK_ACCESS_FS_READ_FILE | 5121 LANDLOCK_ACCESS_FS_READ_DIR | 5122 LANDLOCK_ACCESS_FS_EXECUTE); 5123 if (res) 5124 goto errout; 5125 } else if (!strcmp(name, "org.openwrt.ujail.landlock.rw")) { 5126 res = landlock_config_add_paths(&opts.landlock, val, 5127 LANDLOCK_ACCESS_FS_READ_FILE | 5128 LANDLOCK_ACCESS_FS_READ_DIR | 5129 LANDLOCK_ACCESS_FS_WRITE_FILE | 5130 LANDLOCK_ACCESS_FS_TRUNCATE | 5131 LANDLOCK_ACCESS_FS_MAKE_REG | 5132 LANDLOCK_ACCESS_FS_MAKE_DIR | 5133 LANDLOCK_ACCESS_FS_REMOVE_FILE | 5134 LANDLOCK_ACCESS_FS_REMOVE_DIR); 5135 if (res) 5136 goto errout; 5137 } else if (!strcmp(name, "org.openwrt.procd.ubus")) { 5138 opts.private_ubus = !strcmp(val, "true") || !strcmp(val, "1"); 5139 } else if (!strcmp(name, "org.openwrt.procd.netifd")) { 5140 opts.private_netifd = !strcmp(val, "true") || !strcmp(val, "1"); 5141 if (opts.private_netifd) 5142 opts.private_ubus = true; 5143 } else if (!strcmp(name, "org.openwrt.cgroup.memory.pct")) { 5144 pct = strtol(val, &pct_end, 10); 5145 if (pct_end == val || pct < 1 || pct > 100) { 5146 ERROR("cgroup.memory.pct: invalid value '%s'\n", val); 5147 res = EINVAL; 5148 goto errout; 5149 } 5150 memtotal = read_memtotal_bytes(); 5151 if (memtotal < 0) { 5152 ERROR("cgroup.memory.pct: cannot read MemTotal\n"); 5153 res = EIO; 5154 goto errout; 5155 } 5156 cgroups_set_memory_limit(memtotal * pct / 100); 5157 } 5158 5159 if ((opts.mdwe_flags & PR_MDWE_NO_INHERIT) && 5160 !(opts.mdwe_flags & PR_MDWE_REFUSE_EXEC_GAIN)) { 5161 ERROR("mdwe: no_inherit requires refuse_exec_gain\n"); 5162 res = ENOTSUP; 5163 goto errout; 5164 } 5165 } 5166 5167 if (opts.landlock.n > 0) 5168 opts.no_new_privs = 1; 5169 } 5170 5171 if (opts.private_netifd && mount_is_defined("/etc/resolv.conf")) { 5172 ERROR("bundle bind-mounts /etc/resolv.conf but the container has its own netifd\n"); 5173 res = EINVAL; 5174 goto errout; 5175 } 5176 5177 if (opts.hostname && opts.hostname[0] && !jail_has_utsns()) { 5178 ERROR("hostname requires a UTS namespace\n"); 5179 jail_reason_set("hostname", EINVAL); 5180 res = EINVAL; 5181 goto errout; 5182 } 5183 5184 if (opts.domainname && opts.domainname[0] && !jail_has_utsns()) { 5185 ERROR("domainname requires a UTS namespace\n"); 5186 jail_reason_set("domainname", EINVAL); 5187 res = EINVAL; 5188 goto errout; 5189 } 5190 5191 errout: 5192 jail_oci_root_restore(prev_root); 5193 blob_buf_free(&ocibuf); 5194 5195 return res; 5196 } 5197 5198 static int set_oom_score_adj(void) 5199 { 5200 int f; 5201 char fname[32]; 5202 5203 if (!opts.set_oom_score_adj) 5204 return 0; 5205 5206 snprintf(fname, sizeof(fname), "/proc/%u/oom_score_adj", jail_process.pid); 5207 f = open(fname, O_WRONLY | O_TRUNC); 5208 if (f < 0) 5209 return errno; 5210 5211 dprintf(f, "%d", opts.oom_score_adj); 5212 close(f); 5213 5214 return 0; 5215 } 5216 5217 5218 enum { 5219 OCI_STATE_CREATING, 5220 OCI_STATE_CREATED, 5221 OCI_STATE_RUNNING, 5222 OCI_STATE_PAUSED, 5223 OCI_STATE_STOPPED, 5224 }; 5225 5226 static int jail_oci_state = OCI_STATE_CREATING; 5227 static bool jail_create_done; 5228 static void pipe_send_start_container(struct uloop_timeout *t); 5229 static struct uloop_timeout start_container_timeout = { 5230 .cb = pipe_send_start_container, 5231 }; 5232 5233 static bool jail_oci_live(void) 5234 { 5235 return jail_create_done && 5236 (jail_oci_state == OCI_STATE_CREATED || 5237 jail_oci_state == OCI_STATE_RUNNING); 5238 } 5239 5240 static int handle_start(struct ubus_context *ctx, struct ubus_object *obj, 5241 struct ubus_request_data *req, const char *method, 5242 struct blob_attr *msg) 5243 { 5244 if (!jail_create_done || jail_oci_state != OCI_STATE_CREATED) 5245 return UBUS_STATUS_INVALID_ARGUMENT; 5246 5247 if (!opts.jail_argv) { 5248 ERROR("start refused: the bundle defines no process\n"); 5249 return UBUS_STATUS_INVALID_ARGUMENT; 5250 } 5251 5252 uloop_timeout_add(&start_container_timeout); 5253 5254 return UBUS_STATUS_OK; 5255 } 5256 5257 struct netns_ifinfo { 5258 int ifindex; 5259 char name[IF_NAMESIZE]; 5260 char mac[18]; 5261 }; 5262 5263 struct netns_ifaddr { 5264 int ifindex; 5265 char cidr[INET6_ADDRSTRLEN + 4]; 5266 }; 5267 5268 static int netns_open_sock(pid_t pid) 5269 { 5270 struct sockaddr_nl sa = { .nl_family = AF_NETLINK }; 5271 struct timeval tv = { .tv_sec = 1 }; 5272 char path[64]; 5273 int netns_fd, self_fd, sock, saved_err; 5274 5275 snprintf(path, sizeof(path), "/proc/%d/ns/net", pid); 5276 netns_fd = open(path, O_RDONLY | O_CLOEXEC); 5277 if (netns_fd < 0) 5278 return -1; 5279 5280 self_fd = open("/proc/self/ns/net", O_RDONLY | O_CLOEXEC); 5281 if (self_fd < 0) { 5282 close(netns_fd); 5283 return -1; 5284 } 5285 5286 if (setns(netns_fd, CLONE_NEWNET)) { 5287 close(netns_fd); 5288 close(self_fd); 5289 return -1; 5290 } 5291 5292 sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); 5293 saved_err = errno; 5294 if (setns(self_fd, CLONE_NEWNET)) 5295 ERROR("cannot return to own network namespace: %m\n"); 5296 close(netns_fd); 5297 close(self_fd); 5298 if (sock < 0) { 5299 errno = saved_err; 5300 return -1; 5301 } 5302 5303 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 5304 close(sock); 5305 return -1; 5306 } 5307 5308 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 5309 5310 return sock; 5311 } 5312 5313 static int netns_parse_link(struct nlmsghdr *nh, struct netns_ifinfo **ifaces, size_t *n) 5314 { 5315 struct ifinfomsg *ifi = NLMSG_DATA(nh); 5316 struct netns_ifinfo *tmp, *iface; 5317 struct rtattr *rta; 5318 const uint8_t *hw; 5319 int len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); 5320 5321 if (ifi->ifi_flags & IFF_LOOPBACK) 5322 return 0; 5323 5324 tmp = realloc(*ifaces, (*n + 1) * sizeof(*tmp)); 5325 if (!tmp) 5326 return ENOMEM; 5327 5328 *ifaces = tmp; 5329 iface = &tmp[(*n)++]; 5330 memset(iface, 0, sizeof(*iface)); 5331 iface->ifindex = ifi->ifi_index; 5332 5333 for (rta = IFLA_RTA(ifi); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { 5334 if (rta->rta_type == IFLA_IFNAME) { 5335 strncpy(iface->name, RTA_DATA(rta), sizeof(iface->name) - 1); 5336 } else if (rta->rta_type == IFLA_ADDRESS && RTA_PAYLOAD(rta) == 6) { 5337 hw = RTA_DATA(rta); 5338 snprintf(iface->mac, sizeof(iface->mac), 5339 "%02x:%02x:%02x:%02x:%02x:%02x", 5340 hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]); 5341 } 5342 } 5343 5344 return 0; 5345 } 5346 5347 static int netns_parse_addr(struct nlmsghdr *nh, struct netns_ifaddr **addrs, size_t *n) 5348 { 5349 struct ifaddrmsg *ifa = NLMSG_DATA(nh); 5350 struct netns_ifaddr *tmp, *addr; 5351 struct rtattr *rta, *sel = NULL; 5352 char abuf[INET6_ADDRSTRLEN]; 5353 int len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)); 5354 5355 if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) 5356 return 0; 5357 5358 for (rta = IFA_RTA(ifa); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { 5359 if (rta->rta_type == IFA_LOCAL) 5360 sel = rta; 5361 else if (rta->rta_type == IFA_ADDRESS && !sel) 5362 sel = rta; 5363 } 5364 5365 if (!sel || !inet_ntop(ifa->ifa_family, RTA_DATA(sel), abuf, sizeof(abuf))) 5366 return 0; 5367 5368 tmp = realloc(*addrs, (*n + 1) * sizeof(*tmp)); 5369 if (!tmp) 5370 return ENOMEM; 5371 5372 *addrs = tmp; 5373 addr = &tmp[(*n)++]; 5374 addr->ifindex = ifa->ifa_index; 5375 snprintf(addr->cidr, sizeof(addr->cidr), "%s/%u", abuf, ifa->ifa_prefixlen); 5376 5377 return 0; 5378 } 5379 5380 static int netns_dump(int sock, int type, struct netns_ifinfo **ifaces, size_t *nifaces, 5381 struct netns_ifaddr **addrs, size_t *naddrs) 5382 { 5383 struct { 5384 struct nlmsghdr hdr; 5385 struct rtgenmsg gen; 5386 } req = { 5387 .hdr = { 5388 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 5389 .nlmsg_type = type, 5390 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, 5391 .nlmsg_seq = type, 5392 }, 5393 .gen = { .rtgen_family = AF_UNSPEC }, 5394 }; 5395 struct nlmsghdr *nh; 5396 char buf[32768]; 5397 ssize_t n; 5398 int msglen, err; 5399 5400 if (send(sock, &req, req.hdr.nlmsg_len, 0) < 0) 5401 return errno; 5402 5403 while (1) { 5404 n = recv(sock, buf, sizeof(buf), 0); 5405 if (n < 0) { 5406 if (errno == EINTR) 5407 continue; 5408 return errno; 5409 } 5410 if (n == 0) 5411 return EIO; 5412 5413 msglen = n; 5414 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, msglen); nh = NLMSG_NEXT(nh, msglen)) { 5415 err = 0; 5416 if (nh->nlmsg_type == NLMSG_DONE) 5417 return 0; 5418 else if (nh->nlmsg_type == NLMSG_ERROR) 5419 return EIO; 5420 else if (nh->nlmsg_type == RTM_NEWLINK) 5421 err = netns_parse_link(nh, ifaces, nifaces); 5422 else if (nh->nlmsg_type == RTM_NEWADDR) 5423 err = netns_parse_addr(nh, addrs, naddrs); 5424 if (err) 5425 return err; 5426 } 5427 } 5428 } 5429 5430 static void netns_fill_interfaces(struct blob_buf *b, pid_t pid) 5431 { 5432 struct netns_ifinfo *ifaces = NULL; 5433 struct netns_ifaddr *addrs = NULL; 5434 size_t nifaces = 0, naddrs = 0, i, j; 5435 void *a, *t, *aa; 5436 int sock; 5437 5438 sock = netns_open_sock(pid); 5439 if (sock < 0) 5440 return; 5441 5442 if (netns_dump(sock, RTM_GETLINK, &ifaces, &nifaces, &addrs, &naddrs) || 5443 netns_dump(sock, RTM_GETADDR, &ifaces, &nifaces, &addrs, &naddrs)) 5444 goto out; 5445 5446 a = blobmsg_open_array(b, "interfaces"); 5447 for (i = 0; i < nifaces; i++) { 5448 t = blobmsg_open_table(b, NULL); 5449 blobmsg_add_string(b, "name", ifaces[i].name); 5450 if (ifaces[i].mac[0]) 5451 blobmsg_add_string(b, "mac", ifaces[i].mac); 5452 aa = blobmsg_open_array(b, "addresses"); 5453 for (j = 0; j < naddrs; j++) 5454 if (addrs[j].ifindex == ifaces[i].ifindex) 5455 blobmsg_add_string(b, NULL, addrs[j].cidr); 5456 blobmsg_close_array(b, aa); 5457 blobmsg_close_table(b, t); 5458 } 5459 blobmsg_close_array(b, a); 5460 5461 out: 5462 free(ifaces); 5463 free(addrs); 5464 close(sock); 5465 } 5466 5467 static const char *annotation_get(struct blob_attr *attrs, const char *key) 5468 { 5469 struct blob_attr *cur; 5470 int rem; 5471 5472 if (!attrs) 5473 return NULL; 5474 5475 blobmsg_for_each_attr(cur, attrs, rem) 5476 if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING && 5477 !strcmp(blobmsg_name(cur), key)) 5478 return blobmsg_get_string(cur); 5479 5480 return NULL; 5481 } 5482 5483 static struct timespec jail_created; 5484 5485 static void oci_state_fill_runtime(struct blob_buf *b) 5486 { 5487 char buf[40]; 5488 struct tm tm; 5489 size_t len; 5490 5491 if (opts.extroot) 5492 blobmsg_add_string(b, "rootfs", opts.extroot); 5493 5494 if (!jail_created.tv_sec) 5495 return; 5496 5497 if (!gmtime_r(&jail_created.tv_sec, &tm)) 5498 return; 5499 5500 len = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tm); 5501 if (!len) 5502 return; 5503 5504 snprintf(buf + len, sizeof(buf) - len, ".%09ldZ", jail_created.tv_nsec); 5505 blobmsg_add_string(b, "created", buf); 5506 } 5507 5508 static void oci_state_fill_network(struct blob_buf *b) 5509 { 5510 struct blob_buf sidecar = { 0 }; 5511 char path[128]; 5512 const char *mode, *attach; 5513 void *c; 5514 5515 if (opts.setns.net != -1) 5516 mode = "joined"; 5517 else if (opts.namespace & CLONE_NEWNET) 5518 mode = "private"; 5519 else 5520 mode = "host"; 5521 5522 c = blobmsg_open_table(b, "org.openwrt.network"); 5523 blobmsg_add_string(b, "namespace", mode); 5524 5525 blob_buf_init(&sidecar, 0); 5526 snprintf(path, sizeof(path), "/tmp/run/uvol/.meta/uxc/%s.annotations", opts.name); 5527 blobmsg_add_json_from_file(&sidecar, path); 5528 5529 attach = annotation_get(sidecar.head, "org.openwrt.network.attach"); 5530 if (!attach) 5531 attach = annotation_get(opts.annotations, "org.openwrt.network.attach"); 5532 if (attach && !*attach) 5533 attach = NULL; 5534 if (!attach && (opts.namespace & CLONE_NEWNET)) 5535 attach = "none"; 5536 if (attach) 5537 blobmsg_add_string(b, "attach", attach); 5538 blob_buf_free(&sidecar); 5539 5540 if (strcmp(mode, "host") && jail_running && 5541 (jail_oci_state == OCI_STATE_CREATED || 5542 jail_oci_state == OCI_STATE_RUNNING || 5543 jail_oci_state == OCI_STATE_PAUSED)) 5544 netns_fill_interfaces(b, jail_process.pid); 5545 5546 blobmsg_close_table(b, c); 5547 } 5548 5549 static struct blob_buf bb; 5550 static void oci_state_fill(struct blob_buf *b) 5551 { 5552 char *statusstr; 5553 5554 switch (jail_oci_state) { 5555 case OCI_STATE_CREATING: 5556 statusstr = "creating"; 5557 break; 5558 case OCI_STATE_CREATED: 5559 statusstr = "created"; 5560 break; 5561 case OCI_STATE_RUNNING: 5562 statusstr = "running"; 5563 break; 5564 case OCI_STATE_PAUSED: 5565 statusstr = "paused"; 5566 break; 5567 case OCI_STATE_STOPPED: 5568 statusstr = "stopped"; 5569 break; 5570 default: 5571 statusstr = "unknown"; 5572 } 5573 5574 blobmsg_add_string(b, "ociVersion", OCI_VERSION_STRING); 5575 blobmsg_add_string(b, "id", opts.name); 5576 blobmsg_add_string(b, "status", statusstr); 5577 if (jail_oci_state == OCI_STATE_CREATED || 5578 jail_oci_state == OCI_STATE_RUNNING || 5579 jail_oci_state == OCI_STATE_PAUSED) { 5580 int64_t v; 5581 5582 blobmsg_add_u32(b, "pid", jail_process.pid); 5583 5584 v = cgroups_read_int64("memory.peak"); 5585 if (v >= 0) 5586 blobmsg_add_u64(b, "memoryPeak", (uint64_t)v); 5587 v = cgroups_read_int64("memory.swap.peak"); 5588 if (v >= 0) 5589 blobmsg_add_u64(b, "memorySwapPeak", (uint64_t)v); 5590 v = cgroups_read_int64("pids.peak"); 5591 if (v >= 0) 5592 blobmsg_add_u64(b, "pidsPeak", (uint64_t)v); 5593 5594 int events_fd = cgroups_open_attr("memory.events.local"); 5595 if (events_fd >= 0) { 5596 char ebuf[1024], *line, *next; 5597 ssize_t en = read(events_fd, ebuf, sizeof(ebuf) - 1); 5598 5599 close(events_fd); 5600 if (en > 0) { 5601 void *sub = blobmsg_open_table(b, "memoryEventsLocal"); 5602 5603 ebuf[en] = '\0'; 5604 next = ebuf; 5605 while ((line = strsep(&next, "\n"))) { 5606 char *space = strchr(line, ' '); 5607 5608 if (!space) 5609 continue; 5610 *space = '\0'; 5611 blobmsg_add_u64(b, line, 5612 strtoull(space + 1, NULL, 10)); 5613 } 5614 blobmsg_close_table(b, sub); 5615 } 5616 } 5617 } 5618 5619 blobmsg_add_string(b, "bundle", opts.ocibundle); 5620 5621 if (opts.annotations) 5622 blobmsg_add_blob(b, opts.annotations); 5623 } 5624 5625 static int handle_state(struct ubus_context *ctx, struct ubus_object *obj, 5626 struct ubus_request_data *req, const char *method, 5627 struct blob_attr *msg) 5628 { 5629 blob_buf_init(&bb, 0); 5630 oci_state_fill(&bb); 5631 oci_state_fill_runtime(&bb); 5632 oci_state_fill_network(&bb); 5633 ubus_send_reply(ctx, req, bb.head); 5634 5635 return UBUS_STATUS_OK; 5636 } 5637 5638 #define UXC_STOP_TIMEOUT 120 5639 5640 enum { 5641 CONTAINER_KILL_ATTR_SIGNAL, 5642 CONTAINER_KILL_ATTR_ALL, 5643 __CONTAINER_KILL_ATTR_MAX, 5644 }; 5645 5646 static const struct blobmsg_policy container_kill_attrs[__CONTAINER_KILL_ATTR_MAX] = { 5647 [CONTAINER_KILL_ATTR_SIGNAL] = { "signal", BLOBMSG_TYPE_INT32 }, 5648 [CONTAINER_KILL_ATTR_ALL] = { "all", BLOBMSG_TYPE_BOOL }, 5649 }; 5650 5651 static int 5652 container_handle_kill(struct ubus_context *ctx, struct ubus_object *obj, 5653 struct ubus_request_data *req, const char *method, 5654 struct blob_attr *msg) 5655 { 5656 struct blob_attr *tb[__CONTAINER_KILL_ATTR_MAX], *cur; 5657 bool escalate = false; 5658 int sig = SIGTERM; 5659 bool all = false; 5660 bool creating; 5661 bool stop; 5662 5663 blobmsg_parse(container_kill_attrs, __CONTAINER_KILL_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 5664 5665 cur = tb[CONTAINER_KILL_ATTR_SIGNAL]; 5666 if (cur) { 5667 sig = (int32_t)blobmsg_get_u32(cur); 5668 if (sig < 0) { 5669 sig = SIGTERM; 5670 escalate = true; 5671 } 5672 } 5673 5674 cur = tb[CONTAINER_KILL_ATTR_ALL]; 5675 if (cur) 5676 all = blobmsg_get_bool(cur); 5677 5678 creating = !jail_create_done || jail_oci_state == OCI_STATE_CREATING; 5679 stop = (sig == SIGTERM || sig == SIGKILL); 5680 5681 if (jail_oci_state == OCI_STATE_PAUSED && sig != SIGKILL && sig != 0) 5682 return UBUS_STATUS_PERMISSION_DENIED; 5683 5684 if (creating && !stop) 5685 return UBUS_STATUS_NOT_FOUND; 5686 5687 if (stop) 5688 jail_stop_requested = true; 5689 5690 if (creating) 5691 return 0; 5692 5693 if (all && sig == SIGKILL) { 5694 int rc = cgroups_kill_all(); 5695 if (rc == 0) 5696 return 0; 5697 DEBUG("cgroup.kill unavailable (%d), falling back to per-pid kill\n", rc); 5698 } 5699 5700 if (jail_pidfd_send_signal(sig) == 0) { 5701 if (escalate) 5702 uloop_timeout_set(&jail_process_timeout, UXC_STOP_TIMEOUT * 1000); 5703 return 0; 5704 } 5705 5706 switch (errno) { 5707 case EINVAL: return UBUS_STATUS_INVALID_ARGUMENT; 5708 case EPERM: return UBUS_STATUS_PERMISSION_DENIED; 5709 case ESRCH: return UBUS_STATUS_NOT_FOUND; 5710 case EBADF: return UBUS_STATUS_UNKNOWN_ERROR; 5711 } 5712 5713 return UBUS_STATUS_UNKNOWN_ERROR; 5714 } 5715 5716 static int 5717 container_handle_pause(struct ubus_context *ctx, struct ubus_object *obj, 5718 struct ubus_request_data *req, const char *method, 5719 struct blob_attr *msg) 5720 { 5721 int rc; 5722 5723 if (!jail_oci_live()) 5724 return UBUS_STATUS_INVALID_ARGUMENT; 5725 5726 rc = cgroups_set_frozen(true); 5727 if (rc < 0) { 5728 switch (rc) { 5729 case -ENODEV: 5730 case -ENOENT: 5731 return UBUS_STATUS_NOT_SUPPORTED; 5732 case -EINVAL: 5733 return UBUS_STATUS_INVALID_ARGUMENT; 5734 default: 5735 return UBUS_STATUS_UNKNOWN_ERROR; 5736 } 5737 } 5738 5739 jail_oci_state = OCI_STATE_PAUSED; 5740 return UBUS_STATUS_OK; 5741 } 5742 5743 static int 5744 container_handle_resume(struct ubus_context *ctx, struct ubus_object *obj, 5745 struct ubus_request_data *req, const char *method, 5746 struct blob_attr *msg) 5747 { 5748 int rc; 5749 5750 if (jail_oci_state != OCI_STATE_PAUSED) 5751 return UBUS_STATUS_INVALID_ARGUMENT; 5752 5753 rc = cgroups_set_frozen(false); 5754 if (rc < 0) { 5755 switch (rc) { 5756 case -ENODEV: 5757 case -ENOENT: 5758 return UBUS_STATUS_NOT_SUPPORTED; 5759 case -EINVAL: 5760 return UBUS_STATUS_INVALID_ARGUMENT; 5761 default: 5762 return UBUS_STATUS_UNKNOWN_ERROR; 5763 } 5764 } 5765 5766 jail_oci_state = OCI_STATE_RUNNING; 5767 return UBUS_STATUS_OK; 5768 } 5769 5770 enum { 5771 CONTAINER_RECLAIM_ATTR_BYTES, 5772 CONTAINER_RECLAIM_ATTR_SWAPPINESS, 5773 __CONTAINER_RECLAIM_ATTR_MAX, 5774 }; 5775 5776 static const struct blobmsg_policy container_reclaim_attrs[__CONTAINER_RECLAIM_ATTR_MAX] = { 5777 [CONTAINER_RECLAIM_ATTR_BYTES] = { "bytes", BLOBMSG_CAST_INT64 }, 5778 [CONTAINER_RECLAIM_ATTR_SWAPPINESS] = { "swappiness", BLOBMSG_TYPE_INT32 }, 5779 }; 5780 5781 static int 5782 container_handle_reclaim(struct ubus_context *ctx, struct ubus_object *obj, 5783 struct ubus_request_data *req, const char *method, 5784 struct blob_attr *msg) 5785 { 5786 struct blob_attr *tb[__CONTAINER_RECLAIM_ATTR_MAX]; 5787 int64_t bytes; 5788 int32_t swappiness = -1; 5789 int rc; 5790 5791 if (!jail_oci_live()) 5792 return UBUS_STATUS_INVALID_ARGUMENT; 5793 if (!msg) 5794 return UBUS_STATUS_INVALID_ARGUMENT; 5795 5796 blobmsg_parse(container_reclaim_attrs, __CONTAINER_RECLAIM_ATTR_MAX, tb, 5797 blobmsg_data(msg), blobmsg_data_len(msg)); 5798 if (!tb[CONTAINER_RECLAIM_ATTR_BYTES]) 5799 return UBUS_STATUS_INVALID_ARGUMENT; 5800 5801 bytes = blobmsg_cast_s64(tb[CONTAINER_RECLAIM_ATTR_BYTES]); 5802 if (tb[CONTAINER_RECLAIM_ATTR_SWAPPINESS]) { 5803 uint32_t s = blobmsg_get_u32(tb[CONTAINER_RECLAIM_ATTR_SWAPPINESS]); 5804 if (s > 200) 5805 return UBUS_STATUS_INVALID_ARGUMENT; 5806 swappiness = (int32_t)s; 5807 } 5808 5809 rc = cgroups_reclaim(bytes, swappiness); 5810 if (rc == 0) 5811 return UBUS_STATUS_OK; 5812 if (rc == -EAGAIN) 5813 return UBUS_STATUS_TIMEOUT; 5814 if (rc == -EINVAL) 5815 return UBUS_STATUS_INVALID_ARGUMENT; 5816 if (rc == -ENODEV) 5817 return UBUS_STATUS_NOT_SUPPORTED; 5818 return UBUS_STATUS_UNKNOWN_ERROR; 5819 } 5820 5821 static int 5822 container_handle_update(struct ubus_context *ctx, struct ubus_object *obj, 5823 struct ubus_request_data *req, const char *method, 5824 struct blob_attr *msg) 5825 { 5826 const struct blob_attr *prev_root = jail_oci_root_get(); 5827 const char *prev_reason = jail_reason; 5828 int prev_errno = jail_reason_errno; 5829 int rc; 5830 5831 if (!jail_oci_live()) 5832 return UBUS_STATUS_INVALID_ARGUMENT; 5833 5834 if (!msg) 5835 return UBUS_STATUS_INVALID_ARGUMENT; 5836 5837 jail_oci_root_restore(msg); 5838 rc = parseOCIlinuxcgroups(msg, true); 5839 jail_oci_root_restore(prev_root); 5840 jail_reason_restore(prev_reason, prev_errno); 5841 if (rc) { 5842 switch (rc) { 5843 case ENOTSUP: 5844 return UBUS_STATUS_NOT_SUPPORTED; 5845 case EBUSY: 5846 case EINVAL: 5847 case ENODATA: 5848 case ERANGE: 5849 return UBUS_STATUS_INVALID_ARGUMENT; 5850 case EIO: 5851 return UBUS_STATUS_UNKNOWN_ERROR; 5852 default: 5853 return UBUS_STATUS_UNKNOWN_ERROR; 5854 } 5855 } 5856 5857 rc = cgroups_apply(jail_process.pid); 5858 jail_reason_restore(prev_reason, prev_errno); 5859 if (rc) 5860 return UBUS_STATUS_NOT_SUPPORTED; 5861 5862 return UBUS_STATUS_OK; 5863 } 5864 5865 enum { 5866 CONTAINER_EXEC_ATTR_ARGS, 5867 CONTAINER_EXEC_ATTR_ENV, 5868 CONTAINER_EXEC_ATTR_CWD, 5869 CONTAINER_EXEC_ATTR_USER, 5870 CONTAINER_EXEC_ATTR_CAPABILITIES, 5871 CONTAINER_EXEC_ATTR_RLIMITS, 5872 CONTAINER_EXEC_ATTR_NO_NEW_PRIVS, 5873 CONTAINER_EXEC_ATTR_TERMINAL, 5874 CONTAINER_EXEC_ATTR_CONSOLE_SOCKET, 5875 CONTAINER_EXEC_ATTR_PIDFILE, 5876 CONTAINER_EXEC_ATTR_DETACH, 5877 __CONTAINER_EXEC_ATTR_MAX, 5878 }; 5879 5880 static const struct blobmsg_policy container_exec_attrs[__CONTAINER_EXEC_ATTR_MAX] = { 5881 [CONTAINER_EXEC_ATTR_ARGS] = { "args", BLOBMSG_TYPE_ARRAY }, 5882 [CONTAINER_EXEC_ATTR_ENV] = { "env", BLOBMSG_TYPE_ARRAY }, 5883 [CONTAINER_EXEC_ATTR_CWD] = { "cwd", BLOBMSG_TYPE_STRING }, 5884 [CONTAINER_EXEC_ATTR_USER] = { "user", BLOBMSG_TYPE_TABLE }, 5885 [CONTAINER_EXEC_ATTR_CAPABILITIES] = { "capabilities", BLOBMSG_TYPE_TABLE }, 5886 [CONTAINER_EXEC_ATTR_RLIMITS] = { "rlimits", BLOBMSG_TYPE_ARRAY }, 5887 [CONTAINER_EXEC_ATTR_NO_NEW_PRIVS] = { "noNewPrivileges", BLOBMSG_TYPE_BOOL }, 5888 [CONTAINER_EXEC_ATTR_TERMINAL] = { "terminal", BLOBMSG_TYPE_BOOL }, 5889 [CONTAINER_EXEC_ATTR_CONSOLE_SOCKET] = { "consolesocket", BLOBMSG_TYPE_STRING }, 5890 [CONTAINER_EXEC_ATTR_PIDFILE] = { "pidfile", BLOBMSG_TYPE_STRING }, 5891 [CONTAINER_EXEC_ATTR_DETACH] = { "detach", BLOBMSG_TYPE_BOOL }, 5892 }; 5893 5894 enum { 5895 CONTAINER_EXEC_USER_UID, 5896 CONTAINER_EXEC_USER_GID, 5897 CONTAINER_EXEC_USER_ADDITIONAL_GIDS, 5898 CONTAINER_EXEC_USER_UMASK, 5899 __CONTAINER_EXEC_USER_MAX, 5900 }; 5901 5902 static const struct blobmsg_policy container_exec_user_attrs[__CONTAINER_EXEC_USER_MAX] = { 5903 [CONTAINER_EXEC_USER_UID] = { "uid", BLOBMSG_TYPE_INT32 }, 5904 [CONTAINER_EXEC_USER_GID] = { "gid", BLOBMSG_TYPE_INT32 }, 5905 [CONTAINER_EXEC_USER_ADDITIONAL_GIDS] = { "additionalGids", BLOBMSG_TYPE_ARRAY }, 5906 [CONTAINER_EXEC_USER_UMASK] = { "umask", BLOBMSG_TYPE_INT32 }, 5907 }; 5908 5909 struct container_exec { 5910 struct ubus_context *ctx; 5911 struct ubus_request_data req; 5912 struct uloop_process exec_proc; 5913 char *pidfile; 5914 int notify_fd; 5915 int stdio_fds[STDIO_FDS_NUM]; 5916 }; 5917 5918 static struct container_exec *current_exec; 5919 5920 static char **container_exec_strarray(struct blob_attr *arr) 5921 { 5922 struct blob_attr *cur; 5923 char **out; 5924 int rem, n = 0; 5925 5926 blobmsg_for_each_attr(cur, arr, rem) 5927 ++n; 5928 5929 out = calloc(n + 1, sizeof(char *)); 5930 if (!out) 5931 return NULL; 5932 5933 n = 0; 5934 blobmsg_for_each_attr(cur, arr, rem) 5935 out[n++] = strdup(blobmsg_get_string(cur)); 5936 out[n] = NULL; 5937 return out; 5938 } 5939 5940 static void container_exec_free_strarray(char **a) 5941 { 5942 int i; 5943 5944 if (!a) 5945 return; 5946 for (i = 0; a[i]; i++) 5947 free(a[i]); 5948 free(a); 5949 } 5950 5951 static int wait_status_decode(int wstatus) 5952 { 5953 if (WIFEXITED(wstatus)) 5954 return WEXITSTATUS(wstatus); 5955 5956 if (WIFSIGNALED(wstatus)) 5957 return 128 + WTERMSIG(wstatus); 5958 5959 return 255; 5960 } 5961 5962 static void container_exec_done_reply(struct uloop_process *p, int wstatus) 5963 { 5964 struct container_exec *e = container_of(p, struct container_exec, exec_proc); 5965 static struct blob_buf bb; 5966 int status = wait_status_decode(wstatus); 5967 5968 jail_write_exit_status(e->pidfile, status); 5969 stdio_fds_close(e->stdio_fds); 5970 notify_signal(e->notify_fd); 5971 if (e->notify_fd >= 0) 5972 close(e->notify_fd); 5973 5974 blob_buf_init(&bb, 0); 5975 blobmsg_add_u32(&bb, "status", status); 5976 ubus_send_reply(e->ctx, &e->req, bb.head); 5977 ubus_complete_deferred_request(e->ctx, &e->req, 0); 5978 if (current_exec == e) 5979 current_exec = NULL; 5980 free(e->pidfile); 5981 free(e); 5982 } 5983 5984 static void container_exec_done_reap(struct uloop_process *p, int wstatus) 5985 { 5986 struct container_exec *e = container_of(p, struct container_exec, exec_proc); 5987 5988 jail_write_exit_status(e->pidfile, wait_status_decode(wstatus)); 5989 stdio_fds_close(e->stdio_fds); 5990 notify_signal(e->notify_fd); 5991 if (e->notify_fd >= 0) 5992 close(e->notify_fd); 5993 5994 if (current_exec == e) 5995 current_exec = NULL; 5996 free(e->pidfile); 5997 free(e); 5998 } 5999 6000 static int 6001 container_handle_exec(struct ubus_context *ctx, struct ubus_object *obj, 6002 struct ubus_request_data *req, const char *method, 6003 struct blob_attr *msg) 6004 { 6005 struct blob_attr *tb[__CONTAINER_EXEC_ATTR_MAX]; 6006 struct blob_attr *tu[__CONTAINER_EXEC_USER_MAX] = { 0 }; 6007 static const char * const ns_names[] = { "user", "ipc", "uts", "net", "cgroup", "pid", "mnt" }; 6008 static const int ns_flags[] = { 6009 CLONE_NEWUSER, CLONE_NEWIPC, CLONE_NEWUTS, CLONE_NEWNET, 6010 CLONE_NEWCGROUP, CLONE_NEWPID, CLONE_NEWNS, 6011 }; 6012 int ns_fds[7] = { -1, -1, -1, -1, -1, -1, -1 }; 6013 char **args = NULL, **env = NULL; 6014 const char *cwd = "/", *pidfile = NULL; 6015 const char *console_socket = NULL; 6016 uint32_t uid, gid; 6017 bool detach = false; 6018 bool terminal = false; 6019 bool exec_nnp = opts.no_new_privs; 6020 struct jail_capset exec_capset = opts.capset; 6021 struct rlimit exec_rlimits[RLIM_NLIMITS]; 6022 bool exec_rlimits_set[RLIM_NLIMITS] = { 0 }; 6023 gid_t *exec_additional_gids = NULL; 6024 size_t exec_num_additional_gids = 0; 6025 size_t exec_max_additional_gids; 6026 mode_t exec_umask = opts.umask; 6027 bool exec_set_umask = opts.set_umask; 6028 int console_sock_fd = -1; 6029 bool console_sock_owned = false; 6030 int cgroup_fd = -1; 6031 int pipe_fds[2] = { -1, -1 }; 6032 int stdio_fds[STDIO_FDS_NUM] = { -1, -1, -1 }; 6033 int stdio_sock; 6034 int notify_fd = -1; 6035 pid_t exec_pid, grandchild = -1; 6036 struct container_exec *e = NULL; 6037 char nspath[64]; 6038 int i, rc = UBUS_STATUS_UNKNOWN_ERROR; 6039 6040 if (!jail_oci_live()) 6041 return UBUS_STATUS_INVALID_ARGUMENT; 6042 if (!msg) 6043 return UBUS_STATUS_INVALID_ARGUMENT; 6044 if (current_exec) { 6045 ERROR("exec: another exec is already in progress\n"); 6046 return UBUS_STATUS_PERMISSION_DENIED; 6047 } 6048 6049 uid = (opts.pw_uid > 0) ? (uint32_t)opts.pw_uid : 0; 6050 gid = (opts.pw_gid > 0) ? (uint32_t)opts.pw_gid : 0; 6051 6052 for (i = 0; i < RLIM_NLIMITS; i++) { 6053 if (opts.rlimits[i]) { 6054 exec_rlimits[i] = *opts.rlimits[i]; 6055 exec_rlimits_set[i] = true; 6056 } 6057 } 6058 { 6059 long n_max = sysconf(_SC_NGROUPS_MAX); 6060 if (n_max <= 0) 6061 n_max = NGROUPS_MAX; 6062 exec_max_additional_gids = (size_t)n_max; 6063 } 6064 if (opts.additional_gids && opts.num_additional_gids <= exec_max_additional_gids) { 6065 exec_additional_gids = calloc(opts.num_additional_gids, sizeof(gid_t)); 6066 if (!exec_additional_gids) { 6067 rc = UBUS_STATUS_UNKNOWN_ERROR; 6068 goto out; 6069 } 6070 memcpy(exec_additional_gids, opts.additional_gids, 6071 opts.num_additional_gids * sizeof(gid_t)); 6072 exec_num_additional_gids = opts.num_additional_gids; 6073 } 6074 6075 stdio_sock = ubus_request_get_caller_fd(req); 6076 if (stdio_sock > -1) { 6077 if (stdio_notify_fds_recv(stdio_sock, stdio_fds, ¬ify_fd)) 6078 ERROR("exec: cannot receive caller descriptors: %m\n"); 6079 6080 close(stdio_sock); 6081 } 6082 6083 blobmsg_parse(container_exec_attrs, __CONTAINER_EXEC_ATTR_MAX, tb, 6084 blobmsg_data(msg), blobmsg_data_len(msg)); 6085 6086 if (!tb[CONTAINER_EXEC_ATTR_ARGS]) { 6087 rc = UBUS_STATUS_INVALID_ARGUMENT; 6088 goto out; 6089 } 6090 6091 args = container_exec_strarray(tb[CONTAINER_EXEC_ATTR_ARGS]); 6092 if (!args || !args[0]) { 6093 rc = UBUS_STATUS_INVALID_ARGUMENT; 6094 goto out; 6095 } 6096 6097 if (tb[CONTAINER_EXEC_ATTR_ENV]) 6098 env = container_exec_strarray(tb[CONTAINER_EXEC_ATTR_ENV]); 6099 if (tb[CONTAINER_EXEC_ATTR_CWD]) 6100 cwd = blobmsg_get_string(tb[CONTAINER_EXEC_ATTR_CWD]); 6101 if (tb[CONTAINER_EXEC_ATTR_PIDFILE]) 6102 pidfile = blobmsg_get_string(tb[CONTAINER_EXEC_ATTR_PIDFILE]); 6103 if (tb[CONTAINER_EXEC_ATTR_DETACH]) 6104 detach = blobmsg_get_bool(tb[CONTAINER_EXEC_ATTR_DETACH]); 6105 if (tb[CONTAINER_EXEC_ATTR_TERMINAL]) 6106 terminal = blobmsg_get_bool(tb[CONTAINER_EXEC_ATTR_TERMINAL]); 6107 if (tb[CONTAINER_EXEC_ATTR_CONSOLE_SOCKET]) 6108 console_socket = blobmsg_get_string(tb[CONTAINER_EXEC_ATTR_CONSOLE_SOCKET]); 6109 if (tb[CONTAINER_EXEC_ATTR_NO_NEW_PRIVS]) 6110 exec_nnp = blobmsg_get_bool(tb[CONTAINER_EXEC_ATTR_NO_NEW_PRIVS]); 6111 if (tb[CONTAINER_EXEC_ATTR_CAPABILITIES]) { 6112 memset(&exec_capset, 0, sizeof(exec_capset)); 6113 if (parseOCIcapabilities(&exec_capset, 6114 tb[CONTAINER_EXEC_ATTR_CAPABILITIES])) { 6115 rc = UBUS_STATUS_INVALID_ARGUMENT; 6116 goto out; 6117 } 6118 } 6119 if (tb[CONTAINER_EXEC_ATTR_RLIMITS]) { 6120 struct blob_attr *cur; 6121 int rem; 6122 6123 blobmsg_for_each_attr(cur, tb[CONTAINER_EXEC_ATTR_RLIMITS], rem) { 6124 struct blob_attr *rl[__OCI_PROCESS_RLIMIT_MAX]; 6125 int rlt; 6126 6127 blobmsg_parse(oci_process_rlimit_policy, __OCI_PROCESS_RLIMIT_MAX, 6128 rl, blobmsg_data(cur), blobmsg_len(cur)); 6129 if (!rl[OCI_PROCESS_RLIMIT_TYPE] || 6130 !rl[OCI_PROCESS_RLIMIT_SOFT] || 6131 !rl[OCI_PROCESS_RLIMIT_HARD]) 6132 continue; 6133 rlt = resolve_rlimit(blobmsg_get_string(rl[OCI_PROCESS_RLIMIT_TYPE])); 6134 if (rlt < 0) 6135 continue; 6136 exec_rlimits[rlt].rlim_cur = blobmsg_cast_u64(rl[OCI_PROCESS_RLIMIT_SOFT]); 6137 exec_rlimits[rlt].rlim_max = blobmsg_cast_u64(rl[OCI_PROCESS_RLIMIT_HARD]); 6138 exec_rlimits_set[rlt] = true; 6139 } 6140 } 6141 if (tb[CONTAINER_EXEC_ATTR_USER]) { 6142 blobmsg_parse(container_exec_user_attrs, __CONTAINER_EXEC_USER_MAX, tu, 6143 blobmsg_data(tb[CONTAINER_EXEC_ATTR_USER]), 6144 blobmsg_len(tb[CONTAINER_EXEC_ATTR_USER])); 6145 if (tu[CONTAINER_EXEC_USER_UID]) 6146 uid = blobmsg_get_u32(tu[CONTAINER_EXEC_USER_UID]); 6147 if (tu[CONTAINER_EXEC_USER_GID]) 6148 gid = blobmsg_get_u32(tu[CONTAINER_EXEC_USER_GID]); 6149 if (tu[CONTAINER_EXEC_USER_UMASK]) { 6150 exec_umask = blobmsg_get_u32(tu[CONTAINER_EXEC_USER_UMASK]); 6151 exec_set_umask = true; 6152 } 6153 if (tu[CONTAINER_EXEC_USER_ADDITIONAL_GIDS]) { 6154 struct blob_attr *cur; 6155 int rem; 6156 size_t count = 0; 6157 6158 blobmsg_for_each_attr(cur, tu[CONTAINER_EXEC_USER_ADDITIONAL_GIDS], rem) 6159 count++; 6160 6161 if (count > exec_max_additional_gids) 6162 count = exec_max_additional_gids; 6163 6164 free(exec_additional_gids); 6165 exec_additional_gids = count ? calloc(count, sizeof(gid_t)) : NULL; 6166 if (count && !exec_additional_gids) { 6167 rc = UBUS_STATUS_UNKNOWN_ERROR; 6168 goto out; 6169 } 6170 6171 exec_num_additional_gids = 0; 6172 blobmsg_for_each_attr(cur, tu[CONTAINER_EXEC_USER_ADDITIONAL_GIDS], rem) { 6173 if (exec_num_additional_gids >= count) 6174 break; 6175 exec_additional_gids[exec_num_additional_gids++] = 6176 blobmsg_get_u32(cur); 6177 } 6178 } 6179 } 6180 6181 for (i = 0; i < (int)ARRAY_SIZE(ns_names); i++) { 6182 struct stat nsst, ownst; 6183 6184 snprintf(nspath, sizeof(nspath), "/proc/%d/ns/%s", 6185 jail_process.pid, ns_names[i]); 6186 ns_fds[i] = open(nspath, O_RDONLY | O_CLOEXEC); 6187 if (ns_fds[i] < 0) { 6188 if (ns_flags[i] == CLONE_NEWCGROUP || 6189 ns_flags[i] == CLONE_NEWUSER) 6190 continue; 6191 6192 ERROR("exec: open %s: %m\n", nspath); 6193 goto out; 6194 } 6195 6196 snprintf(nspath, sizeof(nspath), "/proc/self/ns/%s", ns_names[i]); 6197 if (fstat(ns_fds[i], &nsst) || stat(nspath, &ownst)) 6198 continue; 6199 6200 /* joining a namespace we are already in fails for CLONE_NEWUSER */ 6201 if (nsst.st_dev != ownst.st_dev || nsst.st_ino != ownst.st_ino) 6202 continue; 6203 6204 close(ns_fds[i]); 6205 ns_fds[i] = -1; 6206 } 6207 6208 if (terminal != !!console_socket) { 6209 ERROR("exec: terminal and consolesocket must be set together\n"); 6210 rc = UBUS_STATUS_INVALID_ARGUMENT; 6211 goto out; 6212 } 6213 6214 if (terminal && console_socket) { 6215 console_sock_fd = open_console_sock(console_socket, &console_sock_owned, true); 6216 if (console_sock_fd < 0) 6217 goto out; 6218 } 6219 6220 cgroup_fd = cgroups_open_dir(); 6221 if (cgroup_fd < 0) 6222 DEBUG("exec: cgroups_open_dir unavailable, will fall back to cgroups_attach_pid\n"); 6223 6224 if (pipe(pipe_fds) < 0) { 6225 ERROR("exec: pipe: %m\n"); 6226 goto out; 6227 } 6228 6229 exec_pid = fork(); 6230 if (exec_pid < 0) { 6231 ERROR("exec: fork: %m\n"); 6232 goto out; 6233 } 6234 6235 if (exec_pid == 0) { 6236 int wstatus; 6237 int slave_fd = -1; 6238 6239 close(pipe_fds[0]); 6240 for (i = 0; i < (int)ARRAY_SIZE(ns_names); i++) { 6241 if (ns_fds[i] < 0) 6242 continue; 6243 /* 6244 * the cgroup namespace hides our own cgroup, which the 6245 * kernel needs to see to honour CLONE_INTO_CGROUP, so 6246 * the grandchild joins it once it has been placed 6247 */ 6248 if (ns_flags[i] == CLONE_NEWCGROUP) 6249 continue; 6250 6251 if (setns(ns_fds[i], ns_flags[i]) < 0) { 6252 ERROR("exec: setns(%s): %m\n", ns_names[i]); 6253 _exit(126); 6254 } 6255 } 6256 6257 if (terminal && console_sock_fd >= 0) { 6258 int master_fd; 6259 char *slave_name; 6260 6261 master_fd = posix_openpt(O_RDWR | O_NOCTTY); 6262 if (master_fd < 0) 6263 _exit(126); 6264 if (grantpt(master_fd) || unlockpt(master_fd)) 6265 _exit(126); 6266 slave_name = ptsname(master_fd); 6267 if (!slave_name) 6268 _exit(126); 6269 slave_fd = open(slave_name, O_RDWR | O_NOCTTY); 6270 if (slave_fd < 0) 6271 _exit(126); 6272 if (sendmsg_console_fd(console_sock_fd, master_fd, slave_name) < 0) 6273 _exit(126); 6274 close(console_sock_fd); 6275 close(master_fd); 6276 } 6277 6278 { 6279 struct clone_args gargs = { 6280 .exit_signal = SIGCHLD, 6281 }; 6282 if (cgroup_fd >= 0) { 6283 gargs.flags = CLONE_INTO_CGROUP; 6284 gargs.cgroup = (__u64)cgroup_fd; 6285 } 6286 grandchild = jail_clone3(&gargs); 6287 } 6288 if (grandchild < 0) { 6289 ERROR("exec: clone3: %m\n"); 6290 _exit(126); 6291 } 6292 6293 if (grandchild == 0) { 6294 int j; 6295 6296 for (j = 0; j < (int)ARRAY_SIZE(ns_names); j++) { 6297 if (ns_flags[j] != CLONE_NEWCGROUP || ns_fds[j] < 0) 6298 continue; 6299 if (setns(ns_fds[j], CLONE_NEWCGROUP) < 0) 6300 _exit(127); 6301 } 6302 6303 for (j = 0; j < RLIM_NLIMITS; j++) 6304 if (exec_rlimits_set[j] && 6305 setrlimit(j, &exec_rlimits[j]) < 0) { 6306 ERROR("exec: setrlimit(%d): %m\n", j); 6307 _exit(127); 6308 } 6309 if (slave_fd >= 0) { 6310 if (setsid() < 0) 6311 _exit(127); 6312 if (ioctl(slave_fd, TIOCSCTTY, 0) < 0) 6313 _exit(127); 6314 dup2(slave_fd, STDIN_FILENO); 6315 dup2(slave_fd, STDOUT_FILENO); 6316 dup2(slave_fd, STDERR_FILENO); 6317 if (slave_fd > STDERR_FILENO) 6318 close(slave_fd); 6319 } else if (stdio_fds[1] > -1) { 6320 for (j = 0; j < STDIO_FDS_NUM; j++) { 6321 if (dup2(stdio_fds[j], j) < 0) 6322 _exit(127); 6323 if (stdio_fds[j] > STDERR_FILENO) 6324 close(stdio_fds[j]); 6325 } 6326 } 6327 if (exec_set_umask) 6328 umask(exec_umask); 6329 6330 if ((uid || gid || exec_num_additional_gids) && 6331 exec_capset.apply) { 6332 if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP)) { 6333 ERROR("exec: prctl(PR_SET_SECUREBITS): %m\n"); 6334 _exit(127); 6335 } 6336 if (applyOCIcapabilities(exec_capset, 6337 (1LLU << CAP_SETGID) | 6338 (1LLU << CAP_SETUID) | 6339 (1LLU << CAP_SETPCAP))) { 6340 ERROR("exec: applyOCIcapabilities(pre): failed\n"); 6341 _exit(127); 6342 } 6343 } 6344 6345 if (setgroups(exec_num_additional_gids, 6346 exec_num_additional_gids ? exec_additional_gids : NULL) < 0) { 6347 ERROR("exec: setgroups: %m\n"); 6348 _exit(127); 6349 } 6350 if (gid && setresgid(gid, gid, gid) < 0) { 6351 ERROR("exec: setresgid(%u): %m\n", gid); 6352 _exit(127); 6353 } 6354 if (uid && setresuid(uid, uid, uid) < 0) { 6355 ERROR("exec: setresuid(%u): %m\n", uid); 6356 _exit(127); 6357 } 6358 6359 if (exec_capset.apply && 6360 applyOCIcapabilities(exec_capset, 0)) { 6361 ERROR("exec: applyOCIcapabilities: failed\n"); 6362 _exit(127); 6363 } 6364 if (exec_nnp && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 6365 ERROR("exec: prctl(PR_SET_NO_NEW_PRIVS): %m\n"); 6366 _exit(127); 6367 } 6368 if (opts.mdwe_flags && 6369 prctl(PR_SET_MDWE, opts.mdwe_flags, 0, 0, 0)) { 6370 ERROR("exec: prctl(PR_SET_MDWE): %m\n"); 6371 _exit(127); 6372 } 6373 if (chdir(cwd) < 0) { 6374 ERROR("exec: chdir(%s): %m\n", cwd); 6375 _exit(127); 6376 } 6377 syscall(SYS_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC); 6378 if (env) 6379 execvpe(args[0], args, env); 6380 else 6381 execvp(args[0], args); 6382 ERROR("exec: execvpe(%s): %m\n", args[0]); 6383 _exit(127); 6384 } 6385 6386 if (slave_fd >= 0) 6387 close(slave_fd); 6388 6389 (void)!write(pipe_fds[1], &grandchild, sizeof(grandchild)); 6390 close(pipe_fds[1]); 6391 6392 if (waitpid(grandchild, &wstatus, 0) < 0) { 6393 ERROR("exec: waitpid(%d): %m\n", grandchild); 6394 _exit(126); 6395 } 6396 6397 if (WIFEXITED(wstatus)) 6398 _exit(WEXITSTATUS(wstatus)); 6399 _exit(128 + WTERMSIG(wstatus)); 6400 } 6401 6402 close(pipe_fds[1]); 6403 pipe_fds[1] = -1; 6404 { 6405 char gcbuf[sizeof(pid_t)]; 6406 size_t off = 0; 6407 ssize_t n; 6408 6409 while (off < sizeof(gcbuf)) { 6410 n = read(pipe_fds[0], gcbuf + off, sizeof(gcbuf) - off); 6411 if (n < 0) { 6412 if (errno == EINTR) 6413 continue; 6414 grandchild = -1; 6415 break; 6416 } 6417 if (n == 0) { 6418 grandchild = -1; 6419 break; 6420 } 6421 off += (size_t)n; 6422 } 6423 if (off == sizeof(gcbuf)) 6424 memcpy(&grandchild, gcbuf, sizeof(grandchild)); 6425 else 6426 grandchild = -1; 6427 } 6428 close(pipe_fds[0]); 6429 pipe_fds[0] = -1; 6430 6431 for (i = 0; i < (int)ARRAY_SIZE(ns_names); i++) 6432 if (ns_fds[i] >= 0) { 6433 close(ns_fds[i]); 6434 ns_fds[i] = -1; 6435 } 6436 6437 if (console_sock_owned && console_sock_fd >= 0) { 6438 close(console_sock_fd); 6439 console_sock_fd = -1; 6440 } 6441 6442 if (cgroup_fd >= 0) { 6443 close(cgroup_fd); 6444 cgroup_fd = -1; 6445 } else if (grandchild > 0) { 6446 cgroups_attach_pid(grandchild); 6447 } 6448 6449 container_exec_free_strarray(args); 6450 container_exec_free_strarray(env); 6451 args = env = NULL; 6452 free(exec_additional_gids); 6453 exec_additional_gids = NULL; 6454 6455 jail_clear_exit_status(pidfile); 6456 6457 if (pidfile && grandchild > 0) { 6458 FILE *pf = fopen(pidfile, "w"); 6459 if (pf) { 6460 fprintf(pf, "%d", grandchild); 6461 fclose(pf); 6462 } 6463 } 6464 6465 e = calloc(1, sizeof(*e)); 6466 if (!e) { 6467 stdio_fds_close(stdio_fds); 6468 if (notify_fd >= 0) 6469 close(notify_fd); 6470 kill(exec_pid, SIGKILL); 6471 return UBUS_STATUS_UNKNOWN_ERROR; 6472 } 6473 6474 for (i = 0; i < STDIO_FDS_NUM; i++) { 6475 e->stdio_fds[i] = stdio_fds[i]; 6476 stdio_fds[i] = -1; 6477 } 6478 e->ctx = ctx; 6479 e->exec_proc.pid = exec_pid; 6480 e->notify_fd = notify_fd; 6481 notify_fd = -1; 6482 if (pidfile) 6483 e->pidfile = strdup(pidfile); 6484 current_exec = e; 6485 6486 if (detach) { 6487 static struct blob_buf bb; 6488 6489 blob_buf_init(&bb, 0); 6490 if (grandchild > 0) 6491 blobmsg_add_u32(&bb, "pid", grandchild); 6492 ubus_send_reply(ctx, req, bb.head); 6493 6494 e->exec_proc.cb = container_exec_done_reap; 6495 uloop_process_add(&e->exec_proc); 6496 return UBUS_STATUS_OK; 6497 } 6498 6499 e->exec_proc.cb = container_exec_done_reply; 6500 uloop_process_add(&e->exec_proc); 6501 ubus_defer_request(ctx, req, &e->req); 6502 return UBUS_STATUS_OK; 6503 6504 out: 6505 stdio_fds_close(stdio_fds); 6506 if (notify_fd >= 0) 6507 close(notify_fd); 6508 for (i = 0; i < (int)ARRAY_SIZE(ns_names); i++) 6509 if (ns_fds[i] >= 0) 6510 close(ns_fds[i]); 6511 if (pipe_fds[0] >= 0) 6512 close(pipe_fds[0]); 6513 if (pipe_fds[1] >= 0) 6514 close(pipe_fds[1]); 6515 if (console_sock_owned && console_sock_fd >= 0) 6516 close(console_sock_fd); 6517 if (cgroup_fd >= 0) 6518 close(cgroup_fd); 6519 container_exec_free_strarray(args); 6520 container_exec_free_strarray(env); 6521 free(exec_additional_gids); 6522 return rc; 6523 } 6524 6525 static int 6526 jail_writepid(pid_t pid) 6527 { 6528 FILE *_pidfile; 6529 6530 if (!opts.pidfile) 6531 return 0; 6532 6533 jail_clear_exit_status(opts.pidfile); 6534 6535 _pidfile = fopen(opts.pidfile, "w"); 6536 if (_pidfile == NULL) 6537 return errno; 6538 6539 if (fprintf(_pidfile, "%d", pid) < 0) { 6540 fclose(_pidfile); 6541 return errno; 6542 } 6543 6544 if (fclose(_pidfile)) 6545 return errno; 6546 6547 return 0; 6548 } 6549 6550 static int checkpath(const char *path) 6551 { 6552 struct open_how how = { 6553 .flags = O_RDONLY | O_DIRECTORY | O_CLOEXEC, 6554 .resolve = RESOLVE_NO_MAGICLINKS, 6555 }; 6556 int dirfd = sys_openat2(AT_FDCWD, path, &how, sizeof(how)); 6557 if (dirfd < 0) { 6558 ERROR("path %s open failed %m\n", path); 6559 return -1; 6560 } 6561 close(dirfd); 6562 6563 return 0; 6564 } 6565 6566 static void prime_jail_mount(const char *path) 6567 { 6568 int fd; 6569 6570 if (!path) 6571 return; 6572 6573 fd = open(path, O_RDONLY | O_DIRECTORY | O_CLOEXEC); 6574 if (fd >= 0) 6575 close(fd); 6576 } 6577 6578 static int add_volume_source(const char *source) 6579 { 6580 char **tmp; 6581 6582 tmp = realloc(volume_sources, (num_volume_sources + 1) * sizeof(*volume_sources)); 6583 if (!tmp) 6584 return -ENOMEM; 6585 6586 volume_sources = tmp; 6587 volume_sources[num_volume_sources] = strdup(source); 6588 if (!volume_sources[num_volume_sources]) 6589 return -ENOMEM; 6590 6591 ++num_volume_sources; 6592 return 0; 6593 } 6594 6595 static void add_volume(const char *source, const char *dest) 6596 { 6597 char *real; 6598 6599 real = resolve_mount_source(source); 6600 add_volume_source(real ? real : source); 6601 add_mount_volume(real ? real : source, dest, 0); 6602 free(real); 6603 } 6604 6605 static int 6606 container_handle_delete(struct ubus_context *ctx, struct ubus_object *obj, 6607 struct ubus_request_data *req, const char *method, 6608 struct blob_attr *msg) 6609 { 6610 if (delete_deferred || (!delete_awaited && !jail_stop_requested)) 6611 return UBUS_STATUS_INVALID_ARGUMENT; 6612 6613 ubus_defer_request(ctx, req, &delete_request); 6614 delete_deferred = true; 6615 delete_requested = true; 6616 6617 if (delete_awaited) 6618 uloop_timeout_add(&container_delete_timeout); 6619 6620 return UBUS_STATUS_OK; 6621 } 6622 6623 static struct ubus_method container_methods[] = { 6624 UBUS_METHOD_NOARG("start", handle_start), 6625 UBUS_METHOD_NOARG("state", handle_state), 6626 UBUS_METHOD("kill", container_handle_kill, container_kill_attrs), 6627 UBUS_METHOD_NOARG("delete", container_handle_delete), 6628 UBUS_METHOD_NOARG("pause", container_handle_pause), 6629 UBUS_METHOD_NOARG("resume", container_handle_resume), 6630 UBUS_METHOD("reclaim", container_handle_reclaim, container_reclaim_attrs), 6631 UBUS_METHOD_NOARG("update", container_handle_update), 6632 UBUS_METHOD("exec", container_handle_exec, container_exec_attrs), 6633 }; 6634 6635 static struct ubus_object_type container_object_type = 6636 UBUS_OBJECT_TYPE("container", container_methods); 6637 6638 static struct ubus_object container_object = { 6639 .type = &container_object_type, 6640 .methods = container_methods, 6641 .n_methods = ARRAY_SIZE(container_methods), 6642 }; 6643 6644 static void netifd_restart_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, 6645 const char *type, struct blob_attr *msg); 6646 6647 static struct ubus_event_handler netifd_restart_handler = { 6648 .cb = netifd_restart_cb, 6649 }; 6650 6651 static void post_main(struct uloop_timeout *t); 6652 static struct uloop_timeout post_main_timeout = { 6653 .cb = post_main, 6654 }; 6655 static int pidns_fd; 6656 static void post_create_runtime(void); 6657 6658 struct env_e { 6659 struct list_head list; 6660 char *envarg; 6661 }; 6662 6663 int main(int argc, char **argv) 6664 { 6665 uid_t uid = getuid(); 6666 const char log[] = "/dev/log"; 6667 const char ubus[] = "/var/run/ubus/ubus.sock"; 6668 const char udebug[] = "/var/run/udebug.sock"; 6669 int ret = EXIT_FAILURE; 6670 int credidx; 6671 int ch; 6672 char *tmp; 6673 struct list_head envl = LIST_HEAD_INIT(envl); 6674 struct env_e *enve, *tmpenve; 6675 unsigned short int envn = 0, envc = 0; 6676 6677 if (uid) { 6678 ERROR("not root, aborting: %m\n"); 6679 return EXIT_FAILURE; 6680 } 6681 6682 if (restart_argv_save(argc, argv)) { 6683 ERROR("out of memory\n"); 6684 return EXIT_FAILURE; 6685 } 6686 6687 /* those are filehandlers, so -1 indicates unused */ 6688 opts.setns.pid = -1; 6689 opts.setns.net = -1; 6690 opts.setns.ns = -1; 6691 opts.setns.ipc = -1; 6692 opts.setns.uts = -1; 6693 opts.setns.user = -1; 6694 opts.setns.cgroup = -1; 6695 opts.setns.time = -1; 6696 opts.notify_fd = -1; 6697 6698 /* default 5 seconds timeout after SIGTERM before SIGKILL is sent */ 6699 opts.term_timeout = 5; 6700 6701 umask(022); 6702 mount_list_init(); 6703 init_library_search(); 6704 cgroups_prepare(); 6705 exit_from_child = false; 6706 6707 while ((ch = getopt(argc, argv, OPT_ARGS)) != -1) { 6708 switch (ch) { 6709 case 'd': 6710 debug = atoi(optarg); 6711 break; 6712 case 'e': 6713 enve = calloc(1, sizeof(*enve)); 6714 enve->envarg = optarg; 6715 list_add_tail(&enve->list, &envl); 6716 break; 6717 case 'x': 6718 opts.envfile = optarg; 6719 break; 6720 case 'p': 6721 opts.namespace |= CLONE_NEWNS; 6722 opts.procfs = 1; 6723 break; 6724 case 'o': 6725 opts.namespace |= CLONE_NEWNS; 6726 opts.ronly = 1; 6727 break; 6728 case 'f': 6729 if (opts.setns.user == -1) 6730 opts.namespace |= CLONE_NEWUSER; 6731 break; 6732 case 'F': 6733 opts.namespace |= CLONE_NEWCGROUP; 6734 break; 6735 case 'R': 6736 opts.extroot = realpath(optarg, NULL); 6737 break; 6738 case 's': 6739 opts.namespace |= CLONE_NEWNS; 6740 opts.sysfs = 1; 6741 break; 6742 case 'S': 6743 opts.seccomp = optarg; 6744 add_mount_bind(optarg, 1, -1); 6745 break; 6746 case 'C': 6747 opts.capabilities = optarg; 6748 break; 6749 case 'c': 6750 opts.no_new_privs = 1; 6751 break; 6752 case 'n': 6753 opts.name = optarg; 6754 break; 6755 case 'N': 6756 opts.namespace |= CLONE_NEWNET; 6757 break; 6758 case 'h': 6759 opts.namespace |= CLONE_NEWUTS; 6760 opts.hostname = strdup(optarg); 6761 break; 6762 case 'j': 6763 ret = jail_join_ns(optarg); 6764 if (ret) { 6765 ERROR("failed to join namespace: %s\n", 6766 strerror(ret)); 6767 return EXIT_FAILURE; 6768 } 6769 break; 6770 case 'b': 6771 if (!opts.ocibundle) 6772 opts.namespace |= CLONE_NEWNS; 6773 tmp = strchr(optarg, ':'); 6774 if (tmp) { 6775 *(tmp++) = '\0'; 6776 add_2paths_nodeps(optarg, tmp, 1, 0); 6777 } else { 6778 add_2paths_nodeps(optarg, optarg, 1, 0); 6779 } 6780 break; 6781 case 'r': 6782 if (!opts.ocibundle) 6783 opts.namespace |= CLONE_NEWNS; 6784 tmp = strchr(optarg, ':'); 6785 if (tmp) { 6786 *(tmp++) = '\0'; 6787 add_2paths_and_deps(optarg, tmp, 1, 0, 0); 6788 } else { 6789 add_path_and_deps(optarg, 1, 0, 0); 6790 } 6791 break; 6792 case 'w': 6793 if (!opts.ocibundle) 6794 opts.namespace |= CLONE_NEWNS; 6795 tmp = strchr(optarg, ':'); 6796 if (tmp) { 6797 *(tmp++) = '\0'; 6798 add_2paths_and_deps(optarg, tmp, 0, 0, 0); 6799 } else { 6800 add_path_and_deps(optarg, 0, 0, 0); 6801 } 6802 break; 6803 case 'k': 6804 if (!opts.ocibundle) 6805 opts.namespace |= CLONE_NEWNS; 6806 tmp = strchr(optarg, ':'); 6807 if (!tmp) { 6808 ERROR("credential needs a src:dest pair: %s\n", optarg); 6809 return -1; 6810 } 6811 *(tmp++) = '\0'; 6812 if (add_2paths_and_deps(optarg, tmp, 1, 0, 0)) 6813 return -1; 6814 if (n_cred_targets < JAIL_MAX_CREDENTIALS) 6815 cred_targets[n_cred_targets++] = strdup(tmp); 6816 break; 6817 case 'V': 6818 tmp = strchr(optarg, ':'); 6819 if (!tmp) { 6820 ERROR("volume needs a src:dest pair: %s\n", optarg); 6821 return -1; 6822 } 6823 *(tmp++) = '\0'; 6824 add_volume(optarg, tmp); 6825 break; 6826 case 'u': 6827 opts.namespace |= CLONE_NEWNS; 6828 add_mount_bind(ubus, 0, -1); 6829 break; 6830 case 'D': 6831 opts.namespace |= CLONE_NEWNS; 6832 add_mount_bind(udebug, 0, 0); 6833 break; 6834 case 'l': 6835 opts.namespace |= CLONE_NEWNS; 6836 add_mount_bind(log, 0, -1); 6837 break; 6838 case 'U': 6839 opts.user = optarg; 6840 break; 6841 case 'G': 6842 opts.group = optarg; 6843 break; 6844 case 'O': 6845 opts.overlaydir = realpath(optarg, NULL); 6846 break; 6847 case 't': 6848 opts.term_timeout = atoi(optarg); 6849 break; 6850 case 'T': 6851 opts.tmpoverlaysize = optarg; 6852 break; 6853 case 'E': 6854 opts.require_jail = 1; 6855 break; 6856 case 'y': 6857 opts.console = 1; 6858 break; 6859 case 'J': 6860 opts.ocibundle = optarg; 6861 break; 6862 case 'i': 6863 opts.immediately = true; 6864 break; 6865 case 'I': 6866 opts.idmap_offset = strtoul(optarg, NULL, 10); 6867 jail_set_idmap_offset(opts.idmap_offset); 6868 break; 6869 case 'P': 6870 opts.pidfile = optarg; 6871 break; 6872 case 'a': 6873 opts.notify_fd = atoi(optarg); 6874 if (opts.notify_fd <= STDERR_FILENO || 6875 fcntl(opts.notify_fd, F_SETFD, FD_CLOEXEC) || 6876 syscall(SYS_pidfd_send_signal, opts.notify_fd, 0, NULL, 0)) 6877 opts.notify_fd = -1; 6878 break; 6879 case 'A': 6880 opts.incarnation = strtoull(optarg, NULL, 10); 6881 break; 6882 case 'Y': 6883 opts.console_socket = optarg; 6884 break; 6885 case 'Z': 6886 opts.systemd_cgroup = true; 6887 break; 6888 case 'm': 6889 if (!strcmp(optarg, "trace")) 6890 opts.seccomp_mode = SECCOMP_MODE_TRACE; 6891 else if (!strcmp(optarg, "audit")) 6892 opts.seccomp_mode = SECCOMP_MODE_AUDIT; 6893 else if (!strcmp(optarg, "complain")) 6894 opts.seccomp_mode = SECCOMP_MODE_COMPLAIN; 6895 else 6896 opts.seccomp_mode = SECCOMP_MODE_ENFORCE; 6897 break; 6898 case 'M': 6899 opts.seccomp_log = optarg; 6900 break; 6901 } 6902 } 6903 6904 if (opts.console_socket && parse_inherited_console_fd(opts.console_socket) < 0) { 6905 static char fdspec[16]; 6906 bool owned; 6907 int csfd; 6908 6909 csfd = open_console_sock(opts.console_socket, &owned, false); 6910 if (csfd >= 0) { 6911 fcntl(csfd, F_SETFD, 0); 6912 snprintf(fdspec, sizeof(fdspec), "%d", csfd); 6913 opts.console_socket = fdspec; 6914 } 6915 } 6916 6917 if (opts.namespace && !opts.ocibundle) 6918 opts.namespace |= CLONE_NEWIPC | CLONE_NEWPID; 6919 6920 /* 6921 * env import from cmdline is not available for OCI containers 6922 */ 6923 if (opts.ocibundle && !list_empty(&envl)) { 6924 ret=EXIT_FAILURE; 6925 goto errout; 6926 } 6927 6928 /* 6929 * prepare list of env variables to import for slim containers 6930 */ 6931 if (!list_empty(&envl)) { 6932 list_for_each_entry(enve, &envl, list) 6933 ++envn; 6934 6935 opts.envp = calloc(1 + envn, sizeof(char*)); 6936 list_for_each_entry_safe(enve, tmpenve, &envl, list) { 6937 tmp = getenv(enve->envarg); 6938 if (tmp) { 6939 ret = asprintf(&opts.envp[envc++], "%s=%s", enve->envarg, tmp); 6940 if (ret < 0) { 6941 ERROR("filed to handle envargs %s\n", tmp); 6942 free(enve); 6943 ret=EXIT_FAILURE; 6944 goto errout; 6945 } 6946 } 6947 6948 list_del(&enve->list); 6949 free(enve); 6950 } 6951 6952 opts.envp[envc] = NULL; 6953 } 6954 6955 /* 6956 * uid in parent user namespace representing root user in new 6957 * user namespace, defaults to nobody unless specified in uidMappings 6958 */ 6959 opts.root_map_uid = 65534; 6960 6961 if (opts.capabilities && parseOCIcapabilities_from_file(&opts.capset, opts.capabilities)) { 6962 ERROR("failed to read capabilities from file %s\n", opts.capabilities); 6963 ret=EXIT_FAILURE; 6964 goto errout; 6965 } 6966 6967 if (opts.ocibundle) { 6968 char *jsonfile; 6969 int ocires; 6970 6971 ulog_open(ULOG_STDIO, LOG_DAEMON, "jail"); 6972 6973 if (!opts.name) { 6974 ERROR("OCI bundle needs a named jail\n"); 6975 ret=EXIT_FAILURE; 6976 goto errout; 6977 } 6978 6979 parent_ctx = ubus_connect(NULL); 6980 if (!parent_ctx) { 6981 ERROR("Connection to ubus failed\n"); 6982 ret = EXIT_FAILURE; 6983 goto errout; 6984 } 6985 6986 if (asprintf(&jsonfile, "%s/config.json", opts.ocibundle) < 0) { 6987 jail_reason_set("jail.internal", ENOMEM); 6988 ret=EXIT_FAILURE; 6989 goto errout; 6990 } 6991 /* an absent process.capabilities block means the empty set */ 6992 opts.capset.apply = 1; 6993 6994 ocires = parseOCI(jsonfile); 6995 free(jsonfile); 6996 if (ocires) { 6997 ERROR("parsing of OCI JSON spec has failed: %s (%d)\n", strerror(ocires), ocires); 6998 jail_reason_set("jail.bundle", ocires); 6999 ret=EXIT_FAILURE; 7000 goto errout; 7001 } 7002 7003 /* stdout and stderr belong to the container, not to us */ 7004 ulog_open(ULOG_SYSLOG, LOG_DAEMON, "jail"); 7005 } 7006 7007 if (opts.setns.ns != -1 && (opts.namespace & CLONE_NEWNS)) { 7008 ERROR("cannot build a jail filesystem in a joined mount namespace\n"); 7009 ret = EXIT_FAILURE; 7010 goto errout; 7011 } 7012 7013 /* clone(CLONE_NEWPID) after setns(CLONE_NEWPID) is EINVAL */ 7014 if (opts.setns.net != -1) 7015 opts.namespace &= ~CLONE_NEWNET; 7016 if (opts.setns.ipc != -1) 7017 opts.namespace &= ~CLONE_NEWIPC; 7018 if (opts.setns.uts != -1) 7019 opts.namespace &= ~CLONE_NEWUTS; 7020 if (opts.setns.pid != -1) 7021 opts.namespace &= ~CLONE_NEWPID; 7022 if (opts.setns.user != -1) 7023 opts.namespace &= ~CLONE_NEWUSER; 7024 if (opts.setns.cgroup != -1) 7025 opts.namespace &= ~CLONE_NEWCGROUP; 7026 7027 if (opts.setns.user != -1) 7028 joined_userns_mapped = userns_root_map(); 7029 7030 for (credidx = 0; credidx < n_cred_targets; credidx++) { 7031 ret = fs_mount_enable_idmap(cred_targets[credidx], 7032 opts.pw_uid > 0 ? (uint32_t)opts.pw_uid : 0, 7033 opts.pw_gid > 0 ? (uint32_t)opts.pw_gid : 0); 7034 if (ret) { 7035 ERROR("failed to idmap credential %s: %s\n", 7036 cred_targets[credidx], strerror(ret)); 7037 ret = EXIT_FAILURE; 7038 goto errout; 7039 } 7040 } 7041 7042 if (opts.namespace & CLONE_NEWNET) { 7043 if (!opts.name) { 7044 ERROR("netns needs a named jail\n"); 7045 ret=EXIT_FAILURE; 7046 goto errout; 7047 } 7048 } 7049 7050 7051 if (!opts.extroot && (opts.user || opts.group)) { 7052 int precheck_uid, precheck_gid, precheck_grgid; 7053 7054 get_jail_user(&precheck_uid, &precheck_gid, &precheck_grgid); 7055 } 7056 7057 if (opts.tmpoverlaysize && strlen(opts.tmpoverlaysize) > 8) { 7058 ERROR("size parameter too long: \"%s\"\n", opts.tmpoverlaysize); 7059 ret=EXIT_FAILURE; 7060 goto errout; 7061 } 7062 7063 if (opts.extroot && checkpath(opts.extroot)) { 7064 ERROR("invalid rootfs path '%s'", opts.extroot); 7065 ret=EXIT_FAILURE; 7066 goto errout; 7067 } 7068 7069 if (opts.overlaydir && checkpath(opts.overlaydir)) { 7070 ERROR("invalid rootfs overlay path '%s'", opts.overlaydir); 7071 ret=EXIT_FAILURE; 7072 goto errout; 7073 } 7074 7075 /* no <binary> param found */ 7076 if (!opts.ocibundle && (argc - optind < 1)) { 7077 usage(); 7078 ret=EXIT_FAILURE; 7079 goto errout; 7080 } 7081 if (!(opts.ocibundle||opts.namespace||opts.capabilities||opts.seccomp|| 7082 (opts.seccomp_mode != SECCOMP_MODE_ENFORCE) || 7083 (opts.setns.net != -1) || 7084 (opts.setns.ns != -1) || 7085 (opts.setns.ipc != -1) || 7086 (opts.setns.uts != -1) || 7087 (opts.setns.user != -1) || 7088 (opts.setns.cgroup != -1))) { 7089 ERROR("Not using namespaces, capabilities or seccomp !!!\n\n"); 7090 usage(); 7091 ret=EXIT_FAILURE; 7092 goto errout; 7093 } 7094 DEBUG("Using namespaces(0x%08x), capabilities(%d), seccomp(%d)\n", 7095 opts.namespace, 7096 opts.capset.apply, 7097 opts.seccomp != 0 || opts.ociseccomp != 0); 7098 7099 uloop_init(); 7100 signals_init(); 7101 7102 if (!parent_ctx) 7103 parent_ctx = ubus_connect(NULL); 7104 7105 if (!parent_ctx) { 7106 ERROR("Connection to ubus failed\n"); 7107 ret = EXIT_FAILURE; 7108 goto errout; 7109 } 7110 7111 ubus_add_uloop(parent_ctx); 7112 7113 if (opts.ocibundle) { 7114 char *objname; 7115 if (asprintf(&objname, "container.%s", opts.name) < 0) { 7116 jail_reason_set("jail.internal", ENOMEM); 7117 ret=EXIT_FAILURE; 7118 goto errout; 7119 } 7120 7121 container_object.name = objname; 7122 ret = ubus_add_object(parent_ctx, &container_object); 7123 if (ret) { 7124 ERROR("Failed to add object: %s\n", ubus_strerror(ret)); 7125 jail_reason_set("jail.name", EEXIST); 7126 ret=EXIT_FAILURE; 7127 goto errout; 7128 } 7129 container_registered = true; 7130 } 7131 7132 /* deliberately not using 'else' on unrelated conditional branches */ 7133 if (!opts.ocibundle) { 7134 /* allocate NULL-terminated array for argv */ 7135 opts.jail_argv = calloc(1 + argc - optind, sizeof(void *)); 7136 if (!opts.jail_argv) { 7137 ret=EXIT_FAILURE; 7138 goto errout; 7139 } 7140 for (size_t s = optind; s < argc; s++) 7141 opts.jail_argv[s - optind] = strdup(argv[s]); 7142 7143 if (opts.namespace & CLONE_NEWUSER) { 7144 get_jail_user(&opts.pw_uid, &opts.pw_gid, &opts.gr_gid); 7145 7146 if (!opts.uidmap && opts.user) { 7147 int primary_gid = (opts.gr_gid != -1) ? opts.gr_gid : opts.pw_gid; 7148 7149 if (!resolve_jail_user_gids(primary_gid)) 7150 WARNING("could not resolve supplementary groups for " 7151 "user %s; jail will start with no supplementary " 7152 "groups\n", opts.user); 7153 } 7154 } 7155 } 7156 7157 if (!opts.extroot) { 7158 if (opts.namespace && add_path_and_deps(*opts.jail_argv, 1, -1, 0)) { 7159 ERROR("failed to load dependencies\n"); 7160 ret=EXIT_FAILURE; 7161 goto errout; 7162 } 7163 } 7164 7165 if (opts.seccomp && !opts.ociseccomp && 7166 seccomp_compile_file(opts.seccomp)) { 7167 ERROR("failed to compile seccomp filter %s\n", opts.seccomp); 7168 opts.seccomp = 0; 7169 if (opts.require_jail) { 7170 ret=EXIT_FAILURE; 7171 goto errout; 7172 } 7173 } 7174 7175 uloop_timeout_add(&post_main_timeout); 7176 uloop_run(); 7177 7178 errout: 7179 free_and_exit(ret); 7180 return ret; 7181 } 7182 7183 static void post_prestart(void) 7184 { 7185 if (hook_chain_failed) { 7186 ERROR("prestart hook failed; aborting container\n"); 7187 jail_reason_set("hooks.prestart", ECANCELED); 7188 free_and_exit(EXIT_FAILURE); 7189 } 7190 7191 if (jail_reaped) { 7192 poststop(); 7193 return; 7194 } 7195 7196 run_hooks(opts.hooks.createRuntime, post_create_runtime); 7197 } 7198 7199 static int run_uxc_net(const char *action) 7200 { 7201 char *argv[] = { "/sbin/uxc-net", opts.name, (char *)action, opts.ocibundle, NULL }; 7202 pid_t pid; 7203 int status; 7204 7205 if (!opts.ocibundle || !opts.name) 7206 return 0; 7207 7208 pid = fork(); 7209 if (pid == 0) { 7210 execv(argv[0], argv); 7211 ERROR("failed to execv uxc-net: %m\n"); 7212 _exit(127); 7213 } else if (pid < 0) { 7214 ERROR("uxc-net fork error: %m\n"); 7215 return -1; 7216 } 7217 7218 while (waitpid(pid, &status, 0) < 0 && errno == EINTR); 7219 7220 return (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? 0 : -1; 7221 } 7222 7223 static void netifd_restart_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, 7224 const char *type, struct blob_attr *msg) 7225 { 7226 static const struct blobmsg_policy pol = { 7227 .name = "path", .type = BLOBMSG_TYPE_STRING 7228 }; 7229 struct blob_attr *tb; 7230 7231 if (!msg) 7232 return; 7233 7234 blobmsg_parse(&pol, 1, &tb, blob_data(msg), blob_len(msg)); 7235 if (!tb || strcmp(blobmsg_get_string(tb), "network.interface")) 7236 return; 7237 7238 if (!jail_running || jail_stop_requested || netifd_restart_pending) 7239 return; 7240 7241 INFO("netifd restarted, restarting the container\n"); 7242 netifd_restart_pending = true; 7243 if (jail_pidfd_send_signal(SIGTERM)) { 7244 ERROR("cannot stop the container for the restart: %m\n"); 7245 netifd_restart_pending = false; 7246 return; 7247 } 7248 uloop_timeout_set(&jail_process_timeout, UXC_STOP_TIMEOUT * 1000); 7249 } 7250 7251 static void netifd_restart_watch(void) 7252 { 7253 if (!(opts.namespace & CLONE_NEWNET) || !opts.ocibundle || !opts.name) 7254 return; 7255 7256 if (ubus_register_event_handler(parent_ctx, &netifd_restart_handler, "ubus.object.add")) 7257 WARNING("cannot watch for netifd restarts\n"); 7258 } 7259 7260 static void post_main(struct uloop_timeout *t) 7261 { 7262 int child_status; 7263 int nsret; 7264 7265 if (apply_rlimits()) { 7266 ERROR("error applying resource limits\n"); 7267 free_and_exit(EXIT_FAILURE); 7268 } 7269 7270 if (opts.name) 7271 prctl(PR_SET_NAME, opts.name, NULL, NULL, NULL); 7272 7273 if (pipe(&pipes[0]) < 0) 7274 free_and_exit(-1); 7275 7276 if (socketpair(AF_UNIX, SOCK_STREAM, 0, &pipes[2]) < 0) 7277 free_and_exit(-1); 7278 7279 if (pipe2(&userns_pipe[0], O_CLOEXEC) < 0 || pipe2(&userns_pipe[2], O_CLOEXEC) < 0) 7280 free_and_exit(-1); 7281 7282 parent_pidfd = syscall(SYS_pidfd_open, getpid(), 0); 7283 if (parent_pidfd < 0) { 7284 ERROR("pidfd_open() failed: %m\n"); 7285 free_and_exit(EXIT_FAILURE); 7286 } 7287 7288 if (pipe2(exec_ack, O_CLOEXEC) < 0) 7289 free_and_exit(-1); 7290 7291 if (opts.ocibundle) 7292 cgroups_create(); 7293 7294 if (has_namespaces()) { 7295 if (opts.namespace & CLONE_NEWNS) { 7296 if (!opts.extroot && (opts.user || opts.group)) { 7297 add_mount_bind("/etc/passwd", 1, -1); 7298 add_mount_bind("/etc/group", 1, -1); 7299 } 7300 7301 #if defined(__GLIBC__) 7302 if (!opts.extroot) 7303 add_mount_bind("/etc/nsswitch.conf", 1, -1); 7304 #endif 7305 if (opts.setns.ns == -1) { 7306 if (!(opts.namespace & CLONE_NEWNET)) { 7307 add_mount_bind("/etc/resolv.conf", 1, 0); 7308 } else if (opts.private_netifd) { 7309 char hostdir[PATH_MAX], hostresolv[PATH_MAX]; 7310 int hostresolvfd; 7311 7312 snprintf(hostdir, PATH_MAX, "/tmp/resolv.conf-%s.d", opts.name); 7313 if (mkdir_p(hostdir, 0755)) { 7314 ERROR("mkdir(%s) failed: %m\n", hostdir); 7315 free_and_exit(-1); 7316 } 7317 snprintf(hostresolv, PATH_MAX, "%s/resolv.conf.auto", hostdir); 7318 hostresolvfd = open(hostresolv, O_WRONLY | O_CREAT, 0644); 7319 if (hostresolvfd >= 0) 7320 close(hostresolvfd); 7321 add_mount(hostdir, "/dev/resolv.conf.d", NULL, 7322 MS_BIND | MS_NOEXEC | MS_NOATIME | MS_NOSUID | MS_NODEV | MS_RDONLY, 0, NULL, 0); 7323 } 7324 } 7325 /* default mounts */ 7326 add_mount(NULL, "/dev", "tmpfs", MS_NOATIME | MS_NOEXEC | MS_NOSUID, 0, "size=1M", -1); 7327 add_mount("shm", "/dev/shm", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, 0, 7328 "mode=1777,size=10%", -1); 7329 { 7330 const char *ptsopts = jail_has_userns() ? 7331 "newinstance,ptmxmode=0666,mode=0620,gid=0" : 7332 "newinstance,ptmxmode=0666,mode=0620,gid=5"; 7333 7334 add_mount(NULL, "/dev/pts", "devpts", MS_NOATIME | MS_NOEXEC | MS_NOSUID, 0, ptsopts, 0); 7335 } 7336 7337 bool defer_userns = userns_deferred(); 7338 7339 if (defer_userns) 7340 add_mount(PROCD_NOAFILE, JAIL_NOAFILE, NULL, 7341 MS_BIND | MS_RDONLY | MS_NOSUID | MS_NOEXEC | MS_NODEV, 0, NULL, -1); 7342 7343 if (opts.procfs || opts.ocibundle) { 7344 add_mount("proc", "/proc", "proc", 7345 detect_atime_flag("/proc") | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0, NULL, -1); 7346 7347 /* 7348 * hack to make /proc/sys/net read-write while the rest of /proc/sys is read-only 7349 * which cannot be expressed with OCI spec, but happends to be very useful. 7350 * Only apply it if '/proc/sys' is not already listed as mount, maskedPath or 7351 * readonlyPath. 7352 * If not running in a new network namespace, only make /proc/sys read-only. 7353 * If running in a new network namespace, temporarily stash (ie. mount-bind) 7354 * /proc/sys/net into (totally unrelated, but surely existing) /proc/self/net. 7355 * Then we mount-bind /proc/sys read-only and then mount-move /proc/self/net into 7356 * /proc/sys/net. 7357 * Mounts are established in the order they are added, so the three 7358 * steps are registered in exactly the order they have to happen in. 7359 * 7360 * A jail that defers its own CLONE_NEWUSER applies this (and all other 7361 * default masking below) itself in phase 2, once it regains its own 7362 * mount namespace: a mount locked here, while still privileged, can 7363 * never be replaced by that same, now less-privileged phase, since a 7364 * locked mount stays present underneath anything mounted over it and 7365 * still counts against the kernel's mount-visibility check for any 7366 * nested runtime's own /proc mount. 7367 */ 7368 if (!defer_userns && !mount_is_defined("/proc/sys")) { 7369 if (opts.namespace & CLONE_NEWNET) 7370 add_mount_inner("/proc/sys/net", "/proc/self/net", NULL, MS_BIND, 0, NULL, -1); 7371 7372 if (!add_mount(NULL, "/proc/sys", NULL, MS_BIND | MS_RDONLY, 0, NULL, -1) && 7373 (opts.namespace & CLONE_NEWNET)) 7374 add_mount_inner("/proc/self/net", "/proc/sys/net", NULL, MS_MOVE, 0, NULL, -1); 7375 } 7376 7377 } 7378 if (opts.sysfs || opts.ocibundle) 7379 add_mount("sysfs", "/sys", "sysfs", 7380 detect_atime_flag("/sys") | MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RDONLY, 0, NULL, -1); 7381 7382 if (!opts.ocibundle && !defer_userns) { 7383 if (opts.procfs && 7384 (mask_default_paths(proc_mask_critical, true) || 7385 mask_default_paths(proc_mask_optional, false))) 7386 free_and_exit(-1); 7387 if (opts.sysfs && mask_default_paths(sys_mask_critical, true)) 7388 free_and_exit(-1); 7389 } 7390 7391 } 7392 7393 if (opts.setns.pid != -1) { 7394 pidns_fd = ns_open_pid("pid", getpid()); 7395 nsret = setns_open(CLONE_NEWPID); 7396 if (nsret) { 7397 ERROR("failed to join pid namespace: %s\n", 7398 strerror(nsret)); 7399 free_and_exit(EXIT_FAILURE); 7400 } 7401 } else { 7402 pidns_fd = -1; 7403 } 7404 7405 if ((opts.namespace & CLONE_NEWTIME) && opts.setns.time == -1 && 7406 access("/proc/self/ns/time", F_OK)) { 7407 ERROR("kernel lacks time namespace support\n"); 7408 free_and_exit(EXIT_FAILURE); 7409 } 7410 7411 if ((opts.namespace & CLONE_NEWNS) && prepare_jail_dev()) { 7412 ERROR("prepare_jail_dev() failed\n"); 7413 free_and_exit(EXIT_FAILURE); 7414 } 7415 7416 if (jail_has_userns()) { 7417 if (opts.overlaydir) { 7418 if (chown(opts.overlaydir, opts.root_map_uid, opts.root_map_uid)) { 7419 ERROR("chown(%s, %d, %d) failed: %m\n", 7420 opts.overlaydir, opts.root_map_uid, opts.root_map_uid); 7421 free_and_exit(EXIT_FAILURE); 7422 } 7423 } 7424 if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP)) { 7425 ERROR("prctl(PR_SET_SECUREBITS) failed: %m\n"); 7426 free_and_exit(EXIT_FAILURE); 7427 } 7428 if (seteuid(opts.root_map_uid)) { 7429 ERROR("seteuid(%d) failed: %m\n", opts.root_map_uid); 7430 free_and_exit(EXIT_FAILURE); 7431 } 7432 } 7433 7434 if (opts.console) { 7435 char *slave_name; 7436 int parent_master; 7437 7438 parent_master = posix_openpt(O_RDWR | O_NOCTTY); 7439 if (parent_master < 0) { 7440 ERROR("posix_openpt: %m\n"); 7441 free_and_exit(-1); 7442 } 7443 if (grantpt(parent_master) || unlockpt(parent_master) || 7444 !(slave_name = ptsname(parent_master))) { 7445 ERROR("grantpt/unlockpt/ptsname failed\n"); 7446 close(parent_master); 7447 free_and_exit(-1); 7448 } 7449 if (opts.console_height && opts.console_width) { 7450 struct winsize ws = { 7451 .ws_row = opts.console_height, 7452 .ws_col = opts.console_width, 7453 }; 7454 ioctl(parent_master, TIOCSWINSZ, &ws); 7455 } 7456 strncpy(console_slave_name, slave_name, sizeof(console_slave_name) - 1); 7457 console_slave_name[sizeof(console_slave_name) - 1] = '\0'; 7458 if (opts.console_socket) { 7459 if (send_console_fd(opts.console_socket, parent_master, slave_name)) { 7460 ERROR("send_console_fd failed\n"); 7461 close(parent_master); 7462 free_and_exit(-1); 7463 } 7464 close(parent_master); 7465 } else { 7466 console_fd = parent_master; 7467 if (jail_has_userns() && seteuid(0)) { 7468 ERROR("seteuid(0) failed: %m\n"); 7469 free_and_exit(EXIT_FAILURE); 7470 } 7471 pass_console(console_fd); 7472 if (jail_has_userns() && seteuid(opts.root_map_uid)) { 7473 ERROR("seteuid(%d) failed: %m\n", opts.root_map_uid); 7474 free_and_exit(EXIT_FAILURE); 7475 } 7476 } 7477 } 7478 7479 /* 7480 * CLONE_NEWUSER is excluded here; the child creates its own 7481 * later, in enter_userns(). See exec_jail() for why. 7482 */ 7483 int init_cgroup_fd = -1; 7484 struct clone_args cargs = { 7485 .flags = (opts.namespace & ~(CLONE_NEWCGROUP | CLONE_NEWTIME | 7486 (userns_deferred() ? CLONE_NEWUSER : 0))) | CLONE_PIDFD, 7487 .pidfd = (__u64)(uintptr_t)&jail_process_pidfd, 7488 .exit_signal = SIGCHLD, 7489 }; 7490 7491 if (opts.ocibundle) { 7492 init_cgroup_fd = cgroups_open_dir(); 7493 if (init_cgroup_fd >= 0) { 7494 cargs.flags |= CLONE_INTO_CGROUP; 7495 cargs.cgroup = (__u64)init_cgroup_fd; 7496 } 7497 } 7498 7499 /* a clone-time userns cannot mount sysfs of a foreign netns */ 7500 if ((opts.namespace & CLONE_NEWUSER) && !userns_deferred() && 7501 !(opts.namespace & CLONE_NEWNET) && premount_sysfs()) 7502 WARNING("cannot mount sysfs for the jail: %m\n"); 7503 7504 prime_jail_mount(opts.extroot); 7505 prime_jail_mount(opts.overlaydir); 7506 for (size_t i = 0; i < (size_t)num_volume_sources; i++) 7507 prime_jail_mount(volume_sources[i]); 7508 7509 jail_process.pid = jail_clone3(&cargs); 7510 if (init_cgroup_fd >= 0) 7511 close(init_cgroup_fd); 7512 } else { 7513 jail_process.pid = fork(); 7514 } 7515 7516 if (jail_process.pid > 0) { 7517 /* parent process */ 7518 char sig_buf[1]; 7519 7520 close(parent_pidfd); 7521 uloop_process_add(&jail_process); 7522 jail_running = 1; 7523 if (seteuid(0)) { 7524 ERROR("seteuid(%d) failed: %m\n", opts.root_map_uid); 7525 free_and_exit(EXIT_FAILURE); 7526 } 7527 7528 prctl(PR_SET_SECUREBITS, 0); 7529 7530 if (jail_stop_requested) { 7531 INFO("stop requested before the jail was started\n"); 7532 jail_pidfd_send_signal(SIGKILL); 7533 while (waitpid(jail_process.pid, NULL, 0) < 0 && 7534 errno == EINTR); 7535 uloop_process_delete(&jail_process); 7536 jail_running = 0; 7537 free_and_exit(128 + SIGTERM); 7538 } 7539 7540 if (pidns_fd != -1) { 7541 setns(pidns_fd, CLONE_NEWPID); 7542 close(pidns_fd); 7543 } 7544 if (opts.setns.net != -1) 7545 close(opts.setns.net); 7546 if (opts.setns.ns != -1) 7547 close(opts.setns.ns); 7548 if (opts.setns.ipc != -1) 7549 close(opts.setns.ipc); 7550 if (opts.setns.uts != -1) 7551 close(opts.setns.uts); 7552 if (opts.setns.user != -1) 7553 close(opts.setns.user); 7554 if (opts.setns.cgroup != -1) 7555 close(opts.setns.cgroup); 7556 #ifdef CLONE_NEWTIME 7557 if (opts.setns.time != -1) 7558 close(opts.setns.time); 7559 #endif 7560 close(pipes[1]); 7561 close(pipes[2]); 7562 close(userns_pipe[1]); 7563 close(userns_pipe[2]); 7564 if (exec_ack[1] >= 0) { 7565 close(exec_ack[1]); 7566 exec_ack[1] = -1; 7567 } 7568 if (exec_ack[0] >= 0) { 7569 exec_ack_uloop.fd = exec_ack[0]; 7570 uloop_fd_add(&exec_ack_uloop, ULOOP_READ); 7571 } 7572 if (read(pipes[0], sig_buf, 1) < 1) { 7573 child_status = 0; 7574 if (waitpid(jail_process.pid, &child_status, 0) == jail_process.pid && 7575 WIFSIGNALED(child_status)) 7576 ERROR("can't read from child: killed by signal %d\n", WTERMSIG(child_status)); 7577 else if (WIFEXITED(child_status)) 7578 ERROR("can't read from child: exited %d\n", WEXITSTATUS(child_status)); 7579 else 7580 ERROR("can't read from child\n"); 7581 free_and_exit(-1); 7582 } 7583 close(pipes[0]); 7584 set_oom_score_adj(); 7585 7586 if (opts.ocibundle) { 7587 if (cgroups_configure()) 7588 free_and_exit(ENOTSUP); 7589 7590 cgroups_attach_pid(jail_process.pid); 7591 } 7592 7593 if (jail_idmap_active()) { 7594 num_idmap_fds = jail_idmap_build(opts.extroot, 7595 opts.uidmappings, opts.gidmappings, 7596 idmap_fds, JAIL_IDMAP_MAX_FDS); 7597 if (num_idmap_fds < 0) { 7598 ERROR("failed to build idmapped jail mounts\n"); 7599 free_and_exit(-1); 7600 } 7601 7602 jail_chown_writable_surfaces(); 7603 } 7604 7605 if ((opts.namespace & CLONE_NEWNET) && opts.name && opts.ocibundle && 7606 run_uxc_net("up")) { 7607 ERROR("uxc-net failed to configure the container network\n"); 7608 free_and_exit(EXIT_FAILURE); 7609 } 7610 7611 if ((opts.namespace & CLONE_NEWNET) && opts.name) 7612 jail_network_attach(parent_ctx, opts.name, jail_process.pid); 7613 7614 if ((opts.namespace & CLONE_NEWNET) && opts.private_ubus) { 7615 opts.jail_network_started = true; 7616 if (jail_network_start(parent_ctx, opts.name, jail_process.pid, 7617 opts.private_netifd)) { 7618 jail_reason_set("jail.network", EIO); 7619 free_and_exit(EXIT_FAILURE); 7620 } 7621 } 7622 7623 if (opts.netdevices && 7624 ((opts.namespace & CLONE_NEWNET) || opts.setns.net != -1) && 7625 move_netdevs_into_jail(jail_process.pid)) 7626 free_and_exit(-1); 7627 7628 if (jail_writepid(jail_process.pid)) { 7629 ERROR("failed to write pidfile: %m\n"); 7630 free_and_exit(-1); 7631 } 7632 } else if (jail_process.pid == 0) { 7633 /* fork child process */ 7634 free_and_exit(exec_jail(NULL)); 7635 } else { 7636 ERROR("failed to clone/fork: %m\n"); 7637 free_and_exit(EXIT_FAILURE); 7638 } 7639 7640 clock_gettime(CLOCK_REALTIME, &jail_created); 7641 jail_oci_state = OCI_STATE_CREATED; 7642 7643 run_hooks(opts.hooks.prestart, post_prestart); 7644 } 7645 7646 static void emit_instance_event(const char *event) 7647 { 7648 if (!opts.ocibundle || !opts.name || !parent_ctx) 7649 return; 7650 7651 if (!strcmp(event, "instance.stopped") && !exit_from_child && 7652 !cgroups_destroyed()) { 7653 ERROR("instance.stopped emitted before the cgroup was destroyed\n"); 7654 cgroups_destroy(); 7655 } 7656 7657 blob_buf_init(¬ify_buf, 0); 7658 blobmsg_add_string(¬ify_buf, "service", opts.name); 7659 blobmsg_add_string(¬ify_buf, "instance", opts.name); 7660 blobmsg_add_u32(¬ify_buf, "pid", getpid()); 7661 if (opts.incarnation) 7662 blobmsg_add_u64(¬ify_buf, "incarnation", opts.incarnation); 7663 if (!strcmp(event, "instance.stopped") || 7664 !strcmp(event, "instance.create_failed")) { 7665 if (jail_reason) 7666 blobmsg_add_string(¬ify_buf, "reason", jail_reason); 7667 if (jail_reason && jail_reason_errno) 7668 blobmsg_add_u32(¬ify_buf, "errno", 7669 jail_reason_errno); 7670 if (jail_reaped) 7671 blobmsg_add_u32(¬ify_buf, "exit_code", 7672 jail_return_code); 7673 } 7674 ubus_send_event(parent_ctx, event, notify_buf.head); 7675 } 7676 7677 static void post_poststart(void); 7678 static void poststart_dispatch(bool executed) 7679 { 7680 if (!poststart_pending) 7681 return; 7682 7683 poststart_pending = false; 7684 7685 if (executed) { 7686 run_hooks(opts.hooks.poststart, post_poststart); 7687 return; 7688 } 7689 7690 if (jail_reaped) 7691 poststop(); 7692 } 7693 7694 static void exec_ack_cb(struct uloop_fd *fd, unsigned int events) 7695 { 7696 int exec_errno = 0; 7697 ssize_t n; 7698 7699 do { 7700 n = read(fd->fd, exec_ack_buf + exec_ack_len, 7701 sizeof(exec_ack_buf) - exec_ack_len); 7702 if (n > 0) 7703 exec_ack_len += n; 7704 } while (n > 0 && exec_ack_len < sizeof(exec_ack_buf)); 7705 7706 if (n < 0 && fd->registered) 7707 return; 7708 7709 uloop_fd_delete(fd); 7710 close(fd->fd); 7711 exec_ack[0] = -1; 7712 7713 if (jail_dev_staged) { 7714 umount2(jail_dev, MNT_DETACH); 7715 rmdir(jail_dev); 7716 jail_dev_staged = false; 7717 } 7718 7719 if (!exec_ack_len) { 7720 INFO("the jail exited before its entrypoint was executed\n"); 7721 poststart_dispatch(false); 7722 return; 7723 } 7724 7725 if (exec_ack_buf[0] != EXEC_ACK_EXEC) { 7726 ERROR("container.start: unexpected exec acknowledgement\n"); 7727 poststart_dispatch(false); 7728 return; 7729 } 7730 7731 if (exec_ack_len == 1) { 7732 emit_instance_event("instance.running"); 7733 poststart_dispatch(true); 7734 return; 7735 } 7736 7737 if (exec_ack_len == sizeof(exec_ack_buf)) 7738 memcpy(&exec_errno, exec_ack_buf + 1, sizeof(exec_errno)); 7739 7740 ERROR("container.start: cannot execute the entrypoint: %s\n", 7741 exec_errno ? strerror(exec_errno) : "reason not reported"); 7742 jail_reason_set("process.args", exec_errno ?: ENOEXEC); 7743 poststart_dispatch(false); 7744 } 7745 7746 static void post_create_runtime(void) 7747 { 7748 if (hook_chain_failed) { 7749 ERROR("createRuntime hook failed; aborting container\n"); 7750 jail_reason_set("hooks.createRuntime", ECANCELED); 7751 free_and_exit(EXIT_FAILURE); 7752 } 7753 7754 if (jail_reaped) { 7755 poststop(); 7756 return; 7757 } 7758 7759 if (sock_send_fds(pipes[3], 'O', idmap_fds, num_idmap_fds) < 0) { 7760 ERROR("can't write to child\n"); 7761 free_and_exit(-1); 7762 } 7763 7764 while (num_idmap_fds > 0) 7765 close(idmap_fds[--num_idmap_fds]); 7766 7767 if ((opts.namespace & CLONE_NEWUSER) && opts.setns.user == -1) { 7768 char ubuf[1]; 7769 7770 if (xread_byte(userns_pipe[0], ubuf) < 1) { 7771 ERROR("can't read from child\n"); 7772 free_and_exit(-1); 7773 } 7774 close(userns_pipe[0]); 7775 7776 if (write_setgroups(jail_process.pid, true)) { 7777 ERROR("can't write setgroups\n"); 7778 free_and_exit(-1); 7779 } 7780 if (!opts.uidmap) { 7781 bool has_gr = (opts.gr_gid != -1); 7782 int primary_gid = has_gr ? opts.gr_gid : 7783 ((opts.pw_uid != -1) ? opts.pw_gid : 65534); 7784 int target_uid = (opts.pw_uid != -1) ? opts.pw_uid : 65534; 7785 7786 if (write_single_uid_gid_map(jail_process.pid, 0, target_uid)) { 7787 ERROR("failed to map uid %d into the jail's user " 7788 "namespace (mapping a uid other than your own " 7789 "requires CAP_SETUID, typically real root; use " 7790 "-U with your own account, run as a privileged " 7791 "user, or supply an explicit --uidmap)\n", 7792 target_uid); 7793 free_and_exit(-1); 7794 } 7795 7796 if (opts.additional_gids && opts.num_additional_gids) { 7797 char *gidmap = build_group_gidmap(primary_gid); 7798 7799 if (gidmap) { 7800 if (write_uid_gid_map(jail_process.pid, 1, gidmap)) { 7801 ERROR("failed to map supplementary groups for " 7802 "%s into the jail's user namespace " 7803 "(mapping a gid other than your own " 7804 "requires CAP_SETGID, typically real " 7805 "root)\n", opts.user); 7806 free(gidmap); 7807 free_and_exit(-1); 7808 } 7809 free(gidmap); 7810 } else { 7811 WARNING("failed to build supplementary group map for " 7812 "%s; falling back to primary gid only\n", opts.user); 7813 if (write_single_uid_gid_map(jail_process.pid, 1, primary_gid)) { 7814 ERROR("failed to map gid %d into the jail's " 7815 "user namespace (mapping a gid other " 7816 "than your own requires CAP_SETGID, " 7817 "typically real root)\n", primary_gid); 7818 free_and_exit(-1); 7819 } 7820 } 7821 } else { 7822 if (write_single_uid_gid_map(jail_process.pid, 1, primary_gid)) { 7823 ERROR("failed to map gid %d into the jail's user " 7824 "namespace (mapping a gid other than your " 7825 "own requires CAP_SETGID, typically real " 7826 "root)\n", primary_gid); 7827 free_and_exit(-1); 7828 } 7829 } 7830 } else { 7831 if (write_uid_gid_map(jail_process.pid, 0, opts.uidmap)) { 7832 ERROR("failed to write uidmap (check --uidmap values " 7833 "and privileges)\n"); 7834 free_and_exit(-1); 7835 } 7836 if (opts.gidmap && write_uid_gid_map(jail_process.pid, 1, opts.gidmap)) { 7837 ERROR("failed to write gidmap (check --gidmap values " 7838 "and privileges)\n"); 7839 free_and_exit(-1); 7840 } 7841 } 7842 7843 ubuf[0] = 'O'; 7844 if (xwrite_byte(userns_pipe[3], ubuf[0]) < 0) { 7845 ERROR("can't write to child\n"); 7846 free_and_exit(-1); 7847 } 7848 close(userns_pipe[3]); 7849 } else { 7850 close(userns_pipe[0]); 7851 close(userns_pipe[3]); 7852 } 7853 7854 jail_create_done = true; 7855 emit_instance_event("instance.ready"); 7856 7857 if (opts.ocibundle && !opts.immediately) 7858 uloop_run(); /* wait for 'start' command via ubus */ 7859 else 7860 pipe_send_start_container(NULL); 7861 } 7862 7863 static bool jail_inproc_seccomp(void) 7864 { 7865 if (seccomp_oci_needs_inproc()) 7866 return true; 7867 7868 return opts.ocibundle && !opts.no_new_privs && opts.seccomp_mode == SECCOMP_MODE_ENFORCE; 7869 } 7870 7871 static bool jail_ptrace_seccomp(void) 7872 { 7873 if (opts.seccomp_mode == SECCOMP_MODE_TRACE) 7874 return true; 7875 7876 return opts.ociseccomp && !jail_inproc_seccomp(); 7877 } 7878 7879 static void jail_seccomp_run(void) 7880 { 7881 struct seccomp_trace_opts t = { 7882 .mode = opts.seccomp_mode, 7883 .name = opts.name ? opts.name : "trace", 7884 .log_fd = -1, 7885 .main_boundary = (opts.seccomp_mode == SECCOMP_MODE_TRACE), 7886 .dedup = 0, 7887 }; 7888 int fd = -1; 7889 7890 if (opts.seccomp_log) { 7891 fd = open(opts.seccomp_log, O_WRONLY | O_CREAT | O_TRUNC, 0644); 7892 if (fd < 0) 7893 ERROR("seccomp-trace: cannot open log %s: %m\n", opts.seccomp_log); 7894 t.log_fd = fd; 7895 } 7896 7897 seccomp_trace_run(jail_process.pid, &t); 7898 7899 if (fd >= 0) 7900 close(fd); 7901 7902 free_and_exit(0); 7903 } 7904 7905 static bool seccomp_target_is_static(pid_t pid) 7906 { 7907 unsigned long pair[2]; 7908 bool dynamic = false; 7909 char path[32]; 7910 FILE *f; 7911 7912 snprintf(path, sizeof(path), "/proc/%d/auxv", (int)pid); 7913 f = fopen(path, "rb"); 7914 if (!f) 7915 return false; 7916 7917 while (fread(pair, sizeof(pair), 1, f) == 1) { 7918 if (pair[0] == 0) 7919 break; 7920 if (pair[0] == 7 && pair[1]) 7921 dynamic = true; 7922 } 7923 fclose(f); 7924 return !dynamic; 7925 } 7926 7927 static bool seccomp_main_trackable(pid_t pid) 7928 { 7929 unsigned long at_entry, lsm; 7930 int main_argidx; 7931 7932 if (seccomp_marker_addrs(pid, &at_entry, &lsm, &main_argidx)) 7933 return false; 7934 7935 return lsm != 0; 7936 } 7937 7938 static int jail_seccomp_handshake(void) 7939 { 7940 struct sock_fprog *aprog; 7941 int status, rc, mrc; 7942 7943 if (!jail_ptrace_seccomp()) 7944 return 0; 7945 7946 while (waitpid(jail_process.pid, &status, 0) < 0) { 7947 if (errno == EINTR) 7948 continue; 7949 ERROR("seccomp-inject: waitpid: %m\n"); 7950 return -1; 7951 } 7952 7953 if (!WIFSTOPPED(status)) { 7954 if (WIFEXITED(status)) 7955 ERROR("seccomp-inject: jail exited (code %d) before entrypoint exec\n", WEXITSTATUS(status)); 7956 else if (WIFSIGNALED(status)) 7957 ERROR("seccomp-inject: jail killed by signal %d before entrypoint exec\n", WTERMSIG(status)); 7958 else 7959 ERROR("seccomp-inject: jail exited before entrypoint exec\n"); 7960 uloop_process_delete(&jail_process); 7961 jail_process_handler(&jail_process, status); 7962 return -1; 7963 } 7964 7965 if (opts.seccomp_mode == SECCOMP_MODE_TRACE) 7966 jail_seccomp_run(); 7967 7968 if (opts.seccomp_mode == SECCOMP_MODE_ENFORCE && 7969 seccomp_target_is_static(jail_process.pid)) { 7970 if (opts.ociseccomp_init && 7971 seccomp_main_trackable(jail_process.pid)) { 7972 if (seccomp_inject(jail_process.pid, opts.ociseccomp_init)) { 7973 ERROR("seccomp-inject: failed to arm init filter\n"); 7974 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 7975 return -1; 7976 } 7977 if (seccomp_run_to_main(jail_process.pid)) { 7978 ERROR("seccomp-inject: failed to reach main\n"); 7979 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 7980 return -1; 7981 } 7982 if (opts.ociseccomp_delta_main && 7983 seccomp_inject(jail_process.pid, opts.ociseccomp_delta_main)) { 7984 ERROR("seccomp-inject: failed to arm main delta\n"); 7985 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 7986 return -1; 7987 } 7988 } else if (seccomp_inject(jail_process.pid, opts.ociseccomp)) { 7989 ERROR("seccomp-inject: failed to arm filter\n"); 7990 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 7991 return -1; 7992 } 7993 if (ptrace(PTRACE_DETACH, jail_process.pid, 0, 0)) { 7994 ERROR("seccomp-inject: PTRACE_DETACH: %m\n"); 7995 return -1; 7996 } 7997 return 0; 7998 } 7999 8000 if (opts.seccomp_mode == SECCOMP_MODE_ENFORCE && !opts.ociseccomp_linker) { 8001 if (seccomp_inject(jail_process.pid, opts.ociseccomp)) { 8002 ERROR("seccomp-inject: failed to arm filter\n"); 8003 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8004 return -1; 8005 } 8006 if (ptrace(PTRACE_DETACH, jail_process.pid, 0, 0)) { 8007 ERROR("seccomp-inject: PTRACE_DETACH: %m\n"); 8008 return -1; 8009 } 8010 return 0; 8011 } 8012 8013 if (opts.seccomp_mode == SECCOMP_MODE_ENFORCE && opts.ociseccomp_linker && 8014 seccomp_inject(jail_process.pid, opts.ociseccomp_linker)) { 8015 ERROR("seccomp-inject: failed to arm linker filter\n"); 8016 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8017 return -1; 8018 } 8019 8020 if (seccomp_run_to_entry(jail_process.pid)) { 8021 ERROR("seccomp-inject: failed to reach entry point\n"); 8022 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8023 return -1; 8024 } 8025 8026 if (opts.seccomp_mode == SECCOMP_MODE_AUDIT || 8027 opts.seccomp_mode == SECCOMP_MODE_COMPLAIN) { 8028 aprog = seccomp_oci_audit_filter(opts.ociseccomp); 8029 if (!aprog) { 8030 ERROR("seccomp-trace: failed to build audit filter\n"); 8031 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8032 return -1; 8033 } 8034 rc = seccomp_inject(jail_process.pid, aprog); 8035 free(aprog->filter); 8036 free(aprog); 8037 if (rc) { 8038 ERROR("seccomp-trace: failed to arm audit filter\n"); 8039 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8040 return -1; 8041 } 8042 jail_seccomp_run(); 8043 } 8044 8045 if (opts.seccomp_mode == SECCOMP_MODE_ENFORCE) { 8046 if (opts.ociseccomp_delta_entry && 8047 seccomp_inject(jail_process.pid, opts.ociseccomp_delta_entry)) { 8048 ERROR("seccomp-inject: failed to arm entry delta\n"); 8049 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8050 return -1; 8051 } 8052 } else if (opts.ociseccomp_init && 8053 seccomp_inject(jail_process.pid, opts.ociseccomp_init)) { 8054 ERROR("seccomp-inject: failed to arm init filter\n"); 8055 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8056 return -1; 8057 } 8058 8059 mrc = seccomp_run_to_main_from_entry(jail_process.pid); 8060 if (mrc < 0) { 8061 ERROR("seccomp-inject: failed to reach main\n"); 8062 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8063 return -1; 8064 } 8065 8066 if (opts.seccomp_mode == SECCOMP_MODE_ENFORCE) { 8067 if (opts.ociseccomp_delta_main && 8068 seccomp_inject(jail_process.pid, opts.ociseccomp_delta_main)) { 8069 ERROR("seccomp-inject: failed to arm main delta\n"); 8070 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8071 return -1; 8072 } 8073 } else if (seccomp_inject(jail_process.pid, opts.ociseccomp)) { 8074 ERROR("seccomp-inject: failed to arm filter\n"); 8075 ptrace(PTRACE_KILL, jail_process.pid, 0, 0); 8076 return -1; 8077 } 8078 8079 if (ptrace(PTRACE_DETACH, jail_process.pid, 0, 0)) { 8080 ERROR("seccomp-inject: PTRACE_DETACH: %m\n"); 8081 return -1; 8082 } 8083 8084 return 0; 8085 } 8086 8087 static void pipe_send_start_container(struct uloop_timeout *t) 8088 { 8089 char sig_buf[1]; 8090 8091 jail_oci_state = OCI_STATE_RUNNING; 8092 sig_buf[0] = '!'; 8093 if (write(pipes[3], sig_buf, 1) < 0) { 8094 ERROR("can't write to child\n"); 8095 free_and_exit(-1); 8096 } 8097 close(pipes[3]); 8098 8099 if (jail_seccomp_handshake()) { 8100 if (!jail_reaped) 8101 free_and_exit(-1); 8102 8103 return; 8104 } 8105 8106 poststart_pending = true; 8107 } 8108 8109 static void post_poststart(void) 8110 { 8111 if (hook_chain_failed) { 8112 ERROR("poststart hook failed; stopping container\n"); 8113 jail_reason_set("hooks.poststart", ECANCELED); 8114 } else if (!jail_reaped) { 8115 netifd_restart_watch(); 8116 uloop_run(); /* idle here while jail is running */ 8117 } 8118 8119 if (jail_running) { 8120 DEBUG("killing jail process\n"); 8121 jail_pidfd_send_signal(SIGTERM); 8122 uloop_timeout_set(&jail_process_timeout, 1000); 8123 uloop_run(); 8124 } 8125 8126 poststop(); 8127 } 8128 8129 static void poststop(void) 8130 { 8131 jail_oci_state = OCI_STATE_STOPPED; 8132 8133 if (jail_restarting()) 8134 jail_reason_set("jail.restart", 0); 8135 else 8136 notify_signal(opts.notify_fd); 8137 8138 if (opts.jail_network_started) { 8139 jail_network_teardown(); 8140 opts.jail_network_started = false; 8141 } 8142 if ((opts.namespace & CLONE_NEWNET) && opts.name && opts.ocibundle) 8143 run_uxc_net("down"); 8144 8145 if (opts.ocibundle && container_registered) 8146 cgroups_destroy(); 8147 8148 stop_announced = true; 8149 emit_instance_event(container_registered ? "instance.stopped" : 8150 "instance.create_failed"); 8151 8152 /* a restart re-execs in place, so no delete will ever follow it */ 8153 if (opts.ocibundle && container_registered && !jail_restarting() && 8154 !delete_requested) { 8155 delete_awaited = true; 8156 return; 8157 } 8158 8159 poststop_hooks(); 8160 } 8161
This page was automatically generated by LXR 0.3.1. • OpenWrt