From: Jeff Layton <jlayton@kernel.org>
To: Amir Goldstein <amir73il@gmail.com>
Cc: Christian Brauner <brauner@kernel.org>,
Aleksa Sarai <cyphar@cyphar.com>,
Chuck Lever <chuck.lever@oracle.com>,
linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org
Subject: Re: [RFC PATCH 2/2] fs: open_by_handle_at() support for decoding connectable file handles
Date: Sat, 21 Sep 2024 07:33:12 +0200 [thread overview]
Message-ID: <8aa01edea8972c1bde3b34df32f9db72e29420ed.camel@kernel.org> (raw)
In-Reply-To: <CAOQ4uxjkN2WgT8QJeeZfbRCqrTMED+PtYEXrkDmWjh0iw+PGGw@mail.gmail.com>
On Fri, 2024-09-20 at 18:38 +0200, Amir Goldstein wrote:
> On Fri, Sep 20, 2024 at 6:02 PM Jeff Layton <jlayton@kernel.org> wrote:
> >
> > On Thu, 2024-09-19 at 16:06 +0200, Amir Goldstein wrote:
> > > Allow using an O_PATH fd as mount fd argument of open_by_handle_at(2).
> > > This was not allowed before, so we use it to enable a new API for
> > > decoding "connectable" file handles that were created using the
> > > AT_HANDLE_CONNECTABLE flag to name_to_handle_at(2).
> > >
> > > When mount fd is an O_PATH fd and decoding an O_PATH fd is requested,
> > > use that as a hint to try to decode a "connected" fd with known path,
> > > which is accessible (to capable user) from mount fd path.
> > >
> > > Note that this does not check if the path is accessible to the calling
> > > user, just that it is accessible wrt the mount namesapce, so if there
> > > is no "connected" alias, or if parts of the path are hidden in the
> > > mount namespace, open_by_handle_at(2) will return -ESTALE.
> > >
> > > Note that the file handles used to decode a "connected" fd do not have
> > > to be encoded with the AT_HANDLE_CONNECTABLE flag. Specifically,
> > > directory file handles are always "connectable", regardless of using
> > > the AT_HANDLE_CONNECTABLE flag.
> > >
> > > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > > ---
> > > fs/fhandle.c | 61 +++++++++++++++++++++++++++++++---------------------
> > > 1 file changed, 37 insertions(+), 24 deletions(-)
> > >
> >
> > The mountfd is only used to get a path, so I don't see a problem with
> > allowing that to be an O_PATH fd.
> >
> > I'm less keen on using the fact that mountfd is an O_PATH fd to change
> > the behaviour of open_by_handle_at(). That seems very subtle. Is there
> > a good reason to do it that way instead of just declaring a new AT_*
> > flag for this?
> >
>
> Not sure if it is a good reason, but open_by_handle_at() has an O_ flags
> argument, not an AT_ flags argument...
>
> If my hack API is not acceptable then we will need to add
> open_by_handle_at2(), with struct open_how argument or something.
>
Oh right, I forgot that open_by_handle_at doesn't take AT_* flags.
A new syscall may be best then.
I can see a couple of other potential approaches:
1/ You could add a new fcntl() cmd that puts the mountfd into a
"connectable filehandles" mode. The downside there is that it'd take 2
syscalls to do your open.
2/ You could add flags to open_how that make openat2() behave like
open_by_handle_at(). Add a flag that allows "pathname" to point to a
filehandle instead, and a second flag that indicates that the fh is
connectable.
Both of those are pretty hacky though.
> >
> > > diff --git a/fs/fhandle.c b/fs/fhandle.c
> > > index 956d9b25d4f7..1fabfb79fd55 100644
> > > --- a/fs/fhandle.c
> > > +++ b/fs/fhandle.c
> > > @@ -146,37 +146,45 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
> > > return err;
> > > }
> > >
> > > -static int get_path_from_fd(int fd, struct path *root)
> > > +enum handle_to_path_flags {
> > > + HANDLE_CHECK_PERMS = (1 << 0),
> > > + HANDLE_CHECK_SUBTREE = (1 << 1),
> > > +};
> > > +
> > > +struct handle_to_path_ctx {
> > > + struct path root;
> > > + enum handle_to_path_flags flags;
> > > + unsigned int fh_flags;
> > > + unsigned int o_flags;
> > > +};
> > > +
> > > +static int get_path_from_fd(int fd, struct handle_to_path_ctx *ctx)
> > > {
> > > if (fd == AT_FDCWD) {
> > > struct fs_struct *fs = current->fs;
> > > spin_lock(&fs->lock);
> > > - *root = fs->pwd;
> > > - path_get(root);
> > > + ctx->root = fs->pwd;
> > > + path_get(&ctx->root);
> > > spin_unlock(&fs->lock);
> > > } else {
> > > - struct fd f = fdget(fd);
> > > + struct fd f = fdget_raw(fd);
> > > if (!f.file)
> > > return -EBADF;
> > > - *root = f.file->f_path;
> > > - path_get(root);
> > > + ctx->root = f.file->f_path;
> > > + path_get(&ctx->root);
> > > + /*
> > > + * Use O_PATH mount fd and requested O_PATH fd as a hint for
> > > + * decoding an fd with connected path, that is accessible from
> > > + * the mount fd path.
> > > + */
> > > + if (ctx->o_flags & O_PATH && f.file->f_mode & FMODE_PATH)
> > > + ctx->flags |= HANDLE_CHECK_SUBTREE;
> > > fdput(f);
> > > }
> > >
> > > return 0;
> > > }
> > >
> > > -enum handle_to_path_flags {
> > > - HANDLE_CHECK_PERMS = (1 << 0),
> > > - HANDLE_CHECK_SUBTREE = (1 << 1),
> > > -};
> > > -
> > > -struct handle_to_path_ctx {
> > > - struct path root;
> > > - enum handle_to_path_flags flags;
> > > - unsigned int fh_flags;
> > > -};
> > > -
> > > static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
> > > {
> > > struct handle_to_path_ctx *ctx = context;
> > > @@ -224,7 +232,13 @@ static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
> > >
> > > if (!(ctx->flags & HANDLE_CHECK_SUBTREE) || d == root)
> > > retval = 1;
> > > - WARN_ON_ONCE(d != root && d != root->d_sb->s_root);
> > > + /*
> > > + * exportfs_decode_fh_raw() does not call acceptable() callback with
> > > + * a disconnected directory dentry, so we should have reached either
> > > + * mount fd directory or sb root.
> > > + */
> > > + if (ctx->fh_flags & EXPORT_FH_DIR_ONLY)
> > > + WARN_ON_ONCE(d != root && d != root->d_sb->s_root);
> >
> > I don't quite understand why the above change is necessary. Can you
> > explain why we need to limit this only to the case where
> > EXPORT_FH_DIR_ONLY is set?
> >
>
> With EXPORT_FH_DIR_ONLY, exportfs_decode_fh_raw() should
> only be calling acceptable() with a connected directory dentry.
>
> Until this patch, vfs_dentry_acceptable() would only be called with
> EXPORT_FH_DIR_ONLY so the WARN_ON could be unconditional.
>
> After this patch, vfs_dentry_acceptable() could also be called for
> a disconnected non-dir dentry and then it should just fail to
> accept the dentry, but should not WARN_ON.
>
> Thanks for the review!
> Amir.
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2024-09-21 5:33 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-19 14:06 [RFC PATCH 0/2] API for exporting connectable file handles to userspace Amir Goldstein
2024-09-19 14:06 ` [RFC PATCH 1/2] fs: name_to_handle_at() support for connectable file handles Amir Goldstein
2024-09-20 7:13 ` Jeff Layton
2024-09-20 7:36 ` Jeff Layton
2024-09-20 8:40 ` Amir Goldstein
2024-09-19 14:06 ` [RFC PATCH 2/2] fs: open_by_handle_at() support for decoding " Amir Goldstein
2024-09-20 16:02 ` Jeff Layton
2024-09-20 16:38 ` Amir Goldstein
2024-09-21 5:33 ` Jeff Layton [this message]
2024-09-21 9:13 ` Aleksa Sarai
2024-09-21 10:25 ` Amir Goldstein
2024-09-21 9:15 ` Aleksa Sarai
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=8aa01edea8972c1bde3b34df32f9db72e29420ed.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=cyphar@cyphar.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@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).