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.
This commit is contained in:
Lennart Poettering
2025-12-21 07:04:42 +01:00
parent 6e07fc6bcc
commit 46341769b7
2 changed files with 14 additions and 4 deletions
+12 -4
View File
@@ -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;
@@ -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));