mirror of
https://github.com/systemd/systemd.git
synced 2025-03-08 08:58:27 +03:00
Merge pull request #28913 from keszybz/tmpfs-top-level-dir-mode
systemd-mount: do not create tmpfs mounts with sticky permission bit
This commit is contained in:
commit
3b9b33a143
@ -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>
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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 = sd_bus_message_append(m, "(sv)", "Options", "s", options ?: arg_mount_options);
|
||||
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;
|
||||
|
||||
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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user