setxattr() flags

668 views
Skip to first unread message

Nikolaus Rath

unread,
Feb 28, 2012, 7:25:10 PM2/28/12
to fus...@googlegroups.com
Hello,

It seems to me (again, just from looking at the code, I don't have OS-X)
that OS-X supports some additional setxattr() flags: XATTR_NOFOLLOW,
XATTR_NOSECURITY and XATTR_NODEFAULT.

Am I right that XATTR_NOFOLLOW and XATTR_NOSECURITY are handled in the
kernel and will never be passed to the FUSE setxattr() low-level handler?

Could someone explain to me the semantics of XATTR_NODEFAULT? Is this
something that may be passed to the FUSE handler? I couldn't find any
documentation of it...


Best,

-Nikolaus

--
»Time flies like an arrow, fruit flies like a Banana.«

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C

Anatol Pomozov

unread,
Feb 29, 2012, 3:28:14 PM2/29/12
to fus...@googlegroups.com
Hi

On Tue, Feb 28, 2012 at 4:25 PM, Nikolaus Rath <Niko...@rath.org> wrote:
Hello,

It seems to me (again, just from looking at the code, I don't have OS-X)
that OS-X supports some additional setxattr() flags: XATTR_NOFOLLOW,
XATTR_NOSECURITY and XATTR_NODEFAULT.

Am I right that XATTR_NOFOLLOW and XATTR_NOSECURITY are handled in the
kernel and will never be passed to the FUSE setxattr() low-level handler?

Could someone explain to me the semantics of XATTR_NODEFAULT? Is this
something that may be passed to the FUSE handler? I couldn't find any
documentation of it...

The best documentation that I have is the kernel source code itself. https://github.com/anatol/xnu

if flag XATTR_NODEFAULT is not set then if a filesystem (e.g. fuse4x) returns ENOTSUP for the xattr then kernel reads a forkfile [1] and tries to read xattr value from this file https://github.com/anatol/xnu/blob/master/bsd/vfs/vfs_xattr.c#L1450

What I see from the code is that XATTR_NODEFAULT is passed to the filesystem. XATTR_NOSECURITY is also used by kernel and also might be passed to filesystem. Do not know about XATTR_NOFOLLOW.  Then Fuse4X kernel extension passes all setxattr flags up to userspace. It probably easier just write a program and test what flags a fs might receive.

This might be a good question for darwin-kernel maillist [2]

Hans Beckérus

unread,
Mar 6, 2012, 11:31:50 AM3/6/12
to fus...@googlegroups.com
Regarding XATTR_NOFOLLOW. From what I know that is having the same effect as lsetxattr() on Linux. Actually, it is not only setxattr that is affected by this, but all functions in the xattr suit.

Hans

Anatol Pomozov

unread,
Mar 7, 2012, 1:13:04 PM3/7/12
to fus...@googlegroups.com
Hi

On Tue, Mar 6, 2012 at 8:31 AM, Hans Beckérus <hans.b...@gmail.com> wrote:
Regarding XATTR_NOFOLLOW. From what I know that is having the same effect as lsetxattr() on Linux. Actually, it is not only setxattr that is affected by this, but all functions in the xattr suit.

Indeed. If you talk about libc (libSystem in macosx) then passing XATTR_NOFOLLOW to xattr function is the same as lxattr in Linux. In fact there is no lxattr functions in libSystem so passing XATTR_NOFOLLOW is the only way to emulate lxattr functions.

While we speak about xattr in macosx/fuse4x there is worth mention that this functions suit is not a part of POSIX. And declaration for them differs between linux and macosx. e.g. setxattr/getxattr in macosx have additional parameter "position", man page states: "position specifies an offset within the extended attribute.  In the current implementation, this argument is only used with the resource fork attribute.  For all other extended attributes, this parameter is reserved and should be zero". In fuse4x the additional parameter (position) is always 0.

setxattr flags are also different - e.g. macosx has flag XATTR_SHOWCOMPRESSION that is HFS specific.... It also looks like xnu might pass kernel-specific flags XATTR_NODEFAULT, XATTR_NOSECURITY to fuse4x. These flags do not look useful for userspace filesystem but it is not clear for me if fuse4x should filter it out automatically. Currently fuse4x passes all flags straight to userspace.

Nikolaus Rath

unread,
Apr 21, 2012, 5:59:03 PM4/21/12
to fus...@googlegroups.com


On Wednesday, March 7, 2012 1:13:04 PM UTC-5, Anatol Pomozov wrote:
setxattr flags are also different - e.g. macosx has flag XATTR_SHOWCOMPRESSION that is HFS specific.... It also looks like xnu might pass kernel-specific flags XATTR_NODEFAULT, XATTR_NOSECURITY to fuse4x. These flags do not look useful for userspace filesystem but it is not clear for me if fuse4x should filter it out automatically. Currently fuse4x passes all flags straight to userspace.
 
The advantage of filtering them out is that this allows a FUSE file system to check if it understands the request correctly. For example, a file system may check flags for XATTR_CREATE and XATTR_REPLACE (because it knows what to do with them) and fail if any other flags are present (because then it can't be sure that it knows what the caller wants). If there are additional options that are actually of no concern to the file system, this isn't as easy. The file system would have to come with a hardcoded list of unimportant flags, and would also have to take into account if it's running under FUSE4X, FUSE or FUSE4BSD.

Therefore, I think it would be better if the number of flags that may be passed to setxattr is well-defined and restricted to flags meaningful for a fuse fs.

Best,
Nikolaus

Hans Beckérus

unread,
Apr 22, 2012, 3:45:23 PM4/22/12
to fus...@googlegroups.com
Yes, It would be so much simpler if there was a uniform interface for the entire xattr suit. I already faced this issue and was forced to add logic to handle the case when the fs is built against Fuse or Fuse4x. But, I also see a limitation in the Fuse reference implementation which choose to filter out also important flags such as XATTR_NOFOLLOW. Since the fs does not see this flag, what function should it call on Linux, the one that follows- or the one that do not follow- symbolic links? Currently my implementation choose to use the l-suit of functions on Linux and force setting XATTR_NOFOLLOW on eg. OSX.
I do not know if this was the correct choice though. But I had to do something since Fuse does not provide the l-suit of callbacks. At least not the last time I checked.

Hans

Nikolaus Rath

unread,
Apr 22, 2012, 6:49:10 PM4/22/12
to fus...@googlegroups.com
On 04/22/2012 03:45 PM, Hans Beckérus wrote:
> Yes, It would be so much simpler if there was a uniform interface for
> the entire xattr suit. I already faced this issue and was forced to add
> logic to handle the case when the fs is built against Fuse or Fuse4x.
> But, I also see a limitation in the Fuse reference implementation which
> choose to filter out also important flags such as XATTR_NOFOLLOW. Since
> the fs does not see this flag, what function should it call on Linux,
> the one that follows- or the one that do not follow- symbolic links?

I don't follow. Your file system is not supposed to call any specific
functions, it's supposed to set the provided extended attribute for the
provided inode. If the client application attempted to set the
attributes on a symbolic link without specifying XATTR_NOFOLLOW, the
kernel will resolve this and pass the inode of the symlink target to
your FUSE file system. A FUSE file system does not need to know anything
about the original request.

> I do not know if this was the correct choice though. But I had to do
> something since Fuse does not provide the l-suit of callbacks. At least
> not the last time I checked.

No, because that would be pointless. The implementation of the non-l
functions would be the same for every fuse file system: follow the link,
and then call the l variant of the function.

Hans Beckérus

unread,
Apr 23, 2012, 2:24:03 AM4/23/12
to fus...@googlegroups.com
On Monday, April 23, 2012 12:49:10 AM UTC+2, Nikolaus Rath wrote:

> I do not know if this was the correct choice though. But I had to do
> something since Fuse does not provide the l-suit of callbacks. At least
> not the last time I checked.

No, because that would be pointless. The implementation of the non-l
functions would be the same for every fuse file system: follow the link,
and then call the l variant of the function.

Ok, I probably got this completely wrong. So if someone calls eg.lsetxattr() on some symbolic link that request will terminate in the kernel and never reach the FUSE userspace?
How would a user otherwise know if the request is targeting the link itself or the file it links to? But do OSX and Linux handle this the same way?

Hans

Nikolaus Rath

unread,
Apr 23, 2012, 8:17:53 AM4/23/12
to fus...@googlegroups.com
On 04/23/2012 02:24 AM, Hans Beckérus wrote:
> On Monday, April 23, 2012 12:49:10 AM UTC+2, Nikolaus Rath wrote:
>
> > I do not know if this was the correct choice though. But I had to do
> > something since Fuse does not provide the l-suit of callbacks. At
> least
> > not the last time I checked.
>
> No, because that would be pointless. The implementation of the non-l
> functions would be the same for every fuse file system: follow the link,
> and then call the l variant of the function.
>
> Ok, I probably got this completely wrong. So if someone calls
> eg.lsetxattr() on some symbolic link that request will terminate in the
> kernel and never reach the FUSE userspace?

In a way. The request will reach FUSE userspace, but possibly with a
different inode (the link target).

> How would a user otherwise know if the request is targeting the link
> itself or the file it links to?

I guess you mean the FUSE file system here, not the user, right? The
FUSE file system does not need to know it. If the *user* targeted the
link, the kernel will pass the inode of the link to the FUSE file
system. If the user targeted the target of the link, the kernel will
resolve the link and pass the inode of the destination to the FUSE fs.
In any case, the FUSE fs just has to work on the provided inode.

> But do OSX and Linux handle this the
> same way?

Linux handles it this way, and I think this also makes most sense. I
would hope that Fuse4x behaves the same way.

Hans Beckérus

unread,
Apr 23, 2012, 2:29:07 PM4/23/12
to fus...@googlegroups.com


On Monday, April 23, 2012 2:17:53 PM UTC+2, Nikolaus Rath wrote:

> How would a user otherwise know if the request is targeting the link
> itself or the file it links to?

I guess you mean the FUSE file system here, not the user, right? The
FUSE file system does not need to know it. If the *user* targeted the
link, the kernel will pass the inode of the link to the FUSE file
system. If the user targeted the target of the link, the kernel will
resolve the link and pass the inode of the destination to the FUSE fs.
In any case, the FUSE fs just has to work on the provided inode.

Ah, but herein lies the problem ;) I guess your are referring to the low-level API.
But for the high-level API there is no inode involved. How would the FUSE fs using the high-level API know if the xattr call is targeting the link or not when there is no l-set of callback unless some flags was forwarded from kernel?

Hans

Nikolaus Rath

unread,
Apr 23, 2012, 2:49:37 PM4/23/12
to fus...@googlegroups.com

Since the high level API runs on top of the low level API, every path
passed to the high-level functions has been generated from the low level
inode parameter, and is therefore the final path to work on. No link
following has to be done.

Hans Beckérus

unread,
Apr 23, 2012, 3:01:28 PM4/23/12
to fus...@googlegroups.com


On Monday, April 23, 2012 8:49:37 PM UTC+2, Nikolaus Rath wrote:
On 04/23/2012 02:29 PM, Hans Beckérus wrote:
>
>
> On Monday, April 23, 2012 2:17:53 PM UTC+2, Nikolaus Rath wrote:
>
>
>     > How would a user otherwise know if the request is targeting the link
>     > itself or the file it links to?
>
>     I guess you mean the FUSE file system here, not the user, right? The
>     FUSE file system does not need to know it. If the *user* targeted the
>     link, the kernel will pass the inode of the link to the FUSE file
>     system. If the user targeted the target of the link, the kernel will
>     resolve the link and pass the inode of the destination to the FUSE fs.
>     In any case, the FUSE fs just has to work on the provided inode.
>
> Ah, but herein lies the problem ;) I guess your are referring to the
> low-level API.
> But for the high-level API there is no inode involved. How would the
> FUSE fs using the high-level API know if the xattr call is targeting the
> link or not when there is no l-set of callback unless some flags was
> forwarded from kernel?

Since the high level API runs on top of the low level API, every path
passed to the high-level functions has been generated from the low level
inode parameter, and is therefore the final path to work on. No link
following has to be done.


Yes, I sort of realized that soon after pushing the post button ;)
Thanks for the clarification.

Hans
 
Reply all
Reply to author
Forward
0 new messages