[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