Skip to content

Commit d19fb70

Browse files
kinglongmeeJ. Bruce Fields
authored andcommitted
NFSD: Fix a null reference case in find_or_create_lock_stateid()
nfsd assigns the nfs4_free_lock_stateid to .sc_free in init_lock_stateid(). If nfsd doesn't go through init_lock_stateid() and put stateid at end, there is a NULL reference to .sc_free when calling nfs4_put_stid(ns). This patch let the nfs4_stid.sc_free assignment to nfs4_alloc_stid(). Cc: stable@vger.kernel.org Fixes: 356a95e "nfsd: clean up races in lock stateid searching..." Signed-off-by: Kinglong Mee <kinglongmee@gmail.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 566cf87 commit d19fb70

File tree

3 files changed

+13
-15
lines changed

3 files changed

+13
-15
lines changed

fs/nfsd/nfs4layouts.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,11 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate,
223223
struct nfs4_layout_stateid *ls;
224224
struct nfs4_stid *stp;
225225

226-
stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache);
226+
stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache,
227+
nfsd4_free_layout_stateid);
227228
if (!stp)
228229
return NULL;
229-
stp->sc_free = nfsd4_free_layout_stateid;
230+
230231
get_nfs4_file(fp);
231232
stp->sc_file = fp;
232233

fs/nfsd/nfs4state.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,8 @@ find_or_hash_clnt_odstate(struct nfs4_file *fp, struct nfs4_clnt_odstate *new)
633633
return co;
634634
}
635635

636-
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
637-
struct kmem_cache *slab)
636+
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
637+
void (*sc_free)(struct nfs4_stid *))
638638
{
639639
struct nfs4_stid *stid;
640640
int new_id;
@@ -650,6 +650,8 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
650650
idr_preload_end();
651651
if (new_id < 0)
652652
goto out_free;
653+
654+
stid->sc_free = sc_free;
653655
stid->sc_client = cl;
654656
stid->sc_stateid.si_opaque.so_id = new_id;
655657
stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
@@ -675,15 +677,12 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
675677
static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp)
676678
{
677679
struct nfs4_stid *stid;
678-
struct nfs4_ol_stateid *stp;
679680

680-
stid = nfs4_alloc_stid(clp, stateid_slab);
681+
stid = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_ol_stateid);
681682
if (!stid)
682683
return NULL;
683684

684-
stp = openlockstateid(stid);
685-
stp->st_stid.sc_free = nfs4_free_ol_stateid;
686-
return stp;
685+
return openlockstateid(stid);
687686
}
688687

689688
static void nfs4_free_deleg(struct nfs4_stid *stid)
@@ -781,11 +780,10 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh,
781780
goto out_dec;
782781
if (delegation_blocked(&current_fh->fh_handle))
783782
goto out_dec;
784-
dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab));
783+
dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab, nfs4_free_deleg));
785784
if (dp == NULL)
786785
goto out_dec;
787786

788-
dp->dl_stid.sc_free = nfs4_free_deleg;
789787
/*
790788
* delegation seqid's are never incremented. The 4.1 special
791789
* meaning of seqid 0 isn't meaningful, really, but let's avoid
@@ -5580,7 +5578,6 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
55805578
stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
55815579
get_nfs4_file(fp);
55825580
stp->st_stid.sc_file = fp;
5583-
stp->st_stid.sc_free = nfs4_free_lock_stateid;
55845581
stp->st_access_bmap = 0;
55855582
stp->st_deny_bmap = open_stp->st_deny_bmap;
55865583
stp->st_openstp = open_stp;
@@ -5623,7 +5620,7 @@ find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi,
56235620
lst = find_lock_stateid(lo, fi);
56245621
if (lst == NULL) {
56255622
spin_unlock(&clp->cl_lock);
5626-
ns = nfs4_alloc_stid(clp, stateid_slab);
5623+
ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid);
56275624
if (ns == NULL)
56285625
return NULL;
56295626

fs/nfsd/state.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
603603
__be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
604604
stateid_t *stateid, unsigned char typemask,
605605
struct nfs4_stid **s, struct nfsd_net *nn);
606-
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
607-
struct kmem_cache *slab);
606+
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
607+
void (*sc_free)(struct nfs4_stid *));
608608
void nfs4_unhash_stid(struct nfs4_stid *s);
609609
void nfs4_put_stid(struct nfs4_stid *s);
610610
void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);

0 commit comments

Comments
 (0)