Skip to content

Commit e09c978

Browse files
committed
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: 87dda67 ("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+
1 parent 16590a2 commit e09c978

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

fs/nfs/callback_proc.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,8 @@ static bool referring_call_exists(struct nfs_client *clp,
454454
((u32 *)&rclist->rcl_sessionid.data)[3],
455455
ref->rc_sequenceid, ref->rc_slotid);
456456

457-
spin_lock(&tbl->slot_tbl_lock);
458-
status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
459-
tbl->slots[ref->rc_slotid].seq_nr ==
457+
status = nfs4_slot_seqid_in_use(tbl, ref->rc_slotid,
460458
ref->rc_sequenceid);
461-
spin_unlock(&tbl->slot_tbl_lock);
462459
if (status)
463460
goto out;
464461
}

fs/nfs/nfs4session.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,39 @@ struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid)
172172
return ERR_PTR(-E2BIG);
173173
}
174174

175+
static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
176+
u32 *seq_nr)
177+
__must_hold(&tbl->slot_tbl_lock)
178+
{
179+
struct nfs4_slot *slot;
180+
181+
slot = nfs4_lookup_slot(tbl, slotid);
182+
if (IS_ERR(slot))
183+
return PTR_ERR(slot);
184+
*seq_nr = slot->seq_nr;
185+
return 0;
186+
}
187+
188+
/*
189+
* nfs4_slot_seqid_in_use - test if a slot sequence id is still in use
190+
*
191+
* Given a slot table, slot id and sequence number, determine if the
192+
* RPC call in question is still in flight. This function is mainly
193+
* intended for use by the callback channel.
194+
*/
195+
bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
196+
{
197+
u32 cur_seq;
198+
bool ret = false;
199+
200+
spin_lock(&tbl->slot_tbl_lock);
201+
if (nfs4_slot_get_seqid(tbl, slotid, &cur_seq) == 0 &&
202+
cur_seq == seq_nr && test_bit(slotid, tbl->used_slots))
203+
ret = true;
204+
spin_unlock(&tbl->slot_tbl_lock);
205+
return ret;
206+
}
207+
175208
/*
176209
* nfs4_alloc_slot - efficiently look for a free slot
177210
*

fs/nfs/nfs4session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
7878
extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
7979
extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
8080
extern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
81+
extern bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr);
8182
extern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
8283
extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
8384
extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);

0 commit comments

Comments
 (0)