summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/svc.c1
-rw-r--r--fs/nfsd/lockd.c8
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/nfssvc.c9
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--include/linux/sunrpc/svc.h1
-rw-r--r--net/sunrpc/svcauth_unix.c72
7 files changed, 77 insertions, 18 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index cfef0f0feff8..1f515cfb294b 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -389,5 +389,6 @@ struct svc_program nlmsvc_program = {
.pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
.pg_vers = nlmsvc_version, /* version table */
.pg_name = "lockd", /* service name */
+ .pg_class = "nfsd", /* share authentication with nfsd */
.pg_stats = &nlmsvc_stats, /* stats table */
};
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index a3f9df90d9f2..5da1ed2e8ccd 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -32,18 +32,12 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
fh.fh_export = NULL;
exp_readlock();
- rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
- if (rqstp->rq_client == NULL)
- nfserr = nfserr_stale;
- else
- nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
+ nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
if (!nfserr) {
dget(filp->f_dentry);
mntget(filp->f_vfsmnt);
}
fh_put(&fh);
- if (rqstp->rq_client)
- auth_domain_put(rqstp->rq_client);
rqstp->rq_client = NULL;
exp_readunlock();
/* nlm and nfsd don't share error codes.
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 70d84e36fadc..d3f021582efd 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -103,6 +103,8 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
int data_left = fh->fh_size/4;
error = nfserr_stale;
+ if (rqstp->rq_client == NULL)
+ goto out;
if (rqstp->rq_vers > 2)
error = nfserr_badhandle;
if (rqstp->rq_vers == 4 && fh->fh_size == 0)
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 65f455e529ba..1044a94d69ae 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -206,10 +206,6 @@ nfsd(struct svc_rqst *rqstp)
/* Lock the export hash tables for reading. */
exp_readlock();
- /* Validate the client's address. This will also defeat
- * port probes on port 2049 by unauthorized clients.
- */
- rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
/* Process request with signals blocked. */
spin_lock_irq(&current->sig->siglock);
siginitsetinv(&current->blocked, ALLOWED_SIGS);
@@ -219,10 +215,6 @@ nfsd(struct svc_rqst *rqstp)
svc_process(serv, rqstp);
/* Unlock export hash tables */
- if (rqstp->rq_client) {
- auth_domain_put(rqstp->rq_client);
- rqstp->rq_client = NULL;
- }
exp_readunlock();
update_thread_usage(atomic_read(&nfsd_busy));
atomic_dec(&nfsd_busy);
@@ -369,5 +361,6 @@ struct svc_program nfsd_program = {
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
.pg_vers = nfsd_version, /* version table */
.pg_name = "nfsd", /* program name */
+ .pg_class = "nfsd", /* authentication class */
.pg_stats = &nfsd_svcstats, /* version table */
};
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 61c7bd03d3f0..7069a472a095 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -154,7 +154,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
struct dentry *mounts = dget(dentry);
while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
;
- exp2 = exp_get_by_name(rqstp->rq_client, mnt, mounts);
+ exp2 = exp_get_by_name(exp->ex_client, mnt, mounts);
if (exp2 && EX_CROSSMNT(exp2)) {
/* successfully crossed mount point */
exp = exp2;
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 57c5a49d2b0a..95e6b8d20fd1 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -142,6 +142,7 @@ struct svc_program {
unsigned int pg_nvers; /* number of versions */
struct svc_version ** pg_vers; /* version array */
char * pg_name; /* service name */
+ char * pg_class; /* class name: services sharing authentication */
struct svc_stat * pg_stats; /* rpc statistics */
};
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index c5e7e20c44c4..ce13795dcbcb 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -201,6 +201,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
{
struct svc_buf *argp = &rqstp->rq_argbuf;
struct svc_buf *resp = &rqstp->rq_resbuf;
+ int rv=0;
+ struct ip_map key, *ipm;
if ((argp->len -= 3) < 0) {
return SVC_GARBAGE;
@@ -224,12 +226,45 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
/* Put NULL verifier */
svc_putu32(resp, RPC_AUTH_NULL);
svc_putu32(resp, 0);
- return SVC_OK;
+
+ key.m_class = rqstp->rq_server->sv_program->pg_class;
+ key.m_addr = rqstp->rq_addr.sin_addr;
+
+ ipm = ip_map_lookup(&key, 0);
+
+ rqstp->rq_client = NULL;
+
+ if (ipm)
+ switch (cache_check(&ip_map_cache, &ipm->h)) {
+ case -EAGAIN:
+ rv = SVC_DROP;
+ break;
+ case -ENOENT:
+ rv = SVC_OK; /* rq_client is NULL */
+ break;
+ case 0:
+ rqstp->rq_client = &ipm->m_client->h;
+ cache_get(&rqstp->rq_client->h);
+ ip_map_put(&ipm->h, &ip_map_cache);
+ rv = SVC_OK;
+ break;
+ default: BUG();
+ }
+ else rv = SVC_DROP;
+
+ if (rqstp->rq_client == NULL && proc != 0)
+ *authp = rpc_autherr_badcred;
+
+ return rv;
}
static int
svcauth_null_release(struct svc_rqst *rqstp)
{
+ if (rqstp->rq_client)
+ auth_domain_put(rqstp->rq_client);
+ rqstp->rq_client = NULL;
+
return 0; /* don't drop */
}
@@ -250,6 +285,8 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
struct svc_cred *cred = &rqstp->rq_cred;
u32 *bufp = argp->buf, slen, i;
int len = argp->len;
+ int rv=0;
+ struct ip_map key, *ipm;
if ((len -= 3) < 0)
return SVC_GARBAGE;
@@ -285,7 +322,34 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
svc_putu32(resp, RPC_AUTH_NULL);
svc_putu32(resp, 0);
- return SVC_OK;
+ key.m_class = rqstp->rq_server->sv_program->pg_class;
+ key.m_addr = rqstp->rq_addr.sin_addr;
+
+ ipm = ip_map_lookup(&key, 0);
+
+ rqstp->rq_client = NULL;
+
+ if (ipm)
+ switch (cache_check(&ip_map_cache, &ipm->h)) {
+ case -EAGAIN:
+ rv = SVC_DROP;
+ break;
+ case -ENOENT:
+ rv = SVC_OK; /* rq_client is NULL */
+ break;
+ case 0:
+ rqstp->rq_client = &ipm->m_client->h;
+ cache_get(&rqstp->rq_client->h);
+ ip_map_put(&ipm->h, &ip_map_cache);
+ rv = SVC_OK;
+ break;
+ default: BUG();
+ }
+ else rv = SVC_DROP;
+
+ if (rqstp->rq_client == NULL && proc != 0)
+ goto badcred;
+ return rv;
badcred:
*authp = rpc_autherr_badcred;
@@ -297,6 +361,10 @@ svcauth_unix_release(struct svc_rqst *rqstp)
{
/* Verifier (such as it is) is already in place.
*/
+ if (rqstp->rq_client)
+ auth_domain_put(rqstp->rq_client);
+ rqstp->rq_client = NULL;
+
return 0;
}