diff options
-rw-r--r-- | fs/nfsd/netns.h | 5 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 38 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 13 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_crypto.c | 82 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 21 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 12 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 1 |
7 files changed, 106 insertions, 66 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index b10d557f9c9e..ee36efd5aece 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
@@ -84,6 +84,8 @@ struct nfsd_net { | |||
84 | struct list_head client_lru; | 84 | struct list_head client_lru; |
85 | struct list_head close_lru; | 85 | struct list_head close_lru; |
86 | struct list_head del_recall_lru; | 86 | struct list_head del_recall_lru; |
87 | |||
88 | /* protected by blocked_locks_lock */ | ||
87 | struct list_head blocked_locks_lru; | 89 | struct list_head blocked_locks_lru; |
88 | 90 | ||
89 | struct delayed_work laundromat_work; | 91 | struct delayed_work laundromat_work; |
@@ -91,6 +93,9 @@ struct nfsd_net { | |||
91 | /* client_lock protects the client lru list and session hash table */ | 93 | /* client_lock protects the client lru list and session hash table */ |
92 | spinlock_t client_lock; | 94 | spinlock_t client_lock; |
93 | 95 | ||
96 | /* protects blocked_locks_lru */ | ||
97 | spinlock_t blocked_locks_lock; | ||
98 | |||
94 | struct file *rec_file; | 99 | struct file *rec_file; |
95 | bool in_grace; | 100 | bool in_grace; |
96 | const struct nfsd4_client_tracking_ops *client_tracking_ops; | 101 | const struct nfsd4_client_tracking_ops *client_tracking_ops; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9752beb78659..4b4beaaa4eaa 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -217,7 +217,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh, | |||
217 | { | 217 | { |
218 | struct nfsd4_blocked_lock *cur, *found = NULL; | 218 | struct nfsd4_blocked_lock *cur, *found = NULL; |
219 | 219 | ||
220 | spin_lock(&nn->client_lock); | 220 | spin_lock(&nn->blocked_locks_lock); |
221 | list_for_each_entry(cur, &lo->lo_blocked, nbl_list) { | 221 | list_for_each_entry(cur, &lo->lo_blocked, nbl_list) { |
222 | if (fh_match(fh, &cur->nbl_fh)) { | 222 | if (fh_match(fh, &cur->nbl_fh)) { |
223 | list_del_init(&cur->nbl_list); | 223 | list_del_init(&cur->nbl_list); |
@@ -226,7 +226,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh, | |||
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | } | 228 | } |
229 | spin_unlock(&nn->client_lock); | 229 | spin_unlock(&nn->blocked_locks_lock); |
230 | if (found) | 230 | if (found) |
231 | posix_unblock_lock(&found->nbl_lock); | 231 | posix_unblock_lock(&found->nbl_lock); |
232 | return found; | 232 | return found; |
@@ -1227,9 +1227,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp, | |||
1227 | 1227 | ||
1228 | static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) | 1228 | static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) |
1229 | { | 1229 | { |
1230 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | 1230 | lockdep_assert_held(&stp->st_stid.sc_client->cl_lock); |
1231 | |||
1232 | lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); | ||
1233 | 1231 | ||
1234 | list_del_init(&stp->st_locks); | 1232 | list_del_init(&stp->st_locks); |
1235 | nfs4_unhash_stid(&stp->st_stid); | 1233 | nfs4_unhash_stid(&stp->st_stid); |
@@ -1238,12 +1236,12 @@ static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) | |||
1238 | 1236 | ||
1239 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | 1237 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) |
1240 | { | 1238 | { |
1241 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | 1239 | struct nfs4_client *clp = stp->st_stid.sc_client; |
1242 | bool unhashed; | 1240 | bool unhashed; |
1243 | 1241 | ||
1244 | spin_lock(&oo->oo_owner.so_client->cl_lock); | 1242 | spin_lock(&clp->cl_lock); |
1245 | unhashed = unhash_lock_stateid(stp); | 1243 | unhashed = unhash_lock_stateid(stp); |
1246 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | 1244 | spin_unlock(&clp->cl_lock); |
1247 | if (unhashed) | 1245 | if (unhashed) |
1248 | nfs4_put_stid(&stp->st_stid); | 1246 | nfs4_put_stid(&stp->st_stid); |
1249 | } | 1247 | } |
@@ -4665,7 +4663,7 @@ nfs4_laundromat(struct nfsd_net *nn) | |||
4665 | * indefinitely once the lock does become free. | 4663 | * indefinitely once the lock does become free. |
4666 | */ | 4664 | */ |
4667 | BUG_ON(!list_empty(&reaplist)); | 4665 | BUG_ON(!list_empty(&reaplist)); |
4668 | spin_lock(&nn->client_lock); | 4666 | spin_lock(&nn->blocked_locks_lock); |
4669 | while (!list_empty(&nn->blocked_locks_lru)) { | 4667 | while (!list_empty(&nn->blocked_locks_lru)) { |
4670 | nbl = list_first_entry(&nn->blocked_locks_lru, | 4668 | nbl = list_first_entry(&nn->blocked_locks_lru, |
4671 | struct nfsd4_blocked_lock, nbl_lru); | 4669 | struct nfsd4_blocked_lock, nbl_lru); |
@@ -4678,7 +4676,7 @@ nfs4_laundromat(struct nfsd_net *nn) | |||
4678 | list_move(&nbl->nbl_lru, &reaplist); | 4676 | list_move(&nbl->nbl_lru, &reaplist); |
4679 | list_del_init(&nbl->nbl_list); | 4677 | list_del_init(&nbl->nbl_list); |
4680 | } | 4678 | } |
4681 | spin_unlock(&nn->client_lock); | 4679 | spin_unlock(&nn->blocked_locks_lock); |
4682 | 4680 | ||
4683 | while (!list_empty(&reaplist)) { | 4681 | while (!list_empty(&reaplist)) { |
4684 | nbl = list_first_entry(&nn->blocked_locks_lru, | 4682 | nbl = list_first_entry(&nn->blocked_locks_lru, |
@@ -5439,13 +5437,13 @@ nfsd4_lm_notify(struct file_lock *fl) | |||
5439 | bool queue = false; | 5437 | bool queue = false; |
5440 | 5438 | ||
5441 | /* An empty list means that something else is going to be using it */ | 5439 | /* An empty list means that something else is going to be using it */ |
5442 | spin_lock(&nn->client_lock); | 5440 | spin_lock(&nn->blocked_locks_lock); |
5443 | if (!list_empty(&nbl->nbl_list)) { | 5441 | if (!list_empty(&nbl->nbl_list)) { |
5444 | list_del_init(&nbl->nbl_list); | 5442 | list_del_init(&nbl->nbl_list); |
5445 | list_del_init(&nbl->nbl_lru); | 5443 | list_del_init(&nbl->nbl_lru); |
5446 | queue = true; | 5444 | queue = true; |
5447 | } | 5445 | } |
5448 | spin_unlock(&nn->client_lock); | 5446 | spin_unlock(&nn->blocked_locks_lock); |
5449 | 5447 | ||
5450 | if (queue) | 5448 | if (queue) |
5451 | nfsd4_run_cb(&nbl->nbl_cb); | 5449 | nfsd4_run_cb(&nbl->nbl_cb); |
@@ -5868,10 +5866,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5868 | 5866 | ||
5869 | if (fl_flags & FL_SLEEP) { | 5867 | if (fl_flags & FL_SLEEP) { |
5870 | nbl->nbl_time = jiffies; | 5868 | nbl->nbl_time = jiffies; |
5871 | spin_lock(&nn->client_lock); | 5869 | spin_lock(&nn->blocked_locks_lock); |
5872 | list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked); | 5870 | list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked); |
5873 | list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); | 5871 | list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); |
5874 | spin_unlock(&nn->client_lock); | 5872 | spin_unlock(&nn->blocked_locks_lock); |
5875 | } | 5873 | } |
5876 | 5874 | ||
5877 | err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); | 5875 | err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); |
@@ -5900,10 +5898,10 @@ out: | |||
5900 | if (nbl) { | 5898 | if (nbl) { |
5901 | /* dequeue it if we queued it before */ | 5899 | /* dequeue it if we queued it before */ |
5902 | if (fl_flags & FL_SLEEP) { | 5900 | if (fl_flags & FL_SLEEP) { |
5903 | spin_lock(&nn->client_lock); | 5901 | spin_lock(&nn->blocked_locks_lock); |
5904 | list_del_init(&nbl->nbl_list); | 5902 | list_del_init(&nbl->nbl_list); |
5905 | list_del_init(&nbl->nbl_lru); | 5903 | list_del_init(&nbl->nbl_lru); |
5906 | spin_unlock(&nn->client_lock); | 5904 | spin_unlock(&nn->blocked_locks_lock); |
5907 | } | 5905 | } |
5908 | free_blocked_lock(nbl); | 5906 | free_blocked_lock(nbl); |
5909 | } | 5907 | } |
@@ -6943,9 +6941,11 @@ static int nfs4_state_create_net(struct net *net) | |||
6943 | INIT_LIST_HEAD(&nn->client_lru); | 6941 | INIT_LIST_HEAD(&nn->client_lru); |
6944 | INIT_LIST_HEAD(&nn->close_lru); | 6942 | INIT_LIST_HEAD(&nn->close_lru); |
6945 | INIT_LIST_HEAD(&nn->del_recall_lru); | 6943 | INIT_LIST_HEAD(&nn->del_recall_lru); |
6946 | INIT_LIST_HEAD(&nn->blocked_locks_lru); | ||
6947 | spin_lock_init(&nn->client_lock); | 6944 | spin_lock_init(&nn->client_lock); |
6948 | 6945 | ||
6946 | spin_lock_init(&nn->blocked_locks_lock); | ||
6947 | INIT_LIST_HEAD(&nn->blocked_locks_lru); | ||
6948 | |||
6949 | INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main); | 6949 | INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main); |
6950 | get_net(net); | 6950 | get_net(net); |
6951 | 6951 | ||
@@ -7063,14 +7063,14 @@ nfs4_state_shutdown_net(struct net *net) | |||
7063 | } | 7063 | } |
7064 | 7064 | ||
7065 | BUG_ON(!list_empty(&reaplist)); | 7065 | BUG_ON(!list_empty(&reaplist)); |
7066 | spin_lock(&nn->client_lock); | 7066 | spin_lock(&nn->blocked_locks_lock); |
7067 | while (!list_empty(&nn->blocked_locks_lru)) { | 7067 | while (!list_empty(&nn->blocked_locks_lru)) { |
7068 | nbl = list_first_entry(&nn->blocked_locks_lru, | 7068 | nbl = list_first_entry(&nn->blocked_locks_lru, |
7069 | struct nfsd4_blocked_lock, nbl_lru); | 7069 | struct nfsd4_blocked_lock, nbl_lru); |
7070 | list_move(&nbl->nbl_lru, &reaplist); | 7070 | list_move(&nbl->nbl_lru, &reaplist); |
7071 | list_del_init(&nbl->nbl_list); | 7071 | list_del_init(&nbl->nbl_list); |
7072 | } | 7072 | } |
7073 | spin_unlock(&nn->client_lock); | 7073 | spin_unlock(&nn->blocked_locks_lock); |
7074 | 7074 | ||
7075 | while (!list_empty(&reaplist)) { | 7075 | while (!list_empty(&reaplist)) { |
7076 | nbl = list_first_entry(&nn->blocked_locks_lru, | 7076 | nbl = list_first_entry(&nn->blocked_locks_lru, |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d8bd97a5a7c9..3dfd769dc5b5 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1616,7 +1616,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1616 | { | 1616 | { |
1617 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; | 1617 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1618 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1618 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1619 | __be32 seq; | 1619 | __be32 *seq = NULL; |
1620 | struct kvec iov; | 1620 | struct kvec iov; |
1621 | struct xdr_buf verf_buf; | 1621 | struct xdr_buf verf_buf; |
1622 | struct xdr_netobj mic; | 1622 | struct xdr_netobj mic; |
@@ -1631,9 +1631,12 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1631 | goto out_bad; | 1631 | goto out_bad; |
1632 | if (flav != RPC_AUTH_GSS) | 1632 | if (flav != RPC_AUTH_GSS) |
1633 | goto out_bad; | 1633 | goto out_bad; |
1634 | seq = htonl(task->tk_rqstp->rq_seqno); | 1634 | seq = kmalloc(4, GFP_NOFS); |
1635 | iov.iov_base = &seq; | 1635 | if (!seq) |
1636 | iov.iov_len = sizeof(seq); | 1636 | goto out_bad; |
1637 | *seq = htonl(task->tk_rqstp->rq_seqno); | ||
1638 | iov.iov_base = seq; | ||
1639 | iov.iov_len = 4; | ||
1637 | xdr_buf_from_iov(&iov, &verf_buf); | 1640 | xdr_buf_from_iov(&iov, &verf_buf); |
1638 | mic.data = (u8 *)p; | 1641 | mic.data = (u8 *)p; |
1639 | mic.len = len; | 1642 | mic.len = len; |
@@ -1653,11 +1656,13 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1653 | gss_put_ctx(ctx); | 1656 | gss_put_ctx(ctx); |
1654 | dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n", | 1657 | dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n", |
1655 | task->tk_pid, __func__); | 1658 | task->tk_pid, __func__); |
1659 | kfree(seq); | ||
1656 | return p + XDR_QUADLEN(len); | 1660 | return p + XDR_QUADLEN(len); |
1657 | out_bad: | 1661 | out_bad: |
1658 | gss_put_ctx(ctx); | 1662 | gss_put_ctx(ctx); |
1659 | dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__, | 1663 | dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__, |
1660 | PTR_ERR(ret)); | 1664 | PTR_ERR(ret)); |
1665 | kfree(seq); | ||
1661 | return ret; | 1666 | return ret; |
1662 | } | 1667 | } |
1663 | 1668 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 244245bcbbd2..90115ceefd49 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -166,8 +166,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
166 | unsigned int usage, struct xdr_netobj *cksumout) | 166 | unsigned int usage, struct xdr_netobj *cksumout) |
167 | { | 167 | { |
168 | struct scatterlist sg[1]; | 168 | struct scatterlist sg[1]; |
169 | int err; | 169 | int err = -1; |
170 | u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; | 170 | u8 *checksumdata; |
171 | u8 rc4salt[4]; | 171 | u8 rc4salt[4]; |
172 | struct crypto_ahash *md5; | 172 | struct crypto_ahash *md5; |
173 | struct crypto_ahash *hmac_md5; | 173 | struct crypto_ahash *hmac_md5; |
@@ -187,23 +187,22 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
187 | return GSS_S_FAILURE; | 187 | return GSS_S_FAILURE; |
188 | } | 188 | } |
189 | 189 | ||
190 | checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); | ||
191 | if (!checksumdata) | ||
192 | return GSS_S_FAILURE; | ||
193 | |||
190 | md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); | 194 | md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); |
191 | if (IS_ERR(md5)) | 195 | if (IS_ERR(md5)) |
192 | return GSS_S_FAILURE; | 196 | goto out_free_cksum; |
193 | 197 | ||
194 | hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, | 198 | hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, |
195 | CRYPTO_ALG_ASYNC); | 199 | CRYPTO_ALG_ASYNC); |
196 | if (IS_ERR(hmac_md5)) { | 200 | if (IS_ERR(hmac_md5)) |
197 | crypto_free_ahash(md5); | 201 | goto out_free_md5; |
198 | return GSS_S_FAILURE; | ||
199 | } | ||
200 | 202 | ||
201 | req = ahash_request_alloc(md5, GFP_KERNEL); | 203 | req = ahash_request_alloc(md5, GFP_KERNEL); |
202 | if (!req) { | 204 | if (!req) |
203 | crypto_free_ahash(hmac_md5); | 205 | goto out_free_hmac_md5; |
204 | crypto_free_ahash(md5); | ||
205 | return GSS_S_FAILURE; | ||
206 | } | ||
207 | 206 | ||
208 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); | 207 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); |
209 | 208 | ||
@@ -232,11 +231,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
232 | 231 | ||
233 | ahash_request_free(req); | 232 | ahash_request_free(req); |
234 | req = ahash_request_alloc(hmac_md5, GFP_KERNEL); | 233 | req = ahash_request_alloc(hmac_md5, GFP_KERNEL); |
235 | if (!req) { | 234 | if (!req) |
236 | crypto_free_ahash(hmac_md5); | 235 | goto out_free_hmac_md5; |
237 | crypto_free_ahash(md5); | ||
238 | return GSS_S_FAILURE; | ||
239 | } | ||
240 | 236 | ||
241 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); | 237 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); |
242 | 238 | ||
@@ -258,8 +254,12 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
258 | cksumout->len = kctx->gk5e->cksumlength; | 254 | cksumout->len = kctx->gk5e->cksumlength; |
259 | out: | 255 | out: |
260 | ahash_request_free(req); | 256 | ahash_request_free(req); |
261 | crypto_free_ahash(md5); | 257 | out_free_hmac_md5: |
262 | crypto_free_ahash(hmac_md5); | 258 | crypto_free_ahash(hmac_md5); |
259 | out_free_md5: | ||
260 | crypto_free_ahash(md5); | ||
261 | out_free_cksum: | ||
262 | kfree(checksumdata); | ||
263 | return err ? GSS_S_FAILURE : 0; | 263 | return err ? GSS_S_FAILURE : 0; |
264 | } | 264 | } |
265 | 265 | ||
@@ -276,8 +276,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
276 | struct crypto_ahash *tfm; | 276 | struct crypto_ahash *tfm; |
277 | struct ahash_request *req; | 277 | struct ahash_request *req; |
278 | struct scatterlist sg[1]; | 278 | struct scatterlist sg[1]; |
279 | int err; | 279 | int err = -1; |
280 | u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; | 280 | u8 *checksumdata; |
281 | unsigned int checksumlen; | 281 | unsigned int checksumlen; |
282 | 282 | ||
283 | if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) | 283 | if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) |
@@ -291,15 +291,17 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
291 | return GSS_S_FAILURE; | 291 | return GSS_S_FAILURE; |
292 | } | 292 | } |
293 | 293 | ||
294 | checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); | ||
295 | if (checksumdata == NULL) | ||
296 | return GSS_S_FAILURE; | ||
297 | |||
294 | tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); | 298 | tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); |
295 | if (IS_ERR(tfm)) | 299 | if (IS_ERR(tfm)) |
296 | return GSS_S_FAILURE; | 300 | goto out_free_cksum; |
297 | 301 | ||
298 | req = ahash_request_alloc(tfm, GFP_KERNEL); | 302 | req = ahash_request_alloc(tfm, GFP_KERNEL); |
299 | if (!req) { | 303 | if (!req) |
300 | crypto_free_ahash(tfm); | 304 | goto out_free_ahash; |
301 | return GSS_S_FAILURE; | ||
302 | } | ||
303 | 305 | ||
304 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); | 306 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); |
305 | 307 | ||
@@ -349,7 +351,10 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
349 | cksumout->len = kctx->gk5e->cksumlength; | 351 | cksumout->len = kctx->gk5e->cksumlength; |
350 | out: | 352 | out: |
351 | ahash_request_free(req); | 353 | ahash_request_free(req); |
354 | out_free_ahash: | ||
352 | crypto_free_ahash(tfm); | 355 | crypto_free_ahash(tfm); |
356 | out_free_cksum: | ||
357 | kfree(checksumdata); | ||
353 | return err ? GSS_S_FAILURE : 0; | 358 | return err ? GSS_S_FAILURE : 0; |
354 | } | 359 | } |
355 | 360 | ||
@@ -368,8 +373,8 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
368 | struct crypto_ahash *tfm; | 373 | struct crypto_ahash *tfm; |
369 | struct ahash_request *req; | 374 | struct ahash_request *req; |
370 | struct scatterlist sg[1]; | 375 | struct scatterlist sg[1]; |
371 | int err; | 376 | int err = -1; |
372 | u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; | 377 | u8 *checksumdata; |
373 | unsigned int checksumlen; | 378 | unsigned int checksumlen; |
374 | 379 | ||
375 | if (kctx->gk5e->keyed_cksum == 0) { | 380 | if (kctx->gk5e->keyed_cksum == 0) { |
@@ -383,16 +388,18 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
383 | return GSS_S_FAILURE; | 388 | return GSS_S_FAILURE; |
384 | } | 389 | } |
385 | 390 | ||
391 | checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); | ||
392 | if (!checksumdata) | ||
393 | return GSS_S_FAILURE; | ||
394 | |||
386 | tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); | 395 | tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); |
387 | if (IS_ERR(tfm)) | 396 | if (IS_ERR(tfm)) |
388 | return GSS_S_FAILURE; | 397 | goto out_free_cksum; |
389 | checksumlen = crypto_ahash_digestsize(tfm); | 398 | checksumlen = crypto_ahash_digestsize(tfm); |
390 | 399 | ||
391 | req = ahash_request_alloc(tfm, GFP_KERNEL); | 400 | req = ahash_request_alloc(tfm, GFP_KERNEL); |
392 | if (!req) { | 401 | if (!req) |
393 | crypto_free_ahash(tfm); | 402 | goto out_free_ahash; |
394 | return GSS_S_FAILURE; | ||
395 | } | ||
396 | 403 | ||
397 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); | 404 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); |
398 | 405 | ||
@@ -433,7 +440,10 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
433 | } | 440 | } |
434 | out: | 441 | out: |
435 | ahash_request_free(req); | 442 | ahash_request_free(req); |
443 | out_free_ahash: | ||
436 | crypto_free_ahash(tfm); | 444 | crypto_free_ahash(tfm); |
445 | out_free_cksum: | ||
446 | kfree(checksumdata); | ||
437 | return err ? GSS_S_FAILURE : 0; | 447 | return err ? GSS_S_FAILURE : 0; |
438 | } | 448 | } |
439 | 449 | ||
@@ -666,14 +676,17 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf, | |||
666 | u32 ret; | 676 | u32 ret; |
667 | struct scatterlist sg[1]; | 677 | struct scatterlist sg[1]; |
668 | SKCIPHER_REQUEST_ON_STACK(req, cipher); | 678 | SKCIPHER_REQUEST_ON_STACK(req, cipher); |
669 | u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2]; | 679 | u8 *data; |
670 | struct page **save_pages; | 680 | struct page **save_pages; |
671 | u32 len = buf->len - offset; | 681 | u32 len = buf->len - offset; |
672 | 682 | ||
673 | if (len > ARRAY_SIZE(data)) { | 683 | if (len > GSS_KRB5_MAX_BLOCKSIZE * 2) { |
674 | WARN_ON(0); | 684 | WARN_ON(0); |
675 | return -ENOMEM; | 685 | return -ENOMEM; |
676 | } | 686 | } |
687 | data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_NOFS); | ||
688 | if (!data) | ||
689 | return -ENOMEM; | ||
677 | 690 | ||
678 | /* | 691 | /* |
679 | * For encryption, we want to read from the cleartext | 692 | * For encryption, we want to read from the cleartext |
@@ -708,6 +721,7 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf, | |||
708 | ret = write_bytes_to_xdr_buf(buf, offset, data, len); | 721 | ret = write_bytes_to_xdr_buf(buf, offset, data, len); |
709 | 722 | ||
710 | out: | 723 | out: |
724 | kfree(data); | ||
711 | return ret; | 725 | return ret; |
712 | } | 726 | } |
713 | 727 | ||
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index d67f7e1bc82d..45662d7f0943 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -718,30 +718,37 @@ gss_write_null_verf(struct svc_rqst *rqstp) | |||
718 | static int | 718 | static int |
719 | gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq) | 719 | gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq) |
720 | { | 720 | { |
721 | __be32 xdr_seq; | 721 | __be32 *xdr_seq; |
722 | u32 maj_stat; | 722 | u32 maj_stat; |
723 | struct xdr_buf verf_data; | 723 | struct xdr_buf verf_data; |
724 | struct xdr_netobj mic; | 724 | struct xdr_netobj mic; |
725 | __be32 *p; | 725 | __be32 *p; |
726 | struct kvec iov; | 726 | struct kvec iov; |
727 | int err = -1; | ||
727 | 728 | ||
728 | svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS); | 729 | svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS); |
729 | xdr_seq = htonl(seq); | 730 | xdr_seq = kmalloc(4, GFP_KERNEL); |
731 | if (!xdr_seq) | ||
732 | return -1; | ||
733 | *xdr_seq = htonl(seq); | ||
730 | 734 | ||
731 | iov.iov_base = &xdr_seq; | 735 | iov.iov_base = xdr_seq; |
732 | iov.iov_len = sizeof(xdr_seq); | 736 | iov.iov_len = 4; |
733 | xdr_buf_from_iov(&iov, &verf_data); | 737 | xdr_buf_from_iov(&iov, &verf_data); |
734 | p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len; | 738 | p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len; |
735 | mic.data = (u8 *)(p + 1); | 739 | mic.data = (u8 *)(p + 1); |
736 | maj_stat = gss_get_mic(ctx_id, &verf_data, &mic); | 740 | maj_stat = gss_get_mic(ctx_id, &verf_data, &mic); |
737 | if (maj_stat != GSS_S_COMPLETE) | 741 | if (maj_stat != GSS_S_COMPLETE) |
738 | return -1; | 742 | goto out; |
739 | *p++ = htonl(mic.len); | 743 | *p++ = htonl(mic.len); |
740 | memset((u8 *)p + mic.len, 0, round_up_to_quad(mic.len) - mic.len); | 744 | memset((u8 *)p + mic.len, 0, round_up_to_quad(mic.len) - mic.len); |
741 | p += XDR_QUADLEN(mic.len); | 745 | p += XDR_QUADLEN(mic.len); |
742 | if (!xdr_ressize_check(rqstp, p)) | 746 | if (!xdr_ressize_check(rqstp, p)) |
743 | return -1; | 747 | goto out; |
744 | return 0; | 748 | err = 0; |
749 | out: | ||
750 | kfree(xdr_seq); | ||
751 | return err; | ||
745 | } | 752 | } |
746 | 753 | ||
747 | struct gss_domain { | 754 | struct gss_domain { |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index 2d8545c34095..20027f8de129 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c | |||
@@ -177,18 +177,26 @@ xprt_rdma_bc_allocate(struct rpc_task *task) | |||
177 | return -EINVAL; | 177 | return -EINVAL; |
178 | } | 178 | } |
179 | 179 | ||
180 | /* svc_rdma_sendto releases this page */ | ||
180 | page = alloc_page(RPCRDMA_DEF_GFP); | 181 | page = alloc_page(RPCRDMA_DEF_GFP); |
181 | if (!page) | 182 | if (!page) |
182 | return -ENOMEM; | 183 | return -ENOMEM; |
183 | |||
184 | rqst->rq_buffer = page_address(page); | 184 | rqst->rq_buffer = page_address(page); |
185 | |||
186 | rqst->rq_rbuffer = kmalloc(rqst->rq_rcvsize, RPCRDMA_DEF_GFP); | ||
187 | if (!rqst->rq_rbuffer) { | ||
188 | put_page(page); | ||
189 | return -ENOMEM; | ||
190 | } | ||
185 | return 0; | 191 | return 0; |
186 | } | 192 | } |
187 | 193 | ||
188 | static void | 194 | static void |
189 | xprt_rdma_bc_free(struct rpc_task *task) | 195 | xprt_rdma_bc_free(struct rpc_task *task) |
190 | { | 196 | { |
191 | /* No-op: ctxt and page have already been freed. */ | 197 | struct rpc_rqst *rqst = task->tk_rqstp; |
198 | |||
199 | kfree(rqst->rq_rbuffer); | ||
192 | } | 200 | } |
193 | 201 | ||
194 | static int | 202 | static int |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 0137af1c0916..e01c825bc683 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2563,6 +2563,7 @@ static int bc_malloc(struct rpc_task *task) | |||
2563 | buf->len = PAGE_SIZE; | 2563 | buf->len = PAGE_SIZE; |
2564 | 2564 | ||
2565 | rqst->rq_buffer = buf->data; | 2565 | rqst->rq_buffer = buf->data; |
2566 | rqst->rq_rbuffer = (char *)rqst->rq_buffer + rqst->rq_callsize; | ||
2566 | return 0; | 2567 | return 0; |
2567 | } | 2568 | } |
2568 | 2569 | ||