minijail: add --no-fs-restrictions flag.
This is a general flag, instead of being specific to disabling
profile-fs-restrictions, because future versions of the default
runtime environment may also include Landlock.
BUG=b:264449526
TEST=security.Minijail*
TEST=minijail unit tests, including new tests
Change-Id: I12fbb87f1e2307b16057976187fe640297bab30b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minijail/+/4136129
Tested-by: Ben Scarlato <akhna@google.com>
Reviewed-by: Allen Webb <allenwebb@google.com>
Commit-Queue: Ben Scarlato <akhna@google.com>
Auto-Submit: Ben Scarlato <akhna@google.com>
diff --git a/libminijail.c b/libminijail.c
index 38a5148..091e50b 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -165,6 +165,7 @@
bool forward_signals : 1;
bool setsid : 1;
bool using_minimalistic_mountns : 1;
+ bool enable_fs_restrictions : 1;
bool enable_profile_fs_restrictions : 1;
bool enable_default_runtime : 1;
} flags;
@@ -368,6 +369,7 @@
int remount_proc_ro = j->flags.remount_proc_ro;
int userns = j->flags.userns;
int using_minimalistic_mountns = j->flags.using_minimalistic_mountns;
+ int enable_fs_restrictions = j->flags.enable_fs_restrictions;
int enable_profile_fs_restrictions = j->flags.enable_profile_fs_restrictions;
int enable_default_runtime = j->flags.enable_default_runtime;
if (j->user)
@@ -391,6 +393,7 @@
j->flags.remount_proc_ro = remount_proc_ro;
j->flags.userns = userns;
j->flags.using_minimalistic_mountns = using_minimalistic_mountns;
+ j->flags.enable_fs_restrictions = enable_fs_restrictions;
j->flags.enable_profile_fs_restrictions = enable_profile_fs_restrictions;
j->flags.enable_default_runtime = enable_default_runtime;
/* Note, |pids| will already have been used before this call. */
@@ -404,6 +407,7 @@
if (j) {
j->remount_mode = MS_PRIVATE;
j->flags.using_minimalistic_mountns = false;
+ j->flags.enable_fs_restrictions = true;
j->flags.enable_profile_fs_restrictions = true;
j->flags.enable_default_runtime = true;
}
@@ -570,6 +574,10 @@
return j->flags.enable_default_runtime;
}
+void API minijail_disable_fs_restrictions(struct minijail *j) {
+ j->flags.enable_fs_restrictions = false;
+}
+
void API minijail_set_enable_profile_fs_restrictions(struct minijail *j)
{
j->flags.enable_profile_fs_restrictions = true;
@@ -2492,6 +2500,9 @@
{
struct fs_rule *r;
attribute_cleanup_fd int ruleset_fd = -1;
+ if (!j->flags.enable_fs_restrictions) {
+ return;
+ }
r = j->fs_rules_head;
while (r) {
diff --git a/libminijail.h b/libminijail.h
index 9cba632..9c15dfc 100644
--- a/libminijail.h
+++ b/libminijail.h
@@ -117,6 +117,7 @@
* Exposed for unit tests and allowlisting services.
*/
bool minijail_get_enable_default_runtime(struct minijail *j);
+void minijail_disable_fs_restrictions(struct minijail *j);
void minijail_set_enable_profile_fs_restrictions(struct minijail *j);
void minijail_add_minimalistic_mountns_fs_rules(struct minijail *j);
void minijail_enable_default_fs_restrictions(struct minijail *j);
diff --git a/libminijail_unittest.cc b/libminijail_unittest.cc
index 12b790d..97bbef3 100644
--- a/libminijail_unittest.cc
+++ b/libminijail_unittest.cc
@@ -1715,6 +1715,29 @@
EXPECT_NE(status, 0);
}
+TEST_F(LandlockTest, test_fs_rules_disabled) {
+ int mj_run_ret;
+ int status;
+ char *argv[4];
+ if (!run_landlock_tests_)
+ GTEST_SKIP();
+ ScopedMinijail j(minijail_new());
+ SetupLandlockTestingNamespaces(j.get());
+ minijail_add_fs_restriction_rx(j.get(), kBinPath);
+ minijail_disable_fs_restrictions(j.get());
+
+ argv[0] = const_cast<char*>(kShellPath);
+ argv[1] = "-c";
+ argv[2] = "exec echo 'bar' > /tmp/fs-rules-test";
+ argv[3] = NULL;
+
+ mj_run_ret = minijail_run_no_preload(j.get(), argv[0], argv);
+ EXPECT_EQ(mj_run_ret, 0);
+ status = minijail_wait(j.get());
+ // Rules aren't applied, so cmd succeeds.
+ EXPECT_EQ(status, 0);
+}
+
TEST_F(LandlockTest, test_rule_allow_symlinks_advanced_rw) {
int mj_run_ret;
int status;
diff --git a/minijail0_cli.c b/minijail0_cli.c
index b2cacb54..a8105b3 100644
--- a/minijail0_cli.c
+++ b/minijail0_cli.c
@@ -499,6 +499,7 @@
OPT_GEN_CONFIG,
OPT_LOGGING,
OPT_NO_DEFAULT_RUNTIME,
+ OPT_NO_FS_RESTRICTIONS,
OPT_PRELOAD_LIBRARY,
OPT_PROFILE,
OPT_SECCOMP_BPF_BINARY,
@@ -542,6 +543,8 @@
{"fs-path-advanced-rw", required_argument, 0, OPT_FS_PATH_ADVANCED_RW},
{"no-default-runtime-environment", no_argument, 0,
OPT_NO_DEFAULT_RUNTIME},
+ {"no-fs-restrictions", no_argument, 0,
+ OPT_NO_FS_RESTRICTIONS},
{0, 0, 0, 0},
};
@@ -674,6 +677,8 @@
" Adds an allowed read-write path.\n"
" --fs-path-advanced-rw\n"
" Adds an allowed advanced read-write path.\n"
+" --no-fs-restrictions\n"
+" Disables path-based filesystem restrictions.\n"
" --no-default-runtime-environment\n"
" Disables default seccomp policy and setting of no_new_privs.\n"
" --preload-library=<file>\n"
@@ -858,6 +863,8 @@
struct option_entry *opt_entry_head = NULL;
struct option_entry *opt_entry_tail = NULL;
char* config_path = NULL;
+ bool fs_path_flag_used = false;
+ bool fs_path_rules_enabled = true;
while ((opt = getopt_conf_or_cli(argc, argv, &conf_entry_list,
&conf_index)) != -1) {
@@ -1128,18 +1135,27 @@
break;
case OPT_FS_DEFAULT_PATHS:
minijail_enable_default_fs_restrictions(j);
+ fs_path_flag_used = true;
break;
case OPT_FS_PATH_RX:
minijail_add_fs_restriction_rx(j, optarg);
+ fs_path_flag_used = true;
break;
case OPT_FS_PATH_RO:
minijail_add_fs_restriction_ro(j, optarg);
+ fs_path_flag_used = true;
break;
case OPT_FS_PATH_RW:
minijail_add_fs_restriction_rw(j, optarg);
+ fs_path_flag_used = true;
break;
case OPT_FS_PATH_ADVANCED_RW:
minijail_add_fs_restriction_advanced_rw(j, optarg);
+ fs_path_flag_used = true;
+ break;
+ case OPT_NO_FS_RESTRICTIONS:
+ minijail_disable_fs_restrictions(j);
+ fs_path_rules_enabled = false;
break;
case OPT_NO_DEFAULT_RUNTIME:
minijail_set_enable_default_runtime(j, false);
@@ -1262,6 +1278,11 @@
}
}
+ if (fs_path_flag_used && !fs_path_rules_enabled) {
+ errx(1, "Can't combine --no-fs-restrictions "
+ "with directly using fs path flags");
+ }
+
/* Handle config file generation. */
if (gen_config) {
struct option_entry *r = opt_entry_head;
diff --git a/minijail0_cli_unittest.cc b/minijail0_cli_unittest.cc
index 7a93537..d6299f3 100644
--- a/minijail0_cli_unittest.cc
+++ b/minijail0_cli_unittest.cc
@@ -338,6 +338,23 @@
ASSERT_EXIT(parse_args_(argv), testing::ExitedWithCode(1), "");
}
+// Valid usage of the no-fs-restrictions option.
+TEST_F(CliTest, valid_no_fs_restrictions) {
+ std::vector<std::string> argv = {"--profile", "minimalistic-mountns",
+ "--no-fs-restrictions", "/bin/sh"};
+
+ ASSERT_TRUE(parse_args_(argv));
+}
+
+// Invalid usage of the no-fs-restrictions option.
+TEST_F(CliTest, invalid_no_fs_restrictions) {
+ // Using an fs-path-* flag at the same time shouldn't be allowed.
+ std::vector<std::string> argv = {"--fs-path-rx", "/",
+ "--no-fs-restrictions", "/bin/sh"};
+
+ ASSERT_EXIT(parse_args_(argv), testing::ExitedWithCode(1), "");
+}
+
// Valid calls to the chroot option.
TEST_F(CliTest, valid_chroot) {
std::vector<std::string> argv = {"-C", "/", "/bin/sh"};