diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index 24f6e23e23..0e0bd964ee 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 e9c69f07d8..356f9938aa 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));