From: Greg Kroah-Hartman Date: Thu, 26 Jan 2012 18:19:57 +0000 (-0800) Subject: 3.0-stable patches X-Git-Tag: v3.0.19~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3b51186af70d026707c3e19a3d5e41a3263bcd5a;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: alsa-hda-fix-silent-outputs-from-docking-station-jacks-of-dell-laptops.patch drm-fix-authentication-kernel-crash.patch drm-radeon-kms-add-an-msi-quirk-for-dell-rs690.patch ecryptfs-check-inode-changes-in-setattr.patch ecryptfs-fix-oops-when-printing-debug-info-in-extent-crypto-functions.patch ecryptfs-improve-metadata-read-failure-logging.patch ecryptfs-make-truncate-path-killable.patch ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch xfs-fix-missing-xfs_iunlock-on-error-recovery-path-in-xfs_readlink.patch --- diff --git a/queue-3.0/alsa-hda-fix-silent-outputs-from-docking-station-jacks-of-dell-laptops.patch b/queue-3.0/alsa-hda-fix-silent-outputs-from-docking-station-jacks-of-dell-laptops.patch new file mode 100644 index 00000000000..d9e298497dc --- /dev/null +++ b/queue-3.0/alsa-hda-fix-silent-outputs-from-docking-station-jacks-of-dell-laptops.patch @@ -0,0 +1,61 @@ +From b4ead019afc201f71c39cd0dfcaafed4a97b3dd2 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 23 Jan 2012 18:23:36 +0100 +Subject: ALSA: hda - Fix silent outputs from docking-station jacks of Dell laptops + +From: Takashi Iwai + +commit b4ead019afc201f71c39cd0dfcaafed4a97b3dd2 upstream. + +The recent change of the power-widget handling for IDT codecs caused +the silent output from the docking-station line-out jack. This was +partially fixed by the commit f2cbba7602383cd9cdd21f0a5d0b8bd1aad47b33 +"ALSA: hda - Fix the lost power-setup of seconary pins after PM resume". +But the line-out on the docking-station is still silent when booted +with the jack plugged even by this fix. + +The remainig bug is that the power-widget is set off in stac92xx_init() +because the pins in cfg->line_out_pins[] aren't checked there properly +but only hp_pins[] are checked in is_nid_hp_pin(). + +This patch fixes the problem by checking both HP and line-out pins +and leaving the power-map correctly. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42637 + +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_sigmatel.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -4162,13 +4162,15 @@ static int enable_pin_detect(struct hda_ + return 1; + } + +-static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) ++static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) + { + int i; + for (i = 0; i < cfg->hp_outs; i++) + if (cfg->hp_pins[i] == nid) + return 1; /* nid is a HP-Out */ +- ++ for (i = 0; i < cfg->line_outs; i++) ++ if (cfg->line_out_pins[i] == nid) ++ return 1; /* nid is a line-Out */ + return 0; /* nid is not a HP-Out */ + }; + +@@ -4354,7 +4356,7 @@ static int stac92xx_init(struct hda_code + continue; + } + +- if (is_nid_hp_pin(cfg, nid)) ++ if (is_nid_out_jack_pin(cfg, nid)) + continue; /* already has an unsol event */ + + pinctl = snd_hda_codec_read(codec, nid, 0, diff --git a/queue-3.0/drm-fix-authentication-kernel-crash.patch b/queue-3.0/drm-fix-authentication-kernel-crash.patch new file mode 100644 index 00000000000..aca8630a5f3 --- /dev/null +++ b/queue-3.0/drm-fix-authentication-kernel-crash.patch @@ -0,0 +1,85 @@ +From 598781d71119827b454fd75d46f84755bca6f0c6 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Tue, 24 Jan 2012 18:54:21 +0100 +Subject: drm: Fix authentication kernel crash + +From: Thomas Hellstrom + +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 +Reviewed-by: Daniel Vetter +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -101,7 +101,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; +@@ -136,6 +136,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) + { +@@ -173,6 +175,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 +@@ -486,6 +486,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 +@@ -1323,6 +1323,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-3.0/drm-radeon-kms-add-an-msi-quirk-for-dell-rs690.patch b/queue-3.0/drm-radeon-kms-add-an-msi-quirk-for-dell-rs690.patch new file mode 100644 index 00000000000..47f7806fafd --- /dev/null +++ b/queue-3.0/drm-radeon-kms-add-an-msi-quirk-for-dell-rs690.patch @@ -0,0 +1,36 @@ +From 44517c44496062180a6376cc704b33129441ce60 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Sun, 15 Jan 2012 08:51:12 -0500 +Subject: drm/radeon/kms: Add an MSI quirk for Dell RS690 + +From: Alex Deucher + +commit 44517c44496062180a6376cc704b33129441ce60 upstream. + +Interrupts only work with MSIs. +https://bugs.freedesktop.org/show_bug.cgi?id=37679 + +Reported-by: Dmitry Podgorny +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_irq_kms.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c +@@ -134,6 +134,12 @@ static bool radeon_msi_ok(struct radeon_ + /* Dell RS690 only seems to work with MSIs. */ + if ((rdev->pdev->device == 0x791f) && + (rdev->pdev->subsystem_vendor == 0x1028) && ++ (rdev->pdev->subsystem_device == 0x01fc)) ++ return true; ++ ++ /* Dell RS690 only seems to work with MSIs. */ ++ if ((rdev->pdev->device == 0x791f) && ++ (rdev->pdev->subsystem_vendor == 0x1028) && + (rdev->pdev->subsystem_device == 0x01fd)) + return true; + diff --git a/queue-3.0/ecryptfs-check-inode-changes-in-setattr.patch b/queue-3.0/ecryptfs-check-inode-changes-in-setattr.patch new file mode 100644 index 00000000000..25ff39c9788 --- /dev/null +++ b/queue-3.0/ecryptfs-check-inode-changes-in-setattr.patch @@ -0,0 +1,120 @@ +From a261a03904849c3df50bd0300efb7fb3f865137d Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Thu, 19 Jan 2012 20:33:44 -0600 +Subject: eCryptfs: Check inode changes in setattr + +From: Tyler Hicks + +commit a261a03904849c3df50bd0300efb7fb3f865137d upstream. + +Most filesystems call inode_change_ok() very early in ->setattr(), but +eCryptfs didn't call it at all. It allowed the lower filesystem to make +the call in its ->setattr() function. Then, eCryptfs would copy the +appropriate inode attributes from the lower inode to the eCryptfs inode. + +This patch changes that and actually calls inode_change_ok() on the +eCryptfs inode, fairly early in ecryptfs_setattr(). Ideally, the call +would happen earlier in ecryptfs_setattr(), but there are some possible +inode initialization steps that must happen first. + +Since the call was already being made on the lower inode, the change in +functionality should be minimal, except for the case of a file extending +truncate call. In that case, inode_newsize_ok() was never being +called on the eCryptfs inode. Rather than inode_newsize_ok() catching +maximum file size errors early on, eCryptfs would encrypt zeroed pages +and write them to the lower filesystem until the lower filesystem's +write path caught the error in generic_write_checks(). This patch +introduces a new function, called ecryptfs_inode_newsize_ok(), which +checks if the new lower file size is within the appropriate limits when +the truncate operation will be growing the lower file. + +In summary this change prevents eCryptfs truncate operations (and the +resulting page encryptions), which would exceed the lower filesystem +limits or FSIZE rlimits, from ever starting. + +Signed-off-by: Tyler Hicks +Reviewed-by: Li Wang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/inode.c | 48 ++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 36 insertions(+), 12 deletions(-) + +--- a/fs/ecryptfs/inode.c ++++ b/fs/ecryptfs/inode.c +@@ -854,18 +854,6 @@ static int truncate_upper(struct dentry + size_t num_zeros = (PAGE_CACHE_SIZE + - (ia->ia_size & ~PAGE_CACHE_MASK)); + +- +- /* +- * XXX(truncate) this should really happen at the begginning +- * of ->setattr. But the code is too messy to that as part +- * of a larger patch. ecryptfs is also totally missing out +- * on the inode_change_ok check at the beginning of +- * ->setattr while would include this. +- */ +- rc = inode_newsize_ok(inode, ia->ia_size); +- if (rc) +- goto out; +- + if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { + truncate_setsize(inode, ia->ia_size); + lower_ia->ia_size = ia->ia_size; +@@ -915,6 +903,28 @@ out: + return rc; + } + ++static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset) ++{ ++ struct ecryptfs_crypt_stat *crypt_stat; ++ loff_t lower_oldsize, lower_newsize; ++ ++ crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; ++ lower_oldsize = upper_size_to_lower_size(crypt_stat, ++ i_size_read(inode)); ++ lower_newsize = upper_size_to_lower_size(crypt_stat, offset); ++ if (lower_newsize > lower_oldsize) { ++ /* ++ * The eCryptfs inode and the new *lower* size are mixed here ++ * because we may not have the lower i_mutex held and/or it may ++ * not be appropriate to call inode_newsize_ok() with inodes ++ * from other filesystems. ++ */ ++ return inode_newsize_ok(inode, lower_newsize); ++ } ++ ++ return 0; ++} ++ + /** + * ecryptfs_truncate + * @dentry: The ecryptfs layer dentry +@@ -931,6 +941,10 @@ int ecryptfs_truncate(struct dentry *den + struct iattr lower_ia = { .ia_valid = 0 }; + int rc; + ++ rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length); ++ if (rc) ++ return rc; ++ + rc = truncate_upper(dentry, &ia, &lower_ia); + if (!rc && lower_ia.ia_valid & ATTR_SIZE) { + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); +@@ -1012,6 +1026,16 @@ static int ecryptfs_setattr(struct dentr + } + } + mutex_unlock(&crypt_stat->cs_mutex); ++ ++ rc = inode_change_ok(inode, ia); ++ if (rc) ++ goto out; ++ if (ia->ia_valid & ATTR_SIZE) { ++ rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size); ++ if (rc) ++ goto out; ++ } ++ + if (S_ISREG(inode->i_mode)) { + rc = filemap_write_and_wait(inode->i_mapping); + if (rc) diff --git a/queue-3.0/ecryptfs-fix-oops-when-printing-debug-info-in-extent-crypto-functions.patch b/queue-3.0/ecryptfs-fix-oops-when-printing-debug-info-in-extent-crypto-functions.patch new file mode 100644 index 00000000000..f2ba8d69231 --- /dev/null +++ b/queue-3.0/ecryptfs-fix-oops-when-printing-debug-info-in-extent-crypto-functions.patch @@ -0,0 +1,101 @@ +From 58ded24f0fcb85bddb665baba75892f6ad0f4b8a Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Tue, 24 Jan 2012 10:02:22 -0600 +Subject: eCryptfs: Fix oops when printing debug info in extent crypto functions + +From: Tyler Hicks + +commit 58ded24f0fcb85bddb665baba75892f6ad0f4b8a upstream. + +If pages passed to the eCryptfs extent-based crypto functions are not +mapped and the module parameter ecryptfs_verbosity=1 was specified at +loading time, a NULL pointer dereference will occur. + +Note that this wouldn't happen on a production system, as you wouldn't +pass ecryptfs_verbosity=1 on a production system. It leaks private +information to the system logs and is for debugging only. + +The debugging info printed in these messages is no longer very useful +and rather than doing a kmap() in these debugging paths, it will be +better to simply remove the debugging paths completely. + +https://launchpad.net/bugs/913651 + +Signed-off-by: Tyler Hicks +Reported-by: Daniel DeFreez +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/crypto.c | 40 ---------------------------------------- + 1 file changed, 40 deletions(-) + +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -417,17 +417,6 @@ static int ecryptfs_encrypt_extent(struc + (unsigned long long)(extent_base + extent_offset), rc); + goto out; + } +- if (unlikely(ecryptfs_verbosity > 0)) { +- ecryptfs_printk(KERN_DEBUG, "Encrypting extent " +- "with iv:\n"); +- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); +- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " +- "encryption:\n"); +- ecryptfs_dump_hex((char *) +- (page_address(page) +- + (extent_offset * crypt_stat->extent_size)), +- 8); +- } + rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, + page, (extent_offset + * crypt_stat->extent_size), +@@ -440,14 +429,6 @@ static int ecryptfs_encrypt_extent(struc + goto out; + } + rc = 0; +- if (unlikely(ecryptfs_verbosity > 0)) { +- ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; " +- "rc = [%d]\n", +- (unsigned long long)(extent_base + extent_offset), rc); +- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " +- "encryption:\n"); +- ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8); +- } + out: + return rc; + } +@@ -543,17 +524,6 @@ static int ecryptfs_decrypt_extent(struc + (unsigned long long)(extent_base + extent_offset), rc); + goto out; + } +- if (unlikely(ecryptfs_verbosity > 0)) { +- ecryptfs_printk(KERN_DEBUG, "Decrypting extent " +- "with iv:\n"); +- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); +- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " +- "decryption:\n"); +- ecryptfs_dump_hex((char *) +- (page_address(enc_extent_page) +- + (extent_offset * crypt_stat->extent_size)), +- 8); +- } + rc = ecryptfs_decrypt_page_offset(crypt_stat, page, + (extent_offset + * crypt_stat->extent_size), +@@ -567,16 +537,6 @@ static int ecryptfs_decrypt_extent(struc + goto out; + } + rc = 0; +- if (unlikely(ecryptfs_verbosity > 0)) { +- ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; " +- "rc = [%d]\n", +- (unsigned long long)(extent_base + extent_offset), rc); +- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " +- "decryption:\n"); +- ecryptfs_dump_hex((char *)(page_address(page) +- + (extent_offset +- * crypt_stat->extent_size)), 8); +- } + out: + return rc; + } diff --git a/queue-3.0/ecryptfs-improve-metadata-read-failure-logging.patch b/queue-3.0/ecryptfs-improve-metadata-read-failure-logging.patch new file mode 100644 index 00000000000..89f46ad8db8 --- /dev/null +++ b/queue-3.0/ecryptfs-improve-metadata-read-failure-logging.patch @@ -0,0 +1,56 @@ +From 30373dc0c87ffef68d5628e77d56ffb1fa22e1ee Mon Sep 17 00:00:00 2001 +From: Tim Gardner +Date: Thu, 12 Jan 2012 16:31:55 +0100 +Subject: ecryptfs: Improve metadata read failure logging + +From: Tim Gardner + +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 +Reviewed-by: Kees Cook +Signed-off-by: Tyler Hicks +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/crypto.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -1618,7 +1618,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; + } +@@ -1627,7 +1628,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 +@@ -1638,7 +1640,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-3.0/ecryptfs-make-truncate-path-killable.patch b/queue-3.0/ecryptfs-make-truncate-path-killable.patch new file mode 100644 index 00000000000..ac2e3f59ecd --- /dev/null +++ b/queue-3.0/ecryptfs-make-truncate-path-killable.patch @@ -0,0 +1,69 @@ +From 5e6f0d769017cc49207ef56996e42363ec26c1f0 Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Wed, 18 Jan 2012 18:30:04 -0600 +Subject: eCryptfs: Make truncate path killable + +From: Tyler Hicks + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -132,6 +132,11 @@ int ecryptfs_write(struct inode *ecryptf + 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) { +@@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptf + } + 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-3.0/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch b/queue-3.0/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch new file mode 100644 index 00000000000..3e20654f583 --- /dev/null +++ b/queue-3.0/ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch @@ -0,0 +1,101 @@ +From db10e556518eb9d21ee92ff944530d84349684f4 Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Thu, 12 Jan 2012 11:30:44 +0100 +Subject: eCryptfs: Sanitize write counts of /dev/ecryptfs + +From: Tyler Hicks + +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 +Reported-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/miscdev.c | 56 +++++++++++++++++++++++++++++++++----------------- + 1 file changed, 38 insertions(+), 18 deletions(-) + +--- a/fs/ecryptfs/miscdev.c ++++ b/fs/ecryptfs/miscdev.c +@@ -409,11 +409,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", +@@ -435,23 +471,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-3.0/series b/queue-3.0/series new file mode 100644 index 00000000000..945daa65ac5 --- /dev/null +++ b/queue-3.0/series @@ -0,0 +1,9 @@ +alsa-hda-fix-silent-outputs-from-docking-station-jacks-of-dell-laptops.patch +ecryptfs-sanitize-write-counts-of-dev-ecryptfs.patch +ecryptfs-improve-metadata-read-failure-logging.patch +ecryptfs-make-truncate-path-killable.patch +ecryptfs-check-inode-changes-in-setattr.patch +ecryptfs-fix-oops-when-printing-debug-info-in-extent-crypto-functions.patch +drm-radeon-kms-add-an-msi-quirk-for-dell-rs690.patch +drm-fix-authentication-kernel-crash.patch +xfs-fix-missing-xfs_iunlock-on-error-recovery-path-in-xfs_readlink.patch diff --git a/queue-3.0/xfs-fix-missing-xfs_iunlock-on-error-recovery-path-in-xfs_readlink.patch b/queue-3.0/xfs-fix-missing-xfs_iunlock-on-error-recovery-path-in-xfs_readlink.patch new file mode 100644 index 00000000000..2d5c0ce221e --- /dev/null +++ b/queue-3.0/xfs-fix-missing-xfs_iunlock-on-error-recovery-path-in-xfs_readlink.patch @@ -0,0 +1,35 @@ +From 9b025eb3a89e041bab6698e3858706be2385d692 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 11 Jan 2012 18:52:10 +0000 +Subject: xfs: Fix missing xfs_iunlock() on error recovery path in xfs_readlink() + +From: Jan Kara + +commit 9b025eb3a89e041bab6698e3858706be2385d692 upstream. + +Commit b52a360b forgot to call xfs_iunlock() when it detected corrupted +symplink and bailed out. Fix it by jumping to 'out' instead of doing return. + +CC: Carlos Maiolino +Signed-off-by: Jan Kara +Reviewed-by: Alex Elder +Reviewed-by: Dave Chinner +Signed-off-by: Ben Myers +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_vnodeops.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/xfs/xfs_vnodeops.c ++++ b/fs/xfs/xfs_vnodeops.c +@@ -554,7 +554,8 @@ xfs_readlink( + __func__, (unsigned long long) ip->i_ino, + (long long) pathlen); + ASSERT(0); +- return XFS_ERROR(EFSCORRUPTED); ++ error = XFS_ERROR(EFSCORRUPTED); ++ goto out; + } + +