|
|
2aacef |
From 6ab61ac93e534aec1ea4d16e77c1c355c8286e64 Mon Sep 17 00:00:00 2001
|
|
|
2aacef |
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
|
|
2aacef |
Date: Thu, 27 Oct 2022 13:14:12 +0200
|
|
|
2aacef |
Subject: [PATCH] namespace: Add hidepid/subset support check
|
|
|
2aacef |
|
|
|
2aacef |
Using fsopen()/fsconfig(), we can check if hidepid/subset are supported to
|
|
|
2aacef |
avoid the noisy logs from the kernel if they aren't supported. This works
|
|
|
2aacef |
on centos/redhat 8 as well since they've backported fsopen()/fsconfig().
|
|
|
2aacef |
|
|
|
2aacef |
(cherry picked from commit 1c265fcd5963603d338233840129ecad8d9c1420)
|
|
|
2aacef |
|
|
|
2aacef |
Related #2138081
|
|
|
2aacef |
---
|
|
|
2aacef |
meson.build | 2 ++
|
|
|
2aacef |
src/basic/missing_syscall.h | 40 +++++++++++++++++++++++++++++++
|
|
|
2aacef |
src/core/namespace.c | 47 ++++++++++++++++++++++++++++++++-----
|
|
|
2aacef |
3 files changed, 83 insertions(+), 6 deletions(-)
|
|
|
2aacef |
|
|
|
2aacef |
diff --git a/meson.build b/meson.build
|
|
|
2aacef |
index 76ad51d3fb..7750534466 100644
|
|
|
2aacef |
--- a/meson.build
|
|
|
2aacef |
+++ b/meson.build
|
|
|
2aacef |
@@ -606,6 +606,8 @@ foreach ident : [
|
|
|
2aacef |
['mount_setattr', '''#include <sys/mount.h>'''],
|
|
|
2aacef |
['move_mount', '''#include <sys/mount.h>'''],
|
|
|
2aacef |
['open_tree', '''#include <sys/mount.h>'''],
|
|
|
2aacef |
+ ['fsopen', '''#include <sys/mount.h>'''],
|
|
|
2aacef |
+ ['fsconfig', '''#include <sys/mount.h>'''],
|
|
|
2aacef |
['getdents64', '''#include <dirent.h>'''],
|
|
|
2aacef |
]
|
|
|
2aacef |
|
|
|
2aacef |
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
|
|
|
2aacef |
index 793d111c55..d54e59fdf9 100644
|
|
|
2aacef |
--- a/src/basic/missing_syscall.h
|
|
|
2aacef |
+++ b/src/basic/missing_syscall.h
|
|
|
2aacef |
@@ -593,6 +593,46 @@ static inline int missing_move_mount(
|
|
|
2aacef |
|
|
|
2aacef |
/* ======================================================================= */
|
|
|
2aacef |
|
|
|
2aacef |
+#if !HAVE_FSOPEN
|
|
|
2aacef |
+
|
|
|
2aacef |
+#ifndef FSOPEN_CLOEXEC
|
|
|
2aacef |
+#define FSOPEN_CLOEXEC 0x00000001
|
|
|
2aacef |
+#endif
|
|
|
2aacef |
+
|
|
|
2aacef |
+static inline int missing_fsopen(const char *fsname, unsigned flags) {
|
|
|
2aacef |
+# if defined __NR_fsopen && __NR_fsopen >= 0
|
|
|
2aacef |
+ return syscall(__NR_fsopen, fsname, flags);
|
|
|
2aacef |
+# else
|
|
|
2aacef |
+ errno = ENOSYS;
|
|
|
2aacef |
+ return -1;
|
|
|
2aacef |
+# endif
|
|
|
2aacef |
+}
|
|
|
2aacef |
+
|
|
|
2aacef |
+# define fsopen missing_fsopen
|
|
|
2aacef |
+#endif
|
|
|
2aacef |
+
|
|
|
2aacef |
+/* ======================================================================= */
|
|
|
2aacef |
+
|
|
|
2aacef |
+#if !HAVE_FSCONFIG
|
|
|
2aacef |
+
|
|
|
2aacef |
+#ifndef FSCONFIG_SET_STRING
|
|
|
2aacef |
+#define FSCONFIG_SET_STRING 1 /* Set parameter, supplying a string value */
|
|
|
2aacef |
+#endif
|
|
|
2aacef |
+
|
|
|
2aacef |
+static inline int missing_fsconfig(int fd, unsigned cmd, const char *key, const void *value, int aux) {
|
|
|
2aacef |
+# if defined __NR_fsconfig && __NR_fsconfig >= 0
|
|
|
2aacef |
+ return syscall(__NR_fsconfig, fd, cmd, key, value, aux);
|
|
|
2aacef |
+# else
|
|
|
2aacef |
+ errno = ENOSYS;
|
|
|
2aacef |
+ return -1;
|
|
|
2aacef |
+# endif
|
|
|
2aacef |
+}
|
|
|
2aacef |
+
|
|
|
2aacef |
+# define fsconfig missing_fsconfig
|
|
|
2aacef |
+#endif
|
|
|
2aacef |
+
|
|
|
2aacef |
+/* ======================================================================= */
|
|
|
2aacef |
+
|
|
|
2aacef |
#if !HAVE_GETDENTS64
|
|
|
2aacef |
|
|
|
2aacef |
static inline ssize_t missing_getdents64(int fd, void *buffer, size_t length) {
|
|
|
2aacef |
diff --git a/src/core/namespace.c b/src/core/namespace.c
|
|
|
2aacef |
index c3cced7410..852be3bdde 100644
|
|
|
2aacef |
--- a/src/core/namespace.c
|
|
|
2aacef |
+++ b/src/core/namespace.c
|
|
|
2aacef |
@@ -26,6 +26,7 @@
|
|
|
2aacef |
#include "list.h"
|
|
|
2aacef |
#include "loop-util.h"
|
|
|
2aacef |
#include "loopback-setup.h"
|
|
|
2aacef |
+#include "missing_syscall.h"
|
|
|
2aacef |
#include "mkdir-label.h"
|
|
|
2aacef |
#include "mount-util.h"
|
|
|
2aacef |
#include "mountpoint-util.h"
|
|
|
2aacef |
@@ -1073,6 +1074,27 @@ static int mount_sysfs(const MountEntry *m) {
|
|
|
2aacef |
return 1;
|
|
|
2aacef |
}
|
|
|
2aacef |
|
|
|
2aacef |
+static bool mount_option_supported(const char *fstype, const char *key, const char *value) {
|
|
|
2aacef |
+ _cleanup_close_ int fd = -1;
|
|
|
2aacef |
+ int r;
|
|
|
2aacef |
+
|
|
|
2aacef |
+ /* This function assumes support by default. Only if the fsconfig() call fails with -EINVAL/-EOPNOTSUPP
|
|
|
2aacef |
+ * will it report that the option/value is not supported. */
|
|
|
2aacef |
+
|
|
|
2aacef |
+ fd = fsopen(fstype, FSOPEN_CLOEXEC);
|
|
|
2aacef |
+ if (fd < 0) {
|
|
|
2aacef |
+ if (errno != ENOSYS)
|
|
|
2aacef |
+ log_debug_errno(errno, "Failed to open superblock context for '%s': %m", fstype);
|
|
|
2aacef |
+ return true; /* If fsopen() fails for whatever reason, assume the value is supported. */
|
|
|
2aacef |
+ }
|
|
|
2aacef |
+
|
|
|
2aacef |
+ r = fsconfig(fd, FSCONFIG_SET_STRING, key, value, 0);
|
|
|
2aacef |
+ if (r < 0 && !IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS))
|
|
|
2aacef |
+ log_debug_errno(errno, "Failed to set '%s=%s' on '%s' superblock context: %m", key, value, fstype);
|
|
|
2aacef |
+
|
|
|
2aacef |
+ return r >= 0 || !IN_SET(errno, EINVAL, EOPNOTSUPP);
|
|
|
2aacef |
+}
|
|
|
2aacef |
+
|
|
|
2aacef |
static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {
|
|
|
2aacef |
_cleanup_free_ char *opts = NULL;
|
|
|
2aacef |
const char *entry_path;
|
|
|
2aacef |
@@ -1090,12 +1112,25 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {
|
|
|
2aacef |
* per-instance, we'll exclusively use the textual value for hidepid=, since support was
|
|
|
2aacef |
* added in the same commit: if it's supported it is thus also per-instance. */
|
|
|
2aacef |
|
|
|
2aacef |
- opts = strjoin("hidepid=",
|
|
|
2aacef |
- ns_info->protect_proc == PROTECT_PROC_DEFAULT ? "off" :
|
|
|
2aacef |
- protect_proc_to_string(ns_info->protect_proc),
|
|
|
2aacef |
- ns_info->proc_subset == PROC_SUBSET_PID ? ",subset=pid" : "");
|
|
|
2aacef |
- if (!opts)
|
|
|
2aacef |
- return -ENOMEM;
|
|
|
2aacef |
+ const char *hpv = ns_info->protect_proc == PROTECT_PROC_DEFAULT ?
|
|
|
2aacef |
+ "off" :
|
|
|
2aacef |
+ protect_proc_to_string(ns_info->protect_proc);
|
|
|
2aacef |
+
|
|
|
2aacef |
+ /* hidepid= support was added in 5.8, so we can use fsconfig()/fsopen() (which were added in
|
|
|
2aacef |
+ * 5.2) to check if hidepid= is supported. This avoids a noisy dmesg log by the kernel when
|
|
|
2aacef |
+ * trying to use hidepid= on systems where it isn't supported. The same applies for subset=.
|
|
|
2aacef |
+ * fsopen()/fsconfig() was also backported on some distros which allows us to detect
|
|
|
2aacef |
+ * hidepid=/subset= support in even more scenarios. */
|
|
|
2aacef |
+
|
|
|
2aacef |
+ if (mount_option_supported("proc", "hidepid", hpv)) {
|
|
|
2aacef |
+ opts = strjoin("hidepid=", hpv);
|
|
|
2aacef |
+ if (!opts)
|
|
|
2aacef |
+ return -ENOMEM;
|
|
|
2aacef |
+ }
|
|
|
2aacef |
+
|
|
|
2aacef |
+ if (ns_info->proc_subset == PROC_SUBSET_PID && mount_option_supported("proc", "subset", "pid"))
|
|
|
2aacef |
+ if (!strextend_with_separator(&opts, ",", "subset=pid"))
|
|
|
2aacef |
+ return -ENOMEM;
|
|
|
2aacef |
}
|
|
|
2aacef |
|
|
|
2aacef |
entry_path = mount_entry_path(m);
|