View | Details | Raw Unified | Return to bug 277878 | Differences between
and this patch

Collapse All | Expand All

(-)b/net/samba419/Makefile (-2 / +2 lines)
Lines 1-6 Link Here
1
PORTNAME=			${SAMBA4_BASENAME}419
1
PORTNAME=			${SAMBA4_BASENAME}419
2
PORTVERSION=			${SAMBA4_VERSION}
2
PORTVERSION=			${SAMBA4_VERSION}
3
PORTREVISION=			1
3
PORTREVISION=			2
4
CATEGORIES?=			net
4
CATEGORIES?=			net
5
MASTER_SITES=			SAMBA/samba/stable SAMBA/samba/rc
5
MASTER_SITES=			SAMBA/samba/stable SAMBA/samba/rc
6
DISTNAME=			${SAMBA4_DISTNAME}
6
DISTNAME=			${SAMBA4_DISTNAME}
Lines 44-50 EXTRA_PATCHES= \ Link Here
44
				${PATCHDIR}/0025-From-d9b748869a8f4018ebee302aae8246bf29f60309-Mon-Se.patch:-p1 \
44
				${PATCHDIR}/0025-From-d9b748869a8f4018ebee302aae8246bf29f60309-Mon-Se.patch:-p1 \
45
				${PATCHDIR}/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch:-p1 \
45
				${PATCHDIR}/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch:-p1 \
46
				${PATCHDIR}/0027-Add-VFS-module-vfs_freebsd-that-implements-FreeBSD-s.patch:-p1 \
46
				${PATCHDIR}/0027-Add-VFS-module-vfs_freebsd-that-implements-FreeBSD-s.patch:-p1 \
47
				${PATCHDIR}/0100-Fix-pathref-handling-for-FreeBSD-13plus.patch
47
				${PATCHDIR}/0028-s3-lib-system-add-FreeBSD-proc_fd_pattern.patch:-p1 \
48
48
49
SAMBA4_BASENAME=		samba
49
SAMBA4_BASENAME=		samba
50
SAMBA4_PORTNAME=		${SAMBA4_BASENAME}4
50
SAMBA4_PORTNAME=		${SAMBA4_BASENAME}4
(-)b/net/samba419/files/0028-s3-lib-system-add-FreeBSD-proc_fd_pattern.patch (+149 lines)
Added Link Here
1
From 584c69e77abb537a7345222648a397a9963c01b7 Mon Sep 17 00:00:00 2001
2
From: "Timur I. Bakeyev" <timur@FreeBSD.org>
3
Date: Sat, 15 Oct 2022 04:02:43 +0200
4
Subject: [PATCH 28/28] s3:lib:system - add FreeBSD proc_fd_pattern
5
6
Add support for FreeBSD equivalent of /proc/self/fd through a special
7
fdescfs mount with option "nodup". This filesystem should be mounted
8
either to the private $PIDDIR/fd/ directory or to /dev/fd in order to
9
provide security and performance characteristics similar to Linux.
10
11
Signed-off-by: Timur I. Bakeyev <timur@FreeBSD.org>
12
---
13
 source3/lib/system.c | 108 ++++++++++++++++++++++++++++++++++---------
14
 1 file changed, 87 insertions(+), 21 deletions(-)
15
16
diff --git a/source3/lib/system.c b/source3/lib/system.c
17
index 00d31692e00..d22ec08361c 100644
18
--- a/source3/lib/system.c
19
+++ b/source3/lib/system.c
20
@@ -1094,39 +1094,105 @@ int sys_get_number_of_cores(void)
21
 }
22
 #endif
23
 
24
-static struct proc_fd_pattern {
25
-	const char *pattern;
26
-	const char *test_path;
27
-} proc_fd_patterns[] = {
28
-	/* Linux */
29
-	{ "/proc/self/fd/%d", "/proc/self/fd/0" },
30
-	{ NULL, NULL },
31
+static bool freebsd_fdesc_check(const char *pattern)
32
+{
33
+	char fdesc_path[PATH_MAX];
34
+	int fd, fd2;
35
+
36
+	fd = open(lp_pid_directory(), O_DIRECTORY);
37
+	if (fd == -1) {
38
+		DBG_ERR("%s: failed to open pid directory: %s\n",
39
+			lp_pid_directory(), strerror(errno));
40
+		return false;
41
+	}
42
+
43
+	snprintf(fdesc_path, sizeof(fdesc_path), pattern, fd);
44
+
45
+	fd2 = open(fdesc_path, O_DIRECTORY);
46
+	if (fd2 == -1) {
47
+		/*
48
+		 * Setting O_DIRECTORY on open of fdescfs mount
49
+		 * without `nodup` option will fail with ENOTDIR.
50
+		 */
51
+		if (errno == ENOTDIR) {
52
+			DBG_ERR("%s: fdescfs filesystem is not mounted with "
53
+				"'nodup' option. This specific mount option is "
54
+				"required in order to enable race-free handling "
55
+				"of paths.\n"
56
+				"See documentation for Samba's New VFS' "
57
+				"for more details. The `nodup` mount option was "
58
+				"introduced in FreeBSD 13.\n", fdesc_path);
59
+			close(fd);
60
+			return false;
61
+		}
62
+		DBG_ERR("%s: failed to open fdescfs path: %s\n",
63
+			fdesc_path, strerror(errno));
64
+		close(fd);
65
+		return false;
66
+	}
67
+	close(fd);
68
+	close(fd2);
69
+
70
+	return true;
71
+}
72
+
73
+static char* linux_pattern(char *buf, size_t bufsize)
74
+{
75
+	char proc_fd_path[PATH_MAX];
76
+	const char *pattern = "/proc/self/fd/%lu";
77
+	struct stat sb;
78
+
79
+	snprintf(proc_fd_path, sizeof(proc_fd_path), pattern, 0);
80
+	if(stat(proc_fd_path, &sb) == 0) {
81
+		snprintf(buf, bufsize, "%s", pattern);
82
+		return buf;
83
+	}
84
+	return NULL;
85
+}
86
+
87
+static char* freebsd_pattern(char *buf, size_t bufsize) {
88
+	const char** base;
89
+	const char* base_dir[] = {
90
+		lp_pid_directory(), /* This is a preffered location */
91
+		"/dev",
92
+		NULL
93
+	};
94
+
95
+	for(base = &base_dir[0]; *base != NULL; base++) {
96
+		snprintf(buf, bufsize, "%s/fd/%%lu", *base);
97
+		if(freebsd_fdesc_check(buf)) {
98
+			return buf;
99
+		}
100
+	}
101
+	return NULL;
102
+}
103
+
104
+static char* (*proc_fd_patterns[])(char *, size_t) = {
105
+	linux_pattern,
106
+	freebsd_pattern,
107
+	NULL
108
 };
109
 
110
-static const char *proc_fd_pattern;
111
+static char proc_fd_pattern_buf[PATH_MAX];
112
+static const char *proc_fd_pattern = NULL;
113
 
114
 bool sys_have_proc_fds(void)
115
 {
116
-	static bool checked;
117
-	static bool have_proc_fds;
118
-	struct proc_fd_pattern *p = NULL;
119
-	struct stat sb;
120
-	int ret;
121
+	static bool checked = false;
122
+	static bool have_proc_fds = false;
123
+	char* (**pattern_func)(char *, size_t) = NULL;
124
 
125
 	if (checked) {
126
 		return have_proc_fds;
127
 	}
128
 
129
-	for (p = &proc_fd_patterns[0]; p->test_path != NULL; p++) {
130
-		ret = stat(p->test_path, &sb);
131
-		if (ret != 0) {
132
-			continue;
133
+	for (pattern_func = &proc_fd_patterns[0]; *pattern_func != NULL; pattern_func++) {
134
+		if((*pattern_func)(proc_fd_pattern_buf, sizeof(proc_fd_pattern_buf)) != NULL) {
135
+			have_proc_fds = true;
136
+			proc_fd_pattern = proc_fd_pattern_buf;
137
+			break;
138
 		}
139
-		have_proc_fds = true;
140
-		proc_fd_pattern = p->pattern;
141
-		break;
142
 	}
143
-
144
 	checked = true;
145
 	return have_proc_fds;
146
 }
147
-- 
148
2.37.1
149
(-)a/net/samba419/files/0100-Fix-pathref-handling-for-FreeBSD-13plus.patch (-486 lines)
Removed Link Here
1
https://bugzilla.samba.org/show_bug.cgi?id=15376
2
3
--- source3/smbd/open.c	2023-04-19 12:18:56.254875400 +0200
4
+++ source3/smbd/open.c	2023-06-20 08:29:06.210298000 +0200
5
@@ -1204,9 +1204,6 @@
6
 	int new_fd;
7
 	NTSTATUS status;
8
 
9
-	if (!fsp->fsp_flags.have_proc_fds) {
10
-		return NT_STATUS_MORE_PROCESSING_REQUIRED;
11
-	}
12
 
13
 	old_fd = fsp_get_pathref_fd(fsp);
14
 	if (old_fd == -1) {
15
@@ -1222,22 +1219,28 @@
16
 		return NT_STATUS_INVALID_HANDLE;
17
 	}
18
 
19
-	p = sys_proc_fd_path(old_fd, buf, sizeof(buf));
20
-	if (p == NULL) {
21
-		return NT_STATUS_NO_MEMORY;
22
-	}
23
+	
24
+	if (sys_open_real_fd_from_pathref_fd(old_fd, &new_fd, flags) != 0) {
25
+		if (!fsp->fsp_flags.have_proc_fds) {
26
+			return NT_STATUS_MORE_PROCESSING_REQUIRED;
27
+		}
28
 
29
-	proc_fname = (struct smb_filename) {
30
-		.base_name = discard_const_p(char, p),
31
-	};
32
+		p = sys_proc_fd_path(old_fd, buf, sizeof(buf));
33
+		if (p == NULL) {
34
+			return NT_STATUS_NO_MEMORY;
35
+		}
36
 
37
-	fsp->fsp_flags.is_pathref = false;
38
+		proc_fname = (struct smb_filename) {
39
+			.base_name = discard_const_p(char, p),
40
+		};
41
 
42
-	new_fd = SMB_VFS_OPENAT(fsp->conn,
43
-				fsp->conn->cwd_fsp,
44
-				&proc_fname,
45
-				fsp,
46
-				&how);
47
+		new_fd = SMB_VFS_OPENAT(fsp->conn,
48
+					fsp->conn->cwd_fsp,
49
+					&proc_fname,
50
+					fsp,
51
+					&how);
52
+	}
53
+
54
 	if (new_fd == -1) {
55
 		status = map_nt_error_from_unix(errno);
56
 		fd_close(fsp);
57
@@ -1250,6 +1260,8 @@
58
 	}
59
 
60
 	fsp_set_fd(fsp, new_fd);
61
+	fsp->fsp_flags.is_pathref = false;
62
+	
63
 	return NT_STATUS_OK;
64
 }
65
 
66
--- source3/lib/system.c	2023-01-18 16:32:24.174553200 +0100
67
+++ source3/lib/system.c	2023-06-19 23:35:30.132465000 +0200
68
@@ -1022,6 +1022,8 @@
69
 } proc_fd_patterns[] = {
70
 	/* Linux */
71
 	{ "/proc/self/fd/%d", "/proc/self/fd/0" },
72
+	/* FreeBSD */
73
+	{ "/compat/linux/dev/fd/%d", "/compat/linux/dev/fd/0" },
74
 	{ NULL, NULL },
75
 };
76
 
77
@@ -1077,4 +1079,27 @@
78
 	}
79
 
80
 	return buf;
81
+}
82
+
83
+
84
+/* Helper function that opens a usable fd for accessing data
85
+   (metadata & content) from a pathref fd */
86
+int sys_open_real_fd_from_pathref_fd(int fd,
87
+				     int *rfd,
88
+				     int flags) {
89
+	int tfd;
90
+
91
+#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH)
92
+	/* This works for FreeBSD 13+ atleast */
93
+	
94
+	tfd = openat(fd, "", O_EMPTY_PATH|flags);
95
+	if (tfd < 0) {
96
+		return errno;
97
+	}
98
+
99
+	*rfd = tfd;
100
+	return 0;
101
+#else
102
+	return ENOSYS;
103
+#endif
104
 }
105
--- source3/modules/vfs_default.c	2023-05-31 18:06:44.154299500 +0200
106
+++ source3/modules/vfs_default.c	2023-06-19 23:23:58.116903000 +0200
107
@@ -2721,7 +2721,7 @@
108
 
109
 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
110
 {
111
-	int result;
112
+	int result, fd, real_fd;
113
 
114
 	START_PROFILE(syscall_fchmod);
115
 
116
@@ -2731,8 +2731,9 @@
117
 		return result;
118
 	}
119
 
120
+	fd = fsp_get_pathref_fd(fsp);
121
+
122
 	if (fsp->fsp_flags.have_proc_fds) {
123
-		int fd = fsp_get_pathref_fd(fsp);
124
 		const char *p = NULL;
125
 		char buf[PATH_MAX];
126
 
127
@@ -2746,6 +2747,17 @@
128
 		return result;
129
 	}
130
 
131
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
132
+		int saved_errno;
133
+	  
134
+		result = fchmod(real_fd, mode);
135
+		saved_errno = errno;
136
+		close(real_fd);
137
+		errno = saved_errno;
138
+		END_PROFILE(syscall_fchmod);
139
+		return result;
140
+	}
141
+
142
 	/*
143
 	 * This is no longer a handle based call.
144
 	 */
145
@@ -2758,7 +2770,7 @@
146
 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
147
 {
148
 #ifdef HAVE_FCHOWN
149
-	int result;
150
+	int result, fd, real_fd;
151
 
152
 	START_PROFILE(syscall_fchown);
153
 	if (!fsp->fsp_flags.is_pathref) {
154
@@ -2767,8 +2779,9 @@
155
 		return result;
156
 	}
157
 
158
+	fd = fsp_get_pathref_fd(fsp);
159
+	
160
 	if (fsp->fsp_flags.have_proc_fds) {
161
-		int fd = fsp_get_pathref_fd(fsp);
162
 		const char *p = NULL;
163
 		char buf[PATH_MAX];
164
 
165
@@ -2782,6 +2795,17 @@
166
 		return result;
167
 	}
168
 
169
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
170
+		int saved_errno;
171
+	  
172
+		result = fchown(real_fd, uid, gid);
173
+		saved_errno = errno;
174
+		close(real_fd);
175
+		errno = saved_errno;
176
+		END_PROFILE(syscall_fchown);
177
+		return result;
178
+	}
179
+
180
 	/*
181
 	 * This is no longer a handle based call.
182
 	 */
183
@@ -2855,7 +2879,7 @@
184
 			   files_struct *fsp,
185
 			   struct smb_file_time *ft)
186
 {
187
-	int result = -1;
188
+	int result = -1, fd, real_fd;
189
 	struct timespec ts[2];
190
 	struct timespec *times = NULL;
191
 
192
@@ -2900,8 +2924,9 @@
193
 		goto out;
194
 	}
195
 
196
+	fd = fsp_get_pathref_fd(fsp);
197
+	
198
 	if (fsp->fsp_flags.have_proc_fds) {
199
-		int fd = fsp_get_pathref_fd(fsp);
200
 		const char *p = NULL;
201
 		char buf[PATH_MAX];
202
 
203
@@ -2919,6 +2944,16 @@
204
 		goto out;
205
 	}
206
 
207
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
208
+		int saved_errno;
209
+	  
210
+		result = futimens(real_fd, times);
211
+		saved_errno = errno;
212
+		close(real_fd);
213
+		errno = saved_errno;
214
+		goto out;
215
+	}
216
+
217
 	/*
218
 	 * The fd is a pathref (opened with O_PATH) and there isn't fd to
219
 	 * path translation mechanism. Fallback to path based call.
220
@@ -3322,6 +3357,7 @@
221
 {
222
 #ifdef HAVE_FCHFLAGS
223
 	int fd = fsp_get_pathref_fd(fsp);
224
+	int real_fd;
225
 
226
 	SMB_ASSERT(!fsp_is_alternate_stream(fsp));
227
 
228
@@ -3341,6 +3377,16 @@
229
 		return chflags(p, flags);
230
 	}
231
 
232
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
233
+	  int saved_errno, result;
234
+	  
235
+		result = fchflags(real_fd, flags);
236
+		saved_errno = errno;
237
+		close(real_fd);
238
+		errno = saved_errno;
239
+		return result;
240
+	}
241
+
242
 	/*
243
 	 * This is no longer a handle based call.
244
 	 */
245
@@ -3569,6 +3615,7 @@
246
 				 size_t size)
247
 {
248
 	int fd = fsp_get_pathref_fd(fsp);
249
+	int real_fd;
250
 
251
 	SMB_ASSERT(!fsp_is_alternate_stream(fsp));
252
 
253
@@ -3588,6 +3635,16 @@
254
 		return getxattr(p, name, value, size);
255
 	}
256
 
257
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
258
+		int saved_errno, result;
259
+	  
260
+		result = fgetxattr(real_fd, name, value, size);
261
+		saved_errno = errno;
262
+		close(real_fd);
263
+		errno = saved_errno;
264
+		return result;
265
+	}
266
+
267
 	/*
268
 	 * This is no longer a handle based call.
269
 	 */
270
@@ -3895,6 +3952,7 @@
271
 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
272
 {
273
 	int fd = fsp_get_pathref_fd(fsp);
274
+	int real_fd;
275
 
276
 	SMB_ASSERT(!fsp_is_alternate_stream(fsp));
277
 
278
@@ -3914,6 +3972,16 @@
279
 		return listxattr(p, list, size);
280
 	}
281
 
282
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
283
+		int saved_errno, result;
284
+	  
285
+		result = flistxattr(real_fd, list, size);
286
+		saved_errno = errno;
287
+		close(real_fd);
288
+		errno = saved_errno;
289
+		return result;
290
+	}
291
+
292
 	/*
293
 	 * This is no longer a handle based call.
294
 	 */
295
@@ -3923,6 +3991,7 @@
296
 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
297
 {
298
 	int fd = fsp_get_pathref_fd(fsp);
299
+	int real_fd;
300
 
301
 	SMB_ASSERT(!fsp_is_alternate_stream(fsp));
302
 
303
@@ -3942,6 +4011,16 @@
304
 		return removexattr(p, name);
305
 	}
306
 
307
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
308
+		int saved_errno, result;
309
+	  
310
+		result = fremovexattr(real_fd, name);
311
+		saved_errno = errno;
312
+		close(real_fd);
313
+		errno = saved_errno;
314
+		return result;
315
+	}
316
+
317
 	/*
318
 	 * This is no longer a handle based call.
319
 	 */
320
@@ -3951,6 +4030,7 @@
321
 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
322
 {
323
 	int fd = fsp_get_pathref_fd(fsp);
324
+	int real_fd;
325
 
326
 	SMB_ASSERT(!fsp_is_alternate_stream(fsp));
327
 
328
@@ -3968,6 +4048,16 @@
329
 		}
330
 
331
 		return setxattr(p, name, value, size, flags);
332
+	}
333
+
334
+	if (sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
335
+		int saved_errno, result;
336
+	  
337
+		result = fsetxattr(real_fd, name, value, size, flags);
338
+		saved_errno = errno;
339
+		close(real_fd);
340
+		errno = saved_errno;
341
+		return result;
342
 	}
343
 
344
 	/*
345
--- source3/modules/vfs_zfsacl.c	2023-01-18 16:32:24.210553400 +0100
346
+++ source3/modules/vfs_zfsacl.c	2023-06-20 08:51:53.077953000 +0200
347
@@ -234,13 +234,39 @@
348
 
349
 	SMB_ASSERT(i == naces);
350
 
351
-	/* store acl */
352
-	fd = fsp_get_pathref_fd(fsp);
353
-	if (fd == -1) {
354
-		errno = EBADF;
355
-		return false;
356
+	if (!fsp->fsp_flags.is_pathref) {
357
+		rv = facl(fsp_get_io_fd(fsp), ACE_SETACL, naces, acebuf);
358
+	} else {
359
+		const char *procfd_p = NULL;
360
+		char buf[PATH_MAX];
361
+
362
+		fd = fsp_get_pathref_fd(fsp);
363
+		if (fsp->fsp_flags.have_proc_fds && (procfd_p = sys_proc_fd_path(fd, buf, sizeof(buf)))) {
364
+			rv = acl(procfd_p, ACE_SETACL, naces, acebuf);
365
+		} else {
366
+			int real_fd;
367
+
368
+			fd = fsp_get_pathref_fd(fsp);
369
+		
370
+			/* First try this for versions of FreeBSD 13+ that allows facl() on O_PATH fd's */
371
+			rv = facl(fd, ACE_SETACL, naces, acebuf);
372
+		
373
+			if (rv < 0 && errno == EBADF &&
374
+			    sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
375
+				/* Works on FreeBSD 13+ */
376
+				int saved_errno;
377
+
378
+				rv = facl(real_fd, ACE_SETACL, naces, acebuf);
379
+				saved_errno = errno;
380
+				close(real_fd);
381
+				errno = saved_errno;
382
+			} else {
383
+				/* Last ditch fallback */
384
+				rv = acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf);
385
+			}
386
+		}
387
 	}
388
-	rv = facl(fd, ACE_SETACL, naces, acebuf);
389
+
390
 	if (rv != 0) {
391
 		if(errno == ENOSYS) {
392
 			DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not "
393
@@ -284,14 +310,39 @@
394
 {
395
 	int naces, rv;
396
 	ace_t *acebuf = NULL;
397
-	int fd;
398
+	int fd = -1;
399
+	const char *procfd_p = NULL;
400
+	char buf[PATH_MAX];
401
 
402
-	fd = fsp_get_pathref_fd(fsp);
403
-	if (fd == -1) {
404
-		errno = EBADF;
405
-		return -1;
406
+	if (!fsp->fsp_flags.is_pathref) {
407
+		naces = facl(fsp_get_io_fd(fsp), ACE_GETACLCNT, 0, NULL);
408
+	} else {
409
+	  	fd = fsp_get_pathref_fd(fsp);
410
+		
411
+		if (fsp->fsp_flags.have_proc_fds && (procfd_p = sys_proc_fd_path(fd, buf, sizeof(buf)))) {
412
+			/* If we have procfd support, try this first */
413
+			naces = acl(procfd_p, ACE_GETACLCNT, 0, NULL);
414
+		} else {
415
+			int real_fd;
416
+
417
+			/* First try this for versions of FreeBSD 13+ that allows facl() on O_PATH fd's */
418
+			naces = facl(fd, ACE_GETACLCNT, 0, NULL);
419
+			if (naces < 0 && errno == EBADF &&
420
+			    sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
421
+				/* Works on FreeBSD 13+ */
422
+				int saved_errno;
423
+
424
+				naces = facl(real_fd, ACE_GETACLCNT, 0, NULL);
425
+				saved_errno = errno;
426
+				close(real_fd);
427
+				errno = saved_errno;
428
+			} else {
429
+				/* Last ditch fallback */
430
+				naces = acl(fsp->fsp_name->base_name, ACE_GETACLCNT, 0, NULL);
431
+			}
432
+		}
433
 	}
434
-	naces = facl(fd, ACE_GETACLCNT, 0, NULL);
435
+
436
 	if (naces == -1) {
437
 		int dbg_level = 10;
438
 
439
@@ -309,7 +360,32 @@
440
 		return -1;
441
 	}
442
 
443
-	rv = facl(fd, ACE_GETACL, naces, acebuf);
444
+	if (!fsp->fsp_flags.is_pathref) {
445
+		rv = facl(fsp_get_io_fd(fsp), ACE_GETACL, naces, acebuf);
446
+	} else {
447
+		if (procfd_p) {
448
+			rv = acl(procfd_p, ACE_GETACL, naces, acebuf);
449
+		} else {
450
+			int real_fd;
451
+
452
+			/* First try this for versions of FreeBSD that allows facl() on O_PATH fd's */
453
+			rv = facl(fd, ACE_GETACL, naces, acebuf);
454
+			if (rv < 0 && errno == EBADF &&
455
+			    sys_open_real_fd_from_pathref_fd(fd, &real_fd, O_RDONLY|O_NONBLOCK) == 0) {
456
+				/* Works on FreeBSD 13+ */
457
+				int saved_errno;
458
+
459
+				rv = facl(real_fd, ACE_GETACL, naces, acebuf);
460
+				saved_errno = errno;
461
+				close(real_fd);
462
+				errno = saved_errno;
463
+			} else {
464
+				/* Last ditch fallback */
465
+				rv = acl(fsp->fsp_name->base_name, ACE_GETACL, naces, acebuf);
466
+			}
467
+		}
468
+	}
469
+
470
 	if (rv == -1) {
471
 		DBG_DEBUG("acl(ACE_GETACL, %s): %s ",
472
 			  fsp_str_dbg(fsp), strerror(errno));
473
--- source3/include/proto.h	2023-05-31 18:06:44.142299400 +0200
474
+++ source3/include/proto.h	2023-06-19 23:23:58.115127000 +0200
475
@@ -211,6 +211,10 @@
476
 bool sys_have_proc_fds(void);
477
 const char *sys_proc_fd_path(int fd, char *buf, size_t bufsize);
478
 
479
+int sys_open_real_fd_from_pathref_fd(int fd,
480
+				     int *mfd,
481
+				     int flags);
482
+
483
 struct stat;
484
 void init_stat_ex_from_stat (struct stat_ex *dst,
485
 			    const struct stat *src,
486
- 

Return to bug 277878