• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/procd/jail/jail.c

  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, &notify_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(&notify_buf, 0);
7658         blobmsg_add_string(&notify_buf, "service", opts.name);
7659         blobmsg_add_string(&notify_buf, "instance", opts.name);
7660         blobmsg_add_u32(&notify_buf, "pid", getpid());
7661         if (opts.incarnation)
7662                 blobmsg_add_u64(&notify_buf, "incarnation", opts.incarnation);
7663         if (!strcmp(event, "instance.stopped") ||
7664             !strcmp(event, "instance.create_failed")) {
7665                 if (jail_reason)
7666                         blobmsg_add_string(&notify_buf, "reason", jail_reason);
7667                 if (jail_reason && jail_reason_errno)
7668                         blobmsg_add_u32(&notify_buf, "errno",
7669                                         jail_reason_errno);
7670                 if (jail_reaped)
7671                         blobmsg_add_u32(&notify_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