Merge pull request #9977 from sourcejedi/no-remount-superblock3
Namespace fixes
This commit is contained in:
commit
0c09cb0e78
|
@ -265,7 +265,6 @@ static int append_empty_dir_mounts(MountEntry **p, char **strv) {
|
||||||
.path_const = *i,
|
.path_const = *i,
|
||||||
.mode = EMPTY_DIR,
|
.mode = EMPTY_DIR,
|
||||||
.ignore = false,
|
.ignore = false,
|
||||||
.has_prefix = false,
|
|
||||||
.read_only = true,
|
.read_only = true,
|
||||||
.options_const = "mode=755",
|
.options_const = "mode=755",
|
||||||
.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
|
.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
|
||||||
|
@ -304,7 +303,7 @@ static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs,
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
const TemporaryFileSystem *t = tmpfs + i;
|
const TemporaryFileSystem *t = tmpfs + i;
|
||||||
_cleanup_free_ char *o = NULL, *str = NULL;
|
_cleanup_free_ char *o = NULL, *str = NULL;
|
||||||
unsigned long flags = MS_NODEV|MS_STRICTATIME;
|
unsigned long flags;
|
||||||
bool ro = false;
|
bool ro = false;
|
||||||
|
|
||||||
if (!path_is_absolute(t->path)) {
|
if (!path_is_absolute(t->path)) {
|
||||||
|
@ -312,29 +311,25 @@ static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isempty(t->options)) {
|
str = strjoin("mode=0755,", t->options);
|
||||||
str = strjoin("mode=0755,", t->options);
|
if (!str)
|
||||||
if (!str)
|
return -ENOMEM;
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = mount_option_mangle(str, MS_NODEV|MS_STRICTATIME, &flags, &o);
|
r = mount_option_mangle(str, MS_NODEV|MS_STRICTATIME, &flags, &o);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to parse mount option '%s': %m", str);
|
return log_debug_errno(r, "Failed to parse mount option '%s': %m", str);
|
||||||
|
|
||||||
ro = flags & MS_RDONLY;
|
ro = flags & MS_RDONLY;
|
||||||
if (ro)
|
if (ro)
|
||||||
flags ^= MS_RDONLY;
|
flags ^= MS_RDONLY;
|
||||||
}
|
|
||||||
|
|
||||||
*((*p)++) = (MountEntry) {
|
*((*p)++) = (MountEntry) {
|
||||||
.path_const = t->path,
|
.path_const = t->path,
|
||||||
.mode = TMPFS,
|
.mode = TMPFS,
|
||||||
.read_only = ro,
|
.read_only = ro,
|
||||||
.options_malloc = o,
|
.options_malloc = TAKE_PTR(o),
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
o = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -423,11 +418,7 @@ static int mount_path_compare(const void *a, const void *b) {
|
||||||
static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directory) {
|
static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directory) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
/* Prefixes all paths in the bind mount table with the root directory if it is specified and the entry needs
|
/* Prefixes all paths in the bind mount table with the root directory if the entry needs that. */
|
||||||
* that. */
|
|
||||||
|
|
||||||
if (!root_directory)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
char *s;
|
char *s;
|
||||||
|
@ -1026,6 +1017,15 @@ static int apply_mount(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Change the per-mount readonly flag on an existing mount */
|
||||||
|
static int remount_bind_readonly(const char *path, unsigned long orig_flags) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = mount(NULL, path, NULL, MS_REMOUNT | MS_BIND | MS_RDONLY | orig_flags, NULL);
|
||||||
|
|
||||||
|
return r < 0 ? -errno : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int make_read_only(const MountEntry *m, char **blacklist, FILE *proc_self_mountinfo) {
|
static int make_read_only(const MountEntry *m, char **blacklist, FILE *proc_self_mountinfo) {
|
||||||
bool submounts = false;
|
bool submounts = false;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
@ -1035,17 +1035,15 @@ static int make_read_only(const MountEntry *m, char **blacklist, FILE *proc_self
|
||||||
|
|
||||||
if (mount_entry_read_only(m)) {
|
if (mount_entry_read_only(m)) {
|
||||||
if (IN_SET(m->mode, EMPTY_DIR, TMPFS)) {
|
if (IN_SET(m->mode, EMPTY_DIR, TMPFS)) {
|
||||||
/* Make superblock readonly */
|
r = remount_bind_readonly(mount_entry_path(m), m->flags);
|
||||||
if (mount(NULL, mount_entry_path(m), NULL, MS_REMOUNT | MS_RDONLY | m->flags, mount_entry_options(m)) < 0)
|
|
||||||
r = -errno;
|
|
||||||
} else {
|
} else {
|
||||||
submounts = true;
|
submounts = true;
|
||||||
r = bind_remount_recursive_with_mountinfo(mount_entry_path(m), true, blacklist, proc_self_mountinfo);
|
r = bind_remount_recursive_with_mountinfo(mount_entry_path(m), true, blacklist, proc_self_mountinfo);
|
||||||
}
|
}
|
||||||
} else if (m->mode == PRIVATE_DEV) {
|
} else if (m->mode == PRIVATE_DEV) {
|
||||||
/* Superblock can be readonly but the submounts can't */
|
/* Set /dev readonly, but not submounts like /dev/shm. Also, we only set the per-mount read-only flag.
|
||||||
if (mount(NULL, mount_entry_path(m), NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0)
|
* We can't set it on the superblock, if we are inside a user namespace and running Linux <= 4.17. */
|
||||||
r = -errno;
|
r = remount_bind_readonly(mount_entry_path(m), DEV_MOUNT_OPTIONS);
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
Description=Test for ReadOnlyPaths=
|
Description=Test for ReadOnlyPaths=
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ReadOnlyPaths=/etc -/i-dont-exist /usr
|
ReadOnlyPaths=/usr /etc /sys /dev -/i-dont-exist
|
||||||
ExecStart=/bin/sh -x -c 'test ! -w /etc && test ! -w /usr && test ! -e /i-dont-exist && test -w /var'
|
PrivateDevices=yes
|
||||||
|
ExecStart=/bin/sh -x -c 'test ! -w /usr && test ! -w /etc && test ! -w /sys && test ! -w /sys/fs/cgroup'
|
||||||
|
ExecStart=/bin/sh -x -c 'test ! -w /dev && test ! -w /dev/shm && test ! -e /i-dont-exist && test -w /var'
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
|
|
@ -5,11 +5,10 @@ Description=Test for TemporaryFileSystem with mount options
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
|
||||||
# The mount options default to "mode=0755,nodev,strictatime".
|
# The mount options default to "mode=0755,nodev,strictatime".
|
||||||
# Let's override some of them, and test the behaviour of "ro".
|
# Let's override some of them, and test "ro".
|
||||||
TemporaryFileSystem=/var:ro,mode=0700,nostrictatime
|
TemporaryFileSystem=/var:ro,mode=0700,nostrictatime
|
||||||
|
|
||||||
# Check /proc/self/mountinfo
|
# Check /proc/self/mountinfo
|
||||||
ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$11 !~ /(^|,)ro(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
|
|
||||||
ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$11 !~ /(^|,)mode=700(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
|
ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$11 !~ /(^|,)mode=700(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
|
||||||
|
|
||||||
ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 !~ /(^|,)ro(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
|
ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 !~ /(^|,)ro(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
|
||||||
|
|
|
@ -10,6 +10,9 @@ ExecStart=/bin/sh -c 'test -d /var/test-exec-temporaryfilesystem/rw && test -d /
|
||||||
# Check TemporaryFileSystem= are empty
|
# Check TemporaryFileSystem= are empty
|
||||||
ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
|
ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
|
||||||
|
|
||||||
|
# Check default mode
|
||||||
|
ExecStart=sh -x -c 'test "$$(stat -c %%a /var)" = "755"'
|
||||||
|
|
||||||
# Cannot create a file in /var
|
# Cannot create a file in /var
|
||||||
ExecStart=/bin/sh -c '! touch /var/hoge'
|
ExecStart=/bin/sh -c '! touch /var/hoge'
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ ExecStart=test -d /var/test-exec-temporaryfilesystem/rw -a -d /var/test-exec-tem
|
||||||
# Check TemporaryFileSystem= are empty
|
# Check TemporaryFileSystem= are empty
|
||||||
ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
|
ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
|
||||||
|
|
||||||
|
# Check default mode
|
||||||
|
ExecStart=sh -x -c 'test "$$(stat -c %%a /var)" = "755"'
|
||||||
|
|
||||||
# Create a file in /var
|
# Create a file in /var
|
||||||
ExecStart=touch /var/hoge
|
ExecStart=touch /var/hoge
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue