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
@ -163,7 +163,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
|
||||
|
||||
clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
|
||||
|
||||
atomic_set(&clp->cl_count, 1);
|
||||
refcount_set(&clp->cl_count, 1);
|
||||
clp->cl_cons_state = NFS_CS_INITING;
|
||||
|
||||
memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
|
||||
@ -269,7 +269,7 @@ void nfs_put_client(struct nfs_client *clp)
|
||||
|
||||
nn = net_generic(clp->cl_net, nfs_net_id);
|
||||
|
||||
if (atomic_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
|
||||
if (refcount_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
|
||||
list_del(&clp->cl_share_link);
|
||||
nfs_cb_idr_remove_locked(clp);
|
||||
spin_unlock(&nn->nfs_client_lock);
|
||||
@ -314,7 +314,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
|
||||
sap))
|
||||
continue;
|
||||
|
||||
atomic_inc(&clp->cl_count);
|
||||
refcount_inc(&clp->cl_count);
|
||||
return clp;
|
||||
}
|
||||
return NULL;
|
||||
@ -1006,7 +1006,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
|
||||
/* Copy data from the source */
|
||||
server->nfs_client = source->nfs_client;
|
||||
server->destroy = source->destroy;
|
||||
atomic_inc(&server->nfs_client->cl_count);
|
||||
refcount_inc(&server->nfs_client->cl_count);
|
||||
nfs_server_copy_userdata(server, source);
|
||||
|
||||
server->fsid = fattr->fsid;
|
||||
@ -1166,7 +1166,7 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
|
||||
clp->rpc_ops->version,
|
||||
rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
|
||||
rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
|
||||
atomic_read(&clp->cl_count),
|
||||
refcount_read(&clp->cl_count),
|
||||
clp->cl_hostname);
|
||||
rcu_read_unlock();
|
||||
|
||||
|
Reference in New Issue
Block a user