diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 11 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 31 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 2 | ||||
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 5 |
4 files changed, 28 insertions, 21 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 700353b330fd..066c64a97fd8 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -804,19 +804,19 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) integ_len = svc_getnl(&buf->head[0]); if (integ_len & 3) - goto out; + return stat; if (integ_len > buf->len) - goto out; + return stat; if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len)) BUG(); /* copy out mic... */ if (read_u32_from_xdr_buf(buf, integ_len, &mic.len)) BUG(); if (mic.len > RPC_MAX_AUTH_SIZE) - goto out; + return stat; mic.data = kmalloc(mic.len, GFP_KERNEL); if (!mic.data) - goto out; + return stat; if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len)) goto out; maj_stat = gss_verify_mic(ctx, &integ_buf, &mic); @@ -826,6 +826,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) goto out; stat = 0; out: + kfree(mic.data); return stat; } @@ -1065,7 +1066,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) } switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { case -EAGAIN: - goto drop; + case -ETIMEDOUT: case -ENOENT: goto drop; case 0: diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 80aff0474572..14274490f92e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -34,7 +34,7 @@ #define RPCDBG_FACILITY RPCDBG_CACHE -static void cache_defer_req(struct cache_req *req, struct cache_head *item); +static int cache_defer_req(struct cache_req *req, struct cache_head *item); static void cache_revisit_request(struct cache_head *item); static void cache_init(struct cache_head *h) @@ -185,6 +185,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); * * Returns 0 if the cache_head can be used, or cache_puts it and returns * -EAGAIN if upcall is pending, + * -ETIMEDOUT if upcall failed and should be retried, * -ENOENT if cache entry was negative */ int cache_check(struct cache_detail *detail, @@ -236,7 +237,8 @@ int cache_check(struct cache_detail *detail, } if (rv == -EAGAIN) - cache_defer_req(rqstp, h); + if (cache_defer_req(rqstp, h) != 0) + rv = -ETIMEDOUT; if (rv) cache_put(h, detail); @@ -523,14 +525,21 @@ static LIST_HEAD(cache_defer_list); static struct list_head cache_defer_hash[DFR_HASHSIZE]; static int cache_defer_cnt; -static void cache_defer_req(struct cache_req *req, struct cache_head *item) +static int cache_defer_req(struct cache_req *req, struct cache_head *item) { struct cache_deferred_req *dreq; int hash = DFR_HASH(item); + if (cache_defer_cnt >= DFR_MAX) { + /* too much in the cache, randomly drop this one, + * or continue and drop the oldest below + */ + if (net_random()&1) + return -ETIMEDOUT; + } dreq = req->defer(req); if (dreq == NULL) - return; + return -ETIMEDOUT; dreq->item = item; dreq->recv_time = get_seconds(); @@ -546,17 +555,8 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item) /* it is in, now maybe clean up */ dreq = NULL; if (++cache_defer_cnt > DFR_MAX) { - /* too much in the cache, randomly drop - * first or last - */ - if (net_random()&1) - dreq = list_entry(cache_defer_list.next, - struct cache_deferred_req, - recent); - else - dreq = list_entry(cache_defer_list.prev, - struct cache_deferred_req, - recent); + dreq = list_entry(cache_defer_list.prev, + struct cache_deferred_req, recent); list_del(&dreq->recent); list_del(&dreq->hash); cache_defer_cnt--; @@ -571,6 +571,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item) /* must have just been validated... */ cache_revisit_request(item); } + return 0; } static void cache_revisit_request(struct cache_head *item) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index eb44ec929ca1..f3001f3626f6 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -308,7 +308,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, serv->sv_nrpools = npools; serv->sv_pools = - kcalloc(sizeof(struct svc_pool), serv->sv_nrpools, + kcalloc(serv->sv_nrpools, sizeof(struct svc_pool), GFP_KERNEL); if (!serv->sv_pools) { kfree(serv); diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index a0a953a430c2..0d1e8fb83b93 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -53,6 +53,10 @@ struct auth_domain *unix_domain_find(char *name) return NULL; kref_init(&new->h.ref); new->h.name = kstrdup(name, GFP_KERNEL); + if (new->h.name == NULL) { + kfree(new); + return NULL; + } new->h.flavour = &svcauth_unix; new->addr_changes = 0; rv = auth_domain_lookup(name, &new->h); @@ -435,6 +439,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) default: BUG(); case -EAGAIN: + case -ETIMEDOUT: return SVC_DROP; case -ENOENT: return SVC_DENIED; |