summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2012-01-26 10:20:33 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-26 10:20:33 -0800
commit73db2aebb72ba7403c168c5e9cca0ffa943c9a68 (patch)
treea4bc30c1a9c86f358cb30602ee3028a611a1b93a
parente25fd41fdc5a08db29a12caa842121fec1dd29b7 (diff)
downloadlongterm-queue-2.6.32-73db2aebb72ba7403c168c5e9cca0ffa943c9a68.tar.gz
2.6.32-stable patches
added patches: drm-fix-authentication-kernel-crash.patch ecryptfs-improve-metadata-read-failure-logging.patch ecryptfs-make-truncate-path-killable.patch ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch
-rw-r--r--queue-2.6.32/drm-fix-authentication-kernel-crash.patch85
-rw-r--r--queue-2.6.32/ecryptfs-improve-metadata-read-failure-logging.patch56
-rw-r--r--queue-2.6.32/ecryptfs-make-truncate-path-killable.patch69
-rw-r--r--queue-2.6.32/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch101
-rw-r--r--queue-2.6.32/series4
5 files changed, 315 insertions, 0 deletions
diff --git a/queue-2.6.32/drm-fix-authentication-kernel-crash.patch b/queue-2.6.32/drm-fix-authentication-kernel-crash.patch
new file mode 100644
index 0000000..1dbbbf4
--- /dev/null
+++ b/queue-2.6.32/drm-fix-authentication-kernel-crash.patch
@@ -0,0 +1,85 @@
+From 598781d71119827b454fd75d46f84755bca6f0c6 Mon Sep 17 00:00:00 2001
+From: Thomas Hellstrom <thellstrom@vmware.com>
+Date: Tue, 24 Jan 2012 18:54:21 +0100
+Subject: drm: Fix authentication kernel crash
+
+From: Thomas Hellstrom <thellstrom@vmware.com>
+
+commit 598781d71119827b454fd75d46f84755bca6f0c6 upstream.
+
+If the master tries to authenticate a client using drm_authmagic and
+that client has already closed its drm file descriptor,
+either wilfully or because it was terminated, the
+call to drm_authmagic will dereference a stale pointer into kmalloc'ed memory
+and corrupt it.
+
+Typically this results in a hard system hang.
+
+This patch fixes that problem by removing any authentication tokens
+(struct drm_magic_entry) open for a file descriptor when that file
+descriptor is closed.
+
+Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/drm_auth.c | 6 +++++-
+ drivers/gpu/drm/drm_fops.c | 5 +++++
+ include/drm/drmP.h | 1 +
+ 3 files changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_auth.c
++++ b/drivers/gpu/drm/drm_auth.c
+@@ -102,7 +102,7 @@ static int drm_add_magic(struct drm_mast
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_mutex lock.
+ */
+-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
++int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
+ {
+ struct drm_magic_entry *pt;
+ struct drm_hash_item *hash;
+@@ -137,6 +137,8 @@ static int drm_remove_magic(struct drm_m
+ * If there is a magic number in drm_file::magic then use it, otherwise
+ * searches an unique non-zero magic number and add it associating it with \p
+ * file_priv.
++ * This ioctl needs protection by the drm_global_mutex, which protects
++ * struct drm_file::magic and struct drm_magic_entry::priv.
+ */
+ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
+ {
+@@ -174,6 +176,8 @@ int drm_getmagic(struct drm_device *dev,
+ * \return zero if authentication successed, or a negative number otherwise.
+ *
+ * Checks if \p file_priv is associated with the magic number passed in \arg.
++ * This ioctl needs protection by the drm_global_mutex, which protects
++ * struct drm_file::magic and struct drm_magic_entry::priv.
+ */
+ int drm_authmagic(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+--- a/drivers/gpu/drm/drm_fops.c
++++ b/drivers/gpu/drm/drm_fops.c
+@@ -449,6 +449,11 @@ int drm_release(struct inode *inode, str
+ (long)old_encode_dev(file_priv->minor->device),
+ dev->open_count);
+
++ /* Release any auth tokens that might point to this file_priv,
++ (do that under the drm_global_mutex) */
++ if (file_priv->magic)
++ (void) drm_remove_magic(file_priv->master, file_priv->magic);
++
+ /* if the master has gone away we can't do anything with the lock */
+ if (file_priv->minor->master)
+ drm_master_release(dev, filp);
+--- a/include/drm/drmP.h
++++ b/include/drm/drmP.h
+@@ -1221,6 +1221,7 @@ extern int drm_getmagic(struct drm_devic
+ struct drm_file *file_priv);
+ extern int drm_authmagic(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
++extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
+
+ /* Cache management (drm_cache.c) */
+ void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
diff --git a/queue-2.6.32/ecryptfs-improve-metadata-read-failure-logging.patch b/queue-2.6.32/ecryptfs-improve-metadata-read-failure-logging.patch
new file mode 100644
index 0000000..984e63a
--- /dev/null
+++ b/queue-2.6.32/ecryptfs-improve-metadata-read-failure-logging.patch
@@ -0,0 +1,56 @@
+From 30373dc0c87ffef68d5628e77d56ffb1fa22e1ee Mon Sep 17 00:00:00 2001
+From: Tim Gardner <tim.gardner@canonical.com>
+Date: Thu, 12 Jan 2012 16:31:55 +0100
+Subject: ecryptfs: Improve metadata read failure logging
+
+From: Tim Gardner <tim.gardner@canonical.com>
+
+commit 30373dc0c87ffef68d5628e77d56ffb1fa22e1ee upstream.
+
+Print inode on metadata read failure. The only real
+way of dealing with metadata read failures is to delete
+the underlying file system file. Having the inode
+allows one to 'find . -inum INODE`.
+
+[tyhicks@canonical.com: Removed some minor not-for-stable parts]
+Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/crypto.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/ecryptfs/crypto.c
++++ b/fs/ecryptfs/crypto.c
+@@ -1609,7 +1609,8 @@ int ecryptfs_read_metadata(struct dentry
+ rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
+ if (rc) {
+ printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+- "file header region or xattr region\n");
++ "file header region or xattr region, inode %lu\n",
++ ecryptfs_inode->i_ino);
+ rc = -EINVAL;
+ goto out;
+ }
+@@ -1618,7 +1619,8 @@ int ecryptfs_read_metadata(struct dentry
+ ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
+ if (rc) {
+ printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+- "file xattr region either\n");
++ "file xattr region either, inode %lu\n",
++ ecryptfs_inode->i_ino);
+ rc = -EINVAL;
+ }
+ if (crypt_stat->mount_crypt_stat->flags
+@@ -1629,7 +1631,8 @@ int ecryptfs_read_metadata(struct dentry
+ "crypto metadata only in the extended attribute "
+ "region, but eCryptfs was mounted without "
+ "xattr support enabled. eCryptfs will not treat "
+- "this like an encrypted file.\n");
++ "this like an encrypted file, inode %lu\n",
++ ecryptfs_inode->i_ino);
+ rc = -EINVAL;
+ }
+ }
diff --git a/queue-2.6.32/ecryptfs-make-truncate-path-killable.patch b/queue-2.6.32/ecryptfs-make-truncate-path-killable.patch
new file mode 100644
index 0000000..19f3fa0
--- /dev/null
+++ b/queue-2.6.32/ecryptfs-make-truncate-path-killable.patch
@@ -0,0 +1,69 @@
+From 5e6f0d769017cc49207ef56996e42363ec26c1f0 Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@canonical.com>
+Date: Wed, 18 Jan 2012 18:30:04 -0600
+Subject: eCryptfs: Make truncate path killable
+
+From: Tyler Hicks <tyhicks@canonical.com>
+
+commit 5e6f0d769017cc49207ef56996e42363ec26c1f0 upstream.
+
+ecryptfs_write() handles the truncation of eCryptfs inodes. It grabs a
+page, zeroes out the appropriate portions, and then encrypts the page
+before writing it to the lower filesystem. It was unkillable and due to
+the lack of sparse file support could result in tying up a large portion
+of system resources, while encrypting pages of zeros, with no way for
+the truncate operation to be stopped from userspace.
+
+This patch adds the ability for ecryptfs_write() to detect a pending
+fatal signal and return as gracefully as possible. The intent is to
+leave the lower file in a useable state, while still allowing a user to
+break out of the encryption loop. If a pending fatal signal is detected,
+the eCryptfs inode size is updated to reflect the modified inode size
+and then -EINTR is returned.
+
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/read_write.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/fs/ecryptfs/read_write.c
++++ b/fs/ecryptfs/read_write.c
+@@ -136,6 +136,11 @@ int ecryptfs_write(struct file *ecryptfs
+ size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
+ size_t total_remaining_bytes = ((offset + size) - pos);
+
++ if (fatal_signal_pending(current)) {
++ rc = -EINTR;
++ break;
++ }
++
+ if (num_bytes > total_remaining_bytes)
+ num_bytes = total_remaining_bytes;
+ if (pos < offset) {
+@@ -197,15 +202,19 @@ int ecryptfs_write(struct file *ecryptfs
+ }
+ pos += num_bytes;
+ }
+- if ((offset + size) > ecryptfs_file_size) {
+- i_size_write(ecryptfs_inode, (offset + size));
++ if (pos > ecryptfs_file_size) {
++ i_size_write(ecryptfs_inode, pos);
+ if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
+- rc = ecryptfs_write_inode_size_to_metadata(
++ int rc2;
++
++ rc2 = ecryptfs_write_inode_size_to_metadata(
+ ecryptfs_inode);
+- if (rc) {
++ if (rc2) {
+ printk(KERN_ERR "Problem with "
+ "ecryptfs_write_inode_size_to_metadata; "
+- "rc = [%d]\n", rc);
++ "rc = [%d]\n", rc2);
++ if (!rc)
++ rc = rc2;
+ goto out;
+ }
+ }
diff --git a/queue-2.6.32/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch b/queue-2.6.32/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch
new file mode 100644
index 0000000..ca001d0
--- /dev/null
+++ b/queue-2.6.32/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch
@@ -0,0 +1,101 @@
+From db10e556518eb9d21ee92ff944530d84349684f4 Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@canonical.com>
+Date: Thu, 12 Jan 2012 11:30:44 +0100
+Subject: eCryptfs: Sanitize write counts of /dev/ecryptfs
+
+From: Tyler Hicks <tyhicks@canonical.com>
+
+commit db10e556518eb9d21ee92ff944530d84349684f4 upstream.
+
+A malicious count value specified when writing to /dev/ecryptfs may
+result in a a very large kernel memory allocation.
+
+This patch peeks at the specified packet payload size, adds that to the
+size of the packet headers and compares the result with the write count
+value. The resulting maximum memory allocation size is approximately 532
+bytes.
+
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Reported-by: Sasha Levin <levinsasha928@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ecryptfs/miscdev.c | 56 +++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 38 insertions(+), 18 deletions(-)
+
+--- a/fs/ecryptfs/miscdev.c
++++ b/fs/ecryptfs/miscdev.c
+@@ -408,11 +408,47 @@ ecryptfs_miscdev_write(struct file *file
+ ssize_t sz = 0;
+ char *data;
+ uid_t euid = current_euid();
++ unsigned char packet_size_peek[3];
+ int rc;
+
+- if (count == 0)
++ if (count == 0) {
+ goto out;
++ } else if (count == (1 + 4)) {
++ /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
++ goto memdup;
++ } else if (count < (1 + 4 + 1)
++ || count > (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4
++ + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)) {
++ printk(KERN_WARNING "%s: Acceptable packet size range is "
++ "[%d-%lu], but amount of data written is [%zu].",
++ __func__, (1 + 4 + 1),
++ (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4
++ + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES), count);
++ return -EINVAL;
++ }
++
++ if (copy_from_user(packet_size_peek, (buf + 1 + 4),
++ sizeof(packet_size_peek))) {
++ printk(KERN_WARNING "%s: Error while inspecting packet size\n",
++ __func__);
++ return -EFAULT;
++ }
+
++ rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
++ &packet_size_length);
++ if (rc) {
++ printk(KERN_WARNING "%s: Error parsing packet length; "
++ "rc = [%d]\n", __func__, rc);
++ return rc;
++ }
++
++ if ((1 + 4 + packet_size_length + packet_size) != count) {
++ printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
++ packet_size);
++ return -EINVAL;
++ }
++
++memdup:
+ data = memdup_user(buf, count);
+ if (IS_ERR(data)) {
+ printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
+@@ -434,23 +470,7 @@ ecryptfs_miscdev_write(struct file *file
+ }
+ memcpy(&counter_nbo, &data[i], 4);
+ seq = be32_to_cpu(counter_nbo);
+- i += 4;
+- rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
+- &packet_size_length);
+- if (rc) {
+- printk(KERN_WARNING "%s: Error parsing packet length; "
+- "rc = [%d]\n", __func__, rc);
+- goto out_free;
+- }
+- i += packet_size_length;
+- if ((1 + 4 + packet_size_length + packet_size) != count) {
+- printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
+- " + packet_size([%zd]))([%zd]) != "
+- "count([%zd]). Invalid packet format.\n",
+- __func__, packet_size_length, packet_size,
+- (1 + packet_size_length + packet_size), count);
+- goto out_free;
+- }
++ i += 4 + packet_size_length;
+ rc = ecryptfs_miscdev_response(&data[i], packet_size,
+ euid, current_user_ns(),
+ task_pid(current), seq);
diff --git a/queue-2.6.32/series b/queue-2.6.32/series
new file mode 100644
index 0000000..63b0841
--- /dev/null
+++ b/queue-2.6.32/series
@@ -0,0 +1,4 @@
+ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch
+ecryptfs-improve-metadata-read-failure-logging.patch
+ecryptfs-make-truncate-path-killable.patch
+drm-fix-authentication-kernel-crash.patch