Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1db77221 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-3.10' of git://linux-nfs.org/~bfields/linux

Pull nfsd changes from J Bruce Fields:
 "Highlights include:

   - Some more DRC cleanup and performance work from Jeff Layton

   - A gss-proxy upcall from Simo Sorce: currently krb5 mounts to the
     server using credentials from Active Directory often fail due to
     limitations of the svcgssd upcall interface.  This replacement
     lifts those limitations.  The existing upcall is still supported
     for backwards compatibility.

   - More NFSv4.1 support: at this point, if a user with a current
     client who upgrades from 4.0 to 4.1 should see no regressions.  In
     theory we do everything a 4.1 server is required to do.  Patches
     for a couple minor exceptions are ready for 3.11, and with those
     and some more testing I'd like to turn 4.1 on by default in 3.11."

Fix up semantic conflict as per Stephen Rothwell and linux-next:

Commit 030d794b ("SUNRPC: Use gssproxy upcall for server RPCGSS
authentication") adds two new users of "PDE(inode)->data", but we're
supposed to use "PDE_DATA(inode)" instead since commit d9dda78b
("procfs: new helper - PDE_DATA(inode)").

The old PDE() macro is no longer available since commit c30480b9
("proc: Make the PROC_I() and PDE() macros internal to procfs")

* 'for-3.10' of git://linux-nfs.org/~bfields/linux: (60 commits)
  NFSD: SECINFO doesn't handle unsupported pseudoflavors correctly
  NFSD: Simplify GSS flavor encoding in nfsd4_do_encode_secinfo()
  nfsd: make symbol nfsd_reply_cache_shrinker static
  svcauth_gss: fix error return code in rsc_parse()
  nfsd4: don't remap EISDIR errors in rename
  svcrpc: fix gss-proxy to respect user namespaces
  SUNRPC: gssp_procedures[] can be static
  SUNRPC: define {create,destroy}_use_gss_proxy_proc_entry in !PROC case
  nfsd4: better error return to indicate SSV non-support
  nfsd: fix EXDEV checking in rename
  SUNRPC: Use gssproxy upcall for server RPCGSS authentication.
  SUNRPC: Add RPC based upcall mechanism for RPCGSS auth
  SUNRPC: conditionally return endtime from import_sec_context
  SUNRPC: allow disabling idle timeout
  SUNRPC: attempt AF_LOCAL connect on setup
  nfsd: Decode and send 64bit time values
  nfsd4: put_client_renew_locked can be static
  nfsd4: remove unused macro
  nfsd4: remove some useless code
  nfsd4: implement SEQ4_STATUS_RECALLABLE_STATE_REVOKED
  ...
parents 86652188 676e4ebd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -20,3 +20,5 @@ rpc-cache.txt
	- introduction to the caching mechanisms in the sunrpc layer.
idmapper.txt
	- information for configuring request-keys to be used by idmapper
knfsd-rpcgss.txt
	- Information on GSS authentication support in the NFS Server
+91 −0
Original line number Diff line number Diff line

rpcsec_gss support for kernel RPC servers
=========================================

This document gives references to the standards and protocols used to
implement RPCGSS authentication in kernel RPC servers such as the NFS
server and the NFS client's NFSv4.0 callback server.  (But note that
NFSv4.1 and higher don't require the client to act as a server for the
purposes of authentication.)

RPCGSS is specified in a few IETF documents:
 - RFC2203 v1: http://tools.ietf.org/rfc/rfc2203.txt
 - RFC5403 v2: http://tools.ietf.org/rfc/rfc5403.txt
and there is a 3rd version  being proposed:
 - http://tools.ietf.org/id/draft-williams-rpcsecgssv3.txt
   (At draft n. 02 at the time of writing)

Background
----------

The RPCGSS Authentication method describes a way to perform GSSAPI
Authentication for NFS.  Although GSSAPI is itself completely mechanism
agnostic, in many cases only the KRB5 mechanism is supported by NFS
implementations.

The Linux kernel, at the moment, supports only the KRB5 mechanism, and
depends on GSSAPI extensions that are KRB5 specific.

GSSAPI is a complex library, and implementing it completely in kernel is
unwarranted. However GSSAPI operations are fundementally separable in 2
parts:
- initial context establishment
- integrity/privacy protection (signing and encrypting of individual
  packets)

The former is more complex and policy-independent, but less
performance-sensitive.  The latter is simpler and needs to be very fast.

Therefore, we perform per-packet integrity and privacy protection in the
kernel, but leave the initial context establishment to userspace.  We
need upcalls to request userspace to perform context establishment.

NFS Server Legacy Upcall Mechanism
----------------------------------

The classic upcall mechanism uses a custom text based upcall mechanism
to talk to a custom daemon called rpc.svcgssd that is provide by the
nfs-utils package.

This upcall mechanism has 2 limitations:

A) It can handle tokens that are no bigger than 2KiB

In some Kerberos deployment GSSAPI tokens can be quite big, up and
beyond 64KiB in size due to various authorization extensions attacked to
the Kerberos tickets, that needs to be sent through the GSS layer in
order to perform context establishment.

B) It does not properly handle creds where the user is member of more
than a few housand groups (the current hard limit in the kernel is 65K
groups) due to limitation on the size of the buffer that can be send
back to the kernel (4KiB).

NFS Server New RPC Upcall Mechanism
-----------------------------------

The newer upcall mechanism uses RPC over a unix socket to a daemon
called gss-proxy, implemented by a userspace program called Gssproxy.

The gss_proxy RPC protocol is currently documented here:

	https://fedorahosted.org/gss-proxy/wiki/ProtocolDocumentation

This upcall mechanism uses the kernel rpc client and connects to the gssproxy
userspace program over a regular unix socket. The gssproxy protocol does not
suffer from the size limitations of the legacy protocol.

Negotiating Upcall Mechanisms
-----------------------------

To provide backward compatibility, the kernel defaults to using the
legacy mechanism.  To switch to the new mechanism, gss-proxy must bind
to /var/run/gssproxy.sock and then write "1" to
/proc/net/rpc/use-gss-proxy.  If gss-proxy dies, it must repeat both
steps.

Once the upcall mechanism is chosen, it cannot be changed.  To prevent
locking into the legacy mechanisms, the above steps must be performed
before starting nfsd.  Whoever starts nfsd can guarantee this by reading
from /proc/net/rpc/use-gss-proxy and checking that it contains a
"1"--the read will block until gss-proxy has done its write to the file.
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ int nfsd_reply_cache_init(void);
void	nfsd_reply_cache_shutdown(void);
int	nfsd_cache_lookup(struct svc_rqst *);
void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
int	nfsd_reply_cache_stats_open(struct inode *, struct file *);

#ifdef CONFIG_NFSD_V4
void	nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp);
+1 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ struct nfsd_net {
	 */
	struct list_head client_lru;
	struct list_head close_lru;
	struct list_head del_recall_lru;

	struct delayed_work laundromat_work;

+4 −29
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "nfsd.h"
#include "state.h"
#include "netns.h"
#include "xdr4cb.h"

#define NFSDDBG_FACILITY                NFSDDBG_PROC

@@ -53,30 +54,6 @@ enum {
	NFSPROC4_CLNT_CB_SEQUENCE,
};

#define NFS4_MAXTAGLEN		20

#define NFS4_enc_cb_null_sz		0
#define NFS4_dec_cb_null_sz		0
#define cb_compound_enc_hdr_sz		4
#define cb_compound_dec_hdr_sz		(3 + (NFS4_MAXTAGLEN >> 2))
#define sessionid_sz			(NFS4_MAX_SESSIONID_LEN >> 2)
#define cb_sequence_enc_sz		(sessionid_sz + 4 +             \
					1 /* no referring calls list yet */)
#define cb_sequence_dec_sz		(op_dec_sz + sessionid_sz + 4)

#define op_enc_sz			1
#define op_dec_sz			2
#define enc_nfs4_fh_sz			(1 + (NFS4_FHSIZE >> 2))
#define enc_stateid_sz			(NFS4_STATEID_SIZE >> 2)
#define NFS4_enc_cb_recall_sz		(cb_compound_enc_hdr_sz +       \
					cb_sequence_enc_sz +            \
					1 + enc_stateid_sz +            \
					enc_nfs4_fh_sz)

#define NFS4_dec_cb_recall_sz		(cb_compound_dec_hdr_sz  +      \
					cb_sequence_dec_sz +            \
					op_dec_sz)

struct nfs4_cb_compound_hdr {
	/* args */
	u32		ident;	/* minorversion 0 only */
@@ -817,8 +794,7 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
{
	struct nfsd4_callback *cb = calldata;
	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
	struct nfs4_client *clp = dp->dl_stid.sc_client;
	struct nfs4_client *clp = cb->cb_clp;
	u32 minorversion = clp->cl_minorversion;

	cb->cb_minorversion = minorversion;
@@ -839,8 +815,7 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
{
	struct nfsd4_callback *cb = calldata;
	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
	struct nfs4_client *clp = dp->dl_stid.sc_client;
	struct nfs4_client *clp = cb->cb_clp;

	dprintk("%s: minorversion=%d\n", __func__,
		clp->cl_minorversion);
@@ -863,7 +838,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
{
	struct nfsd4_callback *cb = calldata;
	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
	struct nfs4_client *clp = dp->dl_stid.sc_client;
	struct nfs4_client *clp = cb->cb_clp;
	struct rpc_clnt *current_rpc_client = clp->cl_cb_client;

	nfsd4_cb_done(task, calldata);
Loading