[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