mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	NFSv4.1: Fix Oopsable condition in server callback races
The slot table hasn't been an array since v3.7. Ensure that we
use nfs4_lookup_slot() to access the slot correctly.
Fixes: 87dda67e73 ("NFSv4.1: Allow SEQUENCE to resize the slot table...")
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Cc: stable@vger.kernel.org # v3.8+
			
			
This commit is contained in:
		
							parent
							
								
									16590a2281
								
							
						
					
					
						commit
						e09c978aae
					
				
					 3 changed files with 35 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -454,11 +454,8 @@ static bool referring_call_exists(struct nfs_client *clp,
 | 
			
		|||
				((u32 *)&rclist->rcl_sessionid.data)[3],
 | 
			
		||||
				ref->rc_sequenceid, ref->rc_slotid);
 | 
			
		||||
 | 
			
		||||
			spin_lock(&tbl->slot_tbl_lock);
 | 
			
		||||
			status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
 | 
			
		||||
				  tbl->slots[ref->rc_slotid].seq_nr ==
 | 
			
		||||
			status = nfs4_slot_seqid_in_use(tbl, ref->rc_slotid,
 | 
			
		||||
					ref->rc_sequenceid);
 | 
			
		||||
			spin_unlock(&tbl->slot_tbl_lock);
 | 
			
		||||
			if (status)
 | 
			
		||||
				goto out;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -172,6 +172,39 @@ struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid)
 | 
			
		|||
	return ERR_PTR(-E2BIG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nfs4_slot_get_seqid(struct nfs4_slot_table  *tbl, u32 slotid,
 | 
			
		||||
		u32 *seq_nr)
 | 
			
		||||
	__must_hold(&tbl->slot_tbl_lock)
 | 
			
		||||
{
 | 
			
		||||
	struct nfs4_slot *slot;
 | 
			
		||||
 | 
			
		||||
	slot = nfs4_lookup_slot(tbl, slotid);
 | 
			
		||||
	if (IS_ERR(slot))
 | 
			
		||||
		return PTR_ERR(slot);
 | 
			
		||||
	*seq_nr = slot->seq_nr;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * nfs4_slot_seqid_in_use - test if a slot sequence id is still in use
 | 
			
		||||
 *
 | 
			
		||||
 * Given a slot table, slot id and sequence number, determine if the
 | 
			
		||||
 * RPC call in question is still in flight. This function is mainly
 | 
			
		||||
 * intended for use by the callback channel.
 | 
			
		||||
 */
 | 
			
		||||
bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
 | 
			
		||||
{
 | 
			
		||||
	u32 cur_seq;
 | 
			
		||||
	bool ret = false;
 | 
			
		||||
 | 
			
		||||
	spin_lock(&tbl->slot_tbl_lock);
 | 
			
		||||
	if (nfs4_slot_get_seqid(tbl, slotid, &cur_seq) == 0 &&
 | 
			
		||||
	    cur_seq == seq_nr && test_bit(slotid, tbl->used_slots))
 | 
			
		||||
		ret = true;
 | 
			
		||||
	spin_unlock(&tbl->slot_tbl_lock);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * nfs4_alloc_slot - efficiently look for a free slot
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,7 @@ extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
 | 
			
		|||
extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
 | 
			
		||||
extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
 | 
			
		||||
extern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
 | 
			
		||||
extern bool nfs4_slot_seqid_in_use(struct nfs4_slot_table  *tbl, u32 slotid, u32 seq_nr);
 | 
			
		||||
extern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
 | 
			
		||||
extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
 | 
			
		||||
extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue