Skip to content

Commit fb415f2

Browse files
committed
Merge tag 'nfsd-4.9-1' of git://linux-nfs.org/~bfields/linux
Pull nfsd bugfixes from Bruce Fields: "Fixes for some recent regressions including fallout from the vmalloc'd stack change (after which we can no longer encrypt stuff on the stack)" * tag 'nfsd-4.9-1' of git://linux-nfs.org/~bfields/linux: nfsd: Fix general protection fault in release_lock_stateid() svcrdma: backchannel cannot share a page for send and rcv buffers sunrpc: fix some missing rq_rbuffer assignments sunrpc: don't pass on-stack memory to sg_set_buf nfsd: move blocked lock handling under a dedicated spinlock
2 parents 46d7cbb + f46c445 commit fb415f2

7 files changed

Lines changed: 106 additions & 66 deletions

File tree

fs/nfsd/netns.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,18 @@ struct nfsd_net {
8484
struct list_head client_lru;
8585
struct list_head close_lru;
8686
struct list_head del_recall_lru;
87+
88+
/* protected by blocked_locks_lock */
8789
struct list_head blocked_locks_lru;
8890

8991
struct delayed_work laundromat_work;
9092

9193
/* client_lock protects the client lru list and session hash table */
9294
spinlock_t client_lock;
9395

96+
/* protects blocked_locks_lru */
97+
spinlock_t blocked_locks_lock;
98+
9499
struct file *rec_file;
95100
bool in_grace;
96101
const struct nfsd4_client_tracking_ops *client_tracking_ops;

fs/nfsd/nfs4state.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
217217
{
218218
struct nfsd4_blocked_lock *cur, *found = NULL;
219219

220-
spin_lock(&nn->client_lock);
220+
spin_lock(&nn->blocked_locks_lock);
221221
list_for_each_entry(cur, &lo->lo_blocked, nbl_list) {
222222
if (fh_match(fh, &cur->nbl_fh)) {
223223
list_del_init(&cur->nbl_list);
@@ -226,7 +226,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
226226
break;
227227
}
228228
}
229-
spin_unlock(&nn->client_lock);
229+
spin_unlock(&nn->blocked_locks_lock);
230230
if (found)
231231
posix_unblock_lock(&found->nbl_lock);
232232
return found;
@@ -1227,9 +1227,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp,
12271227

12281228
static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp)
12291229
{
1230-
struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner);
1231-
1232-
lockdep_assert_held(&oo->oo_owner.so_client->cl_lock);
1230+
lockdep_assert_held(&stp->st_stid.sc_client->cl_lock);
12331231

12341232
list_del_init(&stp->st_locks);
12351233
nfs4_unhash_stid(&stp->st_stid);
@@ -1238,12 +1236,12 @@ static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp)
12381236

12391237
static void release_lock_stateid(struct nfs4_ol_stateid *stp)
12401238
{
1241-
struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner);
1239+
struct nfs4_client *clp = stp->st_stid.sc_client;
12421240
bool unhashed;
12431241

1244-
spin_lock(&oo->oo_owner.so_client->cl_lock);
1242+
spin_lock(&clp->cl_lock);
12451243
unhashed = unhash_lock_stateid(stp);
1246-
spin_unlock(&oo->oo_owner.so_client->cl_lock);
1244+
spin_unlock(&clp->cl_lock);
12471245
if (unhashed)
12481246
nfs4_put_stid(&stp->st_stid);
12491247
}
@@ -4665,7 +4663,7 @@ nfs4_laundromat(struct nfsd_net *nn)
46654663
* indefinitely once the lock does become free.
46664664
*/
46674665
BUG_ON(!list_empty(&reaplist));
4668-
spin_lock(&nn->client_lock);
4666+
spin_lock(&nn->blocked_locks_lock);
46694667
while (!list_empty(&nn->blocked_locks_lru)) {
46704668
nbl = list_first_entry(&nn->blocked_locks_lru,
46714669
struct nfsd4_blocked_lock, nbl_lru);
@@ -4678,7 +4676,7 @@ nfs4_laundromat(struct nfsd_net *nn)
46784676
list_move(&nbl->nbl_lru, &reaplist);
46794677
list_del_init(&nbl->nbl_list);
46804678
}
4681-
spin_unlock(&nn->client_lock);
4679+
spin_unlock(&nn->blocked_locks_lock);
46824680

46834681
while (!list_empty(&reaplist)) {
46844682
nbl = list_first_entry(&nn->blocked_locks_lru,
@@ -5439,13 +5437,13 @@ nfsd4_lm_notify(struct file_lock *fl)
54395437
bool queue = false;
54405438

54415439
/* 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);
54435441
if (!list_empty(&nbl->nbl_list)) {
54445442
list_del_init(&nbl->nbl_list);
54455443
list_del_init(&nbl->nbl_lru);
54465444
queue = true;
54475445
}
5448-
spin_unlock(&nn->client_lock);
5446+
spin_unlock(&nn->blocked_locks_lock);
54495447

54505448
if (queue)
54515449
nfsd4_run_cb(&nbl->nbl_cb);
@@ -5868,10 +5866,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
58685866

58695867
if (fl_flags & FL_SLEEP) {
58705868
nbl->nbl_time = jiffies;
5871-
spin_lock(&nn->client_lock);
5869+
spin_lock(&nn->blocked_locks_lock);
58725870
list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked);
58735871
list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru);
5874-
spin_unlock(&nn->client_lock);
5872+
spin_unlock(&nn->blocked_locks_lock);
58755873
}
58765874

58775875
err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
@@ -5900,10 +5898,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
59005898
if (nbl) {
59015899
/* dequeue it if we queued it before */
59025900
if (fl_flags & FL_SLEEP) {
5903-
spin_lock(&nn->client_lock);
5901+
spin_lock(&nn->blocked_locks_lock);
59045902
list_del_init(&nbl->nbl_list);
59055903
list_del_init(&nbl->nbl_lru);
5906-
spin_unlock(&nn->client_lock);
5904+
spin_unlock(&nn->blocked_locks_lock);
59075905
}
59085906
free_blocked_lock(nbl);
59095907
}
@@ -6943,9 +6941,11 @@ static int nfs4_state_create_net(struct net *net)
69436941
INIT_LIST_HEAD(&nn->client_lru);
69446942
INIT_LIST_HEAD(&nn->close_lru);
69456943
INIT_LIST_HEAD(&nn->del_recall_lru);
6946-
INIT_LIST_HEAD(&nn->blocked_locks_lru);
69476944
spin_lock_init(&nn->client_lock);
69486945

6946+
spin_lock_init(&nn->blocked_locks_lock);
6947+
INIT_LIST_HEAD(&nn->blocked_locks_lru);
6948+
69496949
INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
69506950
get_net(net);
69516951

@@ -7063,14 +7063,14 @@ nfs4_state_shutdown_net(struct net *net)
70637063
}
70647064

70657065
BUG_ON(!list_empty(&reaplist));
7066-
spin_lock(&nn->client_lock);
7066+
spin_lock(&nn->blocked_locks_lock);
70677067
while (!list_empty(&nn->blocked_locks_lru)) {
70687068
nbl = list_first_entry(&nn->blocked_locks_lru,
70697069
struct nfsd4_blocked_lock, nbl_lru);
70707070
list_move(&nbl->nbl_lru, &reaplist);
70717071
list_del_init(&nbl->nbl_list);
70727072
}
7073-
spin_unlock(&nn->client_lock);
7073+
spin_unlock(&nn->blocked_locks_lock);
70747074

70757075
while (!list_empty(&reaplist)) {
70767076
nbl = list_first_entry(&nn->blocked_locks_lru,

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,7 @@ gss_validate(struct rpc_task *task, __be32 *p)
16161616
{
16171617
struct rpc_cred *cred = task->tk_rqstp->rq_cred;
16181618
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
1619-
__be32 seq;
1619+
__be32 *seq = NULL;
16201620
struct kvec iov;
16211621
struct xdr_buf verf_buf;
16221622
struct xdr_netobj mic;
@@ -1631,9 +1631,12 @@ gss_validate(struct rpc_task *task, __be32 *p)
16311631
goto out_bad;
16321632
if (flav != RPC_AUTH_GSS)
16331633
goto out_bad;
1634-
seq = htonl(task->tk_rqstp->rq_seqno);
1635-
iov.iov_base = &seq;
1636-
iov.iov_len = sizeof(seq);
1634+
seq = kmalloc(4, GFP_NOFS);
1635+
if (!seq)
1636+
goto out_bad;
1637+
*seq = htonl(task->tk_rqstp->rq_seqno);
1638+
iov.iov_base = seq;
1639+
iov.iov_len = 4;
16371640
xdr_buf_from_iov(&iov, &verf_buf);
16381641
mic.data = (u8 *)p;
16391642
mic.len = len;
@@ -1653,11 +1656,13 @@ gss_validate(struct rpc_task *task, __be32 *p)
16531656
gss_put_ctx(ctx);
16541657
dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n",
16551658
task->tk_pid, __func__);
1659+
kfree(seq);
16561660
return p + XDR_QUADLEN(len);
16571661
out_bad:
16581662
gss_put_ctx(ctx);
16591663
dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__,
16601664
PTR_ERR(ret));
1665+
kfree(seq);
16611666
return ret;
16621667
}
16631668

net/sunrpc/auth_gss/gss_krb5_crypto.c

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
166166
unsigned int usage, struct xdr_netobj *cksumout)
167167
{
168168
struct scatterlist sg[1];
169-
int err;
170-
u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
169+
int err = -1;
170+
u8 *checksumdata;
171171
u8 rc4salt[4];
172172
struct crypto_ahash *md5;
173173
struct crypto_ahash *hmac_md5;
@@ -187,23 +187,22 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
187187
return GSS_S_FAILURE;
188188
}
189189

190+
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
191+
if (!checksumdata)
192+
return GSS_S_FAILURE;
193+
190194
md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
191195
if (IS_ERR(md5))
192-
return GSS_S_FAILURE;
196+
goto out_free_cksum;
193197

194198
hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0,
195199
CRYPTO_ALG_ASYNC);
196-
if (IS_ERR(hmac_md5)) {
197-
crypto_free_ahash(md5);
198-
return GSS_S_FAILURE;
199-
}
200+
if (IS_ERR(hmac_md5))
201+
goto out_free_md5;
200202

201203
req = ahash_request_alloc(md5, GFP_KERNEL);
202-
if (!req) {
203-
crypto_free_ahash(hmac_md5);
204-
crypto_free_ahash(md5);
205-
return GSS_S_FAILURE;
206-
}
204+
if (!req)
205+
goto out_free_hmac_md5;
207206

208207
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
209208

@@ -232,11 +231,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
232231

233232
ahash_request_free(req);
234233
req = ahash_request_alloc(hmac_md5, GFP_KERNEL);
235-
if (!req) {
236-
crypto_free_ahash(hmac_md5);
237-
crypto_free_ahash(md5);
238-
return GSS_S_FAILURE;
239-
}
234+
if (!req)
235+
goto out_free_hmac_md5;
240236

241237
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
242238

@@ -258,8 +254,12 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
258254
cksumout->len = kctx->gk5e->cksumlength;
259255
out:
260256
ahash_request_free(req);
261-
crypto_free_ahash(md5);
257+
out_free_hmac_md5:
262258
crypto_free_ahash(hmac_md5);
259+
out_free_md5:
260+
crypto_free_ahash(md5);
261+
out_free_cksum:
262+
kfree(checksumdata);
263263
return err ? GSS_S_FAILURE : 0;
264264
}
265265

@@ -276,8 +276,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
276276
struct crypto_ahash *tfm;
277277
struct ahash_request *req;
278278
struct scatterlist sg[1];
279-
int err;
280-
u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
279+
int err = -1;
280+
u8 *checksumdata;
281281
unsigned int checksumlen;
282282

283283
if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR)
@@ -291,15 +291,17 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
291291
return GSS_S_FAILURE;
292292
}
293293

294+
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
295+
if (checksumdata == NULL)
296+
return GSS_S_FAILURE;
297+
294298
tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
295299
if (IS_ERR(tfm))
296-
return GSS_S_FAILURE;
300+
goto out_free_cksum;
297301

298302
req = ahash_request_alloc(tfm, GFP_KERNEL);
299-
if (!req) {
300-
crypto_free_ahash(tfm);
301-
return GSS_S_FAILURE;
302-
}
303+
if (!req)
304+
goto out_free_ahash;
303305

304306
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
305307

@@ -349,7 +351,10 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
349351
cksumout->len = kctx->gk5e->cksumlength;
350352
out:
351353
ahash_request_free(req);
354+
out_free_ahash:
352355
crypto_free_ahash(tfm);
356+
out_free_cksum:
357+
kfree(checksumdata);
353358
return err ? GSS_S_FAILURE : 0;
354359
}
355360

@@ -368,8 +373,8 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
368373
struct crypto_ahash *tfm;
369374
struct ahash_request *req;
370375
struct scatterlist sg[1];
371-
int err;
372-
u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
376+
int err = -1;
377+
u8 *checksumdata;
373378
unsigned int checksumlen;
374379

375380
if (kctx->gk5e->keyed_cksum == 0) {
@@ -383,16 +388,18 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
383388
return GSS_S_FAILURE;
384389
}
385390

391+
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
392+
if (!checksumdata)
393+
return GSS_S_FAILURE;
394+
386395
tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
387396
if (IS_ERR(tfm))
388-
return GSS_S_FAILURE;
397+
goto out_free_cksum;
389398
checksumlen = crypto_ahash_digestsize(tfm);
390399

391400
req = ahash_request_alloc(tfm, GFP_KERNEL);
392-
if (!req) {
393-
crypto_free_ahash(tfm);
394-
return GSS_S_FAILURE;
395-
}
401+
if (!req)
402+
goto out_free_ahash;
396403

397404
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
398405

@@ -433,7 +440,10 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
433440
}
434441
out:
435442
ahash_request_free(req);
443+
out_free_ahash:
436444
crypto_free_ahash(tfm);
445+
out_free_cksum:
446+
kfree(checksumdata);
437447
return err ? GSS_S_FAILURE : 0;
438448
}
439449

@@ -666,14 +676,17 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf,
666676
u32 ret;
667677
struct scatterlist sg[1];
668678
SKCIPHER_REQUEST_ON_STACK(req, cipher);
669-
u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2];
679+
u8 *data;
670680
struct page **save_pages;
671681
u32 len = buf->len - offset;
672682

673-
if (len > ARRAY_SIZE(data)) {
683+
if (len > GSS_KRB5_MAX_BLOCKSIZE * 2) {
674684
WARN_ON(0);
675685
return -ENOMEM;
676686
}
687+
data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_NOFS);
688+
if (!data)
689+
return -ENOMEM;
677690

678691
/*
679692
* 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,
708721
ret = write_bytes_to_xdr_buf(buf, offset, data, len);
709722

710723
out:
724+
kfree(data);
711725
return ret;
712726
}
713727

0 commit comments

Comments
 (0)