Skip to content

Commit 194bc1f

Browse files
ereshetovaamschuma-ntap
authored andcommitted
fs, nfs: convert nfs4_lock_state.ls_count from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nfs4_lock_state.ls_count is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees Cook <keescook@chromium.org> Reviewed-by: David Windsor <dwindsor@gmail.com> Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 0896cad commit 194bc1f

File tree

3 files changed

+8
-8
lines changed

3 files changed

+8
-8
lines changed

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ struct nfs4_lock_state {
144144
unsigned long ls_flags;
145145
struct nfs_seqid_counter ls_seqid;
146146
nfs4_stateid ls_stateid;
147-
atomic_t ls_count;
147+
refcount_t ls_count;
148148
fl_owner_t ls_owner;
149149
};
150150

fs/nfs/nfs4proc.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,7 +2562,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
25622562
if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
25632563
struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
25642564

2565-
atomic_inc(&lsp->ls_count);
2565+
refcount_inc(&lsp->ls_count);
25662566
spin_unlock(&state->state_lock);
25672567

25682568
nfs4_put_lock_state(prev);
@@ -5923,7 +5923,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
59235923
p->arg.seqid = seqid;
59245924
p->res.seqid = seqid;
59255925
p->lsp = lsp;
5926-
atomic_inc(&lsp->ls_count);
5926+
refcount_inc(&lsp->ls_count);
59275927
/* Ensure we don't close file until we're done freeing locks! */
59285928
p->ctx = get_nfs_open_context(ctx);
59295929
p->l_ctx = nfs_get_lock_context(ctx);
@@ -6139,7 +6139,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
61396139
p->res.lock_seqid = p->arg.lock_seqid;
61406140
p->lsp = lsp;
61416141
p->server = server;
6142-
atomic_inc(&lsp->ls_count);
6142+
refcount_inc(&lsp->ls_count);
61436143
p->ctx = get_nfs_open_context(ctx);
61446144
memcpy(&p->fl, fl, sizeof(p->fl));
61456145
return p;

fs/nfs/nfs4state.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ __nfs4_find_lock_state(struct nfs4_state *state,
825825
ret = pos;
826826
}
827827
if (ret)
828-
atomic_inc(&ret->ls_count);
828+
refcount_inc(&ret->ls_count);
829829
return ret;
830830
}
831831

@@ -843,7 +843,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
843843
if (lsp == NULL)
844844
return NULL;
845845
nfs4_init_seqid_counter(&lsp->ls_seqid);
846-
atomic_set(&lsp->ls_count, 1);
846+
refcount_set(&lsp->ls_count, 1);
847847
lsp->ls_state = state;
848848
lsp->ls_owner = fl_owner;
849849
lsp->ls_seqid.owner_id = ida_simple_get(&server->lockowner_id, 0, 0, GFP_NOFS);
@@ -907,7 +907,7 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
907907
if (lsp == NULL)
908908
return;
909909
state = lsp->ls_state;
910-
if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock))
910+
if (!refcount_dec_and_lock(&lsp->ls_count, &state->state_lock))
911911
return;
912912
list_del(&lsp->ls_locks);
913913
if (list_empty(&state->lock_states))
@@ -927,7 +927,7 @@ static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
927927
struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner;
928928

929929
dst->fl_u.nfs4_fl.owner = lsp;
930-
atomic_inc(&lsp->ls_count);
930+
refcount_inc(&lsp->ls_count);
931931
}
932932

933933
static void nfs4_fl_release_lock(struct file_lock *fl)

0 commit comments

Comments
 (0)