diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2012-01-26 10:20:33 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2012-01-26 10:20:33 -0800 |
commit | 73db2aebb72ba7403c168c5e9cca0ffa943c9a68 (patch) | |
tree | a4bc30c1a9c86f358cb30602ee3028a611a1b93a | |
parent | e25fd41fdc5a08db29a12caa842121fec1dd29b7 (diff) | |
download | longterm-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
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 |