Update patch add-better-range-checking-for-xattr-value-sizes
[ext4-patch-queue.git] / add-better-range-checking-for-xattr-value-sizes
blobdc10d25f4b520492912f9ff06360f0705410abf1
1 ext4: limit xattr size to INT_MAX
3 From: Eric Biggers <ebiggers@google.com>
5 ext4 isn't validating the sizes of xattrs where the value of the xattr
6 is stored in an external inode.  This is problematic because
7 ->e_value_size is a u32, but ext4_xattr_get() returns an int.  A very
8 large size is misinterpreted as an error code, which ext4_get_acl()
9 translates into a bogus ERR_PTR() for which IS_ERR() returns false,
10 causing a crash.
12 Fix this by validating that all xattrs are <= INT_MAX bytes.  Also add
13 explicit checks in ext4_xattr_block_get() and ext4_xattr_ibody_get()
14 just in case the xattr block is corrupted in memory after it is
15 verifeid.
17 This issue has been assigned CVE-2018-1095.
19 https://bugzilla.kernel.org/show_bug.cgi?id=199185
20 https://bugzilla.redhat.com/show_bug.cgi?id=1560793
22 Reported-by: Wen Xu <wen.xu@gatech.edu>
23 Signed-off-by: Eric Biggers <ebiggers@google.com>
24 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
25 Cc: stable@vger.kernel.org
26 Fixes: e50e5129f384 ("ext4: xattr-in-inode support")
27 ---
28  fs/ext4/xattr.c | 14 +++++++++++---
29  1 file changed, 11 insertions(+), 3 deletions(-)
31 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
32 index 63656dbafdc4..d2a9b078e121 100644
33 --- a/fs/ext4/xattr.c
34 +++ b/fs/ext4/xattr.c
35 @@ -195,10 +195,14 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
37         /* Check the values */
38         while (!IS_LAST_ENTRY(entry)) {
39 +               u32 size = le32_to_cpu(entry->e_value_size);
41 +               if (size > INT_MAX)
42 +                       return -EFSCORRUPTED;
44                 if (entry->e_value_size != 0 &&
45                     entry->e_value_inum == 0) {
46                         u16 offs = le16_to_cpu(entry->e_value_offs);
47 -                       u32 size = le32_to_cpu(entry->e_value_size);
48                         void *value;
50                         /*
51 @@ -523,8 +527,10 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
52         if (error)
53                 goto cleanup;
54         size = le32_to_cpu(entry->e_value_size);
55 +       error = -ERANGE;
56 +       if (unlikely(size > INT_MAX))
57 +               goto cleanup;
58         if (buffer) {
59 -               error = -ERANGE;
60                 if (size > buffer_size)
61                         goto cleanup;
62                 if (entry->e_value_inum) {
63 @@ -572,8 +578,10 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
64         if (error)
65                 goto cleanup;
66         size = le32_to_cpu(entry->e_value_size);
67 +       error = -ERANGE;
68 +       if (unlikely(size > INT_MAX))
69 +               goto cleanup;
70         if (buffer) {
71 -               error = -ERANGE;
72                 if (size > buffer_size)
73                         goto cleanup;
74                 if (entry->e_value_inum) {