From: Mike Snitzer <snitzer@kernel.org>
To: NeilBrown <neilb@suse.de>
Cc: Jeff Layton <jlayton@kernel.org>,
Chuck Lever <chuck.lever@oracle.com>,
Anna Schumaker <anna@kernel.org>,
Trond Myklebust <trondmy@hammerspace.com>,
Christoph Hellwig <hch@infradead.org>,
linux-nfs@vger.kernel.org
Subject: Re: Security issue in NFS localio
Date: Thu, 4 Jul 2024 00:31:58 -0400 [thread overview]
Message-ID: <ZoYlvk7LnhyUCYU1@kernel.org> (raw)
In-Reply-To: <172004548435.16071.5145237815071160040@noble.neil.brown.name>
On Thu, Jul 04, 2024 at 08:24:44AM +1000, NeilBrown wrote:
>
> I've been pondering security questions with localio - particularly
> wondering what questions I need to ask. I've found three focal points
> which overlap but help me organise my thoughts:
> 1- the LOCALIO RPC protocol
> 2- the 'auth_domain' that nfsd uses to authorise access
> 3- the credential that is used to access the file
I'm missing some details that are critical to giving your hypothetical
attack vector teeth. But I do think no matter what we need to be
precise with documenting localio's security in localio.rst.
> 1/ It occurs to me that I could find out the UUID reported by a given
> local server (just ask it over the RPC connection), find out the
> filehandle for some file that I don't have write access to (not too
> hard), and create a private NFS server (hacking nfs-ganasha?) which
> reports the same uuid and reports that I have access to a file with
> that filehandle. If I then mount from that server inside a private
> container on the same host that is running the local server, I would get
> localio access to the target file.
Even if nfs-ganasha were modified to allow the nfs client's
nfs_init_localioclient() to establish access to the 'struct net'
associated with the knfsd (rpc_bind_new_program -> GETUUID ->
nfsd_uuid_is_local): what does that _really_ give the nfs client?
The nfs client still needs to call into nfsd with nfsd_open_local_fh()
which requires rpc_clnt->cl_auth to allow access to the server's
files.
In an earlier email Chuck asked why localio's svcauth_unix_set_client()
would ever fail, and he correctly answered his question with:
"Wouldn't it only be because the local application is trying to open a
file it doesn't have permission to?"
Yes, if a client never actually negotiated with the NFS server that
provides access to protected files, then the client must not be
granted access. _This_ is why having a "fake" svc_rqst is important.
[Also "fake" isn't a great name considering it is still meant to
enforce required established NFS credentials.]
> I might not be able to write to it because of credential checking, but I
> think that is getting a lot closer to unauthorised access than I would
> like.
Kind of hand-wavy on the finale... but I'm also relieved ;)
That said, I appreciate the desire to avoid the "fake" svc_rqst based
access control. So I still agree it is worthwhile to carry your
nfsd_file_acquire_local() series through to completion.
> I would much prefer it if there was no credible way to subvert the
> LOCALIO protocol.
>
> My current idea goes like this:
> - NFS client tells nfs_common it is going to probe for localio
> and gets back a nonce. nfs_common records that this probe is happening
> - NFS client sends the nonce to the server over LOCALIO.
> - server tells nfs_common "I just got this nonce - does it mean
> anything?". If it does, the server gets connected with the client
> through nfs_common. The server reports success over LOCALIO.
> If it doesn't the server reports failure of LOCALIO.
> - NFS client gets the reply and tells nfs_common that it has a reply
> so the nonce is invalidated. If the reply was success and nfs_local
> confirms there is a connection, then the two stay connected.
> I think that having a nonce (single-use uuid) is better than using the
> same uuid for the life of the server, and I think that sending it
> proactively by client rather than reactively by the server is also
> safer.
Inverting and tweaking the localio protocol like this is clever, but
it still strikes me as unnecessary (given above).
Having it be less widely accessible is a good idea in general though.
> 2/ The localio access should use exactly the same auth_domain as the
> network access uses. This ensure the credentials implied by
> rootsquash and allsquash are used correctly. I think the current
> code has the client guessing what IP address the server will see and
> finding an auth_domain based on that. I'm not comfortable with that.
nfsd_local_fakerqst_create() isn't guessing. rpc_peeraddr() returns the
IP address of the server because the rpc_clnt is the same as
established for traditional network access.
> In the new LOCALIO protocol I suggest above, the server registers
> with nfs_common at the moment it receives an RPC request. At that
> moment it knows the characteristics of the connection - remote IP?
> krb5? tls? - and can determine an auth_domain and give it to
> nfs_common and so make it available to the client.
>
> Jeff wondered about an export option to explicitly enable LOCALIO. I
> had wondered about that too. But I think that if we firmly tie the
> localio auth_domain to the connection as above, that shouldn't be needed.
I do have concerns that your approach to use "exactly the same
auth_domain" isn't so much better than what the current localio code
does. But I'll concede it sounds better than the hackish "fake"
svc_rqst based security of the current localio code.
Worth doing just to see how it all shakes out in benchmarks, and on a
"better approach" level, but I do currently have "speed kills" concerns.
> 3/ The current code uses the 'struct cred' of the application to look up
> the file in the server code. When a request goes over the wire the
> credential is translated to uid/gid (or krb identity) and this is
> mapped back to a credential on the server which might be in a
> different uid name space (might it? Does that even work for nfsd?)
>
> I think that if rootsquash or allsquash is in effect the correct
> server-side credential is used but otherwise the client-side
> credential is used. That is likely correct in many cases but I'd
> like to be convinced that it is correct in all case. Maybe it is
> time to get a deeper understanding of uid name spaces.
You just made me feel slightly better about not knowing enough about
user namespaces.
> Have I missed anything? Any other thoughts?
Here is the branch again that I'd like to use as a base for continued
_incremental_ localio development (make code evolution clearer, if you
want to rip and replace code, just remove in a separate commit.. I
can rebase to cleanup when the dust settles):
https://git.kernel.org/pub/scm/linux/kernel/git/snitzer/linux.git/log/?h=nfs-localio-for-next
Thanks for spending time on all of this localio stuff!
It's now 4th of July for me, so I'm with Jeff: I need a drink! ;)
Mike
next prev parent reply other threads:[~2024-07-04 4:32 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-03 22:24 Security issue in NFS localio NeilBrown
2024-07-03 23:35 ` Jeff Layton
2024-07-04 4:31 ` Mike Snitzer [this message]
2024-07-05 21:39 ` NeilBrown
2024-07-04 5:45 ` Christoph Hellwig
2024-07-04 19:00 ` Chuck Lever III
2024-07-04 23:25 ` Dave Chinner
2024-07-05 1:42 ` Mike Snitzer
2024-07-05 21:51 ` NeilBrown
2024-07-05 13:45 ` Christoph Hellwig
2024-07-05 13:50 ` Chuck Lever III
2024-07-05 21:56 ` NeilBrown
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=ZoYlvk7LnhyUCYU1@kernel.org \
--to=snitzer@kernel.org \
--cc=anna@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=hch@infradead.org \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@suse.de \
--cc=trondmy@hammerspace.com \
/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.