lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAOQ4uxhtgX4V-zcrkcobZpULvbH2X2RtahM-FJ2JH_S511J+7Q@mail.gmail.com>
Date: Wed, 5 Feb 2025 22:47:46 +0100
From: Amir Goldstein <amir73il@...il.com>
To: Pali Rohár <pali@...nel.org>
Cc: "Darrick J. Wong" <djwong@...nel.org>, ronnie sahlberg <ronniesahlberg@...il.com>, 
	Chuck Lever <chuck.lever@...cle.com>, Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>, 
	Steve French <sfrench@...ba.org>, Alexander Viro <viro@...iv.linux.org.uk>, 
	linux-fsdevel@...r.kernel.org, linux-cifs@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: Immutable vs read-only for Windows compatibility

> > > > What could be useful for userspace is also ability to figure out which
> > > > FS_DOSATTRIB_* are supported by the filesystem. Because for example UDF
> > > > on-disk format supports only FS_DOSATTRIB_HIDDEN bit. And FAT only those
> > > > attributes which are in the lowest byte.
> > > >
> > >
> > > Exactly.
> > > statx has this solved with the stx_attributes_mask field.
> > >
> > > We could do the same for FS_IOC_FS[GS]ETXATTR, but because
> > > right now, this API does not verify that fsx_pad is zero, we will need to
> > > define a new set of ioctl consants FS_IOC_[GS]ETFSXATTR2
> > > with the exact same functionality but that userspace knows that they
> > > publish and respect the dosattrib mask:
> >
> > I understand and this is a problem.
> >
> > > --- a/fs/ioctl.c
> > > +++ b/fs/ioctl.c
> > > @@ -868,9 +868,11 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
> > >         case FS_IOC_SETFLAGS:
> > >                 return ioctl_setflags(filp, argp);
> > >
> > > +       case FS_IOC_GETFSXATTR2:
> > >         case FS_IOC_FSGETXATTR:
> > >                 return ioctl_fsgetxattr(filp, argp);
> > >
> > > +       case FS_IOC_SETFSXATTR2:
> > >         case FS_IOC_FSSETXATTR:
> > >                 return ioctl_fssetxattr(filp, argp);
> > > --- a/include/uapi/linux/fs.h
> > > +++ b/include/uapi/linux/fs.h
> > > @@ -145,7 +145,8 @@ struct fsxattr {
> > >         __u32           fsx_nextents;   /* nextents field value (get)   */
> > >         __u32           fsx_projid;     /* project identifier (get/set) */
> > >         __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> > > -       unsigned char   fsx_pad[8];
> > > +       __u32           fsx_dosattrib;  /* dosattrib field value (get/set) */
> > > +       __u32           fsx_dosattrib_mask; /* dosattrib field validity mask */
> > >  };
> > >
> > >  /*
> > > @@ -238,6 +248,9 @@ struct fsxattr {
> > >  #define FS_IOC32_SETFLAGS              _IOW('f', 2, int)
> > >  #define FS_IOC32_GETVERSION            _IOR('v', 1, int)
> > >  #define FS_IOC32_SETVERSION            _IOW('v', 2, int)
> > > +#define FS_IOC_GETFSXATTR2              _IOR('x', 31, struct fsxattr)
> > > +#define FS_IOC_SETFSXATTR2              _IOW('x', 32, struct fsxattr)
> > > +/* Duplicate legacy ioctl numbers for backward compact */
> > >  #define FS_IOC_FSGETXATTR              _IOR('X', 31, struct fsxattr)
> > >  #define FS_IOC_FSSETXATTR              _IOW('X', 32, struct fsxattr)
> > >  #define FS_IOC_GETFSLABEL              _IOR(0x94, 49, char[FSLABEL_MAX])
> > >
> > > We could also use this opportunity to define a larger fsxattr2 struct
> > > that also includes an fsx_xflags_mask field, so that the xflags namespace
> > > could also be extended in a backward compat way going forward:
> > >
> > > @@ -145,7 +145,21 @@ struct fsxattr {
> > >         __u32           fsx_nextents;   /* nextents field value (get)   */
> > >         __u32           fsx_projid;     /* project identifier (get/set) */
> > >         __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> > >         unsigned char   fsx_pad[8];
> > >
> > >  };
> > > +
> > > +/*
> > > + * Structure for FS_IOC_[GS]ETFSXATTR2.
> > > + */
> > > +struct fsxattr2 {
> > > +       __u32           fsx_xflags;     /* xflags field value (get/set) */
> > > +       __u32           fsx_extsize;    /* extsize field value (get/set)*/
> > > +       __u32           fsx_nextents;   /* nextents field value (get)   */
> > > +       __u32           fsx_projid;     /* project identifier (get/set) */
> > > +       __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> > > +       __u32           fsx_xflags_mask; /* xflags field validity mask */
> > > +       __u32           fsx_dosattrib;  /* dosattrib field value (get/set) */
> > > +       __u32           fsx_dosattrib_mask; /* dosattrib field validity mask */
> > > +};
> > >
> > > And you'd also need to flug those new mask and dosattrib
> > > via struct fileattr into filesystems - too much to explain.
> > > try to figure it out (unless someone objects) and if you can't figure
> > > it out let me know.
> >
> > Yea, I think that this is thing which I should be able to figure out
> > once I start changing it.
> >
> > Anyway, I have alternative idea to the problem with fsx_pad. What about
> > introducing new fsx_xflags flag which would say that fsx_pad=fsx_dosattrib
> > is present? E.g.
> >
> > #define FS_XFLAG_HASDOSATTRIB 0x40000000
> >
> > Then we would not need new FS_IOC_GETFSXATTR2/FS_IOC_SETFSXATTR2 ioctls.
> >
> > Also fsx_pad has 8 bytes, which can store both attrib and mask, so new
> > struct fsxattr2 would not be needed too.
>
> In case we decide to not do 1-to-1 mapping of Windows FILE_ATTRIBUTE_*

The 1-to-1 is definitely not a requirement of the API.

> constants to these new Linux DOSATTRIB_* constants then we do not need
> 32-bit variable, but just 16-bit variable (I counted that we need just
> 10 bits for now).

The "for now" part is what worries me in this sentence.

> fsx_pad has currently 64 bits and we could use it for:
> - 32 bits for fsx_xflags_mask
> - 16 bits for fsx_dosattrib
> - 16 bits for fsx_dosattrib_mask

This is possible.

> And therefore no need for FS_IOC_GETFSXATTR2/FS_IOC_SETFSXATTR2 iocl or
> struct fsxattr2. Just an idea how to simplify new API. Maybe together

no need for struct fsxattr2.
but regarding no new ioctl I am not so sure.

> with new fsx_xflags bit to indicate that fsx_xflags_mask field is present:
> #define FS_XFLAG_HASXFLAGSMASK 0x20000000
>

I don't think that this flag is needed because there is no filesystem
with empty xflags_mask, so any non zero value of xflags_mask
is equivalent to setting this flag.

This is for the get side. For the set side things are more complicated.
A proper backward compat API should reject (-EINVAL) unknown flags.
As far as I can tell ioctl_fssetxattr() does not at any time verify that
fsx_pad is zero and as far as I can tell xfs_fileattr_set() does not
check for unsupported fsx_xflags.

So unless I am missing something, FS_IOC_FSSETXATTR will silently
ignore dosattrib flags (and mask) when called on an old kernel.
This is the justification of FS_IOC_SETFSXATTR2 - it will fail on an
old kernel, so application can trust that if it works - it also respects
dosattib and the masks.

Yes, applications can call FS_IOC_FSGETXATTR, check non zero
mask and deduce that FS_IOC_FSSETXATTR will respect the mask
This will probably work, but it is not a very clean API IMO.

Thanks,
Amir.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ