122 lines
3.4 KiB
Diff
122 lines
3.4 KiB
Diff
From 584c69e77abb537a7345222648a397a9963c01b7 Mon Sep 17 00:00:00 2001
|
|
From: "Timur I. Bakeyev" <timur@FreeBSD.org>
|
|
Date: Sat, 15 Oct 2022 04:02:43 +0200
|
|
Subject: [PATCH 28/28] s3:lib:system - add FreeBSD proc_fd_pattern
|
|
|
|
Add support for FreeBSD equivalent of /proc/self/fd through a special
|
|
fdescfs mount with option "nodup". This filesystem should be mounted
|
|
either to the private $PIDDIR/fd/ directory or to /dev/fd in order to
|
|
provide security and performance characteristics similar to Linux.
|
|
|
|
Signed-off-by: Timur I. Bakeyev <timur@FreeBSD.org>
|
|
Adapted for Samba 4.20 by: Andrea venturoli <ml@netfence.it>
|
|
---
|
|
--- source3/lib/system.c.orig 2025-06-27 15:05:05 UTC
|
|
+++ source3/lib/system.c
|
|
@@ -1047,6 +1047,68 @@ int sys_get_number_of_cores(void)
|
|
}
|
|
#endif
|
|
|
|
+static bool freebsd_fdesc_check(const char *pattern)
|
|
+{
|
|
+ char fdesc_path[PATH_MAX];
|
|
+ int fd, fd2;
|
|
+
|
|
+ fd = open(lp_pid_directory(), O_DIRECTORY);
|
|
+ if (fd == -1) {
|
|
+ DBG_ERR("%s: failed to open pid directory: %s\n",
|
|
+ lp_pid_directory(), strerror(errno));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ snprintf(fdesc_path, sizeof(fdesc_path), pattern, fd);
|
|
+
|
|
+ fd2 = open(fdesc_path, O_DIRECTORY);
|
|
+ if (fd2 == -1) {
|
|
+ /*
|
|
+ * Setting O_DIRECTORY on open of fdescfs mount
|
|
+ * without 'nodup' option will fail with ENOTDIR.
|
|
+ */
|
|
+ if (errno == ENOTDIR) {
|
|
+ DBG_ERR("%s: fdescfs filesystem is not mounted with "
|
|
+ "'nodup' option. This specific mount option is "
|
|
+ "required in order to enable race-free handling "
|
|
+ "of paths.\n"
|
|
+ "See documentation for Samba's New VFS' "
|
|
+ "for more details. The 'nodup' mount option was "
|
|
+ "introduced in FreeBSD 13.\n", fdesc_path);
|
|
+ close(fd);
|
|
+ return false;
|
|
+ }
|
|
+ DBG_ERR("%s: failed to open fdescfs path: %s\n",
|
|
+ fdesc_path, strerror(errno));
|
|
+ close(fd);
|
|
+ return false;
|
|
+ }
|
|
+ close(fd);
|
|
+ close(fd2);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static char* freebsd_pattern(char *buf, size_t bufsize) {
|
|
+ const char** base;
|
|
+ const char* base_dir[] = {
|
|
+ lp_pid_directory(), /* This is a preferred location */
|
|
+ "/dev",
|
|
+ NULL
|
|
+ };
|
|
+
|
|
+ for(base = &base_dir[0]; *base != NULL; base++) {
|
|
+ snprintf(buf, bufsize, "%s/fd/%%lu", *base);
|
|
+ if(freebsd_fdesc_check(buf)) {
|
|
+ return buf;
|
|
+ }
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static char proc_fd_pattern_buf[PATH_MAX];
|
|
+static const char *proc_fd_pattern = NULL;
|
|
+
|
|
bool sys_have_proc_fds(void)
|
|
{
|
|
static bool checked = false;
|
|
@@ -1058,8 +1078,12 @@ bool sys_have_proc_fds(void)
|
|
return have_proc_fds;
|
|
}
|
|
|
|
- ret = stat("/proc/self/fd/0", &sb);
|
|
- have_proc_fds = (ret == 0);
|
|
+ if (freebsd_pattern(proc_fd_pattern_buf, sizeof(proc_fd_pattern_buf)) != NULL) {
|
|
+ have_proc_fds = true;
|
|
+ proc_fd_pattern = proc_fd_pattern_buf;
|
|
+ } else
|
|
+ have_proc_fds = false;
|
|
+
|
|
checked = true;
|
|
|
|
return have_proc_fds;
|
|
@@ -1067,10 +1091,18 @@ char *sys_proc_fd_path(int fd, struct sys_proc_fd_path
|
|
|
|
char *sys_proc_fd_path(int fd, struct sys_proc_fd_path_buf *buf)
|
|
{
|
|
+ bool have_proc_fds = sys_have_proc_fds();
|
|
+ SMB_ASSERT(have_proc_fds);
|
|
+#if defined(__clang__)
|
|
+#pragma clang diagnostic push
|
|
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
|
+#endif
|
|
int written =
|
|
- snprintf(buf->buf, sizeof(buf->buf), "/proc/self/fd/%d", fd);
|
|
-
|
|
- SMB_ASSERT(sys_have_proc_fds() && (written >= 0));
|
|
+ snprintf(buf->buf, sizeof(buf->buf), proc_fd_pattern, fd);
|
|
+#if defined(__clang__)
|
|
+#pragma clang diagnostic pop
|
|
+#endif
|
|
+ SMB_ASSERT(written >= 0);
|
|
|
|
return buf->buf;
|
|
}
|