[Samba] O_PATH, FreeBSD & acl_xx_fd

Peter Eriksson pen at lysator.liu.se
Tue May 30 18:45:20 UTC 2023



> On 30 May 2023, at 19:50, Jeremy Allison <jra at samba.org> wrote:
> 
> On Tue, May 30, 2023 at 07:40:41PM +0200, Peter Eriksson via samba wrote:
>> Urgh…
>> 
>> I modified the FreeBSD kernel to allow all_xx_fd() calls on O_PATH descriptors and that seems make vfs_zfsacl to work fine. Not 100% tested but I could atleast view and modify the ACL on some stuff from a Windows client via Samba that way.
>> 
>> I’m not sure I’ll be able to get them to implement this “officially” though. Reading ACLs via an O_PATH-opened descriptor seems to be on the way of being added though. I can always use my custom kernel but… :-)
>> 
>> Regarding that Linux hack - I wonder if on FreeBSD one might use this to do something similar:
>> 
>>>  A file descriptor created with the O_PATH flag can be opened into normal
>>>    (operable) file descriptor by specifying it as the fd argument to
>>>    openat() with empty path and flag O_EMPTY_PATH.  Such an open behaves as
>>>    if the current path of the file referenced by fd is passed, except that
>>>    the path walk permissions are not checked.  See also the description of
>>>    AT_EMPTY_PATH flag for fstatat(2) and related syscalls.
>> 
>> Hmm… I’ll have to test it. Yes, this seems to work - after this I can read & write ACLs and stuff:
>> 
>>  fd = openat(fd, “”, O_EMPTY_PATH);
> 
> Excellent ! These are the current places where the
> horrid hack is used:
> 
> git grep sys_proc_fd_path
> source3/include/proto.h:const char *sys_proc_fd_path(int fd, char *buf, size_t bufsize);
> source3/lib/system.c:const char *sys_proc_fd_path(int fd, char *buf, size_t bufsize)
> source3/modules/vfs_btrfs.c:    p = sys_proc_fd_path(fsp_fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_default.c:          p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_gpfs.c:                     p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_gpfs.c:             p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_gpfs.c:             p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_gpfs.c:             p = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_posixacl.c:         proc_fd_path = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_posixacl.c:         proc_fd_path = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/modules/vfs_posixacl.c:         proc_fd_path = sys_proc_fd_path(fd, buf, sizeof(buf));
> source3/smbd/open.c:    p = sys_proc_fd_path(old_fd, buf, sizeof(buf));
> 
> So these are all the places you're going to run into the
> same problem with O_PATH opened fd's.
> 

If I’m reading that code correctly most of those places seems to (fchown used as an example):

1. If fsp is not a pathref then: fchown(fsp_get_io_fd(fsp)…)
2. If have_proc_fds is true, then use sys_proc_fd_path to operate on a path (chown)
3. Then as a last fallback get the path from fsp->fsp_name->base_name) and operate on a path (chown)

That is probably why things seems to work for most stuff for me - except the vfs_zfsacl module that doesn’t try to use the #3). 

Hmm. Use openat() or the last fallback? Decisions decisions :-) openat() feels like a better solution but I’m not sure… 

- Peter



More information about the samba-technical mailing list