aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-02 15:49:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-02 15:49:58 -0500
commit1fc576b82b96d9bb033ff0098e1c0bf68de282b2 (patch)
treec4f8cb6640de3dff75ad7c33de0eedae4e230613
parente4178c75049c581114998a850ecdfa5a2811cde6 (diff)
parent034dd34ff4916ec1f8f74e39ca3efb04eab2f791 (diff)
Merge tag 'nfsd-4.10-2' of git://linux-nfs.org/~bfields/linux
Pull nfsd fixes from Bruce Fields: "Three more miscellaneous nfsd bugfixes" * tag 'nfsd-4.10-2' of git://linux-nfs.org/~bfields/linux: svcrpc: fix oops in absence of krb5 module nfsd: special case truncates some more NFSD: Fix a null reference case in find_or_create_lock_stateid()
-rw-r--r--fs/nfsd/nfs4layouts.c5
-rw-r--r--fs/nfsd/nfs4state.c19
-rw-r--r--fs/nfsd/state.h4
-rw-r--r--fs/nfsd/vfs.c97
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_xdr.c2
5 files changed, 51 insertions, 76 deletions
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index 596205d939a1..1fc07a9c70e9 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -223,10 +223,11 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate,
223 struct nfs4_layout_stateid *ls; 223 struct nfs4_layout_stateid *ls;
224 struct nfs4_stid *stp; 224 struct nfs4_stid *stp;
225 225
226 stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache); 226 stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache,
227 nfsd4_free_layout_stateid);
227 if (!stp) 228 if (!stp)
228 return NULL; 229 return NULL;
229 stp->sc_free = nfsd4_free_layout_stateid; 230
230 get_nfs4_file(fp); 231 get_nfs4_file(fp);
231 stp->sc_file = fp; 232 stp->sc_file = fp;
232 233
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4b4beaaa4eaa..a0dee8ae9f97 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -633,8 +633,8 @@ out:
633 return co; 633 return co;
634} 634}
635 635
636struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, 636struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
637 struct kmem_cache *slab) 637 void (*sc_free)(struct nfs4_stid *))
638{ 638{
639 struct nfs4_stid *stid; 639 struct nfs4_stid *stid;
640 int new_id; 640 int new_id;
@@ -650,6 +650,8 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
650 idr_preload_end(); 650 idr_preload_end();
651 if (new_id < 0) 651 if (new_id < 0)
652 goto out_free; 652 goto out_free;
653
654 stid->sc_free = sc_free;
653 stid->sc_client = cl; 655 stid->sc_client = cl;
654 stid->sc_stateid.si_opaque.so_id = new_id; 656 stid->sc_stateid.si_opaque.so_id = new_id;
655 stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid; 657 stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
@@ -675,15 +677,12 @@ out_free:
675static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp) 677static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp)
676{ 678{
677 struct nfs4_stid *stid; 679 struct nfs4_stid *stid;
678 struct nfs4_ol_stateid *stp;
679 680
680 stid = nfs4_alloc_stid(clp, stateid_slab); 681 stid = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_ol_stateid);
681 if (!stid) 682 if (!stid)
682 return NULL; 683 return NULL;
683 684
684 stp = openlockstateid(stid); 685 return openlockstateid(stid);
685 stp->st_stid.sc_free = nfs4_free_ol_stateid;
686 return stp;
687} 686}
688 687
689static void nfs4_free_deleg(struct nfs4_stid *stid) 688static void nfs4_free_deleg(struct nfs4_stid *stid)
@@ -781,11 +780,10 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh,
781 goto out_dec; 780 goto out_dec;
782 if (delegation_blocked(&current_fh->fh_handle)) 781 if (delegation_blocked(&current_fh->fh_handle))
783 goto out_dec; 782 goto out_dec;
784 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); 783 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab, nfs4_free_deleg));
785 if (dp == NULL) 784 if (dp == NULL)
786 goto out_dec; 785 goto out_dec;
787 786
788 dp->dl_stid.sc_free = nfs4_free_deleg;
789 /* 787 /*
790 * delegation seqid's are never incremented. The 4.1 special 788 * delegation seqid's are never incremented. The 4.1 special
791 * meaning of seqid 0 isn't meaningful, really, but let's avoid 789 * meaning of seqid 0 isn't meaningful, really, but let's avoid
@@ -5580,7 +5578,6 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
5580 stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); 5578 stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
5581 get_nfs4_file(fp); 5579 get_nfs4_file(fp);
5582 stp->st_stid.sc_file = fp; 5580 stp->st_stid.sc_file = fp;
5583 stp->st_stid.sc_free = nfs4_free_lock_stateid;
5584 stp->st_access_bmap = 0; 5581 stp->st_access_bmap = 0;
5585 stp->st_deny_bmap = open_stp->st_deny_bmap; 5582 stp->st_deny_bmap = open_stp->st_deny_bmap;
5586 stp->st_openstp = open_stp; 5583 stp->st_openstp = open_stp;
@@ -5623,7 +5620,7 @@ find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi,
5623 lst = find_lock_stateid(lo, fi); 5620 lst = find_lock_stateid(lo, fi);
5624 if (lst == NULL) { 5621 if (lst == NULL) {
5625 spin_unlock(&clp->cl_lock); 5622 spin_unlock(&clp->cl_lock);
5626 ns = nfs4_alloc_stid(clp, stateid_slab); 5623 ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid);
5627 if (ns == NULL) 5624 if (ns == NULL)
5628 return NULL; 5625 return NULL;
5629 5626
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index c9399366f9df..4516e8b7d776 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -603,8 +603,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
603__be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, 603__be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
604 stateid_t *stateid, unsigned char typemask, 604 stateid_t *stateid, unsigned char typemask,
605 struct nfs4_stid **s, struct nfsd_net *nn); 605 struct nfs4_stid **s, struct nfsd_net *nn);
606struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, 606struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
607 struct kmem_cache *slab); 607 void (*sc_free)(struct nfs4_stid *));
608void nfs4_unhash_stid(struct nfs4_stid *s); 608void nfs4_unhash_stid(struct nfs4_stid *s);
609void nfs4_put_stid(struct nfs4_stid *s); 609void nfs4_put_stid(struct nfs4_stid *s);
610void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid); 610void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 26c6fdb4bf67..ca13236dbb1f 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -332,37 +332,6 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
332 } 332 }
333} 333}
334 334
335static __be32
336nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,
337 struct iattr *iap)
338{
339 struct inode *inode = d_inode(fhp->fh_dentry);
340 int host_err;
341
342 if (iap->ia_size < inode->i_size) {
343 __be32 err;
344
345 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
346 NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE);
347 if (err)
348 return err;
349 }
350
351 host_err = get_write_access(inode);
352 if (host_err)
353 goto out_nfserrno;
354
355 host_err = locks_verify_truncate(inode, NULL, iap->ia_size);
356 if (host_err)
357 goto out_put_write_access;
358 return 0;
359
360out_put_write_access:
361 put_write_access(inode);
362out_nfserrno:
363 return nfserrno(host_err);
364}
365
366/* 335/*
367 * Set various file attributes. After this call fhp needs an fh_put. 336 * Set various file attributes. After this call fhp needs an fh_put.
368 */ 337 */
@@ -377,7 +346,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
377 __be32 err; 346 __be32 err;
378 int host_err; 347 int host_err;
379 bool get_write_count; 348 bool get_write_count;
380 int size_change = 0;
381 349
382 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) 350 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
383 accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; 351 accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
@@ -390,11 +358,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
390 /* Get inode */ 358 /* Get inode */
391 err = fh_verify(rqstp, fhp, ftype, accmode); 359 err = fh_verify(rqstp, fhp, ftype, accmode);
392 if (err) 360 if (err)
393 goto out; 361 return err;
394 if (get_write_count) { 362 if (get_write_count) {
395 host_err = fh_want_write(fhp); 363 host_err = fh_want_write(fhp);
396 if (host_err) 364 if (host_err)
397 return nfserrno(host_err); 365 goto out_host_err;
398 } 366 }
399 367
400 dentry = fhp->fh_dentry; 368 dentry = fhp->fh_dentry;
@@ -405,50 +373,59 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
405 iap->ia_valid &= ~ATTR_MODE; 373 iap->ia_valid &= ~ATTR_MODE;
406 374
407 if (!iap->ia_valid) 375 if (!iap->ia_valid)
408 goto out; 376 return 0;
409 377
410 nfsd_sanitize_attrs(inode, iap); 378 nfsd_sanitize_attrs(inode, iap);
411 379
380 if (check_guard && guardtime != inode->i_ctime.tv_sec)
381 return nfserr_notsync;
382
412 /* 383 /*
413 * The size case is special, it changes the file in addition to the 384 * The size case is special, it changes the file in addition to the
414 * attributes. 385 * attributes, and file systems don't expect it to be mixed with
386 * "random" attribute changes. We thus split out the size change
387 * into a separate call for vfs_truncate, and do the rest as a
388 * a separate setattr call.
415 */ 389 */
416 if (iap->ia_valid & ATTR_SIZE) { 390 if (iap->ia_valid & ATTR_SIZE) {
417 err = nfsd_get_write_access(rqstp, fhp, iap); 391 struct path path = {
418 if (err) 392 .mnt = fhp->fh_export->ex_path.mnt,
419 goto out; 393 .dentry = dentry,
420 size_change = 1; 394 };
395 bool implicit_mtime = false;
421 396
422 /* 397 /*
423 * RFC5661, Section 18.30.4: 398 * vfs_truncate implicity updates the mtime IFF the file size
424 * Changing the size of a file with SETATTR indirectly 399 * actually changes. Avoid the additional seattr call below if
425 * changes the time_modify and change attributes. 400 * the only other attribute that the client sends is the mtime.
426 *
427 * (and similar for the older RFCs)
428 */ 401 */
429 if (iap->ia_size != i_size_read(inode)) 402 if (iap->ia_size != i_size_read(inode) &&
430 iap->ia_valid |= ATTR_MTIME; 403 ((iap->ia_valid & ~(ATTR_SIZE | ATTR_MTIME)) == 0))
431 } 404 implicit_mtime = true;
432 405
433 iap->ia_valid |= ATTR_CTIME; 406 host_err = vfs_truncate(&path, iap->ia_size);
407 if (host_err)
408 goto out_host_err;
434 409
435 if (check_guard && guardtime != inode->i_ctime.tv_sec) { 410 iap->ia_valid &= ~ATTR_SIZE;
436 err = nfserr_notsync; 411 if (implicit_mtime)
437 goto out_put_write_access; 412 iap->ia_valid &= ~ATTR_MTIME;
413 if (!iap->ia_valid)
414 goto done;
438 } 415 }
439 416
417 iap->ia_valid |= ATTR_CTIME;
418
440 fh_lock(fhp); 419 fh_lock(fhp);
441 host_err = notify_change(dentry, iap, NULL); 420 host_err = notify_change(dentry, iap, NULL);
442 fh_unlock(fhp); 421 fh_unlock(fhp);
443 err = nfserrno(host_err); 422 if (host_err)
423 goto out_host_err;
444 424
445out_put_write_access: 425done:
446 if (size_change) 426 host_err = commit_metadata(fhp);
447 put_write_access(inode); 427out_host_err:
448 if (!err) 428 return nfserrno(host_err);
449 err = nfserrno(commit_metadata(fhp));
450out:
451 return err;
452} 429}
453 430
454#if defined(CONFIG_NFSD_V4) 431#if defined(CONFIG_NFSD_V4)
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
index dc6fb79a361f..25d9a9cf7b66 100644
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
@@ -260,7 +260,7 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
260 if (!oa->data) 260 if (!oa->data)
261 return -ENOMEM; 261 return -ENOMEM;
262 262
263 creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL); 263 creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL);
264 if (!creds) { 264 if (!creds) {
265 kfree(oa->data); 265 kfree(oa->data);
266 return -ENOMEM; 266 return -ENOMEM;