mount_service: use the fsmount API helpers from mount_fsmount.c

The new fsmount API code in mount_service.c should use the new helper
functions that were recently added to mount_fsmount.c.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
This commit is contained in:
Darrick J. Wong
2026-05-11 08:26:42 -07:00
parent 3b24f207ca
commit 7211953256
4 changed files with 141 additions and 235 deletions
+16 -60
View File
@@ -35,17 +35,8 @@
#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 #define MOUNT_ATTR_NOSYMFOLLOW 0x00200000
#endif #endif
/* unsigned long ms_flags_to_mount_attrs(unsigned long ms_flags,
* Convert MS_* mount flags to MOUNT_ATTR_* mount attributes. unsigned int *mount_attrs)
* These flags are passed to fsmount(), not fsconfig().
* Mount attributes control mount-point level behavior.
* To called after set_ms_flags() which consumes the fsconfig flags.
*
* @mount_attrs MOUNT_ATTR flags, built from MS_ flags
* @return remaining MS_* flags
*/
static unsigned long ms_flags_to_mount_attrs(unsigned long ms_flags,
unsigned int *mount_attrs)
{ {
int i; int i;
@@ -65,12 +56,7 @@ static unsigned long ms_flags_to_mount_attrs(unsigned long ms_flags,
return ms_flags; return ms_flags;
} }
/* void log_fsconfig_kmsg(int fd)
* Read and print kernel error messages from fsopen fd.
* The kernel can provide detailed error/warning/info messages via the
* filesystem context fd that are more informative than strerror(errno).
*/
static void log_fsconfig_kmsg(int fd)
{ {
char buf[4096]; char buf[4096];
int err, sz = 0; int err, sz = 0;
@@ -107,19 +93,7 @@ static void log_fsconfig_kmsg(int fd)
errno = err; errno = err;
} }
/* int set_fsconfig_ms_flags(int fsfd, unsigned long *ms_flags)
* Apply VFS superblock (fsconfig) flags to the filesystem context.
* Handles the fsconfig leg of every entry whose is_fsconfig is set
* (ro, rw, sync, async, dirsync). Mount attributes (nosuid, nodev, etc.)
* are handled separately via fsmount().
*
* Entries that have *both* legs (ro/rw) leave the MS_ bit in *ms_flags
* so that ms_flags_to_mount_attrs() can also pick them up.
*
* @ms_flags flags to set, outvalue are the remaining flags
* @return 0 on success, negative error code on failure
*/
static int set_ms_flags(int fsfd, unsigned long *ms_flags)
{ {
int ret, flags = *ms_flags; int ret, flags = *ms_flags;
int i; int i;
@@ -155,16 +129,7 @@ static int set_ms_flags(int fsfd, unsigned long *ms_flags)
return 0; return 0;
} }
/* int apply_fsconfig_opt_fd(int fsfd, const char *value)
* Apply the "fd" parameter via fsconfig
*
* Special handler for the "fd" mount option. Note that despite the name,
* the fd parameter is passed as a u32 string value, not as a file descriptor
* to pass to the kernel. Uses FSCONFIG_SET_STRING rather than FSCONFIG_SET_FD.
*
* Returns 0 on success, negative error code on failure.
*/
static int apply_opt_fd(int fsfd, const char *value)
{ {
int res; int res;
@@ -181,15 +146,7 @@ static int apply_opt_fd(int fsfd, const char *value)
return 0; return 0;
} }
/* int apply_fsconfig_opt_string(int fsfd, const char *key, const char *value)
* Apply a key=value string option via fsconfig
*
* Applies a mount option that consists of a key-value pair (e.g., "rootmode=40000").
* Uses FSCONFIG_SET_STRING to pass the key and value to the filesystem configuration.
*
* Returns 0 on success, negative error code on failure.
*/
static int apply_opt_string(int fsfd, const char *key, const char *value)
{ {
int res, save_errno; int res, save_errno;
@@ -210,6 +167,8 @@ static int apply_opt_string(int fsfd, const char *key, const char *value)
* Applies a mount option that is a simple flag without a value (e.g., "rw"). * Applies a mount option that is a simple flag without a value (e.g., "rw").
* Uses FSCONFIG_SET_FLAG to set the flag in the filesystem configuration. * Uses FSCONFIG_SET_FLAG to set the flag in the filesystem configuration.
* *
* @fsfd fsopen fd
* @opt name of filesystem mount flag option
* Returns 0 on success, negative error code on failure. * Returns 0 on success, negative error code on failure.
*/ */
static int apply_opt_flag(int fsfd, const char *opt) static int apply_opt_flag(int fsfd, const char *opt)
@@ -227,7 +186,6 @@ static int apply_opt_flag(int fsfd, const char *opt)
return 0; return 0;
} }
/* /*
* Parse and apply a single mount option via fsconfig * Parse and apply a single mount option via fsconfig
* *
@@ -238,6 +196,8 @@ static int apply_opt_flag(int fsfd, const char *opt)
* Special handling for the "fd" parameter which is treated as a string * Special handling for the "fd" parameter which is treated as a string
* value rather than a file descriptor to pass. * value rather than a file descriptor to pass.
* *
* @fsfd fsopen fd
* @opt filesystem mount option, may be modified
* Returns 0 on success, negative error code on failure. * Returns 0 on success, negative error code on failure.
*/ */
static int apply_opt_key_value(int fsfd, char *opt) static int apply_opt_key_value(int fsfd, char *opt)
@@ -255,9 +215,9 @@ static int apply_opt_key_value(int fsfd, char *opt)
value = eq + 1; value = eq + 1;
if (strcmp(key, "fd") == 0) if (strcmp(key, "fd") == 0)
return apply_opt_fd(fsfd, value); return apply_fsconfig_opt_fd(fsfd, value);
return apply_opt_string(fsfd, key, value); return apply_fsconfig_opt_string(fsfd, key, value);
} }
/* /*
@@ -287,11 +247,7 @@ static int is_mtab_only_opt(const char *opt)
strcmp(opt, "rw") == 0; strcmp(opt, "rw") == 0;
} }
/* int apply_fsconfig_mount_opts(int fsfd, const char *opts)
* Parse kernel options string and apply via fsconfig
* Options are comma-separated key=value pairs
*/
static int apply_mount_opts(int fsfd, const char *opts)
{ {
char *opts_copy; char *opts_copy;
char *opt; char *opt;
@@ -393,12 +349,12 @@ int fuse_kern_fsmount(const char *mnt, unsigned long flags, int blkdev,
} }
/* Apply VFS superblock (fsconfig) flags (ro, sync, dirsync) */ /* Apply VFS superblock (fsconfig) flags (ro, sync, dirsync) */
res = set_ms_flags(fsfd, &flags); res = set_fsconfig_ms_flags(fsfd, &flags);
if (res != 0) if (res != 0)
goto out_free; goto out_free;
/* Apply kernel options */ /* Apply kernel options */
err = apply_mount_opts(fsfd, kernel_opts); err = apply_fsconfig_mount_opts(fsfd, kernel_opts);
if (err < 0) { if (err < 0) {
log_fsconfig_kmsg(fsfd); log_fsconfig_kmsg(fsfd);
fprintf(stderr, fprintf(stderr,
@@ -408,7 +364,7 @@ int fuse_kern_fsmount(const char *mnt, unsigned long flags, int blkdev,
} }
/* Apply mtab options (overlap with kernel_opts is filtered and tolerated) */ /* Apply mtab options (overlap with kernel_opts is filtered and tolerated) */
err = apply_mount_opts(fsfd, mtab_opts); err = apply_fsconfig_mount_opts(fsfd, mtab_opts);
if (err < 0) { if (err < 0) {
log_fsconfig_kmsg(fsfd); log_fsconfig_kmsg(fsfd);
fprintf(stderr, fprintf(stderr,
+72
View File
@@ -65,4 +65,76 @@ int mount_fusermount_obtain_fd(const char *mountpoint,
int fuse_fusermount_proceed_mnt(int sock_fd); int fuse_fusermount_proceed_mnt(int sock_fd);
/**
* Convert MS_* mount flags to MOUNT_ATTR_* mount attributes.
* These flags are passed to fsmount(), not fsconfig().
* Mount attributes control mount-point level behavior.
* To called after set_ms_flags() which consumes the fsconfig flags.
*
* @mount_attrs MOUNT_ATTR flags, built from MS_ flags
* @return remaining MS_* flags
*/
unsigned long ms_flags_to_mount_attrs(unsigned long ms_flags,
unsigned int *mount_attrs);
/**
* Read and print kernel error messages from fsopen fd.
* The kernel can provide detailed error/warning/info messages via the
* filesystem context fd that are more informative than strerror(errno).
*
* @fd fsopen fd
*/
void log_fsconfig_kmsg(int fd);
/**
* Apply VFS superblock (fsconfig) flags to the filesystem context.
* Handles the fsconfig leg of every entry whose is_fsconfig is set
* (ro, rw, sync, async, dirsync). Mount attributes (nosuid, nodev, etc.)
* are handled separately via fsmount().
*
* Entries that have *both* legs (ro/rw) leave the MS_ bit in *ms_flags
* so that ms_flags_to_mount_attrs() can also pick them up.
*
* @fsfd fsopen fd
* @ms_flags flags to set, outvalue are the remaining flags
* @return 0 on success, negative error code on failure
*/
int set_fsconfig_ms_flags(int fsfd, unsigned long *ms_flags);
/**
* Apply the "fd" parameter via fsconfig
*
* Special handler for the "fd" mount option. Note that despite the name,
* the fd parameter is passed as a u32 string value, not as a file descriptor
* to pass to the kernel. Uses FSCONFIG_SET_STRING rather than FSCONFIG_SET_FD.
*
* @fsfd fsopen fd
* @value fd number of /dev/fuse, as a string
* Returns 0 on success, negative error code on failure.
*/
int apply_fsconfig_opt_fd(int fsfd, const char *value);
/**
* Apply a key=value string option via fsconfig
*
* Applies a mount option that consists of a key-value pair (e.g., "rootmode=40000").
* Uses FSCONFIG_SET_STRING to pass the key and value to the filesystem configuration.
*
* @fsfd fsopen fd
* @key name of filesystem mount option
* @value value of mount option
* Returns 0 on success, negative error code on failure.
*/
int apply_fsconfig_opt_string(int fsfd, const char *key, const char *value);
/**
* Parse kernel options string and apply via fsconfig
* Options are comma-separated key=value pairs
*
* @fsfd fsopen fd
* @opt filesystem mount option string
* Returns 0 on success, negative error code on failure.
*/
int apply_fsconfig_mount_opts(int fsfd, const char *opts);
#endif /* FUSE_MOUNT_I_LINUX_H_ */ #endif /* FUSE_MOUNT_I_LINUX_H_ */
+3
View File
@@ -11,6 +11,9 @@ mount_service_sources = []
mount_service_cflags = [] mount_service_cflags = []
if private_cfg.get('HAVE_SERVICEMOUNT', false) if private_cfg.get('HAVE_SERVICEMOUNT', false)
mount_service_sources += ['mount_service.c', '../lib/mount_util.c', 'fuser_conf.c'] mount_service_sources += ['mount_service.c', '../lib/mount_util.c', 'fuser_conf.c']
if private_cfg.get('HAVE_NEW_MOUNT_API', false)
mount_service_sources += [ '../lib/mount_fsmount.c' ]
endif
mount_service_cflags += ['-DFUSE_CONF="@0@"'.format(fuseconf_path)] mount_service_cflags += ['-DFUSE_CONF="@0@"'.format(fuseconf_path)]
fuservicemount_path = join_paths(get_option('prefix'), get_option('sbindir')) fuservicemount_path = join_paths(get_option('prefix'), get_option('sbindir'))
mount_service_cflags += ['-DFUSERVICEMOUNT_DIR="@0@"'.format(fuservicemount_path)] mount_service_cflags += ['-DFUSERVICEMOUNT_DIR="@0@"'.format(fuservicemount_path)]
+50 -175
View File
@@ -39,6 +39,9 @@
#include "fuse_service_priv.h" #include "fuse_service_priv.h"
#include "mount_service.h" #include "mount_service.h"
#include "fuser_conf.h" #include "fuser_conf.h"
#ifdef HAVE_NEW_MOUNT_API
#include "mount_i_linux.h"
#endif
struct mount_service { struct mount_service {
/* prefix for printing error messages */ /* prefix for printing error messages */
@@ -875,40 +878,6 @@ static int mount_service_handle_fsopen_cmd(struct mount_service *mo,
return mount_service_send_reply(mo, 0); return mount_service_send_reply(mo, 0);
} }
#ifdef HAVE_NEW_MOUNT_API
/* callers must preserve errno */
static void emit_fsconfig_messages(const struct mount_service *mo)
{
uint8_t buf[BUFSIZ];
ssize_t sz;
while ((sz = read(mo->fsopenfd, buf, sizeof(buf) - 1)) >= 1) {
if (buf[sz - 1] == '\n')
buf[--sz] = '\0';
else
buf[sz] = '\0';
if (!*buf)
continue;
switch (buf[0]) {
case 'e':
fprintf(stderr, "Error: %s\n", buf + 2);
break;
case 'w':
fprintf(stderr, "Warning: %s\n", buf + 2);
break;
case 'i':
fprintf(stderr, "Info: %s\n", buf + 2);
break;
default:
fprintf(stderr, " %s\n", buf);
break;
}
}
}
#endif
static int mount_service_handle_source_cmd(struct mount_service *mo, static int mount_service_handle_source_cmd(struct mount_service *mo,
const struct fuse_service_packet *p, const struct fuse_service_packet *p,
size_t psz) size_t psz)
@@ -946,16 +915,11 @@ static int mount_service_handle_source_cmd(struct mount_service *mo,
#ifdef HAVE_NEW_MOUNT_API #ifdef HAVE_NEW_MOUNT_API
if (mo->fsopenfd >= 0) { if (mo->fsopenfd >= 0) {
int ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_STRING, "source", int ret = apply_fsconfig_opt_string(mo->fsopenfd, "source",
oc->value, 0); oc->value);
if (ret) { if (ret < 0) {
int error = errno;
fprintf(stderr, "%s: fsconfig source: %s\n",
mo->msgtag, strerror(error));
emit_fsconfig_messages(mo);
free(source); free(source);
return mount_service_send_reply(mo, error); return mount_service_send_reply(mo, -ret);
} }
} }
#endif #endif
@@ -1002,53 +966,30 @@ static int mount_service_handle_mntopts_cmd(struct mount_service *mo,
} }
/* strtok_r mutates tokstr aka oc->value */ /* strtok_r mutates tokstr aka oc->value */
while ((tok = strtok_r(tokstr, ",", &savetok)) != NULL) { if (getuid() != 0 && !user_allow_other) {
char *equals = strchr(tok, '='); while ((tok = strtok_r(tokstr, ",", &savetok)) != NULL) {
char oldchar = 0; if (!strcmp(tok, "allow_other") ||
!strcmp(tok, "allow_root")) {
fprintf(stderr,
"%s: option %s only allowed if 'user_allow_other' is set in %s\n",
mo->msgtag, tok, FUSE_CONF);
return mount_service_send_reply(mo, EPERM);
}
if (equals) { tokstr = NULL;
oldchar = *equals;
*equals = 0;
}
if (getuid() != 0 && !user_allow_other &&
(!strcmp(tok, "allow_other") ||
!strcmp(tok, "allow_root"))) {
fprintf(stderr,
"%s: option %s only allowed if 'user_allow_other' is set in %s\n",
mo->msgtag, tok, FUSE_CONF);
return mount_service_send_reply(mo, EPERM);
} }
}
#ifdef HAVE_NEW_MOUNT_API #ifdef HAVE_NEW_MOUNT_API
if (mo->fsopenfd >= 0) { if (mo->fsopenfd >= 0) {
int ret; int ret = apply_fsconfig_mount_opts(mo->fsopenfd, oc->value);
if (equals) if (ret < 0) {
ret = fsconfig(mo->fsopenfd, free(mntopts);
FSCONFIG_SET_STRING, tok, return mount_service_send_reply(mo, -ret);
equals + 1, 0);
else
ret = fsconfig(mo->fsopenfd,
FSCONFIG_SET_FLAG, tok,
NULL, 0);
if (ret) {
int error = errno;
fprintf(stderr, "%s: set mount option: %s\n",
mo->msgtag, strerror(error));
emit_fsconfig_messages(mo);
free(mntopts);
return mount_service_send_reply(mo, error);
}
} }
#endif
if (equals)
*equals = oldchar;
tokstr = NULL;
} }
#endif
mo->mntopts = mntopts; mo->mntopts = mntopts;
return mount_service_send_reply(mo, 0); return mount_service_send_reply(mo, 0);
@@ -1452,66 +1393,6 @@ out_realmopts:
} }
#ifdef HAVE_NEW_MOUNT_API #ifdef HAVE_NEW_MOUNT_API
struct ms_to_mount_map {
unsigned long ms_flag;
unsigned int mount_attr_flag;
};
static void get_mount_attr_flags(const struct fuse_service_mount_command *oc,
unsigned int *attr_flags,
unsigned long *leftover_ms_flags)
{
const struct mount_flags *i;
unsigned int ms_flags = ntohl(oc->ms_flags);
unsigned int mount_attr_flags = 0;
for (i = mount_flags; i->opt != NULL; i++) {
if (!i->on || !(ms_flags & i->flag))
continue;
mount_attr_flags |= i->mount_attr;
ms_flags &= ~i->flag;
}
*leftover_ms_flags = ms_flags;
*attr_flags = mount_attr_flags;
}
static int set_ms_flags(struct mount_service *mo, unsigned long ms_flags)
{
const struct mount_flags *i;
int ret;
for (i = mount_flags; i->opt != NULL; i++) {
if (!i->on || !(ms_flags & i->flag))
continue;
ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_FLAG, i->opt,
NULL, 0);
if (ret) {
int error = errno;
fprintf(stderr, "%s: set %s option: %s\n",
mo->msgtag, i->opt, strerror(error));
emit_fsconfig_messages(mo);
errno = error;
return -1;
}
ms_flags &= ~i->flag;
}
/*
* We can't translate all the supplied MS_ flags into MOUNT_ATTR_ flags
* or string flags! Return a magic code so the caller will fall back
* to regular mount(2).
*/
if (ms_flags)
return FUSE_MOUNT_FALLBACK_NEEDED;
return 0;
}
static int mount_service_fsopen_mount(struct mount_service *mo, static int mount_service_fsopen_mount(struct mount_service *mo,
const struct fuse_service_mount_command *oc, const struct fuse_service_mount_command *oc,
const struct stat *stbuf) const struct stat *stbuf)
@@ -1523,63 +1404,57 @@ static int mount_service_fsopen_mount(struct mount_service *mo,
int error; int error;
int ret; int ret;
get_mount_attr_flags(oc, &attr_flags, &ms_flags); ms_flags = ms_flags_to_mount_attrs(ntohl(oc->ms_flags), &attr_flags);
ret = set_ms_flags(mo, ms_flags); ret = set_fsconfig_ms_flags(mo->fsopenfd, &ms_flags);
if (ret == FUSE_MOUNT_FALLBACK_NEEDED)
return ret;
if (ret) { if (ret) {
error = errno; error = errno;
goto fail_mount; goto fail_mount;
} }
ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_STRING, "subtype", /*
mo->subtype, 0); * We can't translate all the supplied MS_ flags into MOUNT_ATTR_ flags
if (ret) { * or string flags! Return a magic code so the caller will fall back
error = errno; * to regular mount(2).
*/
if (ms_flags)
return FUSE_MOUNT_FALLBACK_NEEDED;
ret = apply_fsconfig_opt_string(mo->fsopenfd, "subtype", mo->subtype);
if (ret < 0) {
/* The subtype option was merged after fsopen */ /* The subtype option was merged after fsopen */
if (error == EINVAL) if (ret == -EINVAL)
return FUSE_MOUNT_FALLBACK_NEEDED; return FUSE_MOUNT_FALLBACK_NEEDED;
fprintf(stderr, "%s: set subtype option: %s\n", error = -ret;
mo->msgtag, strerror(error));
goto fail_fsconfig; goto fail_fsconfig;
} }
snprintf(tmp, sizeof(tmp), "%i", mo->fusedevfd); snprintf(tmp, sizeof(tmp), "%i", mo->fusedevfd);
ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_STRING, "fd", tmp, 0); ret = apply_fsconfig_opt_fd(mo->fsopenfd, tmp);
if (ret) { if (ret < 0) {
error = errno; error = -ret;
fprintf(stderr, "%s: set fd option: %s\n",
mo->msgtag, strerror(error));
goto fail_fsconfig; goto fail_fsconfig;
} }
snprintf(tmp, sizeof(tmp), "%o", stbuf->st_mode & S_IFMT); snprintf(tmp, sizeof(tmp), "%o", stbuf->st_mode & S_IFMT);
ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_STRING, "rootmode", tmp, 0); ret = apply_fsconfig_opt_string(mo->fsopenfd, "rootmode", tmp);
if (ret) { if (ret < 0) {
error = errno; error = -ret;
fprintf(stderr, "%s: set rootmode option: %s\n",
mo->msgtag, strerror(error));
goto fail_fsconfig; goto fail_fsconfig;
} }
snprintf(tmp, sizeof(tmp), "%u", getuid()); snprintf(tmp, sizeof(tmp), "%u", getuid());
ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_STRING, "user_id", tmp, 0); ret = apply_fsconfig_opt_string(mo->fsopenfd, "user_id", tmp);
if (ret) { if (ret < 0) {
error = errno; error = -ret;
fprintf(stderr, "%s: set user_id option: %s\n",
mo->msgtag, strerror(error));
goto fail_fsconfig; goto fail_fsconfig;
} }
snprintf(tmp, sizeof(tmp), "%u", getgid()); snprintf(tmp, sizeof(tmp), "%u", getgid());
ret = fsconfig(mo->fsopenfd, FSCONFIG_SET_STRING, "group_id", tmp, 0); ret = apply_fsconfig_opt_string(mo->fsopenfd, "group_id", tmp);
if (ret) { if (ret < 0) {
error = errno; error = -ret;
fprintf(stderr, "%s: set group_id option: %s\n",
mo->msgtag, strerror(error));
goto fail_fsconfig; goto fail_fsconfig;
} }
@@ -1629,7 +1504,7 @@ static int mount_service_fsopen_mount(struct mount_service *mo,
return mount_service_send_reply(mo, 0); return mount_service_send_reply(mo, 0);
fail_fsconfig: fail_fsconfig:
emit_fsconfig_messages(mo); log_fsconfig_kmsg(mo->fsopenfd);
fail_mount: fail_mount:
return mount_service_send_reply(mo, error); return mount_service_send_reply(mo, error);
} }