[linux] 04/04: ecryptfs: forbid opening files without mmap handler (CVE-2016-1583)

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Thu Jun 16 10:52:47 UTC 2016


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch wheezy-security
in repository linux.

commit c085099467ca878d689ebf1bcc4801e89d021225
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Thu Jun 16 03:02:17 2016 +0100

    ecryptfs: forbid opening files without mmap handler (CVE-2016-1583)
    
    Plus another fix it depends on.
---
 debian/changelog                                   |   2 +
 ...cryptfs-fix-handling-of-directory-opening.patch | 144 +++++++++++++++++++++
 ...forbid-opening-files-without-mmap-handler.patch |  38 ++++++
 debian/patches/series                              |   2 +
 4 files changed, 186 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index efcf987..117b2b3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -213,6 +213,8 @@ linux (3.2.81-1) UNRELEASED; urgency=medium
     snd_timer_user_tinterrupt (CVE-2016-4578)
   * tipc: fix an infoleak in tipc_node_get_links (CVE-2016-5243)
   * rds: fix an infoleak in rds_inc_info_copy (CVE-2016-5244)
+  * ecryptfs: fix handling of directory opening
+  * ecryptfs: forbid opening files without mmap handler (CVE-2016-1583)
 
  -- Ben Hutchings <ben at decadent.org.uk>  Fri, 01 Apr 2016 02:11:16 +0100
 
diff --git a/debian/patches/bugfix/all/ecryptfs-fix-handling-of-directory-opening.patch b/debian/patches/bugfix/all/ecryptfs-fix-handling-of-directory-opening.patch
new file mode 100644
index 0000000..20acbec
--- /dev/null
+++ b/debian/patches/bugfix/all/ecryptfs-fix-handling-of-directory-opening.patch
@@ -0,0 +1,144 @@
+From: Al Viro <viro at zeniv.linux.org.uk>
+Date: Wed, 4 May 2016 14:04:13 -0400
+Subject: ecryptfs: fix handling of directory opening
+Origin: https://git.kernel.org/linus/6a480a7842545ec520a91730209ec0bae41694c1
+
+First of all, trying to open them r/w is idiocy; it's guaranteed to fail.
+Moreover, assigning ->f_pos and assuming that everything will work is
+blatantly broken - try that with e.g. tmpfs as underlying layer and watch
+the fireworks.  There may be a non-trivial amount of state associated with
+current IO position, well beyond the numeric offset.  Using the single
+struct file associated with underlying inode is really not a good idea;
+we ought to open one for each ecryptfs directory struct file.
+
+Additionally, file_operations both for directories and non-directories are
+full of pointless methods; non-directories should *not* have ->iterate(),
+directories should not have ->flush(), ->fasync() and ->splice_read().
+
+Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+[bwh: Backported to 3.2:
+ - Use ecryptfs_dentry_to_lower{,_mnt}() instead of
+   ecryptfs_dentry_to_lower_path()
+ - Use %s and explicit lookup of dentry name instead of %pd format
+ - Adjust context]
+---
+ fs/ecryptfs/file.c | 71 ++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 55 insertions(+), 16 deletions(-)
+
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -118,7 +118,6 @@ static int ecryptfs_readdir(struct file
+ 	struct ecryptfs_getdents_callback buf;
+ 
+ 	lower_file = ecryptfs_file_to_lower(file);
+-	lower_file->f_pos = file->f_pos;
+ 	inode = file->f_path.dentry->d_inode;
+ 	memset(&buf, 0, sizeof(buf));
+ 	buf.dirent = dirent;
+@@ -238,14 +237,6 @@ static int ecryptfs_open(struct inode *i
+ 	}
+ 	ecryptfs_set_file_lower(
+ 		file, ecryptfs_inode_to_private(inode)->lower_file);
+-	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
+-		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
+-		mutex_lock(&crypt_stat->cs_mutex);
+-		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+-		mutex_unlock(&crypt_stat->cs_mutex);
+-		rc = 0;
+-		goto out;
+-	}
+ 	rc = read_or_initialize_metadata(ecryptfs_dentry);
+ 	if (rc)
+ 		goto out_put;
+@@ -262,6 +253,46 @@ out:
+ 	return rc;
+ }
+ 
++/**
++ * ecryptfs_dir_open
++ * @inode: inode speciying file to open
++ * @file: Structure to return filled in
++ *
++ * Opens the file specified by inode.
++ *
++ * Returns zero on success; non-zero otherwise
++ */
++static int ecryptfs_dir_open(struct inode *inode, struct file *file)
++{
++	struct dentry *ecryptfs_dentry = file->f_path.dentry;
++	/* Private value of ecryptfs_dentry allocated in
++	 * ecryptfs_lookup() */
++	struct ecryptfs_file_info *file_info;
++	struct file *lower_file;
++
++	/* Released in ecryptfs_release or end of function if failure */
++	file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
++	ecryptfs_set_file_private(file, file_info);
++	if (unlikely(!file_info)) {
++		ecryptfs_printk(KERN_ERR,
++				"Error attempting to allocate memory\n");
++		return -ENOMEM;
++	}
++	lower_file = dentry_open(ecryptfs_dentry_to_lower(ecryptfs_dentry),
++				 ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry),
++				 file->f_flags, current_cred());
++	if (IS_ERR(lower_file)) {
++		printk(KERN_ERR "%s: Error attempting to initialize "
++			"the lower file for the dentry with name "
++			"[%s]; rc = [%ld]\n", __func__,
++			ecryptfs_dentry->d_name.name, PTR_ERR(lower_file));
++		kmem_cache_free(ecryptfs_file_info_cache, file_info);
++		return PTR_ERR(lower_file);
++	}
++	ecryptfs_set_file_lower(file, lower_file);
++	return 0;
++}
++
+ static int ecryptfs_flush(struct file *file, fl_owner_t td)
+ {
+ 	struct file *lower_file = ecryptfs_file_to_lower(file);
+@@ -282,6 +313,19 @@ static int ecryptfs_release(struct inode
+ 	return 0;
+ }
+ 
++static int ecryptfs_dir_release(struct inode *inode, struct file *file)
++{
++	fput(ecryptfs_file_to_lower(file));
++	kmem_cache_free(ecryptfs_file_info_cache,
++			ecryptfs_file_to_private(file));
++	return 0;
++}
++
++static loff_t ecryptfs_dir_llseek(struct file *file, loff_t offset, int whence)
++{
++	return vfs_llseek(ecryptfs_file_to_lower(file), offset, whence);
++}
++
+ static int
+ ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+ {
+@@ -362,13 +406,10 @@ const struct file_operations ecryptfs_di
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl = ecryptfs_compat_ioctl,
+ #endif
+-	.open = ecryptfs_open,
+-	.flush = ecryptfs_flush,
+-	.release = ecryptfs_release,
++	.open = ecryptfs_dir_open,
++	.release = ecryptfs_dir_release,
+ 	.fsync = ecryptfs_fsync,
+-	.fasync = ecryptfs_fasync,
+-	.splice_read = generic_file_splice_read,
+-	.llseek = default_llseek,
++	.llseek = ecryptfs_dir_llseek,
+ };
+ 
+ const struct file_operations ecryptfs_main_fops = {
+@@ -377,7 +418,6 @@ const struct file_operations ecryptfs_ma
+ 	.aio_read = ecryptfs_read_update_atime,
+ 	.write = do_sync_write,
+ 	.aio_write = generic_file_aio_write,
+-	.readdir = ecryptfs_readdir,
+ 	.unlocked_ioctl = ecryptfs_unlocked_ioctl,
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl = ecryptfs_compat_ioctl,
diff --git a/debian/patches/bugfix/all/ecryptfs-forbid-opening-files-without-mmap-handler.patch b/debian/patches/bugfix/all/ecryptfs-forbid-opening-files-without-mmap-handler.patch
new file mode 100644
index 0000000..3cd3345
--- /dev/null
+++ b/debian/patches/bugfix/all/ecryptfs-forbid-opening-files-without-mmap-handler.patch
@@ -0,0 +1,38 @@
+From: Jann Horn <jannh at google.com>
+Date: Wed, 1 Jun 2016 11:55:06 +0200
+Subject: ecryptfs: forbid opening files without mmap handler
+Origin: https://git.kernel.org/linus/2f36db71009304b3f0b95afacd8eba1f9f046b87
+
+This prevents users from triggering a stack overflow through a recursive
+invocation of pagefault handling that involves mapping procfs files into
+virtual memory.
+
+Signed-off-by: Jann Horn <jannh at google.com>
+Acked-by: Tyler Hicks <tyhicks at canonical.com>
+Cc: stable at vger.kernel.org
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+[bwh: Backported to 3.2: There is more to clean up in
+ ecryptfs_privileged_open(), so instead of changing labels and gotos
+ skip the new check if rc != 0.]
+---
+--- a/fs/ecryptfs/kthread.c
++++ b/fs/ecryptfs/kthread.c
+@@ -25,6 +25,7 @@
+ #include <linux/slab.h>
+ #include <linux/wait.h>
+ #include <linux/mount.h>
++#include <linux/file.h>
+ #include "ecryptfs_kernel.h"
+ 
+ struct kmem_cache *ecryptfs_open_req_cache;
+@@ -193,5 +194,10 @@ out_unlock:
+ out_free:
+ 	kmem_cache_free(ecryptfs_open_req_cache, req);
+ out:
++	if (rc == 0 && (*lower_file)->f_op->mmap == NULL) {
++		fput(*lower_file);
++		*lower_file = NULL;
++		rc = -EMEDIUMTYPE;
++	}
+ 	return rc;
+ }
diff --git a/debian/patches/series b/debian/patches/series
index 1f4171c..ae67f7b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1112,6 +1112,8 @@ bugfix/all/alsa-timer-fix-leak-in-events-via-snd_timer_user_cca.patch
 bugfix/all/alsa-timer-fix-leak-in-events-via-snd_timer_user_tin.patch
 bugfix/all/tipc-fix-an-infoleak-in-tipc_nl_compat_link_dump.patch
 bugfix/all/rds-fix-an-infoleak-in-rds_inc_info_copy.patch
+bugfix/all/ecryptfs-fix-handling-of-directory-opening.patch
+bugfix/all/ecryptfs-forbid-opening-files-without-mmap-handler.patch
 
 # ABI maintenance
 debian/perf-hide-abi-change-in-3.2.30.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list