diff options
author | Sona Sarmadi <sona.sarmadi@enea.com> | 2017-02-03 11:01:29 +0100 |
---|---|---|
committer | Adrian Dudau <adrian.dudau@enea.com> | 2017-02-06 10:45:26 +0100 |
commit | ff0bff80783d049ad584e9a0497350211770f138 (patch) | |
tree | a12f5305db185fc78db228f34ccf9e69f1d2067c | |
parent | 5027488b26d6102220ca2444aa73c03c035f0277 (diff) | |
download | meta-enea-bsp-ppc-ff0bff80783d049ad584e9a0497350211770f138.tar.gz |
kernel: CVE-2016-7097
Setting a POSIX ACL via setxattr doesn't clear the setgid bit
The filesystem implementation in the Linux kernel through 4.8.2
preserves the setgid bit during a setxattr call, which allows
local users to gain group privileges by leveraging the existence
of a setgid program with restrictions on execute permissions.
Reference:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7097
Reference to upstream commits (kernel.org 3.12 branch):
https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/log/?id=refs%2Ftags%2Fv3.12.70&qt=grep&q=posix_acl%3A+Clear+SGID+bit+when+setting+file+permissions
Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
-rw-r--r-- | recipes-kernel/linux/files/0002-tmpfs-CVE-2016-7097.patch | 64 | ||||
-rw-r--r-- | recipes-kernel/linux/files/tmpfs-CVE-2016-7097.patch | 440 | ||||
-rw-r--r-- | recipes-kernel/linux/linux-qoriq_3.12.bbappend | 1 |
3 files changed, 505 insertions, 0 deletions
diff --git a/recipes-kernel/linux/files/0002-tmpfs-CVE-2016-7097.patch b/recipes-kernel/linux/files/0002-tmpfs-CVE-2016-7097.patch new file mode 100644 index 0000000..7d8d429 --- /dev/null +++ b/recipes-kernel/linux/files/0002-tmpfs-CVE-2016-7097.patch | |||
@@ -0,0 +1,64 @@ | |||
1 | From b0369e53c851f8cd87afd059d360a4f646840c8c Mon Sep 17 00:00:00 2001 | ||
2 | From: Gu Zheng <guzheng1@huawei.com> | ||
3 | Date: Mon, 9 Jan 2017 09:34:48 +0800 | ||
4 | Subject: tmpfs: clear S_ISGID when setting posix ACLs | ||
5 | |||
6 | commit 497de07d89c1410d76a15bec2bb41f24a2a89f31 upstream. | ||
7 | |||
8 | This change was missed the tmpfs modification in In CVE-2016-7097 | ||
9 | commit 073931017b49 ("posix_acl: Clear SGID bit when setting | ||
10 | file permissions") | ||
11 | It can test by xfstest generic/375, which failed to clear | ||
12 | setgid bit in the following test case on tmpfs: | ||
13 | |||
14 | touch $testfile | ||
15 | chown 100:100 $testfile | ||
16 | chmod 2755 $testfile | ||
17 | _runas -u 100 -g 101 -- setfacl -m u::rwx,g::rwx,o::rwx $testfile | ||
18 | |||
19 | CVE: CVE-2016-7097 | ||
20 | Upstream_status: backport | ||
21 | |||
22 | Signed-off-by: Gu Zheng <guzheng1@huawei.com> | ||
23 | Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> | ||
24 | Signed-off-by: Jan Kara <jack@suse.cz> | ||
25 | Signed-off-by: Jiri Slaby <jslaby@suse.cz> | ||
26 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
27 | --- | ||
28 | fs/generic_acl.c | 12 +++++++----- | ||
29 | 1 file changed, 7 insertions(+), 5 deletions(-) | ||
30 | |||
31 | diff --git a/fs/generic_acl.c b/fs/generic_acl.c | ||
32 | index b3f3676..7855cfb 100644 | ||
33 | --- a/fs/generic_acl.c | ||
34 | +++ b/fs/generic_acl.c | ||
35 | @@ -82,19 +82,21 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value, | ||
36 | return PTR_ERR(acl); | ||
37 | } | ||
38 | if (acl) { | ||
39 | + struct posix_acl *old_acl; | ||
40 | + | ||
41 | error = posix_acl_valid(acl); | ||
42 | if (error) | ||
43 | goto failed; | ||
44 | switch (type) { | ||
45 | case ACL_TYPE_ACCESS: | ||
46 | - error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
47 | + old_acl = acl; | ||
48 | + error = posix_acl_update_mode(inode, &inode->i_mode, | ||
49 | + &acl); | ||
50 | if (error < 0) | ||
51 | goto failed; | ||
52 | + if (!acl) | ||
53 | + posix_acl_release(old_acl); | ||
54 | inode->i_ctime = CURRENT_TIME; | ||
55 | - if (error == 0) { | ||
56 | - posix_acl_release(acl); | ||
57 | - acl = NULL; | ||
58 | - } | ||
59 | break; | ||
60 | case ACL_TYPE_DEFAULT: | ||
61 | if (!S_ISDIR(inode->i_mode)) { | ||
62 | -- | ||
63 | cgit v0.12 | ||
64 | |||
diff --git a/recipes-kernel/linux/files/tmpfs-CVE-2016-7097.patch b/recipes-kernel/linux/files/tmpfs-CVE-2016-7097.patch new file mode 100644 index 0000000..b11830c --- /dev/null +++ b/recipes-kernel/linux/files/tmpfs-CVE-2016-7097.patch | |||
@@ -0,0 +1,440 @@ | |||
1 | From a88a2be387d1d8a5843826e12009c79e32fb46c8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jan Kara <jack@suse.cz> | ||
3 | Date: Tue, 25 Oct 2016 08:44:26 -0500 | ||
4 | Subject: posix_acl: Clear SGID bit when setting file permissions | ||
5 | |||
6 | commit 073931017b49d9458aa351605b43a7e34598caef upstream. | ||
7 | |||
8 | When file permissions are modified via chmod(2) and the user is not in | ||
9 | the owning group or capable of CAP_FSETID, the setgid bit is cleared in | ||
10 | inode_change_ok(). Setting a POSIX ACL via setxattr(2) sets the file | ||
11 | permissions as well as the new ACL, but doesn't clear the setgid bit in | ||
12 | a similar way; this allows to bypass the check in chmod(2). Fix that. | ||
13 | |||
14 | CVE: CVE-2016-7097 | ||
15 | Upstream-Status: Backport | ||
16 | |||
17 | Reviewed-by: Christoph Hellwig <hch@lst.de> | ||
18 | Reviewed-by: Jeff Layton <jlayton@redhat.com> | ||
19 | Signed-off-by: Jan Kara <jack@suse.cz> | ||
20 | Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> | ||
21 | Signed-off-by: Jiri Slaby <jslaby@suse.cz> | ||
22 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
23 | --- | ||
24 | fs/9p/acl.c | 40 +++++++++++++++++----------------------- | ||
25 | fs/btrfs/acl.c | 6 ++---- | ||
26 | fs/ext2/acl.c | 12 ++++-------- | ||
27 | fs/ext3/acl.c | 10 +++------- | ||
28 | fs/ext4/acl.c | 12 ++++-------- | ||
29 | fs/f2fs/acl.c | 6 ++---- | ||
30 | fs/gfs2/acl.c | 14 ++++++-------- | ||
31 | fs/hfsplus/posix_acl.c | 4 ++-- | ||
32 | fs/hfsplus/xattr.c | 5 +++-- | ||
33 | fs/jffs2/acl.c | 9 ++++----- | ||
34 | fs/jfs/xattr.c | 5 +++-- | ||
35 | fs/ocfs2/acl.c | 20 +++++++------------- | ||
36 | fs/posix_acl.c | 31 +++++++++++++++++++++++++++++++ | ||
37 | fs/reiserfs/xattr_acl.c | 8 ++------ | ||
38 | fs/xfs/xfs_acl.c | 15 +++++++-------- | ||
39 | include/linux/posix_acl.h | 1 + | ||
40 | 16 files changed, 98 insertions(+), 100 deletions(-) | ||
41 | |||
42 | diff --git a/fs/9p/acl.c b/fs/9p/acl.c | ||
43 | index 7af425f..9686c1f1 100644 | ||
44 | --- a/fs/9p/acl.c | ||
45 | +++ b/fs/9p/acl.c | ||
46 | @@ -320,32 +320,26 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, | ||
47 | case ACL_TYPE_ACCESS: | ||
48 | name = POSIX_ACL_XATTR_ACCESS; | ||
49 | if (acl) { | ||
50 | - umode_t mode = inode->i_mode; | ||
51 | - retval = posix_acl_equiv_mode(acl, &mode); | ||
52 | - if (retval < 0) | ||
53 | + struct iattr iattr; | ||
54 | + | ||
55 | + retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); | ||
56 | + if (retval) | ||
57 | goto err_out; | ||
58 | - else { | ||
59 | - struct iattr iattr; | ||
60 | - if (retval == 0) { | ||
61 | - /* | ||
62 | - * ACL can be represented | ||
63 | - * by the mode bits. So don't | ||
64 | - * update ACL. | ||
65 | - */ | ||
66 | - acl = NULL; | ||
67 | - value = NULL; | ||
68 | - size = 0; | ||
69 | - } | ||
70 | - /* Updte the mode bits */ | ||
71 | - iattr.ia_mode = ((mode & S_IALLUGO) | | ||
72 | - (inode->i_mode & ~S_IALLUGO)); | ||
73 | - iattr.ia_valid = ATTR_MODE; | ||
74 | - /* FIXME should we update ctime ? | ||
75 | - * What is the following setxattr update the | ||
76 | - * mode ? | ||
77 | + if (!acl) { | ||
78 | + /* | ||
79 | + * ACL can be represented | ||
80 | + * by the mode bits. So don't | ||
81 | + * update ACL. | ||
82 | */ | ||
83 | - v9fs_vfs_setattr_dotl(dentry, &iattr); | ||
84 | + value = NULL; | ||
85 | + size = 0; | ||
86 | } | ||
87 | + iattr.ia_valid = ATTR_MODE; | ||
88 | + /* FIXME should we update ctime ? | ||
89 | + * What is the following setxattr update the | ||
90 | + * mode ? | ||
91 | + */ | ||
92 | + v9fs_vfs_setattr_dotl(dentry, &iattr); | ||
93 | } | ||
94 | break; | ||
95 | case ACL_TYPE_DEFAULT: | ||
96 | diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c | ||
97 | index 0890c83..d6d53e5 100644 | ||
98 | --- a/fs/btrfs/acl.c | ||
99 | +++ b/fs/btrfs/acl.c | ||
100 | @@ -118,11 +118,9 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, | ||
101 | case ACL_TYPE_ACCESS: | ||
102 | name = POSIX_ACL_XATTR_ACCESS; | ||
103 | if (acl) { | ||
104 | - ret = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
105 | - if (ret < 0) | ||
106 | + ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
107 | + if (ret) | ||
108 | return ret; | ||
109 | - if (ret == 0) | ||
110 | - acl = NULL; | ||
111 | } | ||
112 | ret = 0; | ||
113 | break; | ||
114 | diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c | ||
115 | index 110b6b3..48c3c2d 100644 | ||
116 | --- a/fs/ext2/acl.c | ||
117 | +++ b/fs/ext2/acl.c | ||
118 | @@ -206,15 +206,11 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | ||
119 | case ACL_TYPE_ACCESS: | ||
120 | name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; | ||
121 | if (acl) { | ||
122 | - error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
123 | - if (error < 0) | ||
124 | + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
125 | + if (error) | ||
126 | return error; | ||
127 | - else { | ||
128 | - inode->i_ctime = CURRENT_TIME_SEC; | ||
129 | - mark_inode_dirty(inode); | ||
130 | - if (error == 0) | ||
131 | - acl = NULL; | ||
132 | - } | ||
133 | + inode->i_ctime = CURRENT_TIME_SEC; | ||
134 | + mark_inode_dirty(inode); | ||
135 | } | ||
136 | break; | ||
137 | |||
138 | diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c | ||
139 | index dbb5ad5..2f994bb 100644 | ||
140 | --- a/fs/ext3/acl.c | ||
141 | +++ b/fs/ext3/acl.c | ||
142 | @@ -205,15 +205,11 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, | ||
143 | case ACL_TYPE_ACCESS: | ||
144 | name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; | ||
145 | if (acl) { | ||
146 | - error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
147 | + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
148 | if (error < 0) | ||
149 | return error; | ||
150 | - else { | ||
151 | - inode->i_ctime = CURRENT_TIME_SEC; | ||
152 | - ext3_mark_inode_dirty(handle, inode); | ||
153 | - if (error == 0) | ||
154 | - acl = NULL; | ||
155 | - } | ||
156 | + inode->i_ctime = CURRENT_TIME_SEC; | ||
157 | + ext3_mark_inode_dirty(handle, inode); | ||
158 | } | ||
159 | break; | ||
160 | |||
161 | diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c | ||
162 | index 39a54a0..c844f1b 100644 | ||
163 | --- a/fs/ext4/acl.c | ||
164 | +++ b/fs/ext4/acl.c | ||
165 | @@ -211,15 +211,11 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, | ||
166 | case ACL_TYPE_ACCESS: | ||
167 | name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; | ||
168 | if (acl) { | ||
169 | - error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
170 | - if (error < 0) | ||
171 | + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
172 | + if (error) | ||
173 | return error; | ||
174 | - else { | ||
175 | - inode->i_ctime = ext4_current_time(inode); | ||
176 | - ext4_mark_inode_dirty(handle, inode); | ||
177 | - if (error == 0) | ||
178 | - acl = NULL; | ||
179 | - } | ||
180 | + inode->i_ctime = ext4_current_time(inode); | ||
181 | + ext4_mark_inode_dirty(handle, inode); | ||
182 | } | ||
183 | break; | ||
184 | |||
185 | diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c | ||
186 | index b7826ec..f4fefc5 100644 | ||
187 | --- a/fs/f2fs/acl.c | ||
188 | +++ b/fs/f2fs/acl.c | ||
189 | @@ -223,12 +223,10 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | ||
190 | case ACL_TYPE_ACCESS: | ||
191 | name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; | ||
192 | if (acl) { | ||
193 | - error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
194 | - if (error < 0) | ||
195 | + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
196 | + if (error) | ||
197 | return error; | ||
198 | set_acl_inode(fi, inode->i_mode); | ||
199 | - if (error == 0) | ||
200 | - acl = NULL; | ||
201 | } | ||
202 | break; | ||
203 | |||
204 | diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c | ||
205 | index f69ac0a..a61b0c2 100644 | ||
206 | --- a/fs/gfs2/acl.c | ||
207 | +++ b/fs/gfs2/acl.c | ||
208 | @@ -268,15 +268,13 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, | ||
209 | |||
210 | if (type == ACL_TYPE_ACCESS) { | ||
211 | umode_t mode = inode->i_mode; | ||
212 | - error = posix_acl_equiv_mode(acl, &mode); | ||
213 | + struct posix_acl *old_acl = acl; | ||
214 | |||
215 | - if (error <= 0) { | ||
216 | - posix_acl_release(acl); | ||
217 | - acl = NULL; | ||
218 | - | ||
219 | - if (error < 0) | ||
220 | - return error; | ||
221 | - } | ||
222 | + error = posix_acl_update_mode(inode, &mode, &acl); | ||
223 | + if (error < 0) | ||
224 | + goto out_release; | ||
225 | + if (!acl) | ||
226 | + posix_acl_release(old_acl); | ||
227 | |||
228 | error = gfs2_set_mode(inode, mode); | ||
229 | if (error) | ||
230 | diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c | ||
231 | index b609cc1..9f7cc49 100644 | ||
232 | --- a/fs/hfsplus/posix_acl.c | ||
233 | +++ b/fs/hfsplus/posix_acl.c | ||
234 | @@ -72,8 +72,8 @@ static int hfsplus_set_posix_acl(struct inode *inode, | ||
235 | case ACL_TYPE_ACCESS: | ||
236 | xattr_name = POSIX_ACL_XATTR_ACCESS; | ||
237 | if (acl) { | ||
238 | - err = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
239 | - if (err < 0) | ||
240 | + err = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
241 | + if (err) | ||
242 | return err; | ||
243 | } | ||
244 | err = 0; | ||
245 | diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c | ||
246 | index bd8471f..889be3f 100644 | ||
247 | --- a/fs/hfsplus/xattr.c | ||
248 | +++ b/fs/hfsplus/xattr.c | ||
249 | @@ -69,8 +69,9 @@ static int can_set_system_xattr(struct inode *inode, const char *name, | ||
250 | if (IS_ERR(acl)) | ||
251 | return PTR_ERR(acl); | ||
252 | if (acl) { | ||
253 | - err = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
254 | - posix_acl_release(acl); | ||
255 | + struct posix_acl *old_acl = acl; | ||
256 | + err = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
257 | + posix_acl_release(old_acl); | ||
258 | if (err < 0) | ||
259 | return err; | ||
260 | mark_inode_dirty(inode); | ||
261 | diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c | ||
262 | index 223283c..9335b8d 100644 | ||
263 | --- a/fs/jffs2/acl.c | ||
264 | +++ b/fs/jffs2/acl.c | ||
265 | @@ -243,9 +243,10 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | ||
266 | case ACL_TYPE_ACCESS: | ||
267 | xprefix = JFFS2_XPREFIX_ACL_ACCESS; | ||
268 | if (acl) { | ||
269 | - umode_t mode = inode->i_mode; | ||
270 | - rc = posix_acl_equiv_mode(acl, &mode); | ||
271 | - if (rc < 0) | ||
272 | + umode_t mode; | ||
273 | + | ||
274 | + rc = posix_acl_update_mode(inode, &mode, &acl); | ||
275 | + if (rc) | ||
276 | return rc; | ||
277 | if (inode->i_mode != mode) { | ||
278 | struct iattr attr; | ||
279 | @@ -257,8 +258,6 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | ||
280 | if (rc < 0) | ||
281 | return rc; | ||
282 | } | ||
283 | - if (rc == 0) | ||
284 | - acl = NULL; | ||
285 | } | ||
286 | break; | ||
287 | case ACL_TYPE_DEFAULT: | ||
288 | diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c | ||
289 | index d3472f4..8c9b6a0 100644 | ||
290 | --- a/fs/jfs/xattr.c | ||
291 | +++ b/fs/jfs/xattr.c | ||
292 | @@ -693,8 +693,9 @@ static int can_set_system_xattr(struct inode *inode, const char *name, | ||
293 | return rc; | ||
294 | } | ||
295 | if (acl) { | ||
296 | - rc = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
297 | - posix_acl_release(acl); | ||
298 | + struct posix_acl *old_acl = acl; | ||
299 | + rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
300 | + posix_acl_release(old_acl); | ||
301 | if (rc < 0) { | ||
302 | printk(KERN_ERR | ||
303 | "posix_acl_equiv_mode returned %d\n", | ||
304 | diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c | ||
305 | index b4f788e..23095b0 100644 | ||
306 | --- a/fs/ocfs2/acl.c | ||
307 | +++ b/fs/ocfs2/acl.c | ||
308 | @@ -270,20 +270,14 @@ static int ocfs2_set_acl(handle_t *handle, | ||
309 | case ACL_TYPE_ACCESS: | ||
310 | name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; | ||
311 | if (acl) { | ||
312 | - umode_t mode = inode->i_mode; | ||
313 | - ret = posix_acl_equiv_mode(acl, &mode); | ||
314 | - if (ret < 0) | ||
315 | + umode_t mode; | ||
316 | + ret = posix_acl_update_mode(inode, &mode, &acl); | ||
317 | + if (ret) | ||
318 | + return ret; | ||
319 | + ret = ocfs2_acl_set_mode(inode, di_bh, | ||
320 | + handle, mode); | ||
321 | + if (ret) | ||
322 | return ret; | ||
323 | - else { | ||
324 | - if (ret == 0) | ||
325 | - acl = NULL; | ||
326 | - | ||
327 | - ret = ocfs2_acl_set_mode(inode, di_bh, | ||
328 | - handle, mode); | ||
329 | - if (ret) | ||
330 | - return ret; | ||
331 | - | ||
332 | - } | ||
333 | } | ||
334 | break; | ||
335 | case ACL_TYPE_DEFAULT: | ||
336 | diff --git a/fs/posix_acl.c b/fs/posix_acl.c | ||
337 | index 3542f1f..1da000a 100644 | ||
338 | --- a/fs/posix_acl.c | ||
339 | +++ b/fs/posix_acl.c | ||
340 | @@ -407,6 +407,37 @@ posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p) | ||
341 | } | ||
342 | EXPORT_SYMBOL(posix_acl_create); | ||
343 | |||
344 | +/** | ||
345 | + * posix_acl_update_mode - update mode in set_acl | ||
346 | + * | ||
347 | + * Update the file mode when setting an ACL: compute the new file permission | ||
348 | + * bits based on the ACL. In addition, if the ACL is equivalent to the new | ||
349 | + * file mode, set *acl to NULL to indicate that no ACL should be set. | ||
350 | + * | ||
351 | + * As with chmod, clear the setgit bit if the caller is not in the owning group | ||
352 | + * or capable of CAP_FSETID (see inode_change_ok). | ||
353 | + * | ||
354 | + * Called from set_acl inode operations. | ||
355 | + */ | ||
356 | +int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, | ||
357 | + struct posix_acl **acl) | ||
358 | +{ | ||
359 | + umode_t mode = inode->i_mode; | ||
360 | + int error; | ||
361 | + | ||
362 | + error = posix_acl_equiv_mode(*acl, &mode); | ||
363 | + if (error < 0) | ||
364 | + return error; | ||
365 | + if (error == 0) | ||
366 | + *acl = NULL; | ||
367 | + if (!in_group_p(inode->i_gid) && | ||
368 | + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) | ||
369 | + mode &= ~S_ISGID; | ||
370 | + *mode_p = mode; | ||
371 | + return 0; | ||
372 | +} | ||
373 | +EXPORT_SYMBOL(posix_acl_update_mode); | ||
374 | + | ||
375 | int | ||
376 | posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) | ||
377 | { | ||
378 | diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c | ||
379 | index 06c04f7..a86ad7e 100644 | ||
380 | --- a/fs/reiserfs/xattr_acl.c | ||
381 | +++ b/fs/reiserfs/xattr_acl.c | ||
382 | @@ -288,13 +288,9 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, | ||
383 | case ACL_TYPE_ACCESS: | ||
384 | name = POSIX_ACL_XATTR_ACCESS; | ||
385 | if (acl) { | ||
386 | - error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
387 | - if (error < 0) | ||
388 | + error = posix_acl_update_mode(inode, &inode->i_mode, &acl); | ||
389 | + if (error) | ||
390 | return error; | ||
391 | - else { | ||
392 | - if (error == 0) | ||
393 | - acl = NULL; | ||
394 | - } | ||
395 | } | ||
396 | break; | ||
397 | case ACL_TYPE_DEFAULT: | ||
398 | diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c | ||
399 | index 0e2f37e..9c7b5ce 100644 | ||
400 | --- a/fs/xfs/xfs_acl.c | ||
401 | +++ b/fs/xfs/xfs_acl.c | ||
402 | @@ -402,16 +402,15 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, | ||
403 | goto out_release; | ||
404 | |||
405 | if (type == ACL_TYPE_ACCESS) { | ||
406 | - umode_t mode = inode->i_mode; | ||
407 | - error = posix_acl_equiv_mode(acl, &mode); | ||
408 | + umode_t mode; | ||
409 | + struct posix_acl *old_acl = acl; | ||
410 | |||
411 | - if (error <= 0) { | ||
412 | - posix_acl_release(acl); | ||
413 | - acl = NULL; | ||
414 | + error = posix_acl_update_mode(inode, &mode, &acl); | ||
415 | |||
416 | - if (error < 0) | ||
417 | - return error; | ||
418 | - } | ||
419 | + if (error) | ||
420 | + goto out_release; | ||
421 | + if (!acl) | ||
422 | + posix_acl_release(old_acl); | ||
423 | |||
424 | error = xfs_set_mode(inode, mode); | ||
425 | if (error) | ||
426 | diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h | ||
427 | index 7931efe..43cb8d5 100644 | ||
428 | --- a/include/linux/posix_acl.h | ||
429 | +++ b/include/linux/posix_acl.h | ||
430 | @@ -89,6 +89,7 @@ extern int posix_acl_permission(struct inode *, const struct posix_acl *, int); | ||
431 | extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t); | ||
432 | extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *); | ||
433 | extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *); | ||
434 | +extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **); | ||
435 | extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t); | ||
436 | |||
437 | extern struct posix_acl *get_posix_acl(struct inode *, int); | ||
438 | -- | ||
439 | cgit v0.12 | ||
440 | |||
diff --git a/recipes-kernel/linux/linux-qoriq_3.12.bbappend b/recipes-kernel/linux/linux-qoriq_3.12.bbappend index be8cf93..7689676 100644 --- a/recipes-kernel/linux/linux-qoriq_3.12.bbappend +++ b/recipes-kernel/linux/linux-qoriq_3.12.bbappend | |||
@@ -10,5 +10,6 @@ SRC_URI += "file://ppp-CVE-2015-8569.patch \ | |||
10 | file://CVE-2016-5195.patch \ | 10 | file://CVE-2016-5195.patch \ |
11 | file://CVE-2016-6480.patch \ | 11 | file://CVE-2016-6480.patch \ |
12 | file://ring-buffer-CVE-2016-9754.patch \ | 12 | file://ring-buffer-CVE-2016-9754.patch \ |
13 | file://tmpfs-CVE-2016-7097.patch \ | ||
13 | " | 14 | " |
14 | 15 | ||