[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