Lines Matching +full:- +full:j
2 * Use of this source code is governed by a BSD-style license that can be
40 #include "libminijail-private.h"
54 /* New cgroup namespace might not be in linux-headers yet. */
214 static void run_hooks_or_die(const struct minijail *j,
217 static bool seccomp_is_logging_allowed(const struct minijail *j) in seccomp_is_logging_allowed() argument
219 return seccomp_default_ret_log() || j->flags.seccomp_filter_logging; in seccomp_is_logging_allowed()
222 static void free_mounts_list(struct minijail *j) in free_mounts_list() argument
224 while (j->mounts_head) { in free_mounts_list()
225 struct mountpoint *m = j->mounts_head; in free_mounts_list()
226 j->mounts_head = j->mounts_head->next; in free_mounts_list()
227 free(m->data); in free_mounts_list()
228 free(m->type); in free_mounts_list()
229 free(m->dest); in free_mounts_list()
230 free(m->src); in free_mounts_list()
234 j->mounts_tail = NULL; in free_mounts_list()
237 static void free_remounts_list(struct minijail *j) in free_remounts_list() argument
239 while (j->remounts_head) { in free_remounts_list()
240 struct minijail_remount *m = j->remounts_head; in free_remounts_list()
241 j->remounts_head = j->remounts_head->next; in free_remounts_list()
242 free(m->mount_name); in free_remounts_list()
246 j->remounts_tail = NULL; in free_remounts_list()
262 return -errno; in write_exactly()
266 n -= written; in write_exactly()
272 /* Closes *pfd and sets it to -1. */
275 if (*pfd != -1) in close_and_reset()
277 *pfd = -1; in close_and_reset()
285 void minijail_preenter(struct minijail *j) in minijail_preenter() argument
287 j->flags.vfs = 0; in minijail_preenter()
288 j->flags.enter_vfs = 0; in minijail_preenter()
289 j->flags.ns_cgroups = 0; in minijail_preenter()
290 j->flags.net = 0; in minijail_preenter()
291 j->flags.uts = 0; in minijail_preenter()
292 j->flags.remount_proc_ro = 0; in minijail_preenter()
293 j->flags.pids = 0; in minijail_preenter()
294 j->flags.do_init = 0; in minijail_preenter()
295 j->flags.run_as_init = 0; in minijail_preenter()
296 j->flags.pid_file = 0; in minijail_preenter()
297 j->flags.cgroups = 0; in minijail_preenter()
298 j->flags.forward_signals = 0; in minijail_preenter()
299 j->flags.setsid = 0; in minijail_preenter()
300 j->remount_mode = 0; in minijail_preenter()
301 free_remounts_list(j); in minijail_preenter()
305 int add_fs_restriction_path(struct minijail *j, in add_fs_restriction_path() argument
311 return -ENOMEM; in add_fs_restriction_path()
312 r->path = strdup(path); in add_fs_restriction_path()
313 r->landlock_flags = landlock_flags; in add_fs_restriction_path()
315 if (j->fs_rules_tail) { in add_fs_restriction_path()
316 j->fs_rules_tail->next = r; in add_fs_restriction_path()
317 j->fs_rules_tail = r; in add_fs_restriction_path()
319 j->fs_rules_head = r; in add_fs_restriction_path()
320 j->fs_rules_tail = r; in add_fs_restriction_path()
327 return !!(m->flags & MS_BIND); in mount_has_bind_flag()
331 return !!(m->flags & MS_RDONLY); in mount_has_readonly_flag()
335 return !!(m->flags & MS_SHARED) || !!(m->flags & MS_SLAVE); in mount_events_allowed()
342 void minijail_preexec(struct minijail *j) in minijail_preexec() argument
344 int vfs = j->flags.vfs; in minijail_preexec()
345 int enter_vfs = j->flags.enter_vfs; in minijail_preexec()
346 int ns_cgroups = j->flags.ns_cgroups; in minijail_preexec()
347 int net = j->flags.net; in minijail_preexec()
348 int uts = j->flags.uts; in minijail_preexec()
349 int remount_proc_ro = j->flags.remount_proc_ro; in minijail_preexec()
350 int userns = j->flags.userns; in minijail_preexec()
351 if (j->user) in minijail_preexec()
352 free(j->user); in minijail_preexec()
353 j->user = NULL; in minijail_preexec()
354 if (j->suppl_gid_list) in minijail_preexec()
355 free(j->suppl_gid_list); in minijail_preexec()
356 j->suppl_gid_list = NULL; in minijail_preexec()
357 if (j->preload_path) in minijail_preexec()
358 free(j->preload_path); in minijail_preexec()
359 j->preload_path = NULL; in minijail_preexec()
360 free_mounts_list(j); in minijail_preexec()
361 memset(&j->flags, 0, sizeof(j->flags)); in minijail_preexec()
363 j->flags.vfs = vfs; in minijail_preexec()
364 j->flags.enter_vfs = enter_vfs; in minijail_preexec()
365 j->flags.ns_cgroups = ns_cgroups; in minijail_preexec()
366 j->flags.net = net; in minijail_preexec()
367 j->flags.uts = uts; in minijail_preexec()
368 j->flags.remount_proc_ro = remount_proc_ro; in minijail_preexec()
369 j->flags.userns = userns; in minijail_preexec()
377 struct minijail *j = calloc(1, sizeof(struct minijail)); in minijail_new() local
378 if (j) { in minijail_new()
379 j->remount_mode = MS_PRIVATE; in minijail_new()
380 j->using_minimalistic_mountns = false; in minijail_new()
382 return j; in minijail_new()
385 void API minijail_change_uid(struct minijail *j, uid_t uid) in minijail_change_uid() argument
389 j->uid = uid; in minijail_change_uid()
390 j->flags.uid = 1; in minijail_change_uid()
393 void API minijail_change_gid(struct minijail *j, gid_t gid) in minijail_change_gid() argument
397 j->gid = gid; in minijail_change_gid()
398 j->flags.gid = 1; in minijail_change_gid()
401 void API minijail_set_supplementary_gids(struct minijail *j, size_t size, in minijail_set_supplementary_gids() argument
406 if (j->flags.inherit_suppl_gids) in minijail_set_supplementary_gids()
408 if (j->flags.keep_suppl_gids) in minijail_set_supplementary_gids()
413 j->suppl_gid_list = NULL; in minijail_set_supplementary_gids()
414 j->suppl_gid_count = 0; in minijail_set_supplementary_gids()
415 j->flags.set_suppl_gids = 1; in minijail_set_supplementary_gids()
420 j->suppl_gid_list = calloc(size, sizeof(gid_t)); in minijail_set_supplementary_gids()
421 if (!j->suppl_gid_list) { in minijail_set_supplementary_gids()
425 j->suppl_gid_list[i] = list[i]; in minijail_set_supplementary_gids()
427 j->suppl_gid_count = size; in minijail_set_supplementary_gids()
428 j->flags.set_suppl_gids = 1; in minijail_set_supplementary_gids()
431 void API minijail_keep_supplementary_gids(struct minijail *j) in minijail_keep_supplementary_gids() argument
433 j->flags.keep_suppl_gids = 1; in minijail_keep_supplementary_gids()
436 int API minijail_change_user(struct minijail *j, const char *user) in minijail_change_user() argument
443 minijail_change_uid(j, uid); in minijail_change_user()
444 j->user = strdup(user); in minijail_change_user()
445 if (!j->user) in minijail_change_user()
446 return -ENOMEM; in minijail_change_user()
447 j->usergid = gid; in minijail_change_user()
451 int API minijail_change_group(struct minijail *j, const char *group) in minijail_change_group() argument
457 minijail_change_gid(j, gid); in minijail_change_group()
461 void API minijail_use_seccomp(struct minijail *j) in minijail_use_seccomp() argument
463 j->flags.seccomp = 1; in minijail_use_seccomp()
466 void API minijail_no_new_privs(struct minijail *j) in minijail_no_new_privs() argument
468 j->flags.no_new_privs = 1; in minijail_no_new_privs()
471 void API minijail_use_seccomp_filter(struct minijail *j) in minijail_use_seccomp_filter() argument
473 j->flags.seccomp_filter = 1; in minijail_use_seccomp_filter()
476 void API minijail_set_seccomp_filter_tsync(struct minijail *j) in minijail_set_seccomp_filter_tsync() argument
478 if (j->filter_len > 0 && j->filter_prog != NULL) { in minijail_set_seccomp_filter_tsync()
483 if (seccomp_is_logging_allowed(j) && !seccomp_ret_log_available()) { in minijail_set_seccomp_filter_tsync()
493 j->flags.seccomp_filter_tsync = 1; in minijail_set_seccomp_filter_tsync()
496 void API minijail_set_seccomp_filter_allow_speculation(struct minijail *j) in minijail_set_seccomp_filter_allow_speculation() argument
498 if (j->filter_len > 0 && j->filter_prog != NULL) { in minijail_set_seccomp_filter_allow_speculation()
503 j->flags.seccomp_filter_allow_speculation = 1; in minijail_set_seccomp_filter_allow_speculation()
506 void API minijail_log_seccomp_filter_failures(struct minijail *j) in minijail_log_seccomp_filter_failures() argument
508 if (j->filter_len > 0 && j->filter_prog != NULL) { in minijail_log_seccomp_filter_failures()
513 if (j->flags.seccomp_filter_tsync && !seccomp_ret_log_available()) { in minijail_log_seccomp_filter_failures()
524 j->flags.seccomp_filter_logging = 1; in minijail_log_seccomp_filter_failures()
526 warn("non-debug build: ignoring request to enable seccomp " in minijail_log_seccomp_filter_failures()
531 void API minijail_set_using_minimalistic_mountns(struct minijail *j) in minijail_set_using_minimalistic_mountns() argument
533 j->using_minimalistic_mountns = true; in minijail_set_using_minimalistic_mountns()
536 void API minijail_add_minimalistic_mountns_fs_rules(struct minijail *j) in minijail_add_minimalistic_mountns_fs_rules() argument
538 struct mountpoint *m = j->mounts_head; in minijail_add_minimalistic_mountns_fs_rules()
540 if (!j->using_minimalistic_mountns) in minijail_add_minimalistic_mountns_fs_rules()
546 minijail_add_fs_restriction_rx(j, m->dest); in minijail_add_minimalistic_mountns_fs_rules()
549 minijail_add_fs_restriction_rw(j, m->dest); in minijail_add_minimalistic_mountns_fs_rules()
550 m = m->next; in minijail_add_minimalistic_mountns_fs_rules()
553 minijail_enable_default_fs_restrictions(j); in minijail_add_minimalistic_mountns_fs_rules()
554 minijail_add_fs_restriction_edit(j, "/dev"); in minijail_add_minimalistic_mountns_fs_rules()
555 minijail_add_fs_restriction_ro(j, "/proc"); in minijail_add_minimalistic_mountns_fs_rules()
556 if (j->flags.vfs) in minijail_add_minimalistic_mountns_fs_rules()
557 minijail_add_fs_restriction_rw(j, "/tmp"); in minijail_add_minimalistic_mountns_fs_rules()
561 void API minijail_enable_default_fs_restrictions(struct minijail *j) in minijail_enable_default_fs_restrictions() argument
564 minijail_add_fs_restriction_rx(j, "/lib"); in minijail_enable_default_fs_restrictions()
565 minijail_add_fs_restriction_rx(j, "/lib64"); in minijail_enable_default_fs_restrictions()
566 minijail_add_fs_restriction_rx(j, "/usr/lib"); in minijail_enable_default_fs_restrictions()
567 minijail_add_fs_restriction_rx(j, "/usr/lib64"); in minijail_enable_default_fs_restrictions()
569 minijail_add_fs_restriction_rx(j, "/bin"); in minijail_enable_default_fs_restrictions()
570 minijail_add_fs_restriction_rx(j, "/sbin"); in minijail_enable_default_fs_restrictions()
571 minijail_add_fs_restriction_rx(j, "/usr/sbin"); in minijail_enable_default_fs_restrictions()
572 minijail_add_fs_restriction_rx(j, "/usr/bin"); in minijail_enable_default_fs_restrictions()
575 void API minijail_use_caps(struct minijail *j, uint64_t capmask) in minijail_use_caps() argument
578 * 'minijail_use_caps' configures a runtime-capabilities-only in minijail_use_caps()
585 if (j->flags.capbset_drop) { in minijail_use_caps()
587 j->cap_bset = 0; in minijail_use_caps()
588 j->flags.capbset_drop = 0; in minijail_use_caps()
590 j->caps = capmask; in minijail_use_caps()
591 j->flags.use_caps = 1; in minijail_use_caps()
594 void API minijail_capbset_drop(struct minijail *j, uint64_t capmask) in minijail_capbset_drop() argument
596 if (j->flags.use_caps) { in minijail_capbset_drop()
607 j->cap_bset = capmask; in minijail_capbset_drop()
608 j->flags.capbset_drop = 1; in minijail_capbset_drop()
611 void API minijail_set_ambient_caps(struct minijail *j) in minijail_set_ambient_caps() argument
613 j->flags.set_ambient_caps = 1; in minijail_set_ambient_caps()
616 void API minijail_reset_signal_mask(struct minijail *j) in minijail_reset_signal_mask() argument
618 j->flags.reset_signal_mask = 1; in minijail_reset_signal_mask()
621 void API minijail_reset_signal_handlers(struct minijail *j) in minijail_reset_signal_handlers() argument
623 j->flags.reset_signal_handlers = 1; in minijail_reset_signal_handlers()
626 void API minijail_namespace_vfs(struct minijail *j) in minijail_namespace_vfs() argument
628 j->flags.vfs = 1; in minijail_namespace_vfs()
631 void API minijail_namespace_enter_vfs(struct minijail *j, const char *ns_path) in minijail_namespace_enter_vfs() argument
638 j->mountns_fd = ns_fd; in minijail_namespace_enter_vfs()
639 j->flags.enter_vfs = 1; in minijail_namespace_enter_vfs()
642 void API minijail_new_session_keyring(struct minijail *j) in minijail_new_session_keyring() argument
644 j->flags.new_session_keyring = 1; in minijail_new_session_keyring()
647 void API minijail_skip_setting_securebits(struct minijail *j, in minijail_skip_setting_securebits() argument
650 j->securebits_skip_mask = securebits_skip_mask; in minijail_skip_setting_securebits()
653 void API minijail_remount_mode(struct minijail *j, unsigned long mode) in minijail_remount_mode() argument
655 j->remount_mode = mode; in minijail_remount_mode()
658 void API minijail_skip_remount_private(struct minijail *j) in minijail_skip_remount_private() argument
660 j->remount_mode = 0; in minijail_skip_remount_private()
663 void API minijail_namespace_pids(struct minijail *j) in minijail_namespace_pids() argument
665 j->flags.vfs = 1; in minijail_namespace_pids()
666 j->flags.remount_proc_ro = 1; in minijail_namespace_pids()
667 j->flags.pids = 1; in minijail_namespace_pids()
668 j->flags.do_init = 1; in minijail_namespace_pids()
671 void API minijail_namespace_pids_rw_proc(struct minijail *j) in minijail_namespace_pids_rw_proc() argument
673 j->flags.vfs = 1; in minijail_namespace_pids_rw_proc()
674 j->flags.pids = 1; in minijail_namespace_pids_rw_proc()
675 j->flags.do_init = 1; in minijail_namespace_pids_rw_proc()
678 void API minijail_namespace_ipc(struct minijail *j) in minijail_namespace_ipc() argument
680 j->flags.ipc = 1; in minijail_namespace_ipc()
683 void API minijail_namespace_uts(struct minijail *j) in minijail_namespace_uts() argument
685 j->flags.uts = 1; in minijail_namespace_uts()
688 int API minijail_namespace_set_hostname(struct minijail *j, const char *name) in minijail_namespace_set_hostname() argument
690 if (j->hostname) in minijail_namespace_set_hostname()
691 return -EINVAL; in minijail_namespace_set_hostname()
692 minijail_namespace_uts(j); in minijail_namespace_set_hostname()
693 j->hostname = strdup(name); in minijail_namespace_set_hostname()
694 if (!j->hostname) in minijail_namespace_set_hostname()
695 return -ENOMEM; in minijail_namespace_set_hostname()
699 void API minijail_namespace_net(struct minijail *j) in minijail_namespace_net() argument
701 j->flags.net = 1; in minijail_namespace_net()
704 void API minijail_namespace_enter_net(struct minijail *j, const char *ns_path) in minijail_namespace_enter_net() argument
711 j->netns_fd = ns_fd; in minijail_namespace_enter_net()
712 j->flags.enter_net = 1; in minijail_namespace_enter_net()
715 void API minijail_namespace_cgroups(struct minijail *j) in minijail_namespace_cgroups() argument
717 j->flags.ns_cgroups = 1; in minijail_namespace_cgroups()
720 void API minijail_close_open_fds(struct minijail *j) in minijail_close_open_fds() argument
722 j->flags.close_open_fds = 1; in minijail_close_open_fds()
725 void API minijail_remount_proc_readonly(struct minijail *j) in minijail_remount_proc_readonly() argument
727 j->flags.vfs = 1; in minijail_remount_proc_readonly()
728 j->flags.remount_proc_ro = 1; in minijail_remount_proc_readonly()
731 void API minijail_namespace_user(struct minijail *j) in minijail_namespace_user() argument
733 j->flags.userns = 1; in minijail_namespace_user()
736 void API minijail_namespace_user_disable_setgroups(struct minijail *j) in minijail_namespace_user_disable_setgroups() argument
738 j->flags.disable_setgroups = 1; in minijail_namespace_user_disable_setgroups()
741 int API minijail_uidmap(struct minijail *j, const char *uidmap) in minijail_uidmap() argument
743 j->uidmap = strdup(uidmap); in minijail_uidmap()
744 if (!j->uidmap) in minijail_uidmap()
745 return -ENOMEM; in minijail_uidmap()
747 for (ch = j->uidmap; *ch; ch++) { in minijail_uidmap()
754 int API minijail_gidmap(struct minijail *j, const char *gidmap) in minijail_gidmap() argument
756 j->gidmap = strdup(gidmap); in minijail_gidmap()
757 if (!j->gidmap) in minijail_gidmap()
758 return -ENOMEM; in minijail_gidmap()
760 for (ch = j->gidmap; *ch; ch++) { in minijail_gidmap()
767 void API minijail_inherit_usergroups(struct minijail *j) in minijail_inherit_usergroups() argument
769 j->flags.inherit_suppl_gids = 1; in minijail_inherit_usergroups()
772 void API minijail_run_as_init(struct minijail *j) in minijail_run_as_init() argument
778 j->flags.run_as_init = 1; in minijail_run_as_init()
781 int API minijail_enter_chroot(struct minijail *j, const char *dir) in minijail_enter_chroot() argument
783 if (j->chrootdir) in minijail_enter_chroot()
784 return -EINVAL; in minijail_enter_chroot()
785 j->chrootdir = strdup(dir); in minijail_enter_chroot()
786 if (!j->chrootdir) in minijail_enter_chroot()
787 return -ENOMEM; in minijail_enter_chroot()
788 j->flags.chroot = 1; in minijail_enter_chroot()
792 int API minijail_enter_pivot_root(struct minijail *j, const char *dir) in minijail_enter_pivot_root() argument
794 if (j->chrootdir) in minijail_enter_pivot_root()
795 return -EINVAL; in minijail_enter_pivot_root()
796 j->chrootdir = strdup(dir); in minijail_enter_pivot_root()
797 if (!j->chrootdir) in minijail_enter_pivot_root()
798 return -ENOMEM; in minijail_enter_pivot_root()
799 j->flags.pivot_root = 1; in minijail_enter_pivot_root()
803 char API *minijail_get_original_path(struct minijail *j, in minijail_get_original_path() argument
808 b = j->mounts_head; in minijail_get_original_path()
814 * for example: "-b /some/path/exe,/chroot/path/exe" in minijail_get_original_path()
820 if (streq(b->dest, path_inside_chroot)) in minijail_get_original_path()
821 return strdup(b->src); in minijail_get_original_path()
829 if (!strncmp(b->dest, path_inside_chroot, strlen(b->dest))) { in minijail_get_original_path()
831 path_inside_chroot + strlen(b->dest); in minijail_get_original_path()
832 return path_join(b->src, relative_path); in minijail_get_original_path()
834 b = b->next; in minijail_get_original_path()
838 if (j->chrootdir) in minijail_get_original_path()
839 return path_join(j->chrootdir, path_inside_chroot); in minijail_get_original_path()
845 void API minijail_mount_dev(struct minijail *j) in minijail_mount_dev() argument
847 j->flags.mount_dev = 1; in minijail_mount_dev()
850 void API minijail_mount_tmp(struct minijail *j) in minijail_mount_tmp() argument
852 minijail_mount_tmp_size(j, 64 * 1024 * 1024); in minijail_mount_tmp()
855 void API minijail_mount_tmp_size(struct minijail *j, size_t size) in minijail_mount_tmp_size() argument
857 j->tmpfs_size = size; in minijail_mount_tmp_size()
858 j->flags.mount_tmp = 1; in minijail_mount_tmp_size()
861 int API minijail_write_pid_file(struct minijail *j, const char *path) in minijail_write_pid_file() argument
863 j->pid_file_path = strdup(path); in minijail_write_pid_file()
864 if (!j->pid_file_path) in minijail_write_pid_file()
865 return -ENOMEM; in minijail_write_pid_file()
866 j->flags.pid_file = 1; in minijail_write_pid_file()
870 int API minijail_add_to_cgroup(struct minijail *j, const char *path) in minijail_add_to_cgroup() argument
872 if (j->cgroup_count >= MAX_CGROUPS) in minijail_add_to_cgroup()
873 return -ENOMEM; in minijail_add_to_cgroup()
874 j->cgroups[j->cgroup_count] = strdup(path); in minijail_add_to_cgroup()
875 if (!j->cgroups[j->cgroup_count]) in minijail_add_to_cgroup()
876 return -ENOMEM; in minijail_add_to_cgroup()
877 j->cgroup_count++; in minijail_add_to_cgroup()
878 j->flags.cgroups = 1; in minijail_add_to_cgroup()
882 int API minijail_rlimit(struct minijail *j, int type, rlim_t cur, rlim_t max) in minijail_rlimit() argument
886 if (j->rlimit_count >= MAX_RLIMITS) in minijail_rlimit()
887 return -ENOMEM; in minijail_rlimit()
889 for (i = 0; i < j->rlimit_count; i++) { in minijail_rlimit()
890 if (j->rlimits[i].type == type) in minijail_rlimit()
891 return -EEXIST; in minijail_rlimit()
894 j->rlimits[j->rlimit_count].type = type; in minijail_rlimit()
895 j->rlimits[j->rlimit_count].cur = cur; in minijail_rlimit()
896 j->rlimits[j->rlimit_count].max = max; in minijail_rlimit()
897 j->rlimit_count++; in minijail_rlimit()
901 int API minijail_forward_signals(struct minijail *j) in minijail_forward_signals() argument
903 j->flags.forward_signals = 1; in minijail_forward_signals()
907 int API minijail_create_session(struct minijail *j) in minijail_create_session() argument
909 j->flags.setsid = 1; in minijail_create_session()
913 int API minijail_add_fs_restriction_rx(struct minijail *j, const char *path) in minijail_add_fs_restriction_rx() argument
915 return !add_fs_restriction_path(j, path, in minijail_add_fs_restriction_rx()
919 int API minijail_add_fs_restriction_ro(struct minijail *j, const char *path) in minijail_add_fs_restriction_ro() argument
921 return !add_fs_restriction_path(j, path, ACCESS_FS_ROUGHLY_READ); in minijail_add_fs_restriction_ro()
924 int API minijail_add_fs_restriction_rw(struct minijail *j, const char *path) in minijail_add_fs_restriction_rw() argument
926 return !add_fs_restriction_path(j, path, in minijail_add_fs_restriction_rw()
930 int API minijail_add_fs_restriction_advanced_rw(struct minijail *j, in minijail_add_fs_restriction_advanced_rw() argument
933 return !add_fs_restriction_path(j, path, in minijail_add_fs_restriction_advanced_rw()
937 int API minijail_add_fs_restriction_edit(struct minijail *j, in minijail_add_fs_restriction_edit() argument
940 return !add_fs_restriction_path(j, path, in minijail_add_fs_restriction_edit()
953 * -Copy |BINDMOUNT_ALLOWED_PREFIXES| since it lives in .rodata. in is_valid_bind_path()
954 * -Save the original pointer for free()ing. in is_valid_bind_path()
981 int API minijail_mount_with_data(struct minijail *j, const char *src, in minijail_mount_with_data() argument
988 return -EINVAL; in minijail_mount_with_data()
991 return -ENOMEM; in minijail_mount_with_data()
992 m->dest = strdup(dest); in minijail_mount_with_data()
993 if (!m->dest) in minijail_mount_with_data()
995 m->src = strdup(src); in minijail_mount_with_data()
996 if (!m->src) in minijail_mount_with_data()
998 m->type = strdup(type); in minijail_mount_with_data()
999 if (!m->type) in minijail_mount_with_data()
1005 * fs-specific logic here kind of sucks, but considering how in minijail_mount_with_data()
1015 m->data = strdup(data); in minijail_mount_with_data()
1016 if (!m->data) in minijail_mount_with_data()
1018 m->has_data = 1; in minijail_mount_with_data()
1024 m->flags = flags; in minijail_mount_with_data()
1033 if (!j->flags.enter_vfs) in minijail_mount_with_data()
1034 minijail_namespace_vfs(j); in minijail_mount_with_data()
1036 if (j->mounts_tail) in minijail_mount_with_data()
1037 j->mounts_tail->next = m; in minijail_mount_with_data()
1039 j->mounts_head = m; in minijail_mount_with_data()
1040 j->mounts_tail = m; in minijail_mount_with_data()
1041 j->mounts_count++; in minijail_mount_with_data()
1046 free(m->type); in minijail_mount_with_data()
1047 free(m->src); in minijail_mount_with_data()
1048 free(m->dest); in minijail_mount_with_data()
1050 return -ENOMEM; in minijail_mount_with_data()
1053 int API minijail_mount(struct minijail *j, const char *src, const char *dest, in minijail_mount() argument
1056 return minijail_mount_with_data(j, src, dest, type, flags, NULL); in minijail_mount()
1059 int API minijail_bind(struct minijail *j, const char *src, const char *dest, in minijail_bind() argument
1065 * Check for symlinks in bind-mount source paths to warn the user early. in minijail_bind()
1071 return -ELOOP; in minijail_bind()
1087 return minijail_mount(j, src, dest, "minijail_bind", flags); in minijail_bind()
1090 int API minijail_add_remount(struct minijail *j, const char *mount_name, in minijail_add_remount() argument
1096 return -EINVAL; in minijail_add_remount()
1099 return -ENOMEM; in minijail_add_remount()
1100 m->mount_name = strdup(mount_name); in minijail_add_remount()
1101 if (!m->mount_name) { in minijail_add_remount()
1103 return -ENOMEM; in minijail_add_remount()
1106 m->remount_mode = remount_mode; in minijail_add_remount()
1108 if (j->remounts_tail) in minijail_add_remount()
1109 j->remounts_tail->next = m; in minijail_add_remount()
1111 j->remounts_head = m; in minijail_add_remount()
1112 j->remounts_tail = m; in minijail_add_remount()
1117 int API minijail_add_hook(struct minijail *j, minijail_hook_t hook, in minijail_add_hook() argument
1123 return -EINVAL; in minijail_add_hook()
1125 return -EINVAL; in minijail_add_hook()
1128 return -ENOMEM; in minijail_add_hook()
1130 c->hook = hook; in minijail_add_hook()
1131 c->payload = payload; in minijail_add_hook()
1132 c->event = event; in minijail_add_hook()
1134 if (j->hooks_tail) in minijail_add_hook()
1135 j->hooks_tail->next = c; in minijail_add_hook()
1137 j->hooks_head = c; in minijail_add_hook()
1138 j->hooks_tail = c; in minijail_add_hook()
1143 int API minijail_preserve_fd(struct minijail *j, int parent_fd, int child_fd) in minijail_preserve_fd() argument
1146 return -EINVAL; in minijail_preserve_fd()
1147 if (j->preserved_fd_count >= MAX_PRESERVED_FDS) in minijail_preserve_fd()
1148 return -ENOMEM; in minijail_preserve_fd()
1149 j->preserved_fds[j->preserved_fd_count].parent_fd = parent_fd; in minijail_preserve_fd()
1150 j->preserved_fds[j->preserved_fd_count].child_fd = child_fd; in minijail_preserve_fd()
1151 j->preserved_fd_count++; in minijail_preserve_fd()
1155 int API minijail_set_preload_path(struct minijail *j, const char *preload_path) in minijail_set_preload_path() argument
1157 if (j->preload_path) in minijail_set_preload_path()
1158 return -EINVAL; in minijail_set_preload_path()
1159 j->preload_path = strdup(preload_path); in minijail_set_preload_path()
1160 if (!j->preload_path) in minijail_set_preload_path()
1161 return -ENOMEM; in minijail_set_preload_path()
1165 static void clear_seccomp_options(struct minijail *j) in clear_seccomp_options() argument
1167 j->flags.seccomp_filter = 0; in clear_seccomp_options()
1168 j->flags.seccomp_filter_tsync = 0; in clear_seccomp_options()
1169 j->flags.seccomp_filter_logging = 0; in clear_seccomp_options()
1170 j->flags.seccomp_filter_allow_speculation = 0; in clear_seccomp_options()
1171 j->filter_len = 0; in clear_seccomp_options()
1172 j->filter_prog = NULL; in clear_seccomp_options()
1173 j->flags.no_new_privs = 0; in clear_seccomp_options()
1174 if (j->seccomp_policy_path) { in clear_seccomp_options()
1175 free(j->seccomp_policy_path); in clear_seccomp_options()
1177 j->seccomp_policy_path = NULL; in clear_seccomp_options()
1180 static int seccomp_should_use_filters(struct minijail *j) in seccomp_should_use_filters() argument
1182 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL) == -1) { in seccomp_should_use_filters()
1192 clear_seccomp_options(j); in seccomp_should_use_filters()
1201 if (j->flags.seccomp_filter_tsync) { in seccomp_should_use_filters()
1204 SECCOMP_FILTER_FLAG_TSYNC, NULL) == -1) { in seccomp_should_use_filters()
1208 clear_seccomp_options(j); in seccomp_should_use_filters()
1214 clear_seccomp_options(j); in seccomp_should_use_filters()
1225 if (j->flags.seccomp_filter_allow_speculation) { in seccomp_should_use_filters()
1231 j->flags.seccomp_filter_allow_speculation = 0; in seccomp_should_use_filters()
1237 static int set_seccomp_filters_internal(struct minijail *j, in set_seccomp_filters_internal() argument
1245 * If |owned| is true, it's OK to cast away the const-ness since in set_seccomp_filters_internal()
1252 return -ENOMEM; in set_seccomp_filters_internal()
1253 fprog->len = filter->len; in set_seccomp_filters_internal()
1254 fprog->filter = malloc(sizeof(struct sock_filter) * fprog->len); in set_seccomp_filters_internal()
1255 if (!fprog->filter) { in set_seccomp_filters_internal()
1257 return -ENOMEM; in set_seccomp_filters_internal()
1259 memcpy(fprog->filter, filter->filter, in set_seccomp_filters_internal()
1260 sizeof(struct sock_filter) * fprog->len); in set_seccomp_filters_internal()
1263 if (j->filter_prog) { in set_seccomp_filters_internal()
1264 free(j->filter_prog->filter); in set_seccomp_filters_internal()
1265 free(j->filter_prog); in set_seccomp_filters_internal()
1268 j->filter_len = fprog->len; in set_seccomp_filters_internal()
1269 j->filter_prog = fprog; in set_seccomp_filters_internal()
1273 static int parse_seccomp_filters(struct minijail *j, const char *filename, in parse_seccomp_filters() argument
1278 return -ENOMEM; in parse_seccomp_filters()
1287 debug_logging_allowed() && seccomp_is_logging_allowed(j); in parse_seccomp_filters()
1296 if (j->flags.seccomp_filter_tsync) { in parse_seccomp_filters()
1319 return -1; in parse_seccomp_filters()
1322 return set_seccomp_filters_internal(j, fprog, true /* owned */); in parse_seccomp_filters()
1325 void API minijail_parse_seccomp_filters(struct minijail *j, const char *path) in minijail_parse_seccomp_filters() argument
1327 if (!seccomp_should_use_filters(j)) in minijail_parse_seccomp_filters()
1335 if (parse_seccomp_filters(j, path, file) != 0) { in minijail_parse_seccomp_filters()
1339 if (j->seccomp_policy_path) { in minijail_parse_seccomp_filters()
1340 free(j->seccomp_policy_path); in minijail_parse_seccomp_filters()
1342 j->seccomp_policy_path = strdup(path); in minijail_parse_seccomp_filters()
1345 void API minijail_parse_seccomp_filters_from_fd(struct minijail *j, int fd) in minijail_parse_seccomp_filters_from_fd() argument
1350 if (!seccomp_should_use_filters(j)) in minijail_parse_seccomp_filters_from_fd()
1358 if (asprintf(&fd_path, "/proc/self/fd/%d", fd) == -1) in minijail_parse_seccomp_filters_from_fd()
1365 if (parse_seccomp_filters(j, path ? path : "<fd>", file) != 0) { in minijail_parse_seccomp_filters_from_fd()
1369 if (j->seccomp_policy_path) { in minijail_parse_seccomp_filters_from_fd()
1370 free(j->seccomp_policy_path); in minijail_parse_seccomp_filters_from_fd()
1372 j->seccomp_policy_path = path; in minijail_parse_seccomp_filters_from_fd()
1375 void API minijail_set_seccomp_filters(struct minijail *j, in minijail_set_seccomp_filters() argument
1378 if (!seccomp_should_use_filters(j)) in minijail_set_seccomp_filters()
1381 if (seccomp_is_logging_allowed(j)) { in minijail_set_seccomp_filters()
1391 if (set_seccomp_filters_internal(j, filter, false /* owned */) < 0) { in minijail_set_seccomp_filters()
1396 int API minijail_use_alt_syscall(struct minijail *j, const char *table) in minijail_use_alt_syscall() argument
1398 j->alt_syscall_table = strdup(table); in minijail_use_alt_syscall()
1399 if (!j->alt_syscall_table) in minijail_use_alt_syscall()
1400 return -ENOMEM; in minijail_use_alt_syscall()
1401 j->flags.alt_syscall = 1; in minijail_use_alt_syscall()
1414 state->available = available; in marshal_state_init()
1415 state->buf = buf; in marshal_state_init()
1416 state->total = 0; in marshal_state_init()
1422 size_t copy_len = MIN(state->available, length); in marshal_append()
1426 memcpy(state->buf, src, copy_len); in marshal_append()
1427 state->buf += copy_len; in marshal_append()
1428 state->available -= copy_len; in marshal_append()
1431 state->total += length; in marshal_append()
1442 marshal_append(state, m->src, strlen(m->src) + 1); in marshal_mount()
1443 marshal_append(state, m->dest, strlen(m->dest) + 1); in marshal_mount()
1444 marshal_append(state, m->type, strlen(m->type) + 1); in marshal_mount()
1445 marshal_append(state, (char *)&m->has_data, sizeof(m->has_data)); in marshal_mount()
1446 if (m->has_data) in marshal_mount()
1447 marshal_append(state, m->data, strlen(m->data) + 1); in marshal_mount()
1448 marshal_append(state, (char *)&m->flags, sizeof(m->flags)); in marshal_mount()
1452 const struct minijail *j) in minijail_marshal_helper() argument
1457 marshal_append(state, (char *)j, sizeof(*j)); in minijail_marshal_helper()
1458 if (j->user) in minijail_marshal_helper()
1459 marshal_append_string(state, j->user); in minijail_marshal_helper()
1460 if (j->suppl_gid_list) { in minijail_marshal_helper()
1461 marshal_append(state, j->suppl_gid_list, in minijail_marshal_helper()
1462 j->suppl_gid_count * sizeof(gid_t)); in minijail_marshal_helper()
1464 if (j->chrootdir) in minijail_marshal_helper()
1465 marshal_append_string(state, j->chrootdir); in minijail_marshal_helper()
1466 if (j->hostname) in minijail_marshal_helper()
1467 marshal_append_string(state, j->hostname); in minijail_marshal_helper()
1468 if (j->alt_syscall_table) { in minijail_marshal_helper()
1469 marshal_append(state, j->alt_syscall_table, in minijail_marshal_helper()
1470 strlen(j->alt_syscall_table) + 1); in minijail_marshal_helper()
1472 if (j->flags.seccomp_filter && j->filter_prog) { in minijail_marshal_helper()
1473 struct sock_fprog *fp = j->filter_prog; in minijail_marshal_helper()
1474 marshal_append(state, (char *)fp->filter, in minijail_marshal_helper()
1475 fp->len * sizeof(struct sock_filter)); in minijail_marshal_helper()
1477 for (m = j->mounts_head; m; m = m->next) { in minijail_marshal_helper()
1480 for (i = 0; i < j->cgroup_count; ++i) in minijail_marshal_helper()
1481 marshal_append_string(state, j->cgroups[i]); in minijail_marshal_helper()
1482 if (j->seccomp_policy_path) in minijail_marshal_helper()
1483 marshal_append_string(state, j->seccomp_policy_path); in minijail_marshal_helper()
1486 size_t API minijail_size(const struct minijail *j) in minijail_size() argument
1490 minijail_marshal_helper(&state, j); in minijail_size()
1494 int minijail_marshal(const struct minijail *j, char *buf, size_t available) in minijail_marshal() argument
1498 minijail_marshal_helper(&state, j); in minijail_marshal()
1502 int minijail_unmarshal(struct minijail *j, char *serialized, size_t length) in minijail_unmarshal() argument
1506 int ret = -EINVAL; in minijail_unmarshal()
1508 if (length < sizeof(*j)) in minijail_unmarshal()
1510 memcpy((void *)j, serialized, sizeof(*j)); in minijail_unmarshal()
1511 serialized += sizeof(*j); in minijail_unmarshal()
1512 length -= sizeof(*j); in minijail_unmarshal()
1515 j->preload_path = NULL; in minijail_unmarshal()
1516 j->pid_file_path = NULL; in minijail_unmarshal()
1517 j->uidmap = NULL; in minijail_unmarshal()
1518 j->gidmap = NULL; in minijail_unmarshal()
1519 j->mounts_head = NULL; in minijail_unmarshal()
1520 j->mounts_tail = NULL; in minijail_unmarshal()
1521 j->remounts_head = NULL; in minijail_unmarshal()
1522 j->remounts_tail = NULL; in minijail_unmarshal()
1523 j->filter_prog = NULL; in minijail_unmarshal()
1524 j->hooks_head = NULL; in minijail_unmarshal()
1525 j->hooks_tail = NULL; in minijail_unmarshal()
1526 j->fs_rules_head = NULL; in minijail_unmarshal()
1527 j->fs_rules_tail = NULL; in minijail_unmarshal()
1529 if (j->user) { /* stale pointer */ in minijail_unmarshal()
1533 j->user = strdup(user); in minijail_unmarshal()
1534 if (!j->user) in minijail_unmarshal()
1538 if (j->suppl_gid_list) { /* stale pointer */ in minijail_unmarshal()
1539 if (j->suppl_gid_count > NGROUPS_MAX) { in minijail_unmarshal()
1542 size_t gid_list_size = j->suppl_gid_count * sizeof(gid_t); in minijail_unmarshal()
1548 j->suppl_gid_list = calloc(j->suppl_gid_count, sizeof(gid_t)); in minijail_unmarshal()
1549 if (!j->suppl_gid_list) in minijail_unmarshal()
1552 memcpy(j->suppl_gid_list, gid_list_bytes, gid_list_size); in minijail_unmarshal()
1555 if (j->chrootdir) { /* stale pointer */ in minijail_unmarshal()
1559 j->chrootdir = strdup(chrootdir); in minijail_unmarshal()
1560 if (!j->chrootdir) in minijail_unmarshal()
1564 if (j->hostname) { /* stale pointer */ in minijail_unmarshal()
1568 j->hostname = strdup(hostname); in minijail_unmarshal()
1569 if (!j->hostname) in minijail_unmarshal()
1573 if (j->alt_syscall_table) { /* stale pointer */ in minijail_unmarshal()
1577 j->alt_syscall_table = strdup(alt_syscall_table); in minijail_unmarshal()
1578 if (!j->alt_syscall_table) in minijail_unmarshal()
1582 if (j->flags.seccomp_filter && j->filter_len > 0) { in minijail_unmarshal()
1583 size_t ninstrs = j->filter_len; in minijail_unmarshal()
1593 j->filter_prog = malloc(sizeof(struct sock_fprog)); in minijail_unmarshal()
1594 if (!j->filter_prog) in minijail_unmarshal()
1597 j->filter_prog->len = ninstrs; in minijail_unmarshal()
1598 j->filter_prog->filter = malloc(program_len); in minijail_unmarshal()
1599 if (!j->filter_prog->filter) in minijail_unmarshal()
1602 memcpy(j->filter_prog->filter, program, program_len); in minijail_unmarshal()
1605 count = j->mounts_count; in minijail_unmarshal()
1606 j->mounts_count = 0; in minijail_unmarshal()
1634 if (minijail_mount_with_data(j, src, dest, type, *flags, data)) in minijail_unmarshal()
1638 count = j->cgroup_count; in minijail_unmarshal()
1639 j->cgroup_count = 0; in minijail_unmarshal()
1644 j->cgroups[i] = strdup(cgroup); in minijail_unmarshal()
1645 if (!j->cgroups[i]) in minijail_unmarshal()
1647 ++j->cgroup_count; in minijail_unmarshal()
1650 if (j->seccomp_policy_path) { /* stale pointer */ in minijail_unmarshal()
1654 j->seccomp_policy_path = strdup(seccomp_policy_path); in minijail_unmarshal()
1655 if (!j->seccomp_policy_path) in minijail_unmarshal()
1662 * If more is added after j->seccomp_policy_path, then this is needed: in minijail_unmarshal()
1663 * if (j->seccomp_policy_path) in minijail_unmarshal()
1664 * free(j->seccomp_policy_path); in minijail_unmarshal()
1668 free_mounts_list(j); in minijail_unmarshal()
1669 free_remounts_list(j); in minijail_unmarshal()
1670 for (i = 0; i < j->cgroup_count; ++i) in minijail_unmarshal()
1671 free(j->cgroups[i]); in minijail_unmarshal()
1673 if (j->filter_prog && j->filter_prog->filter) in minijail_unmarshal()
1674 free(j->filter_prog->filter); in minijail_unmarshal()
1676 if (j->filter_prog) in minijail_unmarshal()
1677 free(j->filter_prog); in minijail_unmarshal()
1679 if (j->alt_syscall_table) in minijail_unmarshal()
1680 free(j->alt_syscall_table); in minijail_unmarshal()
1682 if (j->hostname) in minijail_unmarshal()
1683 free(j->hostname); in minijail_unmarshal()
1685 if (j->chrootdir) in minijail_unmarshal()
1686 free(j->chrootdir); in minijail_unmarshal()
1688 if (j->suppl_gid_list) in minijail_unmarshal()
1689 free(j->suppl_gid_list); in minijail_unmarshal()
1691 if (j->user) in minijail_unmarshal()
1692 free(j->user); in minijail_unmarshal()
1694 j->user = NULL; in minijail_unmarshal()
1695 j->suppl_gid_list = NULL; in minijail_unmarshal()
1696 j->chrootdir = NULL; in minijail_unmarshal()
1697 j->hostname = NULL; in minijail_unmarshal()
1698 j->alt_syscall_table = NULL; in minijail_unmarshal()
1699 j->cgroup_count = 0; in minijail_unmarshal()
1700 j->seccomp_policy_path = NULL; in minijail_unmarshal()
1711 // clang-format off
1734 // clang-format on
1781 attribute_cleanup_fd int dev_fd = -1; in mount_dev()
1795 ret = mount("minijail-devfs", dev_path, "tmpfs", MS_NOEXEC | MS_NOSUID, in mount_dev()
1815 ret = mknodat(dev_fd, ds->name, ds->mode, in mount_dev()
1816 makedev(ds->major, ds->minor)); in mount_dev()
1824 ret = symlinkat(ds->dest, dev_fd, ds->source); in mount_dev()
1849 static int mount_dev_finalize(const struct minijail *j, char *dev_path) in mount_dev_finalize() argument
1851 int ret = -1; in mount_dev_finalize()
1858 if (asprintf(&dest, "%s/dev", j->chrootdir ?: "") < 0) in mount_dev_finalize()
1873 * mount_one: Applies mounts from @m for @j, recursing as needed.
1874 * @j Minijail these mounts are for
1879 static int mount_one(const struct minijail *j, struct mountpoint *m, in mount_one() argument
1886 bool has_remount_flag = !!(m->flags & MS_REMOUNT); in mount_one()
1890 if (dev_path && strncmp("/dev/", m->dest, 5) == 0) { in mount_one()
1894 if (asprintf(&dest, "%s%s", dev_path, m->dest + 4) < 0) in mount_one()
1895 return -ENOMEM; in mount_one()
1897 if (asprintf(&dest, "%s%s", j->chrootdir ?: "", m->dest) < 0) in mount_one()
1898 return -ENOMEM; in mount_one()
1901 ret = setup_mount_destination(m->src, dest, j->uid, j->gid, in mount_one()
1910 * - Come from the minijail_bind() API, and in mount_one()
1911 * - Add the 'ro' flag in mount_one()
1920 if (has_bind_flag && strcmp(m->type, "minijail_bind") == 0 && in mount_one()
1924 * out whether the bind mount needs to be remounted read-only. in mount_one()
1926 if (get_mount_flags(m->src, &original_mnt_flags)) { in mount_one()
1927 warn("cannot get mount flags for '%s'", m->src); in mount_one()
1931 if ((m->flags & MS_RDONLY) != in mount_one()
1936 * user-settable in a MS_REMOUNT request, but excluding in mount_one()
1937 * MS_RDONLY. The user-requested mount flags will in mount_one()
1947 * Do a final check for symlinks in |m->src|. in mount_one()
1948 * |m->src| will only contain a valid path when purely bind-mounting in mount_one()
1954 if (has_bind_flag && !has_remount_flag && !is_valid_bind_path(m->src)) { in mount_one()
1955 warn("src '%s' is not a valid bind mount path", m->src); in mount_one()
1959 ret = mount(m->src, dest, m->type, m->flags, m->data); in mount_one()
1961 pwarn("cannot mount '%s' as '%s' with flags %#lx", m->src, dest, in mount_one()
1962 m->flags); in mount_one()
1969 mount(m->src, dest, NULL, in mount_one()
1970 m->flags | original_mnt_flags | MS_REMOUNT, m->data); in mount_one()
1973 "cannot bind-remount '%s' as '%s' with flags %#lx", in mount_one()
1974 m->src, dest, in mount_one()
1975 m->flags | original_mnt_flags | MS_REMOUNT); in mount_one()
1981 if (m->next) in mount_one()
1982 return mount_one(j, m->next, dev_path); in mount_one()
1990 static void process_mounts_or_die(const struct minijail *j) in process_mounts_or_die() argument
1997 if (j->flags.mount_dev && mount_dev(&dev_path)) in process_mounts_or_die()
2000 if (j->mounts_head && mount_one(j, j->mounts_head, dev_path)) { in process_mounts_or_die()
2013 if (j->flags.mount_dev && mount_dev_finalize(j, dev_path)) in process_mounts_or_die()
2017 static int enter_chroot(const struct minijail *j) in enter_chroot() argument
2019 run_hooks_or_die(j, MINIJAIL_HOOK_EVENT_PRE_CHROOT); in enter_chroot()
2021 if (chroot(j->chrootdir)) in enter_chroot()
2022 return -errno; in enter_chroot()
2025 return -errno; in enter_chroot()
2030 static int enter_pivot_root(const struct minijail *j) in enter_pivot_root() argument
2032 attribute_cleanup_fd int oldroot = -1; in enter_pivot_root()
2033 attribute_cleanup_fd int newroot = -1; in enter_pivot_root()
2035 run_hooks_or_die(j, MINIJAIL_HOOK_EVENT_PRE_CHROOT); in enter_pivot_root()
2044 newroot = open(j->chrootdir, O_DIRECTORY | O_RDONLY | O_CLOEXEC); in enter_pivot_root()
2046 pdie("failed to open %s for fchdir", j->chrootdir); in enter_pivot_root()
2049 * To ensure j->chrootdir is the root of a filesystem, in enter_pivot_root()
2052 if (mount(j->chrootdir, j->chrootdir, "bind", MS_BIND | MS_REC, "")) in enter_pivot_root()
2053 pdie("failed to bind mount '%s'", j->chrootdir); in enter_pivot_root()
2054 if (chdir(j->chrootdir)) in enter_pivot_root()
2055 return -errno; in enter_pivot_root()
2082 return -errno; in enter_pivot_root()
2084 return -errno; in enter_pivot_root()
2087 return -errno; in enter_pivot_root()
2092 static int mount_tmp(const struct minijail *j) in mount_tmp() argument
2099 ret = snprintf(data, sizeof(data), fmt, j->tmpfs_size); in mount_tmp()
2115 static int remount_proc_readonly(const struct minijail *j) in remount_proc_readonly() argument
2136 * See https://man7.org/linux/man-pages/man7/mount_namespaces.7.html, in remount_proc_readonly()
2145 * In all other non-user-namespace cases the new mount namespace is in remount_proc_readonly()
2149 * We still remount /proc as read-only in the user namespace case in remount_proc_readonly()
2154 if (!j->flags.userns && umount2(kProcPath, MNT_DETACH)) in remount_proc_readonly()
2155 return -errno; in remount_proc_readonly()
2157 return -errno; in remount_proc_readonly()
2161 static void kill_child_and_die(const struct minijail *j, const char *msg) in kill_child_and_die() argument
2163 kill(j->initpid, SIGKILL); in kill_child_and_die()
2167 static void write_pid_file_or_die(const struct minijail *j) in write_pid_file_or_die() argument
2169 if (write_pid_to_path(j->initpid, j->pid_file_path)) in write_pid_file_or_die()
2170 kill_child_and_die(j, "failed to write pid file"); in write_pid_file_or_die()
2173 static void add_to_cgroups_or_die(const struct minijail *j) in add_to_cgroups_or_die() argument
2177 for (i = 0; i < j->cgroup_count; ++i) { in add_to_cgroups_or_die()
2178 if (write_pid_to_path(j->initpid, j->cgroups[i])) in add_to_cgroups_or_die()
2179 kill_child_and_die(j, "failed to add to cgroups"); in add_to_cgroups_or_die()
2183 static void set_rlimits_or_die(const struct minijail *j) in set_rlimits_or_die() argument
2187 for (i = 0; i < j->rlimit_count; ++i) { in set_rlimits_or_die()
2189 limit.rlim_cur = j->rlimits[i].cur; in set_rlimits_or_die()
2190 limit.rlim_max = j->rlimits[i].max; in set_rlimits_or_die()
2191 if (prlimit(j->initpid, j->rlimits[i].type, &limit, NULL)) in set_rlimits_or_die()
2192 kill_child_and_die(j, "failed to set rlimit"); in set_rlimits_or_die()
2196 static void write_ugid_maps_or_die(const struct minijail *j) in write_ugid_maps_or_die() argument
2198 if (j->uidmap && write_proc_file(j->initpid, j->uidmap, "uid_map") != 0) in write_ugid_maps_or_die()
2199 kill_child_and_die(j, "failed to write uid_map"); in write_ugid_maps_or_die()
2200 if (j->gidmap && j->flags.disable_setgroups) { in write_ugid_maps_or_die()
2204 int ret = write_proc_file(j->initpid, "deny", "setgroups"); in write_ugid_maps_or_die()
2206 if (ret == -ENOENT) { in write_ugid_maps_or_die()
2209 * http://man7.org/linux/man-pages/man7/user_namespaces.7.html. in write_ugid_maps_or_die()
2214 j, "failed to disable setgroups(2)"); in write_ugid_maps_or_die()
2217 if (j->gidmap && write_proc_file(j->initpid, j->gidmap, "gid_map") != 0) in write_ugid_maps_or_die()
2218 kill_child_and_die(j, "failed to write gid_map"); in write_ugid_maps_or_die()
2221 static void enter_user_namespace(const struct minijail *j) in enter_user_namespace() argument
2223 int uid = j->flags.uid ? j->uid : 0; in enter_user_namespace()
2224 int gid = j->flags.gid ? j->gid : 0; in enter_user_namespace()
2225 if (j->gidmap && setresgid(gid, gid, gid)) { in enter_user_namespace()
2229 if (j->uidmap && setresuid(uid, uid, uid)) { in enter_user_namespace()
2243 * further parent-side setup to complete before continuing.
2257 static void drop_ugid(const struct minijail *j) in drop_ugid() argument
2259 if (j->flags.inherit_suppl_gids + j->flags.keep_suppl_gids + in drop_ugid()
2260 j->flags.set_suppl_gids > in drop_ugid()
2266 if (j->flags.inherit_suppl_gids) { in drop_ugid()
2267 if (initgroups(j->user, j->usergid)) in drop_ugid()
2268 pdie("initgroups(%s, %d) failed", j->user, j->usergid); in drop_ugid()
2269 } else if (j->flags.set_suppl_gids) { in drop_ugid()
2270 if (setgroups(j->suppl_gid_count, j->suppl_gid_list)) in drop_ugid()
2272 } else if (!j->flags.keep_suppl_gids && !j->flags.disable_setgroups) { in drop_ugid()
2277 * non-privileged user). in drop_ugid()
2279 if ((j->flags.uid || j->flags.gid) && setgroups(0, NULL)) in drop_ugid()
2283 if (j->flags.gid && setresgid(j->gid, j->gid, j->gid)) in drop_ugid()
2284 pdie("setresgid(%d, %d, %d) failed", j->gid, j->gid, j->gid); in drop_ugid()
2286 if (j->flags.uid && setresuid(j->uid, j->uid, j->uid)) in drop_ugid()
2287 pdie("setresuid(%d, %d, %d) failed", j->uid, j->uid, j->uid); in drop_ugid()
2302 static void drop_caps(const struct minijail *j, unsigned int last_valid_cap) in drop_caps() argument
2304 if (!j->flags.use_caps) in drop_caps()
2309 const size_t ncaps = sizeof(j->caps) * 8; in drop_caps()
2319 if (i != CAP_SETPCAP && !(j->caps & (one << i))) in drop_caps()
2341 * set-user-ID-root program, allow them to do so. The default behavior in drop_caps()
2343 * the jailed process tree in a capabilities-only environment. in drop_caps()
2350 if (secure_noroot_set_and_locked(~j->securebits_skip_mask)) { in drop_caps()
2351 drop_capbset(j->caps, last_valid_cap); in drop_caps()
2357 if ((j->caps & (one << CAP_SETPCAP)) == 0) { in drop_caps()
2374 if (j->flags.set_ambient_caps) { in drop_caps()
2384 if (!(j->caps & (one << i))) in drop_caps()
2400 static void apply_landlock_restrictions(const struct minijail *j) in apply_landlock_restrictions() argument
2403 attribute_cleanup_fd int ruleset_fd = -1; in apply_landlock_restrictions()
2405 r = j->fs_rules_head; in apply_landlock_restrictions()
2427 populate_ruleset_internal(r->path, ruleset_fd, r->landlock_flags); in apply_landlock_restrictions()
2428 r = r->next; in apply_landlock_restrictions()
2438 static void set_seccomp_filter(const struct minijail *j) in set_seccomp_filter() argument
2444 if (j->flags.no_new_privs) { in set_seccomp_filter()
2459 if (j->flags.seccomp_filter && running_with_asan()) { in set_seccomp_filter()
2464 if (j->flags.seccomp_filter) { in set_seccomp_filter()
2465 if (seccomp_is_logging_allowed(j)) { in set_seccomp_filter()
2476 } else if (j->flags.seccomp_filter_tsync) { in set_seccomp_filter()
2490 if (j->flags.seccomp_filter) { in set_seccomp_filter()
2491 if (j->flags.seccomp_filter_tsync || in set_seccomp_filter()
2492 j->flags.seccomp_filter_allow_speculation) { in set_seccomp_filter()
2494 (j->flags.seccomp_filter_tsync in set_seccomp_filter()
2497 (j->flags.seccomp_filter_allow_speculation in set_seccomp_filter()
2501 j->filter_prog)) { in set_seccomp_filter()
2506 j->filter_prog)) { in set_seccomp_filter()
2513 static pid_t forward_pid = -1;
2518 if (forward_pid != -1) { in forward_signal()
2542 /* Handle real-time signals. */ in install_signal_handlers()
2552 return "pre-drop-caps"; in lookup_hook_name()
2554 return "pre-execve"; in lookup_hook_name()
2556 return "pre-chroot"; in lookup_hook_name()
2567 static void run_hooks_or_die(const struct minijail *j, in run_hooks_or_die() argument
2572 for (struct hook *c = j->hooks_head; c; c = c->next) { in run_hooks_or_die()
2573 if (c->event != event) in run_hooks_or_die()
2575 rc = c->hook(c->payload); in run_hooks_or_die()
2577 errno = -rc; in run_hooks_or_die()
2586 void API minijail_enter(const struct minijail *j) in minijail_enter() argument
2593 if (j->flags.capbset_drop || j->flags.use_caps) in minijail_enter()
2596 if (j->flags.pids) in minijail_enter()
2597 die("tried to enter a pid-namespaced jail;" in minijail_enter()
2600 if (j->flags.inherit_suppl_gids && !j->user) in minijail_enter()
2609 if (j->flags.enter_vfs) { in minijail_enter()
2610 if (setns(j->mountns_fd, CLONE_NEWNS)) in minijail_enter()
2612 close(j->mountns_fd); in minijail_enter()
2615 if (j->flags.vfs) { in minijail_enter()
2620 * - Passed a specific remount mode, in which case remount with in minijail_enter()
2622 * - Asked not to remount at all, in which case skip the in minijail_enter()
2626 if (j->remount_mode) { in minijail_enter()
2627 if (mount(NULL, "/", NULL, MS_REC | j->remount_mode, in minijail_enter()
2630 "MS_REC | j->remount_mode, NULL) failed"); in minijail_enter()
2632 struct minijail_remount *temp = j->remounts_head; in minijail_enter()
2634 if (temp->remount_mode < j->remount_mode) in minijail_enter()
2637 temp->mount_name); in minijail_enter()
2638 if (mount(NULL, temp->mount_name, NULL, in minijail_enter()
2639 MS_REC | temp->remount_mode, NULL)) in minijail_enter()
2641 "MS_REC | temp->remount_mode, " in minijail_enter()
2643 temp->mount_name); in minijail_enter()
2644 temp = temp->next; in minijail_enter()
2649 if (j->flags.ipc && unshare(CLONE_NEWIPC)) { in minijail_enter()
2653 if (j->flags.uts) { in minijail_enter()
2657 if (j->hostname && in minijail_enter()
2658 sethostname(j->hostname, strlen(j->hostname))) in minijail_enter()
2659 pdie("sethostname(%s) failed", j->hostname); in minijail_enter()
2662 if (j->flags.enter_net) { in minijail_enter()
2663 if (setns(j->netns_fd, CLONE_NEWNET)) in minijail_enter()
2665 close(j->netns_fd); in minijail_enter()
2666 } else if (j->flags.net) { in minijail_enter()
2672 if (j->flags.ns_cgroups && unshare(CLONE_NEWCGROUP)) in minijail_enter()
2675 if (j->flags.new_session_keyring) { in minijail_enter()
2681 process_mounts_or_die(j); in minijail_enter()
2683 if (j->flags.chroot && enter_chroot(j)) in minijail_enter()
2686 if (j->flags.pivot_root && enter_pivot_root(j)) in minijail_enter()
2689 if (j->flags.mount_tmp && mount_tmp(j)) in minijail_enter()
2692 if (j->flags.remount_proc_ro && remount_proc_readonly(j)) in minijail_enter()
2695 run_hooks_or_die(j, MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS); in minijail_enter()
2701 if (j->flags.capbset_drop) { in minijail_enter()
2702 drop_capbset(j->cap_bset, last_valid_cap); in minijail_enter()
2710 if (j->flags.use_caps) { in minijail_enter()
2716 bool require_keep_caps = !j->flags.set_ambient_caps; in minijail_enter()
2717 if (lock_securebits(j->securebits_skip_mask, in minijail_enter()
2723 if (j->flags.no_new_privs) { in minijail_enter()
2727 * don't need to allow privilege-dropping syscalls. in minijail_enter()
2729 drop_ugid(j); in minijail_enter()
2730 drop_caps(j, last_valid_cap); in minijail_enter()
2734 apply_landlock_restrictions(j); in minijail_enter()
2735 set_seccomp_filter(j); in minijail_enter()
2737 apply_landlock_restrictions(j); in minijail_enter()
2746 set_seccomp_filter(j); in minijail_enter()
2747 drop_ugid(j); in minijail_enter()
2748 drop_caps(j, last_valid_cap); in minijail_enter()
2755 if (j->flags.alt_syscall) { in minijail_enter()
2756 if (prctl(PR_ALT_SYSCALL, 1, j->alt_syscall_table)) in minijail_enter()
2762 * privilege-dropping syscalls :) in minijail_enter()
2764 if (j->flags.seccomp && prctl(PR_SET_SECCOMP, 1)) { in minijail_enter()
2801 int API minijail_from_fd(int fd, struct minijail *j) in minijail_from_fd() argument
2808 return -EINVAL; in minijail_from_fd()
2810 return -E2BIG; in minijail_from_fd()
2813 return -ENOMEM; in minijail_from_fd()
2816 return -EINVAL; in minijail_from_fd()
2817 r = minijail_unmarshal(j, buf, sz); in minijail_from_fd()
2821 int API minijail_to_fd(struct minijail *j, int fd) in minijail_to_fd() argument
2823 size_t sz = minijail_size(j); in minijail_to_fd()
2825 return -EINVAL; in minijail_to_fd()
2829 return -ENOMEM; in minijail_to_fd()
2831 int err = minijail_marshal(j, buf, sz); in minijail_to_fd()
2847 return -EINVAL; in minijail_copy_jail()
2851 return -ENOMEM; in minijail_copy_jail()
2860 static int setup_preload(const struct minijail *j attribute_unused, in setup_preload()
2867 const char *preload_path = j->preload_path ?: PRELOADPATH; in setup_preload()
2878 return -1; in setup_preload()
2891 static int setup_seccomp_policy_path(const struct minijail *j, in setup_seccomp_policy_path() argument
2895 j->seccomp_policy_path ? j->seccomp_policy_path in setup_seccomp_policy_path()
2896 : "NO-LABEL", in setup_seccomp_policy_path()
2908 return -EINVAL; in setup_pipe()
2920 return -1; in close_open_fds()
2926 const int fd = strtol(dir_entry->d_name, &end, 10); in close_open_fds()
2952 return fcntl(fd, F_GETFD) != -1 || errno != EBADF; in fd_is_open()
2955 static_assert(FD_SETSIZE >= MAX_PRESERVED_FDS * 2 - 1,
2971 if (fd == -1 || fd_is_open(fd)) { in ensure_no_fd_conflict()
2972 fd = FD_SETSIZE - 1; in ensure_no_fd_conflict()
2974 --fd; in ensure_no_fd_conflict()
2989 if (ret == -1) { in ensure_no_fd_conflict()
2990 return -1; in ensure_no_fd_conflict()
3004 static int get_child_fds(struct minijail *j, fd_set *child_fds_out) in get_child_fds() argument
3007 for (size_t i = 0; i < j->preserved_fd_count; i++) { in get_child_fds()
3008 int child_fd = j->preserved_fds[i].child_fd; in get_child_fds()
3013 int *parent_fd = &j->preserved_fds[i].parent_fd; in get_child_fds()
3015 -1) { in get_child_fds()
3016 return -1; in get_child_fds()
3044 state->pipe_fds, state->child_sync_pipe_fds, state->stdin_fds, in avoid_pipe_conflicts()
3045 state->stdout_fds, state->stderr_fds, in avoid_pipe_conflicts()
3048 if (pipe_fds[i][0] != -1 && in avoid_pipe_conflicts()
3049 ensure_no_fd_conflict(child_fds_out, -1, &pipe_fds[i][0]) == in avoid_pipe_conflicts()
3050 -1) { in avoid_pipe_conflicts()
3051 return -1; in avoid_pipe_conflicts()
3053 if (pipe_fds[i][1] != -1 && in avoid_pipe_conflicts()
3054 ensure_no_fd_conflict(child_fds_out, -1, &pipe_fds[i][1]) == in avoid_pipe_conflicts()
3055 -1) { in avoid_pipe_conflicts()
3056 return -1; in avoid_pipe_conflicts()
3063 * Redirect j->preserved_fds from the parent_fd to the child_fd.
3068 static int redirect_fds(struct minijail *j, fd_set *child_fds) in redirect_fds() argument
3070 for (size_t i = 0; i < j->preserved_fd_count; i++) { in redirect_fds()
3071 if (j->preserved_fds[i].parent_fd == in redirect_fds()
3072 j->preserved_fds[i].child_fd) { in redirect_fds()
3076 fcntl(j->preserved_fds[i].child_fd, F_GETFD); in redirect_fds()
3077 if (flags == -1 || (flags & FD_CLOEXEC) == 0) { in redirect_fds()
3085 if (fcntl(j->preserved_fds[i].child_fd, F_SETFD, in redirect_fds()
3086 flags) == -1) { in redirect_fds()
3088 j->preserved_fds[i].parent_fd); in redirect_fds()
3092 if (dup2(j->preserved_fds[i].parent_fd, in redirect_fds()
3093 j->preserved_fds[i].child_fd) == -1) { in redirect_fds()
3094 return -1; in redirect_fds()
3102 for (size_t i = 0; i < j->preserved_fd_count; i++) { in redirect_fds()
3103 int parent_fd = j->preserved_fds[i].parent_fd; in redirect_fds()
3113 state->child_pid = -1; in minijail_free_run_state()
3115 int *fd_pairs[] = {state->pipe_fds, state->stdin_fds, state->stdout_fds, in minijail_free_run_state()
3116 state->stderr_fds, state->child_sync_pipe_fds}; in minijail_free_run_state()
3122 minijail_free_env(state->child_env); in minijail_free_run_state()
3123 state->child_env = NULL; in minijail_free_run_state()
3127 static void setup_child_std_fds(struct minijail *j, in setup_child_std_fds() argument
3135 {"stdin", state->stdin_fds[0], STDIN_FILENO}, in setup_child_std_fds()
3136 {"stdout", state->stdout_fds[1], STDOUT_FILENO}, in setup_child_std_fds()
3137 {"stderr", state->stderr_fds[1], STDERR_FILENO}, in setup_child_std_fds()
3141 if (fd_map[i].from == -1 || fd_map[i].from == fd_map[i].to) in setup_child_std_fds()
3143 if (dup2(fd_map[i].from, fd_map[i].to) == -1) in setup_child_std_fds()
3148 int *std_pipes[] = {state->stdin_fds, state->stdout_fds, in setup_child_std_fds()
3149 state->stderr_fds}; in setup_child_std_fds()
3164 if (j->flags.setsid || isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || in setup_child_std_fds()
3181 * filename - The program to exec in the child. Should be NULL if elf_fd is set.
3182 * elf_fd - A fd to be used with fexecve. Should be -1 if filename is set.
3184 * argv - Arguments for the child program. Required if |exec_in_child| = 1.
3185 * envp - Environment for the child program. Available if |exec_in_child| = 1.
3186 * use_preload - If true use LD_PRELOAD.
3187 * exec_in_child - If true, run |filename|. Otherwise, the child will return to
3189 * pstdin_fd - Filled with stdin pipe if non-NULL.
3190 * pstdout_fd - Filled with stdout pipe if non-NULL.
3191 * pstderr_fd - Filled with stderr pipe if non-NULL.
3192 * pchild_pid - Filled with the pid of the child process if non-NULL.
3208 minijail_run_config_internal(struct minijail *j,
3211 int API minijail_run(struct minijail *j, const char *filename, in minijail_run() argument
3216 .elf_fd = -1, in minijail_run()
3222 return minijail_run_config_internal(j, &config); in minijail_run()
3225 int API minijail_run_env(struct minijail *j, const char *filename, in minijail_run_env() argument
3230 .elf_fd = -1, in minijail_run_env()
3236 return minijail_run_config_internal(j, &config); in minijail_run_env()
3239 int API minijail_run_pid(struct minijail *j, const char *filename, in minijail_run_pid() argument
3244 .elf_fd = -1, in minijail_run_pid()
3251 return minijail_run_config_internal(j, &config); in minijail_run_pid()
3254 int API minijail_run_pipe(struct minijail *j, const char *filename, in minijail_run_pipe() argument
3259 .elf_fd = -1, in minijail_run_pipe()
3266 return minijail_run_config_internal(j, &config); in minijail_run_pipe()
3269 int API minijail_run_pid_pipes(struct minijail *j, const char *filename, in minijail_run_pid_pipes() argument
3275 .elf_fd = -1, in minijail_run_pid_pipes()
3285 return minijail_run_config_internal(j, &config); in minijail_run_pid_pipes()
3288 int API minijail_run_env_pid_pipes(struct minijail *j, const char *filename, in minijail_run_env_pid_pipes() argument
3295 .elf_fd = -1, in minijail_run_env_pid_pipes()
3305 return minijail_run_config_internal(j, &config); in minijail_run_env_pid_pipes()
3308 int API minijail_run_fd_env_pid_pipes(struct minijail *j, int elf_fd, in minijail_run_fd_env_pid_pipes() argument
3325 return minijail_run_config_internal(j, &config); in minijail_run_fd_env_pid_pipes()
3328 int API minijail_run_no_preload(struct minijail *j, const char *filename, in minijail_run_no_preload() argument
3333 .elf_fd = -1, in minijail_run_no_preload()
3339 return minijail_run_config_internal(j, &config); in minijail_run_no_preload()
3342 int API minijail_run_pid_pipes_no_preload(struct minijail *j, in minijail_run_pid_pipes_no_preload() argument
3350 .elf_fd = -1, in minijail_run_pid_pipes_no_preload()
3360 return minijail_run_config_internal(j, &config); in minijail_run_pid_pipes_no_preload()
3363 int API minijail_run_env_pid_pipes_no_preload(struct minijail *j, in minijail_run_env_pid_pipes_no_preload() argument
3372 .elf_fd = -1, in minijail_run_env_pid_pipes_no_preload()
3382 return minijail_run_config_internal(j, &config); in minijail_run_env_pid_pipes_no_preload()
3385 pid_t API minijail_fork(struct minijail *j) in minijail_fork() argument
3388 .elf_fd = -1, in minijail_fork()
3390 return minijail_run_config_internal(j, &config); in minijail_fork()
3393 static int minijail_run_internal(struct minijail *j, in minijail_run_internal() argument
3400 int pid_namespace = j->flags.pids; in minijail_run_internal()
3405 int do_init = j->flags.do_init && !j->flags.run_as_init; in minijail_run_internal()
3406 int use_preload = config->use_preload; in minijail_run_internal()
3408 if (config->filename != NULL && config->elf_fd != -1) { in minijail_run_internal()
3416 if (use_preload || j->seccomp_policy_path) { in minijail_run_internal()
3417 state_out->child_env = in minijail_run_internal()
3418 minijail_copy_env(config->envp ? config->envp : environ); in minijail_run_internal()
3419 if (!state_out->child_env) in minijail_run_internal()
3423 if (j->seccomp_policy_path && in minijail_run_internal()
3424 setup_seccomp_policy_path(j, &state_out->child_env)) in minijail_run_internal()
3425 return -EFAULT; in minijail_run_internal()
3428 if (j->hooks_head != NULL) in minijail_run_internal()
3430 if (!config->exec_in_child) in minijail_run_internal()
3437 if (setup_preload(j, &state_out->child_env) || in minijail_run_internal()
3438 setup_pipe(&state_out->child_env, state_out->pipe_fds)) in minijail_run_internal()
3439 return -EFAULT; in minijail_run_internal()
3443 if (j->flags.use_caps && j->caps != 0 && in minijail_run_internal()
3444 !j->flags.set_ambient_caps) { in minijail_run_internal()
3445 die("non-empty, non-ambient capabilities are not " in minijail_run_internal()
3455 {config->pstdin_fd != NULL, state_out->stdin_fds}, in minijail_run_internal()
3456 {config->pstdout_fd != NULL, state_out->stdout_fds}, in minijail_run_internal()
3457 {config->pstderr_fd != NULL, state_out->stderr_fds}, in minijail_run_internal()
3462 pipe(pipe_fd_req[i].pipe_fds) == -1) in minijail_run_internal()
3471 if (j->flags.forward_signals || j->flags.pid_file || j->flags.cgroups || in minijail_run_internal()
3472 j->rlimit_count || j->flags.userns) { in minijail_run_internal()
3474 if (pipe(state_out->child_sync_pipe_fds)) in minijail_run_internal()
3475 return -EFAULT; in minijail_run_internal()
3492 * after, but a bunch of seemingly-innocent libc functions like setenv() in minijail_run_internal()
3522 if (j->flags.userns) in minijail_run_internal()
3541 state_out->child_pid = child_pid; in minijail_run_internal()
3543 j->initpid = child_pid; in minijail_run_internal()
3545 if (j->flags.forward_signals) { in minijail_run_internal()
3550 if (j->flags.pid_file) in minijail_run_internal()
3551 write_pid_file_or_die(j); in minijail_run_internal()
3553 if (j->flags.cgroups) in minijail_run_internal()
3554 add_to_cgroups_or_die(j); in minijail_run_internal()
3556 if (j->rlimit_count) in minijail_run_internal()
3557 set_rlimits_or_die(j); in minijail_run_internal()
3559 if (j->flags.userns) in minijail_run_internal()
3560 write_ugid_maps_or_die(j); in minijail_run_internal()
3562 if (j->flags.enter_vfs) in minijail_run_internal()
3563 close(j->mountns_fd); in minijail_run_internal()
3565 if (j->flags.enter_net) in minijail_run_internal()
3566 close(j->netns_fd); in minijail_run_internal()
3569 parent_setup_complete(state_out->child_sync_pipe_fds); in minijail_run_internal()
3590 close_and_reset(&state_out->pipe_fds[0]); in minijail_run_internal()
3591 ret = minijail_to_fd(j, state_out->pipe_fds[1]); in minijail_run_internal()
3592 close_and_reset(&state_out->pipe_fds[1]); in minijail_run_internal()
3615 strerror(-ret)); in minijail_run_internal()
3616 kill(j->initpid, SIGKILL); in minijail_run_internal()
3624 if (j->flags.reset_signal_mask) { in minijail_run_internal()
3632 if (j->flags.reset_signal_handlers) { in minijail_run_internal()
3647 if (j->flags.close_open_fds) { in minijail_run_internal()
3653 state_out->pipe_fds, state_out->child_sync_pipe_fds, in minijail_run_internal()
3654 state_out->stdin_fds, state_out->stdout_fds, in minijail_run_internal()
3655 state_out->stderr_fds, in minijail_run_internal()
3659 if (pipe_fds[i][0] != -1) { in minijail_run_internal()
3662 if (pipe_fds[i][1] != -1) { in minijail_run_internal()
3672 if (j->flags.enter_vfs) in minijail_run_internal()
3673 minijail_preserve_fd(j, j->mountns_fd, j->mountns_fd); in minijail_run_internal()
3674 if (j->flags.enter_net) in minijail_run_internal()
3675 minijail_preserve_fd(j, j->netns_fd, j->netns_fd); in minijail_run_internal()
3677 for (size_t i = 0; i < j->preserved_fd_count; i++) { in minijail_run_internal()
3679 * Preserve all parent_fds. They will be dup2(2)-ed in in minijail_run_internal()
3682 inheritable_fds[size++] = j->preserved_fds[i].parent_fd; in minijail_run_internal()
3685 if (config->elf_fd > -1) { in minijail_run_internal()
3686 inheritable_fds[size++] = config->elf_fd; in minijail_run_internal()
3696 if (get_child_fds(j, &child_fds)) in minijail_run_internal()
3703 int elf_fd = config->elf_fd; in minijail_run_internal()
3704 if (elf_fd != -1 && ensure_no_fd_conflict(&child_fds, -1, &elf_fd)) in minijail_run_internal()
3707 if (redirect_fds(j, &child_fds)) in minijail_run_internal()
3711 wait_for_parent_setup(state_out->child_sync_pipe_fds); in minijail_run_internal()
3713 if (j->flags.userns) in minijail_run_internal()
3714 enter_user_namespace(j); in minijail_run_internal()
3716 setup_child_std_fds(j, state_out); in minijail_run_internal()
3720 j->flags.remount_proc_ro = 0; in minijail_run_internal()
3724 minijail_preexec(j); in minijail_run_internal()
3731 j->flags.pids = 0; in minijail_run_internal()
3739 minijail_enter(j); in minijail_run_internal()
3741 if (config->exec_in_child && pid_namespace && do_init) { in minijail_run_internal()
3761 prctl(PR_SET_NAME, "minijail-init"); in minijail_run_internal()
3764 state_out->child_pid = child_pid; in minijail_run_internal()
3767 run_hooks_or_die(j, MINIJAIL_HOOK_EVENT_PRE_EXECVE); in minijail_run_internal()
3769 if (!config->exec_in_child) in minijail_run_internal()
3781 state_out->pipe_fds[0] = -1; in minijail_run_internal()
3782 char *const *child_env = state_out->child_env; in minijail_run_internal()
3783 state_out->child_env = NULL; in minijail_run_internal()
3787 * If we aren't pid-namespaced, or the jailed program asked to be init: in minijail_run_internal()
3789 * -> execve()-ing process in minijail_run_internal()
3792 * -> init()-ing process in minijail_run_internal()
3793 * -> execve()-ing process in minijail_run_internal()
3796 child_env = config->envp ? config->envp : environ; in minijail_run_internal()
3797 if (elf_fd > -1) { in minijail_run_internal()
3798 fexecve(elf_fd, config->argv, child_env); in minijail_run_internal()
3799 pwarn("fexecve(%d) failed", config->elf_fd); in minijail_run_internal()
3801 execve(config->filename, config->argv, child_env); in minijail_run_internal()
3802 pwarn("execve(%s) failed", config->filename); in minijail_run_internal()
3811 minijail_run_config_internal(struct minijail *j, in minijail_run_config_internal() argument
3815 .child_pid = -1, in minijail_run_config_internal()
3816 .pipe_fds = {-1, -1}, in minijail_run_config_internal()
3817 .stdin_fds = {-1, -1}, in minijail_run_config_internal()
3818 .stdout_fds = {-1, -1}, in minijail_run_config_internal()
3819 .stderr_fds = {-1, -1}, in minijail_run_config_internal()
3820 .child_sync_pipe_fds = {-1, -1}, in minijail_run_config_internal()
3823 int ret = minijail_run_internal(j, config, &state); in minijail_run_config_internal()
3826 if (config->pchild_pid) in minijail_run_config_internal()
3827 *config->pchild_pid = state.child_pid; in minijail_run_config_internal()
3834 {config->pstdin_fd, &state.stdin_fds[1]}, in minijail_run_config_internal()
3835 {config->pstdout_fd, &state.stdout_fds[0]}, in minijail_run_config_internal()
3836 {config->pstderr_fd, &state.stderr_fds[0]}, in minijail_run_config_internal()
3842 *fd_map[i].psrc = -1; in minijail_run_config_internal()
3846 if (!config->exec_in_child) in minijail_run_config_internal()
3855 static int minijail_wait_internal(struct minijail *j, int expected_signal) in minijail_wait_internal() argument
3857 if (j->initpid <= 0) in minijail_wait_internal()
3858 return -ECHILD; in minijail_wait_internal()
3862 const int ret = waitpid(j->initpid, &st, 0); in minijail_wait_internal()
3866 return -errno; in minijail_wait_internal()
3885 j->initpid, in minijail_wait_internal()
3886 j->seccomp_policy_path ? j->seccomp_policy_path in minijail_wait_internal()
3887 : "NO-LABEL"); in minijail_wait_internal()
3892 j->initpid, signum); in minijail_wait_internal()
3901 info("child process %d exited with status %d", j->initpid, in minijail_wait_internal()
3907 int API minijail_kill(struct minijail *j) in minijail_kill() argument
3909 if (j->initpid <= 0) in minijail_kill()
3910 return -ECHILD; in minijail_kill()
3912 if (kill(j->initpid, SIGTERM)) in minijail_kill()
3913 return -errno; in minijail_kill()
3915 return minijail_wait_internal(j, SIGTERM); in minijail_kill()
3918 int API minijail_wait(struct minijail *j) in minijail_wait() argument
3920 return minijail_wait_internal(j, 0); in minijail_wait()
3923 void API minijail_destroy(struct minijail *j) in minijail_destroy() argument
3927 if (j->filter_prog) { in minijail_destroy()
3928 free(j->filter_prog->filter); in minijail_destroy()
3929 free(j->filter_prog); in minijail_destroy()
3931 free_mounts_list(j); in minijail_destroy()
3932 free_remounts_list(j); in minijail_destroy()
3933 while (j->hooks_head) { in minijail_destroy()
3934 struct hook *c = j->hooks_head; in minijail_destroy()
3935 j->hooks_head = c->next; in minijail_destroy()
3938 j->hooks_tail = NULL; in minijail_destroy()
3939 while (j->fs_rules_head) { in minijail_destroy()
3940 struct fs_rule *r = j->fs_rules_head; in minijail_destroy()
3941 j->fs_rules_head = r->next; in minijail_destroy()
3944 j->fs_rules_tail = NULL; in minijail_destroy()
3945 if (j->user) in minijail_destroy()
3946 free(j->user); in minijail_destroy()
3947 if (j->suppl_gid_list) in minijail_destroy()
3948 free(j->suppl_gid_list); in minijail_destroy()
3949 if (j->chrootdir) in minijail_destroy()
3950 free(j->chrootdir); in minijail_destroy()
3951 if (j->pid_file_path) in minijail_destroy()
3952 free(j->pid_file_path); in minijail_destroy()
3953 if (j->uidmap) in minijail_destroy()
3954 free(j->uidmap); in minijail_destroy()
3955 if (j->gidmap) in minijail_destroy()
3956 free(j->gidmap); in minijail_destroy()
3957 if (j->hostname) in minijail_destroy()
3958 free(j->hostname); in minijail_destroy()
3959 if (j->preload_path) in minijail_destroy()
3960 free(j->preload_path); in minijail_destroy()
3961 if (j->alt_syscall_table) in minijail_destroy()
3962 free(j->alt_syscall_table); in minijail_destroy()
3963 for (i = 0; i < j->cgroup_count; ++i) in minijail_destroy()
3964 free(j->cgroups[i]); in minijail_destroy()
3965 if (j->seccomp_policy_path) in minijail_destroy()
3966 free(j->seccomp_policy_path); in minijail_destroy()
3967 free(j); in minijail_destroy()