mountpoint-util: add helper that checks if MS_NOSYMFOLLOW is supported
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mount.h>
|
||||
#if WANT_LINUX_FS_H
|
||||
#include <linux/fs.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user