]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.16.4/ext4-add-extra-checks-to-ext4_xattr_block_get.patch
drop drm patch
[thirdparty/kernel/stable-queue.git] / releases / 4.16.4 / ext4-add-extra-checks-to-ext4_xattr_block_get.patch
1 From 54dd0e0a1b255f115f8647fc6fb93273251b01b9 Mon Sep 17 00:00:00 2001
2 From: Theodore Ts'o <tytso@mit.edu>
3 Date: Fri, 30 Mar 2018 20:04:11 -0400
4 Subject: ext4: add extra checks to ext4_xattr_block_get()
5
6 From: Theodore Ts'o <tytso@mit.edu>
7
8 commit 54dd0e0a1b255f115f8647fc6fb93273251b01b9 upstream.
9
10 Add explicit checks in ext4_xattr_block_get() just in case the
11 e_value_offs and e_value_size fields in the the xattr block are
12 corrupted in memory after the buffer_verified bit is set on the xattr
13 block.
14
15 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
16 Cc: stable@kernel.org
17 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
18
19 ---
20 fs/ext4/xattr.c | 26 +++++++++++++++++++-------
21 fs/ext4/xattr.h | 11 +++++++++++
22 2 files changed, 30 insertions(+), 7 deletions(-)
23
24 --- a/fs/ext4/xattr.c
25 +++ b/fs/ext4/xattr.c
26 @@ -197,7 +197,7 @@ ext4_xattr_check_entries(struct ext4_xat
27 while (!IS_LAST_ENTRY(entry)) {
28 u32 size = le32_to_cpu(entry->e_value_size);
29
30 - if (size > INT_MAX)
31 + if (size > EXT4_XATTR_SIZE_MAX)
32 return -EFSCORRUPTED;
33
34 if (size != 0 && entry->e_value_inum == 0) {
35 @@ -540,8 +540,10 @@ ext4_xattr_block_get(struct inode *inode
36 if (error)
37 goto cleanup;
38 size = le32_to_cpu(entry->e_value_size);
39 + error = -ERANGE;
40 + if (unlikely(size > EXT4_XATTR_SIZE_MAX))
41 + goto cleanup;
42 if (buffer) {
43 - error = -ERANGE;
44 if (size > buffer_size)
45 goto cleanup;
46 if (entry->e_value_inum) {
47 @@ -550,8 +552,12 @@ ext4_xattr_block_get(struct inode *inode
48 if (error)
49 goto cleanup;
50 } else {
51 - memcpy(buffer, bh->b_data +
52 - le16_to_cpu(entry->e_value_offs), size);
53 + u16 offset = le16_to_cpu(entry->e_value_offs);
54 + void *p = bh->b_data + offset;
55 +
56 + if (unlikely(p + size > end))
57 + goto cleanup;
58 + memcpy(buffer, p, size);
59 }
60 }
61 error = size;
62 @@ -589,8 +595,10 @@ ext4_xattr_ibody_get(struct inode *inode
63 if (error)
64 goto cleanup;
65 size = le32_to_cpu(entry->e_value_size);
66 + error = -ERANGE;
67 + if (unlikely(size > EXT4_XATTR_SIZE_MAX))
68 + goto cleanup;
69 if (buffer) {
70 - error = -ERANGE;
71 if (size > buffer_size)
72 goto cleanup;
73 if (entry->e_value_inum) {
74 @@ -599,8 +607,12 @@ ext4_xattr_ibody_get(struct inode *inode
75 if (error)
76 goto cleanup;
77 } else {
78 - memcpy(buffer, (void *)IFIRST(header) +
79 - le16_to_cpu(entry->e_value_offs), size);
80 + u16 offset = le16_to_cpu(entry->e_value_offs);
81 + void *p = (void *)IFIRST(header) + offset;
82 +
83 + if (unlikely(p + size > end))
84 + goto cleanup;
85 + memcpy(buffer, p, size);
86 }
87 }
88 error = size;
89 --- a/fs/ext4/xattr.h
90 +++ b/fs/ext4/xattr.h
91 @@ -71,6 +71,17 @@ struct ext4_xattr_entry {
92 #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
93
94 /*
95 + * XATTR_SIZE_MAX is currently 64k, but for the purposes of checking
96 + * for file system consistency errors, we use a somewhat bigger value.
97 + * This allows XATTR_SIZE_MAX to grow in the future, but by using this
98 + * instead of INT_MAX for certain consistency checks, we don't need to
99 + * worry about arithmetic overflows. (Actually XATTR_SIZE_MAX is
100 + * defined in include/uapi/linux/limits.h, so changing it is going
101 + * not going to be trivial....)
102 + */
103 +#define EXT4_XATTR_SIZE_MAX (1 << 24)
104 +
105 +/*
106 * The minimum size of EA value when you start storing it in an external inode
107 * size of block - size of header - size of 1 entry - 4 null bytes
108 */