diff options
-rw-r--r-- | man/systemd-mount.xml | 19 | ||||
-rw-r--r-- | src/basic/umask-util.h | 4 | ||||
-rw-r--r-- | src/mount/mount-tool.c | 63 | ||||
-rw-r--r-- | src/test/test-umask-util.c | 18 |
4 files changed, 74 insertions, 30 deletions
diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml index 890c950cd0..dfa4a95cb1 100644 --- a/man/systemd-mount.xml +++ b/man/systemd-mount.xml @@ -70,9 +70,9 @@ whose name is generated from the file system label. In this mode the block device or image file must exist at the time of invocation of the command, so that it may be probed. If the device is found to be a removable block device (e.g. a USB stick), an automount point is created instead of a regular mount point - (i.e. the <option>--automount=</option> option is implied, see below). If the option <option>--tmpfs</option> - is specified, then the argument will be interpreted as the path where the new temporary file system will - be mounted on.</para> + (i.e. the <option>--automount=</option> option is implied, see below). If the option + <option>--tmpfs</option> is specified, then the argument is interpreted as the path where the new + temporary file system shall be mounted.</para> <para>If two arguments are specified, the first indicates the mount source (the <replaceable>WHAT</replaceable>) and the second indicates the path to mount it on (the @@ -287,8 +287,17 @@ <term><option>--tmpfs</option></term> <listitem> - <para>Create and mount a new temporary file system on <replaceable>WHERE</replaceable>, with an - optional <replaceable>NAME</replaceable> that defaults to <literal>tmpfs</literal>.</para> + <para>Create and mount a new <constant>tmpfs</constant> file system on + <replaceable>WHERE</replaceable>, with an optional <replaceable>NAME</replaceable> that defaults to + <literal>tmpfs</literal>.</para> + + <para>The file system is mounted with the top-level directory mode determined by the + <citerefentry><refentrytitle>umask</refentrytitle><manvolnum>2</manvolnum></citerefentry> setting + of the caller, i.e. <constant>rwxrwxrwx</constant> masked by the umask of the caller. This matches + what + <citerefentry project='man-pages'><refentrytitle>mkdir</refentrytitle><manvolnum>1</manvolnum></citerefentry> + does, but is different from the kernel default of <literal>rwxrwxrwxt</literal>, i.e. a + world-writable directory with the sticky bit set.</para> </listitem> </varlistentry> diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h index 6f0e1cc2b2..00417fa304 100644 --- a/src/basic/umask-util.h +++ b/src/basic/umask-util.h @@ -8,12 +8,12 @@ #include "macro.h" static inline void umaskp(mode_t *u) { - umask(*u & 0777); + umask(*u); } #define _cleanup_umask_ _cleanup_(umaskp) -/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although +/* We make use of the fact here that the umask() syscall uses only the lower 9 bits of mode_t, although * mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to * distinguish the first and the second iteration of the WITH_UMASK() loop, so that we can run the first one, * and exit on the second. */ diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 31abc0685d..b167176a9f 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -35,6 +35,7 @@ #include "stat-util.h" #include "strv.h" #include "terminal-util.h" +#include "umask-util.h" #include "unit-def.h" #include "unit-name.h" #include "user-util.h" @@ -206,7 +207,7 @@ static int parse_argv(int argc, char *argv[]) { { "bind-device", no_argument, NULL, ARG_BIND_DEVICE }, { "list", no_argument, NULL, ARG_LIST }, { "umount", no_argument, NULL, 'u' }, - { "unmount", no_argument, NULL, 'u' }, + { "unmount", no_argument, NULL, 'u' }, /* Compat spelling */ { "collect", no_argument, NULL, 'G' }, { "tmpfs", no_argument, NULL, 'T' }, {}, @@ -391,15 +392,12 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At least one argument required."); - if (arg_transport != BUS_TRANSPORT_LOCAL) { - int i; - - for (i = optind; i < argc; i++) - if (!path_is_absolute(argv[i]) ) + if (arg_transport != BUS_TRANSPORT_LOCAL) + for (int i = optind; i < argc; i++) + if (!path_is_absolute(argv[i])) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path must be absolute when operating remotely: %s", argv[i]); - } } else { if (optind >= argc) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -407,7 +405,7 @@ static int parse_argv(int argc, char *argv[]) { if (argc > optind+2) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "At most two arguments required."); + "More than two arguments are not allowed."); if (arg_tmpfs) { if (argc <= optind+1) { @@ -509,7 +507,6 @@ static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **p } static int transient_mount_set_properties(sd_bus_message *m) { - _cleanup_free_ char *options = NULL; int r; assert(m); @@ -530,20 +527,43 @@ static int transient_mount_set_properties(sd_bus_message *m) { return r; } + _cleanup_free_ char *options = NULL; + /* Prepend uid=…,gid=… if arg_uid is set */ if (arg_uid != UID_INVALID) { - r = asprintf(&options, - "uid=" UID_FMT ",gid=" GID_FMT "%s%s", - arg_uid, arg_gid, - arg_mount_options ? "," : "", strempty(arg_mount_options)); + r = strextendf_with_separator(&options, ",", + "uid="UID_FMT",gid="GID_FMT, arg_uid, arg_gid); if (r < 0) - return -ENOMEM; + return r; } - if (options || arg_mount_options) { - log_debug("Using mount options: %s", options ?: arg_mount_options); + /* Override the default for tmpfs mounts. The kernel sets the sticky bit on the root directory by + * default. This makes sense for the case when the user does 'mount -t tmpfs tmpfs /tmp', but less so + * for other directories. + * + * Let's also set some reasonable limits. We use the current umask, to match what a command to create + * directory would use, e.g. mkdir. */ + if (arg_tmpfs) { + mode_t mask; + + r = get_process_umask(0, &mask); + if (r < 0) + return r; + + assert((mask & ~0777) == 0); + r = strextendf_with_separator(&options, ",", + "mode=0%o,nodev,nosuid%s", 0777 & ~mask, NESTED_TMPFS_LIMITS); + if (r < 0) + return r; + } + + if (arg_mount_options) + if (!strextend_with_separator(&options, ",", arg_mount_options)) + return r; - r = sd_bus_message_append(m, "(sv)", "Options", "s", options ?: arg_mount_options); + if (options) { + log_debug("Using mount options: %s", options); + r = sd_bus_message_append(m, "(sv)", "Options", "s", options); if (r < 0) return r; } else @@ -1028,10 +1048,10 @@ static int action_umount( int argc, char **argv) { - int i, r, r2 = 0; + int r, r2 = 0; if (arg_transport != BUS_TRANSPORT_LOCAL) { - for (i = optind; i < argc; i++) { + for (int i = optind; i < argc; i++) { _cleanup_free_ char *p = NULL; p = strdup(argv[i]); @@ -1047,7 +1067,7 @@ static int action_umount( return r2; } - for (i = optind; i < argc; i++) { + for (int i = optind; i < argc; i++) { _cleanup_free_ char *u = NULL, *p = NULL; struct stat st; @@ -1411,7 +1431,6 @@ enum { static int list_devices(void) { _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; _cleanup_(table_unrefp) Table *table = NULL; - unsigned c; int r; r = sd_device_enumerator_new(&e); @@ -1440,7 +1459,7 @@ static int list_devices(void) { table_set_header(table, arg_legend); FOREACH_DEVICE(e, d) { - for (c = 0; c < _COLUMN_MAX; c++) { + for (unsigned c = 0; c < _COLUMN_MAX; c++) { const char *x = NULL; switch (c) { diff --git a/src/test/test-umask-util.c b/src/test/test-umask-util.c index bd5bc9cb43..8316dfb44a 100644 --- a/src/test/test-umask-util.c +++ b/src/test/test-umask-util.c @@ -1,11 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "process-util.h" #include "tests.h" #include "umask-util.h" int main(int argc, char *argv[]) { size_t n; - mode_t u; + mode_t u, t; test_setup_logging(LOG_DEBUG); @@ -15,19 +16,31 @@ int main(int argc, char *argv[]) { WITH_UMASK(0123) { assert_se(umask(000) == 0123); n++; + + assert_se(get_process_umask(0, &t) == 0); + assert_se(t == 000); } assert_se(n == 1); assert_se(umask(u) == 0111); + assert_se(get_process_umask(getpid_cached(), &t) == 0); + assert_se(t == u); + WITH_UMASK(0135) { assert_se(umask(000) == 0135); n++; + + assert_se(get_process_umask(0, &t) == 0); + assert_se(t == 000); } assert_se(n == 2); assert_se(umask(0111) == u); + assert_se(get_process_umask(0, &t) == 0); + assert_se(t == 0111); + WITH_UMASK(0315) { assert_se(umask(000) == 0315); n++; @@ -37,5 +50,8 @@ int main(int argc, char *argv[]) { assert_se(n == 3); assert_se(umask(u) == 0111); + assert_se(get_process_umask(0, &t) == 0); + assert_se(t == u); + return EXIT_SUCCESS; } |