From: Lennart Poettering Date: Mon, 6 Mar 2023 21:49:30 +0000 (+0100) Subject: mountpoint-util: add helper that checks if MS_NOSYMFOLLOW is supported X-Git-Tag: v254-rc1~1073^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7d3b157b774600a48f8533491eefc01a8c96c4fb;p=thirdparty%2Fsystemd.git mountpoint-util: add helper that checks if MS_NOSYMFOLLOW is supported --- diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index bc74fbef8f7..b60cf78b5ac 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -3,6 +3,9 @@ #include #include #include +#if WANT_LINUX_FS_H +#include +#endif #include "alloc-util.h" #include "chase-symlinks.h" @@ -10,6 +13,8 @@ #include "fileio.h" #include "filesystems.h" #include "fs-util.h" +#include "missing_fs.h" +#include "missing_mount.h" #include "missing_stat.h" #include "missing_syscall.h" #include "mkdir.h" @@ -602,3 +607,60 @@ int mount_propagation_flag_from_string(const char *name, unsigned long *ret) { bool mount_propagation_flag_is_valid(unsigned long flag) { return IN_SET(flag, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE); } + +unsigned long ms_nosymfollow_supported(void) { + _cleanup_close_ int fsfd = -EBADF, mntfd = -EBADF; + static int cache = -1; + + /* Returns MS_NOSYMFOLLOW if it is supported, zero otherwise. */ + + if (cache >= 0) + return cache ? MS_NOSYMFOLLOW : 0; + + /* Checks if MS_NOSYMFOLLOW is supported (which was added in 5.10). We use the new mount API's + * mount_setattr() call for that, which was added in 5.12, which is close enough. */ + + fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC); + if (fsfd < 0) { + if (ERRNO_IS_NOT_SUPPORTED(errno)) + goto not_supported; + + log_debug_errno(errno, "Failed to open superblock context for tmpfs: %m"); + return 0; + } + + if (fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0) { + if (ERRNO_IS_NOT_SUPPORTED(errno)) + goto not_supported; + + log_debug_errno(errno, "Failed to create tmpfs superblock: %m"); + return 0; + } + + mntfd = fsmount(fsfd, FSMOUNT_CLOEXEC, 0); + if (mntfd < 0) { + if (ERRNO_IS_NOT_SUPPORTED(errno)) + goto not_supported; + + log_debug_errno(errno, "Failed to turn superblock fd into mount fd: %m"); + return 0; + } + + if (mount_setattr(mntfd, "", AT_EMPTY_PATH|AT_RECURSIVE, + &(struct mount_attr) { + .attr_set = MOUNT_ATTR_NOSYMFOLLOW, + }, sizeof(struct mount_attr)) < 0) { + if (ERRNO_IS_NOT_SUPPORTED(errno)) + goto not_supported; + + log_debug_errno(errno, "Failed to set MOUNT_ATTR_NOSYMFOLLOW mount attribute: %m"); + return 0; + } + + cache = true; + return MS_NOSYMFOLLOW; + +not_supported: + cache = false; + return 0; +} diff --git a/src/basic/mountpoint-util.h b/src/basic/mountpoint-util.h index 19709195e84..f8529030849 100644 --- a/src/basic/mountpoint-util.h +++ b/src/basic/mountpoint-util.h @@ -58,3 +58,5 @@ int mount_nofollow(const char *source, const char *target, const char *filesyste const char *mount_propagation_flag_to_string(unsigned long flags); int mount_propagation_flag_from_string(const char *name, unsigned long *ret); bool mount_propagation_flag_is_valid(unsigned long flag); + +unsigned long ms_nosymfollow_supported(void); diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c index ea47c3a5b3a..5df853a1d97 100644 --- a/src/test/test-mountpoint-util.c +++ b/src/test/test-mountpoint-util.c @@ -321,6 +321,10 @@ TEST(fd_is_mount_point) { assert_se(fd_is_mount_point(fd, "", 0) == -EINVAL); } +TEST(ms_nosymfollow_supported) { + log_info("MS_NOSYMFOLLOW supported: %s", yes_no(ms_nosymfollow_supported())); +} + static int intro(void) { /* let's move into our own mount namespace with all propagation from the host turned off, so * that /proc/self/mountinfo is static and constant for the whole time our test runs. */