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

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Fri Jun 24 19:56:44 UTC 2016


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

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

commit 944b91d4dd109d88eebbe5aa1c3abe5c4846f3a4
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Fri Jun 24 21:25:39 2016 +0200

    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 | 139 +++++++++++++++++++++
 ...forbid-opening-files-without-mmap-handler.patch |  54 ++++++++
 debian/patches/series                              |   2 +
 4 files changed, 197 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 5f3174d..2ae3cfe 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -18,6 +18,8 @@ linux (3.16.7-ckt25-2+deb8u1) UNRELEASED; urgency=medium
     - usbnet: cleanup after bind() in probe()
   * atl2: Disable unimplemented scatter/gather feature (CVE-2016-2117)
   * mm: hugetlb: allow hugepages_supported to be architecture specific
+  * ecryptfs: fix handling of directory opening
+  * ecryptfs: forbid opening files without mmap handler (CVE-2016-1583)
 
   [ Salvatore Bonaccorso ]
   * [x86] USB: usbip: fix potential out-of-bounds write (CVE-2016-3955)
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..f658f19
--- /dev/null
+++ b/debian/patches/bugfix/all/ecryptfs-fix-handling-of-directory-opening.patch
@@ -0,0 +1,139 @@
+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.16: adjust context]
+---
+ fs/ecryptfs/file.c | 71 ++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 55 insertions(+), 16 deletions(-)
+
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -119,7 +119,6 @@ static int ecryptfs_readdir(struct file
+ 		.sb = inode->i_sb,
+ 	};
+ 	lower_file = ecryptfs_file_to_lower(file);
+-	lower_file->f_pos = ctx->pos;
+ 	rc = iterate_dir(lower_file, &buf.ctx);
+ 	ctx->pos = buf.ctx.pos;
+ 	if (rc < 0)
+@@ -230,14 +229,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;
+@@ -254,6 +245,45 @@ 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_path(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 "
++			"[%pd]; rc = [%ld]\n", __func__,
++			ecryptfs_dentry, 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);
+@@ -274,6 +304,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)
+ {
+@@ -354,13 +397,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 = {
+@@ -369,7 +409,6 @@ const struct file_operations ecryptfs_ma
+ 	.read_iter = ecryptfs_read_update_atime,
+ 	.write = new_sync_write,
+ 	.write_iter = generic_file_write_iter,
+-	.iterate = 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..4bcaa75
--- /dev/null
+++ b/debian/patches/bugfix/all/ecryptfs-forbid-opening-files-without-mmap-handler.patch
@@ -0,0 +1,54 @@
+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>
+---
+ fs/ecryptfs/kthread.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- 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 ecryptfs_open_req {
+@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file
+ 	flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
+ 	(*lower_file) = dentry_open(&req.path, flags, cred);
+ 	if (!IS_ERR(*lower_file))
+-		goto out;
++		goto have_file;
+ 	if ((flags & O_ACCMODE) == O_RDONLY) {
+ 		rc = PTR_ERR((*lower_file));
+ 		goto out;
+@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file
+ 	mutex_unlock(&ecryptfs_kthread_ctl.mux);
+ 	wake_up(&ecryptfs_kthread_ctl.wait);
+ 	wait_for_completion(&req.done);
+-	if (IS_ERR(*lower_file))
++	if (IS_ERR(*lower_file)) {
+ 		rc = PTR_ERR(*lower_file);
++		goto out;
++	}
++have_file:
++	if ((*lower_file)->f_op->mmap == NULL) {
++		fput(*lower_file);
++		*lower_file = NULL;
++		rc = -EMEDIUMTYPE;
++	}
+ out:
+ 	return rc;
+ }
diff --git a/debian/patches/series b/debian/patches/series
index ccfc536..d1a72b8 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -684,3 +684,5 @@ 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

-- 
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