Make sure there's a gss_put_ctx for every get_ctx. diff -puN net/sunrpc/auth_gss/auth_gss.c~add_gss_put_ctx net/sunrpc/auth_gss/auth_gss.c --- linux-2.5.74/net/sunrpc/auth_gss/auth_gss.c~add_gss_put_ctx 2003-07-03 18:13:47.000000000 -0400 +++ linux-2.5.74-bfields/net/sunrpc/auth_gss/auth_gss.c 2003-07-03 18:14:19.000000000 -0400 @@ -680,12 +680,16 @@ gss_refresh(struct rpc_task *task) struct gss_auth, rpc_auth); struct rpc_xprt *xprt = task->tk_xprt; struct rpc_cred *cred = task->tk_msg.rpc_cred; + struct gss_cl_ctx *ctx; int err = 0; task->tk_timeout = xprt->timeout.to_current; spin_lock(&gss_auth->lock); - if (gss_cred_get_uptodate_ctx(cred)) + ctx = gss_cred_get_uptodate_ctx(cred); + if (ctx) { + gss_put_ctx(ctx); goto out; + } err = gss_upcall(clnt, task, cred->cr_uid); out: spin_unlock(&gss_auth->lock); @@ -733,15 +737,15 @@ gss_validate(struct rpc_task *task, u32 flav = ntohl(*p++); if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) - goto out; + goto out_put_ctx; if (flav != RPC_AUTH_GSS) - goto out; + goto out_put_ctx; mic.data = (u8 *)p; mic.len = len; if (verify_checksum(ctx->gc_gss_ctx, &mic, task->tk_rqstp->rq_seqnos)) - goto out; + goto out_put_ctx; service = gss_pseudoflavor_to_service(gss_cred->gc_flavor); switch (service) { case RPC_GSS_SVC_NONE: @@ -753,11 +757,12 @@ gss_validate(struct rpc_task *task, u32 task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4; break; default: - goto out; + goto out_put_ctx; } return p + XDR_QUADLEN(len); -out: +out_put_ctx: + gss_put_ctx(ctx); dprintk("RPC: gss_validate failed.\n"); return NULL; } @@ -788,13 +793,13 @@ gss_wrap_req(struct rpc_task *task, * wrapping context destruction requests makes the most sense. */ status = encode(rqstp, p, obj); - goto out; + goto out_put_ctx; } service = gss_pseudoflavor_to_service(gss_cred->gc_flavor); switch (service) { case RPC_GSS_SVC_NONE: status = encode(rqstp, p, obj); - goto out; + goto out_put_ctx; case RPC_GSS_SVC_INTEGRITY: integ_len = p++; @@ -803,11 +808,11 @@ gss_wrap_req(struct rpc_task *task, status = encode(rqstp, p, obj); if (status) - goto out; + goto out_put_ctx; if (xdr_buf_subsegment(snd_buf, &integ_buf, offset, snd_buf->len - offset)) - goto out; + goto out_put_ctx; *integ_len = htonl(integ_buf.len); /* guess whether we're in the head or the tail: */ @@ -822,7 +827,7 @@ gss_wrap_req(struct rpc_task *task, &integ_buf, &mic); status = -EIO; /* XXX? */ if (maj_stat) - goto out; + goto out_put_ctx; q = p; *q++ = htonl(mic.len); q += XDR_QUADLEN(mic.len); @@ -833,10 +838,11 @@ gss_wrap_req(struct rpc_task *task, break; case RPC_GSS_SVC_PRIVACY: default: - goto out; + goto out_put_ctx; } status = 0; -out: +out_put_ctx: + gss_put_ctx(ctx); dprintk("RPC: gss_wrap_req returning %d\n", status); return status; } @@ -870,33 +876,34 @@ gss_unwrap_resp(struct rpc_task *task, case RPC_GSS_SVC_INTEGRITY: integ_len = ntohl(*p++); if (integ_len & 3) - goto out; + goto out_put_ctx; data_offset = (u8 *)p - (u8 *)rcv_buf->head[0].iov_base; mic_offset = integ_len + data_offset; if (mic_offset > rcv_buf->len) - goto out; + goto out_put_ctx; if (ntohl(*p++) != req->rq_seqnos[0]) - goto out; + goto out_put_ctx; if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, mic_offset - data_offset)) - goto out; + goto out_put_ctx; if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset)) - goto out; + goto out_put_ctx; maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic, NULL); if (maj_stat != GSS_S_COMPLETE) - goto out; + goto out_put_ctx; break; case RPC_GSS_SVC_PRIVACY: default: - goto out; + goto out_put_ctx; } out_decode: status = decode(rqstp, p, obj); -out: +out_put_ctx: + gss_put_ctx(ctx); dprintk("RPC: gss_unwrap_resp returning %d\n", status); return status; } _