mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	NFSv4.x: Fix wraparound issues when validing the callback sequence id
We need to make sure that we don't allow args->csa_sequenceid == 0. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
This commit is contained in:
		
							parent
							
								
									80f9642724
								
							
						
					
					
						commit
						5f83d86cf5
					
				
					 1 changed files with 17 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -354,23 +354,15 @@ __be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
 | 
			
		|||
 * a single outstanding callback request at a time.
 | 
			
		||||
 */
 | 
			
		||||
static __be32
 | 
			
		||||
validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
 | 
			
		||||
validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
 | 
			
		||||
		const struct cb_sequenceargs * args)
 | 
			
		||||
{
 | 
			
		||||
	struct nfs4_slot *slot;
 | 
			
		||||
 | 
			
		||||
	dprintk("%s enter. slotid %u seqid %u\n",
 | 
			
		||||
		__func__, args->csa_slotid, args->csa_sequenceid);
 | 
			
		||||
	dprintk("%s enter. slotid %u seqid %u, slot table seqid: %u\n",
 | 
			
		||||
		__func__, args->csa_slotid, args->csa_sequenceid, slot->seq_nr);
 | 
			
		||||
 | 
			
		||||
	if (args->csa_slotid > tbl->server_highest_slotid)
 | 
			
		||||
		return htonl(NFS4ERR_BADSLOT);
 | 
			
		||||
 | 
			
		||||
	slot = tbl->slots + args->csa_slotid;
 | 
			
		||||
	dprintk("%s slot table seqid: %u\n", __func__, slot->seq_nr);
 | 
			
		||||
 | 
			
		||||
	/* Normal */
 | 
			
		||||
	if (likely(args->csa_sequenceid == slot->seq_nr + 1))
 | 
			
		||||
		goto out_ok;
 | 
			
		||||
 | 
			
		||||
	/* Replay */
 | 
			
		||||
	if (args->csa_sequenceid == slot->seq_nr) {
 | 
			
		||||
		dprintk("%s seqid %u is a replay\n",
 | 
			
		||||
| 
						 | 
				
			
			@ -386,16 +378,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* Wraparound */
 | 
			
		||||
	if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
 | 
			
		||||
		slot->seq_nr = 1;
 | 
			
		||||
		goto out_ok;
 | 
			
		||||
	}
 | 
			
		||||
	if (unlikely(slot->seq_nr == 0xFFFFFFFFU)) {
 | 
			
		||||
		if (args->csa_sequenceid == 1)
 | 
			
		||||
			return htonl(NFS4_OK);
 | 
			
		||||
	} else if (likely(args->csa_sequenceid == slot->seq_nr + 1))
 | 
			
		||||
		return htonl(NFS4_OK);
 | 
			
		||||
 | 
			
		||||
	/* Misordered request */
 | 
			
		||||
	return htonl(NFS4ERR_SEQ_MISORDERED);
 | 
			
		||||
out_ok:
 | 
			
		||||
	tbl->highest_used_slotid = args->csa_slotid;
 | 
			
		||||
	return htonl(NFS4_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -486,6 +476,13 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
 | 
			
		|||
		goto out_unlock;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	status = validate_seqid(tbl, slot, args);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out_unlock;
 | 
			
		||||
 | 
			
		||||
	cps->slotid = args->csa_slotid;
 | 
			
		||||
	tbl->highest_used_slotid = args->csa_slotid;
 | 
			
		||||
 | 
			
		||||
	memcpy(&res->csr_sessionid, &args->csa_sessionid,
 | 
			
		||||
	       sizeof(res->csr_sessionid));
 | 
			
		||||
	res->csr_sequenceid = args->csa_sequenceid;
 | 
			
		||||
| 
						 | 
				
			
			@ -493,12 +490,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
 | 
			
		|||
	res->csr_highestslotid = tbl->server_highest_slotid;
 | 
			
		||||
	res->csr_target_highestslotid = tbl->target_highest_slotid;
 | 
			
		||||
 | 
			
		||||
	status = validate_seqid(tbl, args);
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto out_unlock;
 | 
			
		||||
 | 
			
		||||
	cps->slotid = args->csa_slotid;
 | 
			
		||||
 | 
			
		||||
	/* The ca_maxresponsesize_cached is 0 with no DRC */
 | 
			
		||||
	if (args->csa_cachethis != 0)
 | 
			
		||||
		return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
 | 
			
		||||
| 
						 | 
				
			
			@ -518,7 +509,7 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
 | 
			
		|||
	 * If CB_SEQUENCE returns an error, then the state of the slot
 | 
			
		||||
	 * (sequence ID, cached reply) MUST NOT change.
 | 
			
		||||
	 */
 | 
			
		||||
	slot->seq_nr++;
 | 
			
		||||
	slot->seq_nr = args->csa_sequenceid;
 | 
			
		||||
out_unlock:
 | 
			
		||||
	spin_unlock(&tbl->slot_tbl_lock);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue