From: Jeff Layton <jlayton@kernel.org>
To: Amir Goldstein <amir73il@gmail.com>
Cc: Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
Aleksa Sarai <cyphar@cyphar.com>,
Chuck Lever <chuck.lever@oracle.com>,
linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org
Subject: Re: [PATCH v4 2/3] fs: name_to_handle_at() support for "explicit connectable" file handles
Date: Fri, 11 Oct 2024 10:18:23 -0400 [thread overview]
Message-ID: <5ce49036cedbf7fa78a1395ded031fe2c0935e32.camel@kernel.org> (raw)
In-Reply-To: <CAOQ4uxgO5rNpsctjdKvJyy7Li7Di4x8AaRahVk5F8_tjgx1V=A@mail.gmail.com>
On Fri, 2024-10-11 at 16:14 +0200, Amir Goldstein wrote:
> On Fri, Oct 11, 2024 at 4:00 PM Jeff Layton <jlayton@kernel.org> wrote:
> >
> > On Fri, 2024-10-11 at 11:00 +0200, Amir Goldstein wrote:
> > > nfsd encodes "connectable" file handles for the subtree_check feature,
> > > which can be resolved to an open file with a connected path.
> > > So far, userspace nfs server could not make use of this functionality.
> > >
> > > Introduce a new flag AT_HANDLE_CONNECTABLE to name_to_handle_at(2).
> > > When used, the encoded file handle is "explicitly connectable".
> > >
> > > The "explicitly connectable" file handle sets bits in the high 16bit of
> > > the handle_type field, so open_by_handle_at(2) will know that it needs
> > > to open a file with a connected path.
> > >
> > > old kernels will now recognize the handle_type with high bits set,
> > > so "explicitly connectable" file handles cannot be decoded by
> > > open_by_handle_at(2) on old kernels.
> > >
> > > The flag AT_HANDLE_CONNECTABLE is not allowed together with either
> > > AT_HANDLE_FID or AT_EMPTY_PATH.
> > >
> > > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > > ---
> > > fs/fhandle.c | 48 ++++++++++++++++++++++++++++++++++----
> > > include/linux/exportfs.h | 2 ++
> > > include/uapi/linux/fcntl.h | 1 +
> > > 3 files changed, 46 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/fs/fhandle.c b/fs/fhandle.c
> > > index 218511f38cbb..8339a1041025 100644
> > > --- a/fs/fhandle.c
> > > +++ b/fs/fhandle.c
> > > @@ -31,6 +31,14 @@ static long do_sys_name_to_handle(const struct path *path,
> > > if (!exportfs_can_encode_fh(path->dentry->d_sb->s_export_op, fh_flags))
> > > return -EOPNOTSUPP;
> > >
> > > + /*
> > > + * A request to encode a connectable handle for a disconnected dentry
> > > + * is unexpected since AT_EMPTY_PATH is not allowed.
> > > + */
> > > + if (fh_flags & EXPORT_FH_CONNECTABLE &&
> > > + WARN_ON(path->dentry->d_flags & DCACHE_DISCONNECTED))
> >
> > Is this even possible? The dentry in this case will have been reached
> > by pathwalk. Oh, but I guess the dfd could point to a disconnected
> > dentry and then you pass in AT_EMPTY_PATH.
>
> But see comment above "...is unexpected since AT_EMPTY_PATH is not allowed."
>
> and see below
>
> + * AT_EMPTY_PATH could be used along with a dfd that refers to a
> + * disconnected non-directory, which cannot be used to encode a
> + * connectable file handle, because its parent is unknown.
> + */
> + if (flag & AT_HANDLE_CONNECTABLE &&
> + flag & (AT_HANDLE_FID | AT_EMPTY_PATH))
> return -EINVAL;
>
> The code/API should not allow this also for a malicious user,
> unless I missed something, hence, the assertion.
>
Ok. If that's the case, I'm fine with this as-is then. If that ever
fires then I guess we'll know that something is wrong.
> >
> > I'm not sure we want to warn in that case though, since this is a
> > situation that an unprivileged user could be able to arrange. Maybe we
> > should just return a more distinct error code in this case?
> >
> > Since the scenario involves a dfd that is disconnected, how about:
> >
> > #define EBADFD 77 /* File descriptor in bad state */
> >
>
> To me it does not look like a good fit, but let's see what others think.
> In the end, it is a rare condition that should never happen
> (hence assert), so I don't think the error value matters that much?
>
Agreed.
> > > + return -EINVAL;
> > > +
> > > if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
> > > return -EFAULT;
> > >
> > > @@ -45,7 +53,7 @@ static long do_sys_name_to_handle(const struct path *path,
> > > /* convert handle size to multiple of sizeof(u32) */
> > > handle_dwords = f_handle.handle_bytes >> 2;
> > >
> > > - /* we ask for a non connectable maybe decodeable file handle */
> > > + /* Encode a possibly decodeable/connectable file handle */
> > > retval = exportfs_encode_fh(path->dentry,
> > > (struct fid *)handle->f_handle,
> > > &handle_dwords, fh_flags);
> > > @@ -67,8 +75,23 @@ static long do_sys_name_to_handle(const struct path *path,
> > > * non variable part of the file_handle
> > > */
> > > handle_bytes = 0;
> > > - } else
> > > + } else {
> > > + /*
> > > + * When asked to encode a connectable file handle, encode this
> > > + * property in the file handle itself, so that we later know
> > > + * how to decode it.
> > > + * For sanity, also encode in the file handle if the encoded
> > > + * object is a directory and verify this during decode, because
> > > + * decoding directory file handles is quite different than
> > > + * decoding connectable non-directory file handles.
> > > + */
> > > + if (fh_flags & EXPORT_FH_CONNECTABLE) {
> > > + handle->handle_type |= FILEID_IS_CONNECTABLE;
> > > + if (d_is_dir(path->dentry))
> > > + fh_flags |= FILEID_IS_DIR;
> > > + }
> > > retval = 0;
> > > + }
> > > /* copy the mount id */
> > > if (unique_mntid) {
> > > if (put_user(real_mount(path->mnt)->mnt_id_unique,
> > > @@ -109,15 +132,30 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
> > > {
> > > struct path path;
> > > int lookup_flags;
> > > - int fh_flags;
> > > + int fh_flags = 0;
> > > int err;
> > >
> > > if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID |
> > > - AT_HANDLE_MNT_ID_UNIQUE))
> > > + AT_HANDLE_MNT_ID_UNIQUE | AT_HANDLE_CONNECTABLE))
> > > + return -EINVAL;
> > > +
> > > + /*
> > > + * AT_HANDLE_FID means there is no intention to decode file handle
> > > + * AT_HANDLE_CONNECTABLE means there is an intention to decode a
> > > + * connected fd (with known path), so these flags are conflicting.
> > > + * AT_EMPTY_PATH could be used along with a dfd that refers to a
> > > + * disconnected non-directory, which cannot be used to encode a
> > > + * connectable file handle, because its parent is unknown.
> > > + */
> > > + if (flag & AT_HANDLE_CONNECTABLE &&
> >
> > nit: might need parenthesis around the above & check.
> >
> > > + flag & (AT_HANDLE_FID | AT_EMPTY_PATH))
>
> I don't think it is needed, but for readability I don't mind adding them.
> I am having a hard time remembering the operation precedence myself,
> but this one is clear to me so I don't bother with ().
I (lately) get warnings from the compiler with W=1 even when the
precedence is fine. If you're not seeing that then this is OK too.
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2024-10-11 14:18 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-11 9:00 [PATCH v4 0/3] API for exporting connectable file handles to userspace Amir Goldstein
2024-10-11 9:00 ` [PATCH v4 1/3] fs: prepare for "explicit connectable" file handles Amir Goldstein
2024-10-14 13:30 ` Jan Kara
2024-10-11 9:00 ` [PATCH v4 2/3] fs: name_to_handle_at() support " Amir Goldstein
2024-10-11 14:00 ` Jeff Layton
2024-10-11 14:14 ` Amir Goldstein
2024-10-11 14:18 ` Jeff Layton [this message]
2024-10-11 18:12 ` Amir Goldstein
2024-10-11 9:00 ` [PATCH v4 3/3] fs: open_by_handle_at() support for decoding " Amir Goldstein
2024-10-14 15:26 ` Jeff Layton
2024-10-11 14:04 ` [PATCH v4 0/3] API for exporting connectable file handles to userspace Jeff Layton
2024-10-11 14:24 ` Chuck Lever III
2024-10-11 18:22 ` Amir Goldstein
2024-10-11 18:40 ` Chuck Lever III
2024-10-14 8:55 ` Amir Goldstein
2024-10-14 14:52 ` Christian Brauner
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=5ce49036cedbf7fa78a1395ded031fe2c0935e32.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=jack@suse.cz \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.