diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-10 09:28:55 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-10 09:28:55 -0700 | 
| commit | 2dbd3cac87250a0d44e07acc86c4224a08522709 (patch) | |
| tree | 4f31fdf50bfe64616aca1c4e2405930fd5b15e84 | |
| parent | a77c005887a6d6f318117176791efa0ef7fcca80 (diff) | |
| parent | 7255e716b1757dc10fa5e3a4d2eaab303ff9f7b6 (diff) | |
| download | olio-linux-3.10-2dbd3cac87250a0d44e07acc86c4224a08522709.tar.xz olio-linux-3.10-2dbd3cac87250a0d44e07acc86c4224a08522709.zip  | |
Merge branch 'for-3.10' of git://linux-nfs.org/~bfields/linux
Pull nfsd fixes from Bruce Fields:
 "Small fixes for two bugs and two warnings"
* 'for-3.10' of git://linux-nfs.org/~bfields/linux:
  nfsd: fix oops when legacy_recdir_name_error is passed a -ENOENT error
  SUNRPC: fix decoding of optional gss-proxy xdr fields
  SUNRPC: Refactor gssx_dec_option_array() to kill uninitialized warning
  nfsd4: don't allow owner override on 4.1 CLAIM_FH opens
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 15 | ||||
| -rw-r--r-- | fs/nfsd/nfs4recover.c | 12 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.c | 58 | 
3 files changed, 48 insertions, 37 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 8ae5abfe6ba..27d74a29451 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -279,6 +279,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str  {  	struct svc_fh *current_fh = &cstate->current_fh;  	__be32 status; +	int accmode = 0;  	/* We don't know the target directory, and therefore can not  	* set the change info @@ -290,9 +291,19 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str  	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&  		(open->op_iattr.ia_size == 0); +	/* +	 * In the delegation case, the client is telling us about an +	 * open that it *already* performed locally, some time ago.  We +	 * should let it succeed now if possible. +	 * +	 * In the case of a CLAIM_FH open, on the other hand, the client +	 * may be counting on us to enforce permissions (the Linux 4.1 +	 * client uses this for normal opens, for example). +	 */ +	if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH) +		accmode = NFSD_MAY_OWNER_OVERRIDE; -	status = do_open_permission(rqstp, current_fh, open, -				    NFSD_MAY_OWNER_OVERRIDE); +	status = do_open_permission(rqstp, current_fh, open, accmode);  	return status;  } diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 899ca26dd19..4e9a21db867 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -146,7 +146,7 @@ out_no_tfm:   * then disable recovery tracking.   */  static void -legacy_recdir_name_error(int error) +legacy_recdir_name_error(struct nfs4_client *clp, int error)  {  	printk(KERN_ERR "NFSD: unable to generate recoverydir "  			"name (%d).\n", error); @@ -159,9 +159,7 @@ legacy_recdir_name_error(int error)  	if (error == -ENOENT) {  		printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "  			"Reboot recovery will not function correctly!\n"); - -		/* the argument is ignored by the legacy exit function */ -		nfsd4_client_tracking_exit(NULL); +		nfsd4_client_tracking_exit(clp->net);  	}  } @@ -184,7 +182,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)  	status = nfs4_make_rec_clidname(dname, &clp->cl_name);  	if (status) -		return legacy_recdir_name_error(status); +		return legacy_recdir_name_error(clp, status);  	status = nfs4_save_creds(&original_cred);  	if (status < 0) @@ -341,7 +339,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)  	status = nfs4_make_rec_clidname(dname, &clp->cl_name);  	if (status) -		return legacy_recdir_name_error(status); +		return legacy_recdir_name_error(clp, status);  	status = mnt_want_write_file(nn->rec_file);  	if (status) @@ -601,7 +599,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)  	status = nfs4_make_rec_clidname(dname, &clp->cl_name);  	if (status) { -		legacy_recdir_name_error(status); +		legacy_recdir_name_error(clp, status);  		return status;  	} diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 5c4c61d527e..357f613df7f 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c @@ -21,16 +21,6 @@  #include <linux/sunrpc/svcauth.h>  #include "gss_rpc_xdr.h" -static bool gssx_check_pointer(struct xdr_stream *xdr) -{ -	__be32 *p; - -	p = xdr_reserve_space(xdr, 4); -	if (unlikely(p == NULL)) -		return -ENOSPC; -	return *p?true:false; -} -  static int gssx_enc_bool(struct xdr_stream *xdr, int v)  {  	__be32 *p; @@ -264,25 +254,27 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,  	if (unlikely(p == NULL))  		return -ENOSPC;  	count = be32_to_cpup(p++); -	if (count != 0) { -		/* we recognize only 1 currently: CREDS_VALUE */ -		oa->count = 1; +	if (!count) +		return 0; -		oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); -		if (!oa->data) -			return -ENOMEM; +	/* we recognize only 1 currently: CREDS_VALUE */ +	oa->count = 1; -		creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); -		if (!creds) { -			kfree(oa->data); -			return -ENOMEM; -		} +	oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); +	if (!oa->data) +		return -ENOMEM; -		oa->data[0].option.data = CREDS_VALUE; -		oa->data[0].option.len = sizeof(CREDS_VALUE); -		oa->data[0].value.data = (void *)creds; -		oa->data[0].value.len = 0; +	creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); +	if (!creds) { +		kfree(oa->data); +		return -ENOMEM;  	} + +	oa->data[0].option.data = CREDS_VALUE; +	oa->data[0].option.len = sizeof(CREDS_VALUE); +	oa->data[0].value.data = (void *)creds; +	oa->data[0].value.len = 0; +  	for (i = 0; i < count; i++) {  		gssx_buffer dummy = { 0, NULL };  		u32 length; @@ -800,6 +792,7 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,  				struct xdr_stream *xdr,  				struct gssx_res_accept_sec_context *res)  { +	u32 value_follows;  	int err;  	/* res->status */ @@ -808,7 +801,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,  		return err;  	/* res->context_handle */ -	if (gssx_check_pointer(xdr)) { +	err = gssx_dec_bool(xdr, &value_follows); +	if (err) +		return err; +	if (value_follows) {  		err = gssx_dec_ctx(xdr, res->context_handle);  		if (err)  			return err; @@ -817,7 +813,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,  	}  	/* res->output_token */ -	if (gssx_check_pointer(xdr)) { +	err = gssx_dec_bool(xdr, &value_follows); +	if (err) +		return err; +	if (value_follows) {  		err = gssx_dec_buffer(xdr, res->output_token);  		if (err)  			return err; @@ -826,7 +825,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,  	}  	/* res->delegated_cred_handle */ -	if (gssx_check_pointer(xdr)) { +	err = gssx_dec_bool(xdr, &value_follows); +	if (err) +		return err; +	if (value_follows) {  		/* we do not support upcall servers sending this data. */  		return -EINVAL;  	}  |