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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox