diff options
| -rw-r--r-- | fs/lockd/svc.c | 1 | ||||
| -rw-r--r-- | fs/nfsd/lockd.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfsfh.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 9 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/svcauth_unix.c | 72 |
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(¤t->sig->siglock); siginitsetinv(¤t->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; } |
