mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
Merge tag 'nfsd-6.18-3' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd fixes from Chuck Lever: "Address recently reported issues or issues found at the recent NFS bake-a-thon held in Raleigh, NC. Issues reported with v6.18-rc: - Address a kernel build issue - Reorder SEQUENCE processing to avoid spurious NFS4ERR_SEQ_MISORDERED Issues that need expedient stable backports: - Close a refcount leak exposure - Report support for NFSv4.2 CLONE correctly - Fix oops during COPY_NOTIFY processing - Prevent rare crash after XDR encoding failure - Prevent crash due to confused or malicious NFSv4.1 client" * tag 'nfsd-6.18-3' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: Revert "SUNRPC: Make RPCSEC_GSS_KRB5 select CRYPTO instead of depending on it" nfsd: ensure SEQUENCE replay sends a valid reply. NFSD: Never cache a COMPOUND when the SEQUENCE operation fails NFSD: Skip close replay processing if XDR encoding fails NFSD: free copynotify stateid in nfs4_free_ol_stateid() nfsd: add missing FATTR4_WORD2_CLONE_BLKSIZE from supported attributes nfsd: fix refcount leak in nfsd_set_fh_dentry()
This commit is contained in:
@@ -1542,7 +1542,8 @@ static void nfs4_free_ol_stateid(struct nfs4_stid *stid)
|
||||
release_all_access(stp);
|
||||
if (stp->st_stateowner)
|
||||
nfs4_put_stateowner(stp->st_stateowner);
|
||||
WARN_ON(!list_empty(&stid->sc_cp_list));
|
||||
if (!list_empty(&stid->sc_cp_list))
|
||||
nfs4_free_cpntf_statelist(stid->sc_client->net, stid);
|
||||
kmem_cache_free(stateid_slab, stid);
|
||||
}
|
||||
|
||||
@@ -3486,7 +3487,20 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
|
||||
struct nfsd4_slot *slot = resp->cstate.slot;
|
||||
unsigned int base;
|
||||
|
||||
dprintk("--> %s slot %p\n", __func__, slot);
|
||||
/*
|
||||
* RFC 5661 Section 2.10.6.1.2:
|
||||
*
|
||||
* Any time SEQUENCE ... returns an error ... [t]he replier MUST NOT
|
||||
* modify the reply cache entry for the slot whenever an error is
|
||||
* returned from SEQUENCE ...
|
||||
*
|
||||
* Because nfsd4_store_cache_entry is called only by
|
||||
* nfsd4_sequence_done(), nfsd4_store_cache_entry() is called only
|
||||
* when a SEQUENCE operation was part of the COMPOUND.
|
||||
* nfs41_check_op_ordering() ensures SEQUENCE is the first op.
|
||||
*/
|
||||
if (resp->opcnt == 1 && resp->cstate.status != nfs_ok)
|
||||
return;
|
||||
|
||||
slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
|
||||
slot->sl_opcnt = resp->opcnt;
|
||||
@@ -4349,6 +4363,36 @@ static bool replay_matches_cache(struct svc_rqst *rqstp,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the response is constructed here both for the case
|
||||
* of a new SEQUENCE request and for a replayed SEQUENCE request.
|
||||
* We do not cache SEQUENCE responses as SEQUENCE is idempotent.
|
||||
*/
|
||||
static void nfsd4_construct_sequence_response(struct nfsd4_session *session,
|
||||
struct nfsd4_sequence *seq)
|
||||
{
|
||||
struct nfs4_client *clp = session->se_client;
|
||||
|
||||
seq->maxslots_response = max(session->se_target_maxslots,
|
||||
seq->maxslots);
|
||||
seq->target_maxslots = session->se_target_maxslots;
|
||||
|
||||
switch (clp->cl_cb_state) {
|
||||
case NFSD4_CB_DOWN:
|
||||
seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
|
||||
break;
|
||||
case NFSD4_CB_FAULT:
|
||||
seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
|
||||
break;
|
||||
default:
|
||||
seq->status_flags = 0;
|
||||
}
|
||||
if (!list_empty(&clp->cl_revoked))
|
||||
seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED;
|
||||
if (atomic_read(&clp->cl_admin_revoked))
|
||||
seq->status_flags |= SEQ4_STATUS_ADMIN_STATE_REVOKED;
|
||||
}
|
||||
|
||||
__be32
|
||||
nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
union nfsd4_op_u *u)
|
||||
@@ -4398,6 +4442,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
dprintk("%s: slotid %d\n", __func__, seq->slotid);
|
||||
|
||||
trace_nfsd_slot_seqid_sequence(clp, seq, slot);
|
||||
|
||||
nfsd4_construct_sequence_response(session, seq);
|
||||
|
||||
status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_flags);
|
||||
if (status == nfserr_replay_cache) {
|
||||
status = nfserr_seq_misordered;
|
||||
@@ -4495,23 +4542,6 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
}
|
||||
|
||||
out:
|
||||
seq->maxslots = max(session->se_target_maxslots, seq->maxslots);
|
||||
seq->target_maxslots = session->se_target_maxslots;
|
||||
|
||||
switch (clp->cl_cb_state) {
|
||||
case NFSD4_CB_DOWN:
|
||||
seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
|
||||
break;
|
||||
case NFSD4_CB_FAULT:
|
||||
seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
|
||||
break;
|
||||
default:
|
||||
seq->status_flags = 0;
|
||||
}
|
||||
if (!list_empty(&clp->cl_revoked))
|
||||
seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED;
|
||||
if (atomic_read(&clp->cl_admin_revoked))
|
||||
seq->status_flags |= SEQ4_STATUS_ADMIN_STATE_REVOKED;
|
||||
trace_nfsd_seq4_status(rqstp, seq);
|
||||
out_no_session:
|
||||
if (conn)
|
||||
|
||||
@@ -5073,7 +5073,7 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
return nfserr;
|
||||
/* Note slotid's are numbered from zero: */
|
||||
/* sr_highest_slotid */
|
||||
nfserr = nfsd4_encode_slotid4(xdr, seq->maxslots - 1);
|
||||
nfserr = nfsd4_encode_slotid4(xdr, seq->maxslots_response - 1);
|
||||
if (nfserr != nfs_ok)
|
||||
return nfserr;
|
||||
/* sr_target_highest_slotid */
|
||||
@@ -5925,8 +5925,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||
*/
|
||||
warn_on_nonidempotent_op(op);
|
||||
xdr_truncate_encode(xdr, op_status_offset + XDR_UNIT);
|
||||
}
|
||||
if (so) {
|
||||
} else if (so) {
|
||||
int len = xdr->buf->len - (op_status_offset + XDR_UNIT);
|
||||
|
||||
so->so_replay.rp_status = op->status;
|
||||
|
||||
@@ -458,6 +458,7 @@ enum {
|
||||
#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
|
||||
(NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
|
||||
FATTR4_WORD2_MODE_UMASK | \
|
||||
FATTR4_WORD2_CLONE_BLKSIZE | \
|
||||
NFSD4_2_SECURITY_ATTRS | \
|
||||
FATTR4_WORD2_XATTR_SUPPORT | \
|
||||
FATTR4_WORD2_TIME_DELEG_ACCESS | \
|
||||
|
||||
@@ -269,9 +269,6 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
|
||||
dentry);
|
||||
}
|
||||
|
||||
fhp->fh_dentry = dentry;
|
||||
fhp->fh_export = exp;
|
||||
|
||||
switch (fhp->fh_maxsize) {
|
||||
case NFS4_FHSIZE:
|
||||
if (dentry->d_sb->s_export_op->flags & EXPORT_OP_NOATOMIC_ATTR)
|
||||
@@ -293,6 +290,9 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
|
||||
goto out;
|
||||
}
|
||||
|
||||
fhp->fh_dentry = dentry;
|
||||
fhp->fh_export = exp;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
exp_put(exp);
|
||||
|
||||
@@ -574,8 +574,9 @@ struct nfsd4_sequence {
|
||||
struct nfs4_sessionid sessionid; /* request/response */
|
||||
u32 seqid; /* request/response */
|
||||
u32 slotid; /* request/response */
|
||||
u32 maxslots; /* request/response */
|
||||
u32 maxslots; /* request */
|
||||
u32 cachethis; /* request */
|
||||
u32 maxslots_response; /* response */
|
||||
u32 target_maxslots; /* response */
|
||||
u32 status_flags; /* response */
|
||||
};
|
||||
|
||||
@@ -18,10 +18,9 @@ config SUNRPC_SWAP
|
||||
|
||||
config RPCSEC_GSS_KRB5
|
||||
tristate "Secure RPC: Kerberos V mechanism"
|
||||
depends on SUNRPC
|
||||
depends on SUNRPC && CRYPTO
|
||||
default y
|
||||
select SUNRPC_GSS
|
||||
select CRYPTO
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_HASH
|
||||
help
|
||||
|
||||
Reference in New Issue
Block a user