From: Allison Henderson <allison.henderson@oracle.com>
To: "djwong@kernel.org" <djwong@kernel.org>
Cc: "linux-xfs@vger.kernel.org" <linux-xfs@vger.kernel.org>
Subject: Re: [PATCH v3 23/26] xfs: Filter XFS_ATTR_PARENT for getfattr
Date: Wed, 28 Sep 2022 18:22:31 +0000 [thread overview]
Message-ID: <5acbdfbc5ac52ba9efaf52d71e779ac4524bc909.camel@oracle.com> (raw)
In-Reply-To: <YzNB1juXibZtPuoj@magnolia>
On Tue, 2022-09-27 at 11:32 -0700, Darrick J. Wong wrote:
> On Mon, Sep 26, 2022 at 09:49:42PM +0000, Allison Henderson wrote:
> > On Fri, 2022-09-23 at 14:45 -0700, Darrick J. Wong wrote:
> > > On Wed, Sep 21, 2022 at 10:44:55PM -0700,
> > > allison.henderson@oracle.com wrote:
> > > > From: Allison Henderson <allison.henderson@oracle.com>
> > > >
> > > > Parent pointers returned to the get_fattr tool cause errors
> > > > since
> > > > the tool cannot parse parent pointers. Fix this by filtering
> > > > parent
> > > > parent pointers from xfs_attr_list.
> > >
> > > Yes!! Parent pointers should /never/ be accessible by the
> > > standard
> > > VFS
> > > xattr syscalls, nor should the XFS ATTR_MULTI calls handle them.
> > >
> > > Changes to parent pointers are performed via separate syscalls
> > > (link/unlink/mknod/creat/etc), and I see you've created a
> > > separate
> > > parent pointer ioctl later on for userspace to retrieve them. I
> > > think
> > > this is the correct access model.
> > >
> > > To check that assertion -- getxattr/setxattr/removexattr (and the
> > > ATTRMULTI
> > > equivalents) are prevented from accessing parent pointers
> > > directly
> > > because you'd have to be able to set XFS_ATTR_PARENT in
> > > xfs_da_args.attr_filter, right?
> > Well, you set XFS_IOC_ATTR_PARENT which later translates to
> > XFS_ATTR_PARENT. I do that later in the set, but I see you've
> > already
> > commented on it
>
> <nod>
>
> > >
> > > And for the VFS to get/set/remove a parent pointer, XFS would
> > > have to
> > > provide a struct xattr_handler with ->flags = XFS_ATTR_PARENT,
> > > which
> > > XFS
> > > will never do, right?
> > Well, this set does not plan to make any vfs modifications at least
> > :-)
> >
> > >
> > > And for ATTR_MULTI to touch a parent pointer, xfs_attr_filter
> > > (and
> > > the
> > > ioctl api) would have to learn about XFS_ATTR_PARENT, which XFS
> > > will
> > > also never do, right?
> > I think we do have to publish that XFS_ATTR_PARENT exists, but I
> > don't
> > think we have to implement the XFS_IOC_ATTR_PARENT translation
>
> Agreed. The fewer symbols that end up in xfs_fs.h the better,
> because
> anything we publish in there becomes a part of the userspace ABI and
> has
> to be supported "forever".
>
> > > If the answers to these three questions are all yes then you're
> > > 95%
> > > of
> > > the way to an RVB, except...
> > >
> > > > Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> > > > ---
> > > > fs/xfs/libxfs/xfs_da_format.h | 3 +++
> > > > fs/xfs/xfs_attr_list.c | 47
> > > > +++++++++++++++++++++++++++----
> > > > ----
> > > > 2 files changed, 39 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/fs/xfs/libxfs/xfs_da_format.h
> > > > b/fs/xfs/libxfs/xfs_da_format.h
> > > > index b02b67f1999e..e9c323fab6f3 100644
> > > > --- a/fs/xfs/libxfs/xfs_da_format.h
> > > > +++ b/fs/xfs/libxfs/xfs_da_format.h
> > > > @@ -697,6 +697,9 @@ struct xfs_attr3_leafblock {
> > > > #define XFS_ATTR_INCOMPLETE (1u << XFS_ATTR_INCOMPLETE_BIT)
> > > > #define XFS_ATTR_NSP_ONDISK_MASK \
> > > > (XFS_ATTR_ROOT | XFS_ATTR_SECURE |
> > > > XFS_ATTR_PARENT)
> > > > +#define XFS_ATTR_ALL \
> > > > + (XFS_ATTR_LOCAL_BIT | XFS_ATTR_ROOT | XFS_ATTR_SECURE |
> > > > \
> > > > + XFS_ATTR_PARENT | XFS_ATTR_INCOMPLETE_BIT)
> > > >
> > > > /*
> > > > * Alignment for namelist and valuelist entries (since they
> > > > are
> > > > mixed
> > > > diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
> > > > index a51f7f13a352..13de597c4996 100644
> > > > --- a/fs/xfs/xfs_attr_list.c
> > > > +++ b/fs/xfs/xfs_attr_list.c
> > > > @@ -39,6 +39,23 @@ xfs_attr_shortform_compare(const void *a,
> > > > const
> > > > void *b)
> > > > }
> > > > }
> > > >
> > > > +/*
> > > > + * Returns true or false if the parent attribute should be
> > > > listed
> > > > + */
> > > > +static bool
> > > > +xfs_attr_filter_parent(
> > > > + struct xfs_attr_list_context *context,
> > > > + int flags)
> > > > +{
> > > > + if (!(flags & XFS_ATTR_PARENT))
> > > > + return true;
> > > > +
> > > > + if (context->attr_filter & XFS_ATTR_PARENT)
> > > > + return true;
> > > > +
> > > > + return false;
> > >
> > > ...wouldn't it suffice to do:
> > >
> > > static inline bool
> > > xfs_attr_filter_listent(
> > > struct xfs_attr_list_context *context,
> > > int flags)
> > > {
> > > return context->attr_filter != (flags &
> > > XFS_ATTR_NSP_ONDISK_MASK);
> > > }
> > Almost.... XFS_ATTR_NSP_ONDISK_MASK includes XFS_ATTR_PARENT, so
> > here
> > we'd want XFS_ATTR_NSP_ONDISK_MASK & ~XFS_ATTR_PARENT
> >
> > Also, XFS_ATTR_NSP_ONDISK_MASK doesnt include XFS_ATTR_LOCAL which
> > was
> > previously allowable
> >
> > Hmm, how bout just:
> > return context->attr_filter != flags & (XFS_ATTR_ROOT |
> > XFS_ATTR_SECURE | XFS_ATTR_LOCAL)
> >
> > I think that preserves the existing behavior
>
> It does, but I think it'll cause conflicts with future online fsck
> code.
>
> (Let me check my understanding of the xfs_attr_list callers first:
>
> There are /three/ namespaces, but only two of them have defined flag
> bits. "root.*" and "secure.*" have XFS_ATTR_{ROOT,SECURE}, but
> "user.*"
> is recorded by the absence of any XFS_ATTR_ flag. IOWs, attr_filter
> isn't a bit mask of all the namespaces that the caller wants; it's a
> cookie value to coordinate between the xfs_attr_list caller and the
> supplied putent function.
>
> vfs_listxattr doesn't allow userspace to specify an xattr namespace,
> so
> it returns xattrs from user.*, root.*, and secure.*.
> xfs_vn_listxattr
> doesn't set attr_filter, and xfs_xattr_put_listent doesn't check.
>
> XFS_IOC_ATTRLIST_BY_HANDLE, on the other hand, requires userspace to
> specify which namespace they want to list. That's why it's the one
> caller that sets context.attr_filter, and xfs_ioc_attr_put_listent
> does
> a comparison to filter attributes from other namespaces.
>
> The xattr scrubber calls xfs_attr_list_ilocked to walk every xattr
> attached to the file. For each call to ->put_listent, it uses the
> built-in hash information to look up the attr name provided to
> confirm
> that hashed lookups also work. For /this/ usecase, we want
> xfs_attr_list_* to return all xattrs because we need to check all
> xattr
> namespaces. Hence it doesn't set context.attr_filter, and
> xchk_xattr_listent doesn't check it either.
>
> ...right?)
>
> ((Come to think of it -- shouldn't the ifork and attr leaf block
> verifiers check that each attr entry struct have at most one of the
> namespace bits set?))
>
> After the addition of parent pointers, xfs_xattr_put_listent needs to
> filter out (flags & XFS_ATTR_PARENT) cases.
> XFS_IOC_ATTRLIST_BY_HANDLE
> won't need any changes if we drop the XFS_IOC_ATTR_PARENT flag, since
> there won't be any way for XFS_ATTR_PARENT to be set in attr_filter.
> The xattr scrubber still needs to walk every xattr to perform a
> complete
> scan. Hence it will still not touch context.attr_filter, nor will it
> want any filtering to be applied at all.
>
> For the forthcoming totally-doesn't-exist-yet parent pointer online
> fsck
> code, I'd sorta like to reuse that function to walk only the parent
> pointers. I'm not 100% sure I will end up doing that -- the
> cursoring
> code would be useful if I have to use a live inode scan to do the
> checking and repair, but OTOH it's a little annoying to deal with the
> warts of the xfs_attr_list_context. But in theory, I'd have
> xchk_parent_listent or whatever the function ends up being named
> ignore
> anything that wasn't XFS_ATTR_PARENT. This mechanism also does not
> want
> the xfs_attr_list_* functions to perform any filtering.
>
> In terms of APIs, xfs_attr_filter_parent doesn't really make a lot of
> sense -- if you set context.attr_filter = XFS_ATTR_PARENT, you'll get
> all the xattrs (including the non-parent ones), but if you set any
> other
> value (e.g. XFS_ATTR_SECURE), you'll get all the non-parent xattrs,
> including the root.* and user.* attrs. The ->put_listent function
> still
> has to do its own filtering. Right?
>
> What if xfs_xattr_put_listent exited early if (flags &
> XFS_ATTR_PARENT)
> and we never define a XFS_IOC_ATTR_ROOT? Won't that suffice to
> prevent
> the userspace xattr APIs from ever returning a parent pointer by
> accident?
>
> Looking ahead to the GETPARENTS code, I think the filtering code in
> xfs_ioc_attr_put_listent would work for returning only the parent
> pointers, right? Since it does set context.attr_filter to
> XFS_ATTR_PARENT on its own? And you wouldn't need any of the other
> changes here?
Ok, I tried this out and it seems to work, so I will add this in the
next revision. Thanks for the reviews!
Allison
>
> --D
>
> > >
> > > like how xfs_ioc_attr_put_listent does? And then...
> > >
> > > > +}
> > > > +
> > > > #define XFS_ISRESET_CURSOR(cursor) \
> > > > (!((cursor)->initted) && !((cursor)->hashval) && \
> > > > !((cursor)->blkno) && !((cursor)->offset))
> > > > @@ -90,11 +107,12 @@ xfs_attr_shortform_list(
> > > >
> > > > sfe-
> > > > > namelen,
> > > >
> > > > sfe-
> > > > > flags)))
> > > > return -EFSCORRUPTED;
> > > > - context->put_listent(context,
> > > > - sfe->flags,
> > > > - sfe->nameval,
> > > > - (int)sfe->namelen,
> > > > - (int)sfe-
> > > > >valuelen);
> > > > + if (xfs_attr_filter_parent(context,
> > > > sfe-
> > > > > flags))
> > > > + context->put_listent(context,
> > > > + sfe-
> > > > >flags,
> > > > + sfe-
> > > > >nameval,
> > > > + (int)sfe-
> > > > > namelen,
> > > > + (int)sfe-
> > > > > valuelen);
> > > > /*
> > > > * Either search callback finished
> > > > early or
> > > > * didn't fit it all in the buffer
> > > > after
> > > > all.
> > > > @@ -185,11 +203,12 @@ xfs_attr_shortform_list(
> > > > error = -EFSCORRUPTED;
> > > > goto out;
> > > > }
> > > > - context->put_listent(context,
> > > > - sbp->flags,
> > > > - sbp->name,
> > > > - sbp->namelen,
> > > > - sbp->valuelen);
> > > > + if (xfs_attr_filter_parent(context, sbp-
> > > > >flags))
> > > > + context->put_listent(context,
> > > > + sbp->flags,
> > > > + sbp->name,
> > > > + sbp->namelen,
> > > > + sbp->valuelen);
> > > > if (context->seen_enough)
> > > > break;
> > > > cursor->offset++;
> > > > @@ -474,8 +493,10 @@ xfs_attr3_leaf_list_int(
> > > > !xfs_attr_namecheck(mp,
> > > > name,
> > > > namelen,
> > > > entry-
> > > > > flags)))
> > > > return -EFSCORRUPTED;
> > > > - context->put_listent(context, entry->flags,
> > > > + if (xfs_attr_filter_parent(context, entry-
> > > > >flags))
> > > > + context->put_listent(context, entry-
> > > > >flags,
> > > > name, namelen,
> > > > valuelen);
> > > > +
> > > > if (context->seen_enough)
> > > > break;
> > > > cursor->offset++;
> > > > @@ -539,6 +560,10 @@ xfs_attr_list(
> > > > if (xfs_is_shutdown(dp->i_mount))
> > > > return -EIO;
> > > >
> > > > + if (context->attr_filter == 0)
> > > > + context->attr_filter =
> > > > + XFS_ATTR_ALL & ~XFS_ATTR_PARENT;
> > >
> > > ...I think this is unnecessary since none of the callers can
> > > actually
> > > set XFS_ATTR_PARENT in the first place, right?
> > >
> > The caller can stuff any bit in there they want, but until now it
> > didn't matter because context->attr_filter was unused (getfattr
> > appears
> > to just leave it as 0). So the existing behavior was that
> > requesting
> > nothing resulted in everything. Now we're flipping that (at least
> > internally).
> >
> > If we use the filter logic above, this would need to turn into
> > context->attr_filter = (XFS_ATTR_ROOT | XFS_ATTR_SECURE |
> > XFS_ATTR_LOCAL)
> >
> > > --D
> > >
> > > > +
> > > > lock_mode = xfs_ilock_attr_map_shared(dp);
> > > > error = xfs_attr_list_ilocked(context);
> > > > xfs_iunlock(dp, lock_mode);
> > > > --
> > > > 2.25.1
> > > >
> >
next prev parent reply other threads:[~2022-09-28 18:22 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-22 5:44 [PATCH v3 00/26] Parent Pointers allison.henderson
2022-09-22 5:44 ` [PATCH v3 01/26] xfs: Add new name to attri/d allison.henderson
2022-09-23 18:53 ` Darrick J. Wong
2022-09-23 20:43 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 02/26] xfs: Increase XFS_DEFER_OPS_NR_INODES to 5 allison.henderson
2022-09-23 19:02 ` Darrick J. Wong
2022-09-23 20:45 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 03/26] xfs: Hold inode locks in xfs_ialloc allison.henderson
2022-09-22 5:44 ` [PATCH v3 04/26] xfs: Hold inode locks in xfs_trans_alloc_dir allison.henderson
2022-09-23 19:04 ` Darrick J. Wong
2022-09-23 20:44 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 05/26] xfs: Hold inode locks in xfs_rename allison.henderson
2022-09-23 19:21 ` Darrick J. Wong
2022-09-23 20:44 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 06/26] xfs: Expose init_xattrs in xfs_create_tmpfile allison.henderson
2022-09-23 19:25 ` Darrick J. Wong
2022-09-23 20:45 ` Allison Henderson
2022-09-23 21:18 ` Darrick J. Wong
2022-09-22 5:44 ` [PATCH v3 07/26] xfs: get directory offset when adding directory name allison.henderson
2022-09-22 5:44 ` [PATCH v3 08/26] xfs: get directory offset when removing " allison.henderson
2022-09-22 5:44 ` [PATCH v3 09/26] xfs: get directory offset when replacing a " allison.henderson
2022-09-22 5:44 ` [PATCH v3 10/26] xfs: add parent pointer support to attribute code allison.henderson
2022-09-22 5:44 ` [PATCH v3 11/26] xfs: define parent pointer xattr format allison.henderson
2022-09-22 5:44 ` [PATCH v3 12/26] xfs: Add xfs_verify_pptr allison.henderson
2022-09-22 5:44 ` [PATCH v3 13/26] xfs: extend transaction reservations for parent attributes allison.henderson
2022-09-23 20:17 ` Darrick J. Wong
2022-09-23 23:53 ` Allison Henderson
2022-09-26 23:53 ` Darrick J. Wong
2022-09-27 20:04 ` Allison Henderson
2022-09-27 20:44 ` Darrick J. Wong
2022-09-22 5:44 ` [PATCH v3 14/26] xfs: parent pointer attribute creation allison.henderson
2022-09-23 21:11 ` Darrick J. Wong
2022-09-26 21:48 ` Allison Henderson
2022-09-26 23:54 ` Darrick J. Wong
2022-09-27 20:10 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 15/26] xfs: add parent attributes to link allison.henderson
2022-09-23 20:31 ` Darrick J. Wong
2022-09-26 21:49 ` Allison Henderson
2022-09-26 23:55 ` Darrick J. Wong
2022-09-22 5:44 ` [PATCH v3 16/26] xfs: add parent attributes to symlink allison.henderson
2022-09-23 21:16 ` Darrick J. Wong
2022-09-26 21:48 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 17/26] xfs: remove parent pointers in unlink allison.henderson
2022-09-23 21:22 ` Darrick J. Wong
2022-09-26 21:49 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 18/26] xfs: Add parent pointers to xfs_cross_rename allison.henderson
2022-09-23 21:52 ` Darrick J. Wong
2022-09-26 21:50 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 19/26] xfs: Indent xfs_rename allison.henderson
2022-09-23 21:22 ` Darrick J. Wong
2022-09-26 21:49 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 20/26] xfs: Add parent pointers to rename allison.henderson
2022-09-23 22:08 ` Darrick J. Wong
2022-09-26 21:50 ` Allison Henderson
2022-09-22 5:44 ` [PATCH v3 21/26] xfs: Add the parent pointer support to the superblock version 5 allison.henderson
2022-09-22 5:44 ` [PATCH v3 22/26] xfs: Add helper function xfs_attr_list_context_init allison.henderson
2022-09-22 5:44 ` [PATCH v3 23/26] xfs: Filter XFS_ATTR_PARENT for getfattr allison.henderson
2022-09-22 16:55 ` Allison Henderson
2022-09-23 21:45 ` Darrick J. Wong
2022-09-26 21:49 ` Allison Henderson
2022-09-27 18:32 ` Darrick J. Wong
2022-09-28 18:22 ` Allison Henderson [this message]
2022-09-28 1:13 ` [xfs] b73248c4ee: xfstests.xfs.269.fail kernel test robot
2022-09-22 5:44 ` [PATCH v3 24/26] xfs: Add parent pointer ioctl allison.henderson
2022-09-24 0:30 ` Darrick J. Wong
2022-09-26 21:50 ` Allison Henderson
2022-09-27 18:34 ` Darrick J. Wong
2022-09-22 5:44 ` [PATCH v3 25/26] xfs: fix unit conversion error in xfs_log_calc_max_attrsetm_res allison.henderson
2022-09-23 21:47 ` Darrick J. Wong
2022-09-26 21:50 ` Allison Henderson
2022-09-27 0:02 ` Darrick J. Wong
2022-09-22 5:44 ` [PATCH v3 26/26] xfs: drop compatibility minimum log size computations for reflink allison.henderson
2022-09-23 21:48 ` Darrick J. Wong
2022-09-26 21:50 ` Allison Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5acbdfbc5ac52ba9efaf52d71e779ac4524bc909.camel@oracle.com \
--to=allison.henderson@oracle.com \
--cc=djwong@kernel.org \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).