summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-07-06 12:33:55 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2011-07-08 23:15:32 -0700
commit9f8cc942aafab2f90c3ff42e1921691b8212fa5e (patch)
tree1d15b586f4af0f4f8519f1a46e9aa90175433496
parentae852760d3e8a170226f30badad6777ec2c1d847 (diff)
fs: fix lock initialization
commit a51cb91d81f8e6fc4e5e08b772cc3ceb13ac9d37 upstream. locks_alloc_lock() assumed that the allocated struct file_lock is already initialized to zero members. This is only true for the first allocation of the structure, after reuse some of the members will have random values. This will for example result in passing random fl_start values to userspace in fuse for FL_FLOCK locks, which is an information leak at best. Fix by reinitializing those members which may be non-zero after freeing. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/locks.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 0a4f50dfadfb..b286539d547a 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -160,10 +160,28 @@ EXPORT_SYMBOL_GPL(unlock_flocks);
static struct kmem_cache *filelock_cache __read_mostly;
+static void locks_init_lock_always(struct file_lock *fl)
+{
+ fl->fl_next = NULL;
+ fl->fl_fasync = NULL;
+ fl->fl_owner = NULL;
+ fl->fl_pid = 0;
+ fl->fl_nspid = NULL;
+ fl->fl_file = NULL;
+ fl->fl_flags = 0;
+ fl->fl_type = 0;
+ fl->fl_start = fl->fl_end = 0;
+}
+
/* Allocate an empty lock structure. */
struct file_lock *locks_alloc_lock(void)
{
- return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
+ struct file_lock *fl = kmem_cache_alloc(filelock_cache, GFP_KERNEL);
+
+ if (fl)
+ locks_init_lock_always(fl);
+
+ return fl;
}
EXPORT_SYMBOL_GPL(locks_alloc_lock);
@@ -200,17 +218,9 @@ void locks_init_lock(struct file_lock *fl)
INIT_LIST_HEAD(&fl->fl_link);
INIT_LIST_HEAD(&fl->fl_block);
init_waitqueue_head(&fl->fl_wait);
- fl->fl_next = NULL;
- fl->fl_fasync = NULL;
- fl->fl_owner = NULL;
- fl->fl_pid = 0;
- fl->fl_nspid = NULL;
- fl->fl_file = NULL;
- fl->fl_flags = 0;
- fl->fl_type = 0;
- fl->fl_start = fl->fl_end = 0;
fl->fl_ops = NULL;
fl->fl_lmops = NULL;
+ locks_init_lock_always(fl);
}
EXPORT_SYMBOL(locks_init_lock);