From: Lennart Poettering Date: Thu, 20 Nov 2025 12:12:40 +0000 (+0100) Subject: mountfsd: optionally accept an access mode for the dir created by MakeDirectory() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46341769b7146d6d7b80507b0b37f253dd7cfda1;p=thirdparty%2Fsystemd.git mountfsd: optionally accept an access mode for the dir created by MakeDirectory() So far we expected the client to access the access mode themselves, and set a restrictive 0700 server-side. However, in some scenarios it's handy if the inode is created server-side already with the right mode, in particular when the client doesn't do anything with the dir just yet, and just needs it to be there with the right mode. If it has to adjust the mode client-side it might otherwise need to fork something off, join the selected userns, adjust the mode, and kill the child off again. --- diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index 24f6e23e231..0e0bd964eeb 100644 --- a/src/mountfsd/mountwork.c +++ b/src/mountfsd/mountwork.c @@ -1003,6 +1003,7 @@ static int vl_method_mount_directory( typedef struct MakeDirectoryParameters { unsigned parent_fd_idx; const char *name; + mode_t mode; } MakeDirectoryParameters; static int vl_method_make_directory( @@ -1012,14 +1013,16 @@ static int vl_method_make_directory( void *userdata) { static const sd_json_dispatch_field dispatch_table[] = { - { "parentFileDescriptor", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(MakeDirectoryParameters, parent_fd_idx), SD_JSON_MANDATORY }, - { "name", SD_JSON_VARIANT_STRING, json_dispatch_const_filename, offsetof(MakeDirectoryParameters, name), SD_JSON_MANDATORY }, + { "parentFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(MakeDirectoryParameters, parent_fd_idx), SD_JSON_MANDATORY }, + { "name", SD_JSON_VARIANT_STRING, json_dispatch_const_filename, offsetof(MakeDirectoryParameters, name), SD_JSON_MANDATORY }, + { "mode", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_access_mode, offsetof(MakeDirectoryParameters, mode), SD_JSON_STRICT }, VARLINK_DISPATCH_POLKIT_FIELD, {} }; MakeDirectoryParameters p = { .parent_fd_idx = UINT_MAX, + .mode = MODE_INVALID, }; Hashmap **polkit_registry = ASSERT_PTR(userdata); int r; @@ -1028,6 +1031,11 @@ static int vl_method_make_directory( if (r != 0) return r; + if (p.mode == MODE_INVALID) + p.mode = 0700; + else + p.mode &= 0775; /* refuse generating world writable dirs */ + if (p.parent_fd_idx == UINT_MAX) return sd_varlink_error_invalid_parameter_name(link, "parentFileDescriptor"); @@ -1089,11 +1097,11 @@ static int vl_method_make_directory( if (r < 0) return r; - _cleanup_close_ int fd = open_mkdir_at(parent_fd, t, O_CLOEXEC, 0700); + _cleanup_close_ int fd = open_mkdir_at(parent_fd, t, O_CLOEXEC, p.mode); if (fd < 0) return fd; - r = RET_NERRNO(fchmod(fd, 0700)); /* Set mode explicitly, as paranoia regarding umask games */ + r = RET_NERRNO(fchmod(fd, p.mode)); /* Set mode explicitly, as paranoia regarding umask games */ if (r < 0) goto fail; diff --git a/src/shared/varlink-io.systemd.MountFileSystem.c b/src/shared/varlink-io.systemd.MountFileSystem.c index e9c69f07d82..356f9938aaa 100644 --- a/src/shared/varlink-io.systemd.MountFileSystem.c +++ b/src/shared/varlink-io.systemd.MountFileSystem.c @@ -113,6 +113,8 @@ static SD_VARLINK_DEFINE_METHOD( SD_VARLINK_DEFINE_INPUT(parentFileDescriptor, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Name of the directory to create."), SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Access mode of the directory to create. Note that the suid, sgid, sticky, world-writable bit is unconditionally masked off."), + SD_VARLINK_DEFINE_INPUT(mode, SD_VARLINK_INT, SD_VARLINK_NULLABLE), VARLINK_DEFINE_POLKIT_INPUT, SD_VARLINK_FIELD_COMMENT("File descriptor referencing the newly created directory."), SD_VARLINK_DEFINE_OUTPUT(directoryFileDescriptor, SD_VARLINK_INT, 0));