fs, nfs: convert nfs_client.cl_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 nfs_client.cl_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>
This commit is contained in:
committed by
Anna Schumaker
parent
2f62b5aa48
commit
212bf41d88
@@ -483,7 +483,7 @@ static int nfs4_match_client(struct nfs_client *pos, struct nfs_client *new,
|
||||
* ID and serverowner fields. Wait for CREATE_SESSION
|
||||
* to finish. */
|
||||
if (pos->cl_cons_state > NFS_CS_READY) {
|
||||
atomic_inc(&pos->cl_count);
|
||||
refcount_inc(&pos->cl_count);
|
||||
spin_unlock(&nn->nfs_client_lock);
|
||||
|
||||
nfs_put_client(*prev);
|
||||
@@ -559,7 +559,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
|
||||
* way that a SETCLIENTID_CONFIRM to pos can succeed is
|
||||
* if new and pos point to the same server:
|
||||
*/
|
||||
atomic_inc(&pos->cl_count);
|
||||
refcount_inc(&pos->cl_count);
|
||||
spin_unlock(&nn->nfs_client_lock);
|
||||
|
||||
nfs_put_client(prev);
|
||||
@@ -715,7 +715,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
|
||||
continue;
|
||||
|
||||
found:
|
||||
atomic_inc(&pos->cl_count);
|
||||
refcount_inc(&pos->cl_count);
|
||||
*result = pos;
|
||||
status = 0;
|
||||
break;
|
||||
@@ -749,7 +749,7 @@ nfs4_find_client_ident(struct net *net, int cb_ident)
|
||||
spin_lock(&nn->nfs_client_lock);
|
||||
clp = idr_find(&nn->cb_ident_idr, cb_ident);
|
||||
if (clp)
|
||||
atomic_inc(&clp->cl_count);
|
||||
refcount_inc(&clp->cl_count);
|
||||
spin_unlock(&nn->nfs_client_lock);
|
||||
return clp;
|
||||
}
|
||||
@@ -804,7 +804,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
|
||||
sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
|
||||
continue;
|
||||
|
||||
atomic_inc(&clp->cl_count);
|
||||
refcount_inc(&clp->cl_count);
|
||||
spin_unlock(&nn->nfs_client_lock);
|
||||
return clp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user