aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorElena Reshetova <elena.reshetova@intel.com>2017-10-20 05:53:37 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2017-11-17 13:48:01 -0500
commit2f62b5aa4814be2c511553fd6afb4d35b6c2503b (patch)
treecf402bfd8d23ea6dbf02e67a45edd9e49a8822af /fs/nfs/inode.c
parent194bc1f48100a3b6fbd50d7a2218b594f0c564b6 (diff)
fs, nfs: convert nfs_lock_context.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_lock_context.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>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 134d9f560240..52a60e399a2d 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -783,7 +783,7 @@ EXPORT_SYMBOL_GPL(nfs_getattr);
783 783
784static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) 784static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
785{ 785{
786 atomic_set(&l_ctx->count, 1); 786 refcount_set(&l_ctx->count, 1);
787 l_ctx->lockowner = current->files; 787 l_ctx->lockowner = current->files;
788 INIT_LIST_HEAD(&l_ctx->list); 788 INIT_LIST_HEAD(&l_ctx->list);
789 atomic_set(&l_ctx->io_count, 0); 789 atomic_set(&l_ctx->io_count, 0);
@@ -797,7 +797,7 @@ static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context
797 do { 797 do {
798 if (pos->lockowner != current->files) 798 if (pos->lockowner != current->files)
799 continue; 799 continue;
800 atomic_inc(&pos->count); 800 refcount_inc(&pos->count);
801 return pos; 801 return pos;
802 } while ((pos = list_entry(pos->list.next, typeof(*pos), list)) != head); 802 } while ((pos = list_entry(pos->list.next, typeof(*pos), list)) != head);
803 return NULL; 803 return NULL;
@@ -836,7 +836,7 @@ void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
836 struct nfs_open_context *ctx = l_ctx->open_context; 836 struct nfs_open_context *ctx = l_ctx->open_context;
837 struct inode *inode = d_inode(ctx->dentry); 837 struct inode *inode = d_inode(ctx->dentry);
838 838
839 if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock)) 839 if (!refcount_dec_and_lock(&l_ctx->count, &inode->i_lock))
840 return; 840 return;
841 list_del(&l_ctx->list); 841 list_del(&l_ctx->list);
842 spin_unlock(&inode->i_lock); 842 spin_unlock(&inode->i_lock);
@@ -913,7 +913,7 @@ EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
913struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) 913struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
914{ 914{
915 if (ctx != NULL) 915 if (ctx != NULL)
916 atomic_inc(&ctx->lock_context.count); 916 refcount_inc(&ctx->lock_context.count);
917 return ctx; 917 return ctx;
918} 918}
919EXPORT_SYMBOL_GPL(get_nfs_open_context); 919EXPORT_SYMBOL_GPL(get_nfs_open_context);
@@ -924,11 +924,11 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
924 struct super_block *sb = ctx->dentry->d_sb; 924 struct super_block *sb = ctx->dentry->d_sb;
925 925
926 if (!list_empty(&ctx->list)) { 926 if (!list_empty(&ctx->list)) {
927 if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) 927 if (!refcount_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
928 return; 928 return;
929 list_del(&ctx->list); 929 list_del(&ctx->list);
930 spin_unlock(&inode->i_lock); 930 spin_unlock(&inode->i_lock);
931 } else if (!atomic_dec_and_test(&ctx->lock_context.count)) 931 } else if (!refcount_dec_and_test(&ctx->lock_context.count))
932 return; 932 return;
933 if (inode != NULL) 933 if (inode != NULL)
934 NFS_PROTO(inode)->close_context(ctx, is_sync); 934 NFS_PROTO(inode)->close_context(ctx, is_sync);