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 | ||
