Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux

Pull nfsd changes from Bruce Fields:
"This includes miscellaneous bugfixes and cleanup and a performance fix
for write-heavy NFSv4 workloads.

(The most significant nfsd-relevant change this time is actually in
the delegation patches that went through Viro, fixing a long-standing
bug that can cause NFSv4 clients to miss updates made by non-nfs users
of the filesystem. Those enable some followup nfsd patches which I
have queued locally, but those can wait till 3.14)"

* 'nfsd-next' of git://linux-nfs.org/~bfields/linux: (24 commits)
nfsd: export proper maximum file size to the client
nfsd4: improve write performance with better sendspace reservations
svcrpc: remove an unnecessary assignment
sunrpc: comment typo fix
Revert "nfsd: remove_stid can be incorporated into nfs4_put_delegation"
nfsd4: fix discarded security labels on setattr
NFSD: Add support for NFS v4.2 operation checking
nfsd4: nfsd_shutdown_net needs state lock
NFSD: Combine decode operations for v4 and v4.1
nfsd: -EINVAL on invalid anonuid/gid instead of silent failure
nfsd: return better errors to exportfs
nfsd: fh_update should error out in unexpected cases
nfsd4: need to destroy revoked delegations in destroy_client
nfsd: no need to unhash_stid before free
nfsd: remove_stid can be incorporated into nfs4_put_delegation
nfsd: nfs4_open_delegation needs to remove_stid rather than unhash_stid
nfsd: nfs4_free_stid
nfsd: fix Kconfig syntax
sunrpc: trim off EC bytes in GSSAPI v2 unwrap
gss_krb5: document that we ignore sequence number
...

+146 -105
+1 -1
fs/nfsd/Kconfig
··· 95 95 Smack policies on NFSv4 files, say N. 96 96 97 97 WARNING: there is still a chance of backwards-incompatible protocol changes. 98 - For now we recommend "Y" only for developers and testers." 98 + For now we recommend "Y" only for developers and testers. 99 99 100 100 config NFSD_FAULT_INJECTION 101 101 bool "NFS server manual fault injection"
+20 -4
fs/nfsd/export.c
··· 536 536 if (err) 537 537 goto out3; 538 538 exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); 539 - if (!uid_valid(exp.ex_anon_uid)) 540 - goto out3; 541 539 542 540 /* anon gid */ 543 541 err = get_int(&mesg, &an_int); 544 542 if (err) 545 543 goto out3; 546 544 exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); 547 - if (!gid_valid(exp.ex_anon_gid)) 548 - goto out3; 549 545 550 546 /* fsid */ 551 547 err = get_int(&mesg, &an_int); ··· 579 583 exp.ex_uuid); 580 584 if (err) 581 585 goto out4; 586 + /* 587 + * No point caching this if it would immediately expire. 588 + * Also, this protects exportfs's dummy export from the 589 + * anon_uid/anon_gid checks: 590 + */ 591 + if (exp.h.expiry_time < seconds_since_boot()) 592 + goto out4; 593 + /* 594 + * For some reason exportfs has been passing down an 595 + * invalid (-1) uid & gid on the "dummy" export which it 596 + * uses to test export support. To make sure exportfs 597 + * sees errors from check_export we therefore need to 598 + * delay these checks till after check_export: 599 + */ 600 + err = -EINVAL; 601 + if (!uid_valid(exp.ex_anon_uid)) 602 + goto out4; 603 + if (!gid_valid(exp.ex_anon_gid)) 604 + goto out4; 605 + err = 0; 582 606 } 583 607 584 608 expp = svc_export_lookup(&exp);
+17 -9
fs/nfsd/nfs4state.c
··· 402 402 idr_remove(stateids, s->sc_stateid.si_opaque.so_id); 403 403 } 404 404 405 + static void nfs4_free_stid(struct kmem_cache *slab, struct nfs4_stid *s) 406 + { 407 + kmem_cache_free(slab, s); 408 + } 409 + 405 410 void 406 411 nfs4_put_delegation(struct nfs4_delegation *dp) 407 412 { 408 413 if (atomic_dec_and_test(&dp->dl_count)) { 409 - kmem_cache_free(deleg_slab, dp); 414 + nfs4_free_stid(deleg_slab, &dp->dl_stid); 410 415 num_delegations--; 411 416 } 412 417 } ··· 615 610 static void free_generic_stateid(struct nfs4_ol_stateid *stp) 616 611 { 617 612 remove_stid(&stp->st_stid); 618 - kmem_cache_free(stateid_slab, stp); 613 + nfs4_free_stid(stateid_slab, &stp->st_stid); 619 614 } 620 615 621 616 static void release_lock_stateid(struct nfs4_ol_stateid *stp) ··· 673 668 static void release_open_stateid(struct nfs4_ol_stateid *stp) 674 669 { 675 670 unhash_open_stateid(stp); 676 - unhash_stid(&stp->st_stid); 677 671 free_generic_stateid(stp); 678 672 } 679 673 ··· 694 690 struct nfs4_ol_stateid *s = oo->oo_last_closed_stid; 695 691 696 692 if (s) { 697 - unhash_stid(&s->st_stid); 698 693 free_generic_stateid(s); 699 694 oo->oo_last_closed_stid = NULL; 700 695 } ··· 1129 1126 while (!list_empty(&reaplist)) { 1130 1127 dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); 1131 1128 destroy_delegation(dp); 1129 + } 1130 + list_splice_init(&clp->cl_revoked, &reaplist); 1131 + while (!list_empty(&reaplist)) { 1132 + dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); 1133 + destroy_revoked_delegation(dp); 1132 1134 } 1133 1135 while (!list_empty(&clp->cl_openowners)) { 1134 1136 oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); ··· 3162 3154 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; 3163 3155 return; 3164 3156 out_free: 3165 - unhash_stid(&dp->dl_stid); 3157 + remove_stid(&dp->dl_stid); 3166 3158 nfs4_put_delegation(dp); 3167 3159 out_no_deleg: 3168 3160 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; ··· 4003 3995 4004 3996 nfsd4_close_open_stateid(stp); 4005 3997 4006 - if (cstate->minorversion) { 4007 - unhash_stid(&stp->st_stid); 3998 + if (cstate->minorversion) 4008 3999 free_generic_stateid(stp); 4009 - } else 4000 + else 4010 4001 oo->oo_last_closed_stid = stp; 4011 4002 4012 4003 if (list_empty(&oo->oo_owner.so_stateids)) { ··· 5126 5119 return ret; 5127 5120 } 5128 5121 5129 - /* should be called with the state lock held */ 5130 5122 void 5131 5123 nfs4_state_shutdown_net(struct net *net) 5132 5124 { ··· 5136 5130 cancel_delayed_work_sync(&nn->laundromat_work); 5137 5131 locks_end_grace(&nn->nfsd4_manager); 5138 5132 5133 + nfs4_lock_state(); 5139 5134 INIT_LIST_HEAD(&reaplist); 5140 5135 spin_lock(&recall_lock); 5141 5136 list_for_each_safe(pos, next, &nn->del_recall_lru) { ··· 5151 5144 5152 5145 nfsd4_client_tracking_exit(net); 5153 5146 nfs4_state_destroy_net(net); 5147 + nfs4_unlock_state(); 5154 5148 } 5155 5149 5156 5150 void
+74 -58
fs/nfsd/nfs4xdr.c
··· 411 411 label->data = kzalloc(dummy32 + 1, GFP_KERNEL); 412 412 if (!label->data) 413 413 return nfserr_jukebox; 414 + label->len = dummy32; 414 415 defer_free(argp, kfree, label->data); 415 416 memcpy(label->data, buf, dummy32); 416 417 } ··· 946 945 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf) 947 946 { 948 947 DECODE_HEAD; 949 - 948 + 949 + if (argp->minorversion >= 1) 950 + return nfserr_notsupp; 951 + 950 952 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid); 951 953 if (status) 952 954 return status; 953 955 READ_BUF(4); 954 956 READ32(open_conf->oc_seqid); 955 - 957 + 956 958 DECODE_TAIL; 957 959 } 958 960 ··· 992 988 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen); 993 989 994 990 DECODE_TAIL; 991 + } 992 + 993 + static __be32 994 + nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, void *p) 995 + { 996 + if (argp->minorversion == 0) 997 + return nfs_ok; 998 + return nfserr_notsupp; 995 999 } 996 1000 997 1001 static __be32 ··· 1073 1061 { 1074 1062 DECODE_HEAD; 1075 1063 1064 + if (argp->minorversion >= 1) 1065 + return nfserr_notsupp; 1066 + 1076 1067 READ_BUF(sizeof(clientid_t)); 1077 1068 COPYMEM(clientid, sizeof(clientid_t)); 1078 1069 ··· 1126 1111 { 1127 1112 DECODE_HEAD; 1128 1113 1114 + if (argp->minorversion >= 1) 1115 + return nfserr_notsupp; 1116 + 1129 1117 READ_BUF(NFS4_VERIFIER_SIZE); 1130 1118 COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE); 1131 1119 ··· 1154 1136 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c) 1155 1137 { 1156 1138 DECODE_HEAD; 1139 + 1140 + if (argp->minorversion >= 1) 1141 + return nfserr_notsupp; 1157 1142 1158 1143 READ_BUF(8 + NFS4_VERIFIER_SIZE); 1159 1144 COPYMEM(&scd_c->sc_clientid, 8); ··· 1240 1219 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner) 1241 1220 { 1242 1221 DECODE_HEAD; 1222 + 1223 + if (argp->minorversion >= 1) 1224 + return nfserr_notsupp; 1243 1225 1244 1226 READ_BUF(12); 1245 1227 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t)); ··· 1543 1519 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm, 1544 1520 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade, 1545 1521 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh, 1546 - [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_noop, 1522 + [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_putpubfh, 1547 1523 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop, 1548 1524 [OP_READ] = (nfsd4_dec)nfsd4_decode_read, 1549 1525 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir, ··· 1560 1536 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1561 1537 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write, 1562 1538 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner, 1563 - }; 1564 - 1565 - static nfsd4_dec nfsd41_dec_ops[] = { 1566 - [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access, 1567 - [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close, 1568 - [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit, 1569 - [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create, 1570 - [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp, 1571 - [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn, 1572 - [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr, 1573 - [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop, 1574 - [OP_LINK] = (nfsd4_dec)nfsd4_decode_link, 1575 - [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock, 1576 - [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt, 1577 - [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku, 1578 - [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup, 1579 - [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop, 1580 - [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1581 - [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open, 1582 - [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp, 1583 - [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_notsupp, 1584 - [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade, 1585 - [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh, 1586 - [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp, 1587 - [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop, 1588 - [OP_READ] = (nfsd4_dec)nfsd4_decode_read, 1589 - [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir, 1590 - [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop, 1591 - [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove, 1592 - [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename, 1593 - [OP_RENEW] = (nfsd4_dec)nfsd4_decode_notsupp, 1594 - [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop, 1595 - [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop, 1596 - [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo, 1597 - [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr, 1598 - [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp, 1599 - [OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp, 1600 - [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1601 - [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write, 1602 - [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp, 1603 1539 1604 1540 /* new operations for NFSv4.1 */ 1605 1541 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_backchannel_ctl, ··· 1583 1599 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, 1584 1600 }; 1585 1601 1586 - struct nfsd4_minorversion_ops { 1587 - nfsd4_dec *decoders; 1588 - int nops; 1589 - }; 1602 + static inline bool 1603 + nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op) 1604 + { 1605 + if (op->opnum < FIRST_NFS4_OP) 1606 + return false; 1607 + else if (argp->minorversion == 0 && op->opnum > LAST_NFS40_OP) 1608 + return false; 1609 + else if (argp->minorversion == 1 && op->opnum > LAST_NFS41_OP) 1610 + return false; 1611 + else if (argp->minorversion == 2 && op->opnum > LAST_NFS42_OP) 1612 + return false; 1613 + return true; 1614 + } 1590 1615 1591 - static struct nfsd4_minorversion_ops nfsd4_minorversion[] = { 1592 - [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) }, 1593 - [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) }, 1594 - [2] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) }, 1595 - }; 1616 + /* 1617 + * Return a rough estimate of the maximum possible reply size. Note the 1618 + * estimate includes rpc headers so is meant to be passed to 1619 + * svc_reserve, not svc_reserve_auth. 1620 + * 1621 + * Also note the current compound encoding permits only one operation to 1622 + * use pages beyond the first one, so the maximum possible length is the 1623 + * maximum over these values, not the sum. 1624 + */ 1625 + static int nfsd4_max_reply(u32 opnum) 1626 + { 1627 + switch (opnum) { 1628 + case OP_READLINK: 1629 + case OP_READDIR: 1630 + /* 1631 + * Both of these ops take a single page for data and put 1632 + * the head and tail in another page: 1633 + */ 1634 + return 2 * PAGE_SIZE; 1635 + case OP_READ: 1636 + return INT_MAX; 1637 + default: 1638 + return PAGE_SIZE; 1639 + } 1640 + } 1596 1641 1597 1642 static __be32 1598 1643 nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 1599 1644 { 1600 1645 DECODE_HEAD; 1601 1646 struct nfsd4_op *op; 1602 - struct nfsd4_minorversion_ops *ops; 1603 1647 bool cachethis = false; 1648 + int max_reply = PAGE_SIZE; 1604 1649 int i; 1605 1650 1606 1651 READ_BUF(4); ··· 1653 1640 } 1654 1641 } 1655 1642 1656 - if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion)) 1643 + if (argp->minorversion > NFSD_SUPPORTED_MINOR_VERSION) 1657 1644 argp->opcnt = 0; 1658 1645 1659 - ops = &nfsd4_minorversion[argp->minorversion]; 1660 1646 for (i = 0; i < argp->opcnt; i++) { 1661 1647 op = &argp->ops[i]; 1662 1648 op->replay = NULL; ··· 1663 1651 READ_BUF(4); 1664 1652 READ32(op->opnum); 1665 1653 1666 - if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP) 1667 - op->status = ops->decoders[op->opnum](argp, &op->u); 1654 + if (nfsd4_opnum_in_range(argp, op)) 1655 + op->status = nfsd4_dec_ops[op->opnum](argp, &op->u); 1668 1656 else { 1669 1657 op->opnum = OP_ILLEGAL; 1670 1658 op->status = nfserr_op_illegal; ··· 1679 1667 * op in the compound wants to be cached: 1680 1668 */ 1681 1669 cachethis |= nfsd4_cache_this_op(op); 1670 + 1671 + max_reply = max(max_reply, nfsd4_max_reply(op->opnum)); 1682 1672 } 1683 1673 /* Sessions make the DRC unnecessary: */ 1684 1674 if (argp->minorversion) 1685 1675 cachethis = false; 1676 + if (max_reply != INT_MAX) 1677 + svc_reserve(argp->rqstp, max_reply); 1686 1678 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; 1687 1679 1688 1680 DECODE_TAIL; ··· 2391 2375 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { 2392 2376 if ((buflen -= 8) < 0) 2393 2377 goto out_resource; 2394 - WRITE64(~(u64)0); 2378 + WRITE64(exp->ex_path.mnt->mnt_sb->s_maxbytes); 2395 2379 } 2396 2380 if (bmval0 & FATTR4_WORD0_MAXLINK) { 2397 2381 if ((buflen -= 4) < 0)
+3 -5
fs/nfsd/nfsfh.c
··· 598 598 _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); 599 599 } else { 600 600 if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) 601 - goto out; 601 + return 0; 602 602 603 603 _fh_update(fhp, fhp->fh_export, dentry); 604 604 if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) 605 605 return nfserr_opnotsupp; 606 606 } 607 - out: 608 607 return 0; 609 - 610 608 out_bad: 611 609 printk(KERN_ERR "fh_update: fh not verified!\n"); 612 - goto out; 610 + return nfserr_serverfault; 613 611 out_negative: 614 612 printk(KERN_ERR "fh_update: %pd2 still negative!\n", 615 613 dentry); 616 - goto out; 614 + return nfserr_serverfault; 617 615 } 618 616 619 617 /*
+3
include/linux/nfs4.h
··· 118 118 119 119 #define FIRST_NFS4_OP OP_ACCESS 120 120 #define LAST_NFS4_OP OP_RECLAIM_COMPLETE 121 + #define LAST_NFS40_OP OP_RELEASE_LOCKOWNER 122 + #define LAST_NFS41_OP OP_RECLAIM_COMPLETE 123 + #define LAST_NFS42_OP OP_RECLAIM_COMPLETE 121 124 122 125 enum nfsstat4 { 123 126 NFS4_OK = 0,
+4 -4
net/sunrpc/auth_gss/gss_krb5_unseal.c
··· 150 150 struct xdr_netobj cksumobj = {.len = sizeof(cksumdata), 151 151 .data = cksumdata}; 152 152 s32 now; 153 - u64 seqnum; 154 153 u8 *ptr = read_token->data; 155 154 u8 *cksumkey; 156 155 u8 flags; ··· 196 197 if (now > ctx->endtime) 197 198 return GSS_S_CONTEXT_EXPIRED; 198 199 199 - /* do sequencing checks */ 200 - 201 - seqnum = be64_to_cpup((__be64 *)ptr + 8); 200 + /* 201 + * NOTE: the sequence number at ptr + 8 is skipped, rpcsec_gss 202 + * doesn't want it checked; see page 6 of rfc 2203. 203 + */ 202 204 203 205 return GSS_S_COMPLETE; 204 206 }
+6 -4
net/sunrpc/auth_gss/gss_krb5_wrap.c
··· 489 489 gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) 490 490 { 491 491 s32 now; 492 - u64 seqnum; 493 492 u8 *ptr; 494 493 u8 flags = 0x00; 495 494 u16 ec, rrc; ··· 524 525 ec = be16_to_cpup((__be16 *)(ptr + 4)); 525 526 rrc = be16_to_cpup((__be16 *)(ptr + 6)); 526 527 527 - seqnum = be64_to_cpup((__be64 *)(ptr + 8)); 528 + /* 529 + * NOTE: the sequence number at ptr + 8 is skipped, rpcsec_gss 530 + * doesn't want it checked; see page 6 of rfc 2203. 531 + */ 528 532 529 533 if (rrc != 0) 530 534 rotate_left(offset + 16, buf, rrc); ··· 576 574 buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; 577 575 buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; 578 576 579 - /* Trim off the checksum blob */ 580 - xdr_buf_trim(buf, GSS_KRB5_TOK_HDR_LEN + tailskip); 577 + /* Trim off the trailing "extra count" and checksum blob */ 578 + xdr_buf_trim(buf, ec + GSS_KRB5_TOK_HDR_LEN + tailskip); 581 579 return GSS_S_COMPLETE; 582 580 } 583 581
+2 -1
net/sunrpc/auth_gss/gss_rpc_upcall.c
··· 298 298 if (res.context_handle) { 299 299 data->out_handle = rctxh.exported_context_token; 300 300 data->mech_oid.len = rctxh.mech.len; 301 - memcpy(data->mech_oid.data, rctxh.mech.data, 301 + if (rctxh.mech.data) 302 + memcpy(data->mech_oid.data, rctxh.mech.data, 302 303 data->mech_oid.len); 303 304 client_name = rctxh.src_name.display_name; 304 305 }
+14 -15
net/sunrpc/auth_gss/gss_rpc_xdr.c
··· 559 559 560 560 /* cred->elements */ 561 561 err = dummy_enc_credel_array(xdr, &cred->elements); 562 + if (err) 563 + return err; 562 564 563 565 /* cred->cred_handle_reference */ 564 566 err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); ··· 742 740 goto done; 743 741 744 742 /* arg->context_handle */ 745 - if (arg->context_handle) { 743 + if (arg->context_handle) 746 744 err = gssx_enc_ctx(xdr, arg->context_handle); 747 - if (err) 748 - goto done; 749 - } else { 745 + else 750 746 err = gssx_enc_bool(xdr, 0); 751 - } 747 + if (err) 748 + goto done; 752 749 753 750 /* arg->cred_handle */ 754 - if (arg->cred_handle) { 751 + if (arg->cred_handle) 755 752 err = gssx_enc_cred(xdr, arg->cred_handle); 756 - if (err) 757 - goto done; 758 - } else { 753 + else 759 754 err = gssx_enc_bool(xdr, 0); 760 - } 755 + if (err) 756 + goto done; 761 757 762 758 /* arg->input_token */ 763 759 err = gssx_enc_in_token(xdr, &arg->input_token); ··· 763 763 goto done; 764 764 765 765 /* arg->input_cb */ 766 - if (arg->input_cb) { 766 + if (arg->input_cb) 767 767 err = gssx_enc_cb(xdr, arg->input_cb); 768 - if (err) 769 - goto done; 770 - } else { 768 + else 771 769 err = gssx_enc_bool(xdr, 0); 772 - } 770 + if (err) 771 + goto done; 773 772 774 773 err = gssx_enc_bool(xdr, arg->ret_deleg_cred); 775 774 if (err)
+2 -2
net/sunrpc/auth_gss/svcauth_gss.c
··· 1167 1167 if (!ud->found_creds) { 1168 1168 /* userspace seem buggy, we should always get at least a 1169 1169 * mapping to nobody */ 1170 - dprintk("RPC: No creds found, marking Negative!\n"); 1171 - set_bit(CACHE_NEGATIVE, &rsci.h.flags); 1170 + dprintk("RPC: No creds found!\n"); 1171 + goto out; 1172 1172 } else { 1173 1173 1174 1174 /* steal creds */
-2
net/sunrpc/svc.c
··· 1104 1104 rqstp->rq_vers = vers = svc_getnl(argv); /* version number */ 1105 1105 rqstp->rq_proc = proc = svc_getnl(argv); /* procedure number */ 1106 1106 1107 - progp = serv->sv_program; 1108 - 1109 1107 for (progp = serv->sv_program; progp; progp = progp->pg_next) 1110 1108 if (prog == progp->pg_prog) 1111 1109 break;