diff options
Diffstat (limited to 'net/sunrpc/auth_gss/svcauth_gss.c')
| -rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 88 | 
1 files changed, 26 insertions, 62 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 09fb638bcaa..4ce5eccec1f 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1167,8 +1167,8 @@ static int gss_proxy_save_rsc(struct cache_detail *cd,  	if (!ud->found_creds) {  		/* userspace seem buggy, we should always get at least a  		 * mapping to nobody */ -		dprintk("RPC:       No creds found, marking Negative!\n"); -		set_bit(CACHE_NEGATIVE, &rsci.h.flags); +		dprintk("RPC:       No creds found!\n"); +		goto out;  	} else {  		/* steal creds */ @@ -1263,65 +1263,34 @@ out:  	return ret;  } -DEFINE_SPINLOCK(use_gssp_lock); - -static bool use_gss_proxy(struct net *net) -{ -	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); - -	if (sn->use_gss_proxy != -1) -		return sn->use_gss_proxy; -	spin_lock(&use_gssp_lock); -	/* -	 * If you wanted gss-proxy, you should have said so before -	 * starting to accept requests: -	 */ -	sn->use_gss_proxy = 0; -	spin_unlock(&use_gssp_lock); -	return 0; -} - -#ifdef CONFIG_PROC_FS - +/* + * Try to set the sn->use_gss_proxy variable to a new value. We only allow + * it to be changed if it's currently undefined (-1). If it's any other value + * then return -EBUSY unless the type wouldn't have changed anyway. + */  static int set_gss_proxy(struct net *net, int type)  {  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); -	int ret = 0; +	int ret;  	WARN_ON_ONCE(type != 0 && type != 1); -	spin_lock(&use_gssp_lock); -	if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type) -		sn->use_gss_proxy = type; -	else -		ret = -EBUSY; -	spin_unlock(&use_gssp_lock); -	wake_up(&sn->gssp_wq); -	return ret; -} - -static inline bool gssp_ready(struct sunrpc_net *sn) -{ -	switch (sn->use_gss_proxy) { -		case -1: -			return false; -		case 0: -			return true; -		case 1: -			return sn->gssp_clnt; -	} -	WARN_ON_ONCE(1); -	return false; +	ret = cmpxchg(&sn->use_gss_proxy, -1, type); +	if (ret != -1 && ret != type) +		return -EBUSY; +	return 0;  } -static int wait_for_gss_proxy(struct net *net, struct file *file) +static bool use_gss_proxy(struct net *net)  {  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); -	if (file->f_flags & O_NONBLOCK && !gssp_ready(sn)) -		return -EAGAIN; -	return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); +	/* If use_gss_proxy is still undefined, then try to disable it */ +	if (sn->use_gss_proxy == -1) +		set_gss_proxy(net, 0); +	return sn->use_gss_proxy;  } +#ifdef CONFIG_PROC_FS  static ssize_t write_gssp(struct file *file, const char __user *buf,  			 size_t count, loff_t *ppos) @@ -1342,10 +1311,10 @@ static ssize_t write_gssp(struct file *file, const char __user *buf,  		return res;  	if (i != 1)  		return -EINVAL; -	res = set_gss_proxy(net, 1); +	res = set_gssp_clnt(net);  	if (res)  		return res; -	res = set_gssp_clnt(net); +	res = set_gss_proxy(net, 1);  	if (res)  		return res;  	return count; @@ -1355,16 +1324,12 @@ static ssize_t read_gssp(struct file *file, char __user *buf,  			 size_t count, loff_t *ppos)  {  	struct net *net = PDE_DATA(file_inode(file)); +	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);  	unsigned long p = *ppos;  	char tbuf[10];  	size_t len; -	int ret; -	ret = wait_for_gss_proxy(net, file); -	if (ret) -		return ret; - -	snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net)); +	snprintf(tbuf, sizeof(tbuf), "%d\n", sn->use_gss_proxy);  	len = strlen(tbuf);  	if (p >= len)  		return 0; @@ -1538,6 +1503,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)  			if (unwrap_integ_data(rqstp, &rqstp->rq_arg,  					gc->gc_seq, rsci->mechctx))  				goto garbage_args; +			rqstp->rq_auth_slack = RPC_MAX_AUTH_SIZE;  			break;  		case RPC_GSS_SVC_PRIVACY:  			/* placeholders for length and seq. number: */ @@ -1546,6 +1512,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)  			if (unwrap_priv_data(rqstp, &rqstp->rq_arg,  					gc->gc_seq, rsci->mechctx))  				goto garbage_args; +			rqstp->rq_auth_slack = RPC_MAX_AUTH_SIZE * 2;  			break;  		default:  			goto auth_err; @@ -1626,8 +1593,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)  	BUG_ON(integ_len % 4);  	*p++ = htonl(integ_len);  	*p++ = htonl(gc->gc_seq); -	if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, -				integ_len)) +	if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len))  		BUG();  	if (resbuf->tail[0].iov_base == NULL) {  		if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) @@ -1635,10 +1601,8 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)  		resbuf->tail[0].iov_base = resbuf->head[0].iov_base  						+ resbuf->head[0].iov_len;  		resbuf->tail[0].iov_len = 0; -		resv = &resbuf->tail[0]; -	} else { -		resv = &resbuf->tail[0];  	} +	resv = &resbuf->tail[0];  	mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;  	if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))  		goto out_err;  | 
