Merge branch 'for-3.14' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields: - Handle some loose ends from the vfs read delegation support. (For example nfsd can stop breaking leases on its own in a fewer places where it can now depend on the vfs to.) - Make life a little easier for NFSv4-only configurations (thanks to Kinglong Mee). - Fix some gss-proxy problems (thanks Jeff Layton). - miscellaneous bug fixes and cleanup * 'for-3.14' of git://linux-nfs.org/~bfields/linux: (38 commits) nfsd: consider CLAIM_FH when handing out delegation nfsd4: fix delegation-unlink/rename race nfsd4: delay setting current_fh in open nfsd4: minor nfs4_setlease cleanup gss_krb5: use lcm from kernel lib nfsd4: decrease nfsd4_encode_fattr stack usage nfsd: fix encode_entryplus_baggage stack usage nfsd4: simplify xdr encoding of nfsv4 names nfsd4: encode_rdattr_error cleanup nfsd4: nfsd4_encode_fattr cleanup minor svcauth_gss.c cleanup nfsd4: better VERIFY comment nfsd4: break only delegations when appropriate NFSD: Fix a memory leak in nfsd4_create_session sunrpc: get rid of use_gssp_lock sunrpc: fix potential race between setting use_gss_proxy and the upcall rpc_clnt sunrpc: don't wait for write before allowing reads from use-gss-proxy file nfsd: get rid of unused function definition Define op_iattr for nfsd4_open instead using macro NFSD: fix compile warning without CONFIG_NFSD_V3 ...
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/sunrpc/gss_krb5.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/lcm.h>
|
||||
|
||||
#ifdef RPC_DEBUG
|
||||
# define RPCDBG_FACILITY RPCDBG_AUTH
|
||||
@@ -72,7 +73,7 @@
|
||||
static void krb5_nfold(u32 inbits, const u8 *in,
|
||||
u32 outbits, u8 *out)
|
||||
{
|
||||
int a, b, c, lcm;
|
||||
unsigned long ulcm;
|
||||
int byte, i, msbit;
|
||||
|
||||
/* the code below is more readable if I make these bytes
|
||||
@@ -82,17 +83,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
|
||||
outbits >>= 3;
|
||||
|
||||
/* first compute lcm(n,k) */
|
||||
|
||||
a = outbits;
|
||||
b = inbits;
|
||||
|
||||
while (b != 0) {
|
||||
c = b;
|
||||
b = a%b;
|
||||
a = c;
|
||||
}
|
||||
|
||||
lcm = outbits*inbits/a;
|
||||
ulcm = lcm(inbits, outbits);
|
||||
|
||||
/* now do the real work */
|
||||
|
||||
@@ -101,7 +92,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
|
||||
|
||||
/* this will end up cycling through k lcm(k,n)/k times, which
|
||||
is correct */
|
||||
for (i = lcm-1; i >= 0; i--) {
|
||||
for (i = ulcm-1; i >= 0; i--) {
|
||||
/* compute the msbit in k which gets added into this byte */
|
||||
msbit = (
|
||||
/* first, start with the msbit in the first,
|
||||
|
@@ -137,7 +137,6 @@ void init_gssp_clnt(struct sunrpc_net *sn)
|
||||
{
|
||||
mutex_init(&sn->gssp_lock);
|
||||
sn->gssp_clnt = NULL;
|
||||
init_waitqueue_head(&sn->gssp_wq);
|
||||
}
|
||||
|
||||
int set_gssp_clnt(struct net *net)
|
||||
@@ -154,7 +153,6 @@ int set_gssp_clnt(struct net *net)
|
||||
sn->gssp_clnt = clnt;
|
||||
}
|
||||
mutex_unlock(&sn->gssp_lock);
|
||||
wake_up(&sn->gssp_wq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -1263,66 +1263,35 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_SPINLOCK(use_gssp_lock);
|
||||
/*
|
||||
* 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;
|
||||
|
||||
WARN_ON_ONCE(type != 0 && type != 1);
|
||||
ret = cmpxchg(&sn->use_gss_proxy, -1, type);
|
||||
if (ret != -1 && ret != type)
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
/* 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 int set_gss_proxy(struct net *net, int type)
|
||||
{
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int wait_for_gss_proxy(struct net *net, struct file *file)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
@@ -1626,8 +1591,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 +1599,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;
|
||||
|
Reference in New Issue
Block a user