mirror of
https://github.com/libfuse/libfuse.git
synced 2026-07-07 14:47:41 +08:00
dc6ce72129
Bernd received a complaint via github that the "unmount" command in the
new fuse service API is prone to malicious symlink creation races
because the umount2 call doesn't use UMOUNT_NOFOLLOW. Therefore, if you
can trick a fuse service into asking the mount service helper to undo
the mount just after you've replaced the mount with a symlink to a
sensitive mount (e.g. /sys) then you whack a system hard.
I don't know why this unmounting functionality exists in libfuse, and
apparently Bernd doesn't like it. Since the fuse service API has not
yet been released, let's just rip out the command and pretend it never
existed.
Fixes: 5d8b9a39a1 ("mount_service: add systemd socket service mounting helper")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
159 lines
4.0 KiB
C
159 lines
4.0 KiB
C
/*
|
|
* FUSE: Filesystem in Userspace
|
|
* Copyright (C) 2025-2026 Oracle.
|
|
* Author: Darrick J. Wong <djwong@kernel.org>
|
|
*
|
|
* This program can be distributed under the terms of the GNU LGPLv2.
|
|
* See the file LGPL2.txt.
|
|
*/
|
|
#ifndef FUSE_SERVICE_PRIV_H_
|
|
#define FUSE_SERVICE_PRIV_H_
|
|
|
|
/* All numeric fields are network order (big-endian) when going across the socket */
|
|
|
|
struct fuse_service_memfd_arg {
|
|
uint32_t pos;
|
|
uint32_t len;
|
|
};
|
|
|
|
struct fuse_service_memfd_argv {
|
|
uint32_t magic;
|
|
uint32_t argc;
|
|
};
|
|
|
|
#define FUSE_SERVICE_MAX_CMD_SIZE (65536)
|
|
|
|
#define FUSE_SERVICE_ARGS_MAGIC 0x41524753 /* ARGS */
|
|
|
|
/* mount.service sends a hello to the server and it replies */
|
|
#define FUSE_SERVICE_HELLO_CMD 0x53414654 /* SAFT */
|
|
#define FUSE_SERVICE_HELLO_REPLY 0x4c415354 /* LAST */
|
|
|
|
/* fuse servers send commands to mount.service */
|
|
#define FUSE_SERVICE_OPEN_CMD 0x4f50454e /* OPEN */
|
|
#define FUSE_SERVICE_OPEN_BDEV_CMD 0x42444556 /* BDEV */
|
|
#define FUSE_SERVICE_FSOPEN_CMD 0x54595045 /* TYPE */
|
|
#define FUSE_SERVICE_SOURCE_CMD 0x4e414d45 /* NAME */
|
|
#define FUSE_SERVICE_MNTOPTS_CMD 0x4f505453 /* OPTS */
|
|
#define FUSE_SERVICE_MNTPT_CMD 0x4d4e5450 /* MNTP */
|
|
#define FUSE_SERVICE_MOUNT_CMD 0x444f4954 /* DOIT */
|
|
#define FUSE_SERVICE_BYE_CMD 0x42594545 /* BYEE */
|
|
#define FUSE_SERVICE_MTABOPTS_CMD 0x4d544142 /* MTAB */
|
|
|
|
/* mount.service sends replies to the fuse server */
|
|
#define FUSE_SERVICE_OPEN_REPLY 0x46494c45 /* FILE */
|
|
#define FUSE_SERVICE_SIMPLE_REPLY 0x5245504c /* REPL */
|
|
|
|
struct fuse_service_packet {
|
|
uint32_t magic; /* FUSE_SERVICE_*_{CMD,REPLY} */
|
|
};
|
|
|
|
#define FUSE_SERVICE_PROTO (1)
|
|
#define FUSE_SERVICE_MIN_PROTO (1)
|
|
#define FUSE_SERVICE_MAX_PROTO (1)
|
|
|
|
#define FUSE_SERVICE_FLAG_ALLOW_OTHER (1U << 0)
|
|
#define FUSE_SERVICE_FLAG_FUSEBLK (1U << 1)
|
|
|
|
#define FUSE_SERVICE_FLAGS (FUSE_SERVICE_FLAG_ALLOW_OTHER | \
|
|
FUSE_SERVICE_FLAG_FUSEBLK)
|
|
|
|
struct fuse_service_hello {
|
|
struct fuse_service_packet p;
|
|
uint16_t min_version;
|
|
uint16_t max_version;
|
|
uint32_t flags;
|
|
};
|
|
|
|
static inline bool check_null_endbyte(const void *p, size_t psz)
|
|
{
|
|
return *((const char *)p + psz - 1) == 0;
|
|
}
|
|
|
|
struct fuse_service_hello_reply {
|
|
struct fuse_service_packet p;
|
|
uint16_t version;
|
|
uint16_t padding;
|
|
};
|
|
|
|
struct fuse_service_simple_reply {
|
|
struct fuse_service_packet p;
|
|
uint32_t error; /* positive errno */
|
|
};
|
|
|
|
struct fuse_service_requested_file {
|
|
struct fuse_service_packet p;
|
|
uint32_t error; /* positive errno */
|
|
char path[];
|
|
};
|
|
|
|
static inline size_t sizeof_fuse_service_requested_file(size_t pathlen)
|
|
{
|
|
return sizeof(struct fuse_service_requested_file) + pathlen + 1;
|
|
}
|
|
|
|
#define FUSE_SERVICE_FSOPEN_FUSEBLK (1U << 0)
|
|
#define FUSE_SERVICE_FSOPEN_FLAGS (FUSE_SERVICE_FSOPEN_FUSEBLK)
|
|
|
|
struct fuse_service_fsopen_command {
|
|
struct fuse_service_packet p;
|
|
uint32_t fsopen_flags;
|
|
};
|
|
|
|
#define FUSE_SERVICE_OPEN_QUIET (1U << 0)
|
|
#define FUSE_SERVICE_OPEN_FLAGS (FUSE_SERVICE_OPEN_QUIET)
|
|
|
|
struct fuse_service_open_command {
|
|
struct fuse_service_packet p;
|
|
uint32_t open_flags;
|
|
uint32_t create_mode;
|
|
uint32_t request_flags;
|
|
uint32_t block_size;
|
|
char path[];
|
|
};
|
|
|
|
static inline size_t sizeof_fuse_service_open_command(size_t pathlen)
|
|
{
|
|
return sizeof(struct fuse_service_open_command) + pathlen + 1;
|
|
}
|
|
|
|
struct fuse_service_string_command {
|
|
struct fuse_service_packet p;
|
|
char value[];
|
|
};
|
|
|
|
static inline size_t sizeof_fuse_service_string_command(size_t len)
|
|
{
|
|
return sizeof(struct fuse_service_string_command) + len + 1;
|
|
}
|
|
|
|
struct fuse_service_mountpoint_command {
|
|
struct fuse_service_packet p;
|
|
uint16_t expected_fmt;
|
|
uint16_t padding;
|
|
char value[];
|
|
};
|
|
|
|
static inline size_t sizeof_fuse_service_mountpoint_command(size_t len)
|
|
{
|
|
return sizeof(struct fuse_service_mountpoint_command) + len + 1;
|
|
}
|
|
|
|
struct fuse_service_bye_command {
|
|
struct fuse_service_packet p;
|
|
uint32_t exitcode;
|
|
};
|
|
|
|
struct fuse_service_mount_command {
|
|
struct fuse_service_packet p;
|
|
uint32_t ms_flags;
|
|
};
|
|
|
|
int fuse_parse_cmdline_service(struct fuse_args *args,
|
|
struct fuse_cmdline_opts *opts);
|
|
|
|
#define FUSE_SERVICE_ARGV "argv"
|
|
#define FUSE_SERVICE_FUSEDEV "fusedev"
|
|
|
|
#endif /* FUSE_SERVICE_PRIV_H_ */
|