Commit d8e8fbec authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfsd-6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd fixes from Chuck Lever:

 - Address three recently introduced regressions

* tag 'nfsd-6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  NFSD: CREATE_SESSION must never cache NFS4ERR_DELAY replies
  SUNRPC: Revert 561141dd
  nfsd: Fix error cleanup path in nfsd_rename()
parents 50108c35 99dc2ef0
......@@ -3831,15 +3831,20 @@ nfsd4_create_session(struct svc_rqst *rqstp,
else
cs_slot = &unconf->cl_cs_slot;
status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
if (status) {
if (status == nfserr_replay_cache) {
switch (status) {
case nfs_ok:
cs_slot->sl_seqid++;
cr_ses->seqid = cs_slot->sl_seqid;
break;
case nfserr_replay_cache:
status = nfsd4_replay_create_session(cr_ses, cs_slot);
fallthrough;
case nfserr_jukebox:
/* The server MUST NOT cache NFS4ERR_DELAY */
goto out_free_conn;
}
default:
goto out_cache_error;
}
cs_slot->sl_seqid++;
cr_ses->seqid = cs_slot->sl_seqid;
/* RFC 8881 Section 18.36.4 Phase 3: Client ID confirmation. */
if (conf) {
......@@ -3859,10 +3864,8 @@ nfsd4_create_session(struct svc_rqst *rqstp,
old = find_confirmed_client_by_name(&unconf->cl_name, nn);
if (old) {
status = mark_client_expired_locked(old);
if (status) {
old = NULL;
goto out_cache_error;
}
if (status)
goto out_expired_error;
trace_nfsd_clid_replaced(&old->cl_clientid);
}
move_to_confirmed(unconf);
......@@ -3894,6 +3897,17 @@ nfsd4_create_session(struct svc_rqst *rqstp,
expire_client(old);
return status;
out_expired_error:
old = NULL;
/*
* Revert the slot seq_nr change so the server will process
* the client's resend instead of returning a cached response.
*/
if (status == nfserr_jukebox) {
cs_slot->sl_seqid--;
cr_ses->seqid = cs_slot->sl_seqid;
goto out_free_conn;
}
out_cache_error:
nfsd4_cache_create_session(cr_ses, cs_slot, status);
out_free_conn:
......
......@@ -1852,7 +1852,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
trap = lock_rename(tdentry, fdentry);
if (IS_ERR(trap)) {
err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
goto out;
goto out_want_write;
}
err = fh_fill_pre_attrs(ffhp);
if (err != nfs_ok)
......@@ -1922,6 +1922,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
}
out_unlock:
unlock_rename(tdentry, fdentry);
out_want_write:
fh_drop_write(ffhp);
/*
......
......@@ -921,8 +921,6 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
* Caller provides the truncation length of the output token (h) in
* cksumout.len.
*
* Note that for RPCSEC, the "initial cipher state" is always all zeroes.
*
* Return values:
* %GSS_S_COMPLETE: Digest computed, @cksumout filled in
* %GSS_S_FAILURE: Call failed
......@@ -933,19 +931,22 @@ u32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
int body_offset, struct xdr_netobj *cksumout)
{
unsigned int ivsize = crypto_sync_skcipher_ivsize(cipher);
static const u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
struct ahash_request *req;
struct scatterlist sg[1];
u8 *iv, *checksumdata;
int err = -ENOMEM;
u8 *checksumdata;
checksumdata = kmalloc(crypto_ahash_digestsize(tfm), GFP_KERNEL);
if (!checksumdata)
return GSS_S_FAILURE;
/* For RPCSEC, the "initial cipher state" is always all zeroes. */
iv = kzalloc(ivsize, GFP_KERNEL);
if (!iv)
goto out_free_mem;
req = ahash_request_alloc(tfm, GFP_KERNEL);
if (!req)
goto out_free_cksumdata;
goto out_free_mem;
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
err = crypto_ahash_init(req);
if (err)
......@@ -969,7 +970,8 @@ u32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
out_free_ahash:
ahash_request_free(req);
out_free_cksumdata:
out_free_mem:
kfree(iv);
kfree_sensitive(checksumdata);
return err ? GSS_S_FAILURE : GSS_S_COMPLETE;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment