hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/fs/attr.c
....@@ -18,6 +18,65 @@
1818 #include <linux/evm.h>
1919 #include <linux/ima.h>
2020
21
+#include "internal.h"
22
+
23
+/**
24
+ * setattr_should_drop_sgid - determine whether the setgid bit needs to be
25
+ * removed
26
+ * @inode: inode to check
27
+ *
28
+ * This function determines whether the setgid bit needs to be removed.
29
+ * We retain backwards compatibility and require setgid bit to be removed
30
+ * unconditionally if S_IXGRP is set. Otherwise we have the exact same
31
+ * requirements as setattr_prepare() and setattr_copy().
32
+ *
33
+ * Return: ATTR_KILL_SGID if setgid bit needs to be removed, 0 otherwise.
34
+ */
35
+int setattr_should_drop_sgid(const struct inode *inode)
36
+{
37
+ umode_t mode = inode->i_mode;
38
+
39
+ if (!(mode & S_ISGID))
40
+ return 0;
41
+ if (mode & S_IXGRP)
42
+ return ATTR_KILL_SGID;
43
+ if (!in_group_or_capable(inode, inode->i_gid))
44
+ return ATTR_KILL_SGID;
45
+ return 0;
46
+}
47
+
48
+/**
49
+ * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
50
+ * be dropped
51
+ * @inode: inode to check
52
+ *
53
+ * This function determines whether the set{g,u}id bits need to be removed.
54
+ * If the setuid bit needs to be removed ATTR_KILL_SUID is returned. If the
55
+ * setgid bit needs to be removed ATTR_KILL_SGID is returned. If both
56
+ * set{g,u}id bits need to be removed the corresponding mask of both flags is
57
+ * returned.
58
+ *
59
+ * Return: A mask of ATTR_KILL_S{G,U}ID indicating which - if any - setid bits
60
+ * to remove, 0 otherwise.
61
+ */
62
+int setattr_should_drop_suidgid(struct inode *inode)
63
+{
64
+ umode_t mode = inode->i_mode;
65
+ int kill = 0;
66
+
67
+ /* suid always must be killed */
68
+ if (unlikely(mode & S_ISUID))
69
+ kill = ATTR_KILL_SUID;
70
+
71
+ kill |= setattr_should_drop_sgid(inode);
72
+
73
+ if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
74
+ return kill;
75
+
76
+ return 0;
77
+}
78
+EXPORT_SYMBOL(setattr_should_drop_suidgid);
79
+
2180 static bool chown_ok(const struct inode *inode, kuid_t uid)
2281 {
2382 if (uid_eq(current_fsuid(), inode->i_uid) &&
....@@ -90,9 +149,8 @@
90149 if (!inode_owner_or_capable(inode))
91150 return -EPERM;
92151 /* Also check the setgid bit! */
93
- if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
94
- inode->i_gid) &&
95
- !capable_wrt_inode_uidgid(inode, CAP_FSETID))
152
+ if (!in_group_or_capable(inode, (ia_valid & ATTR_GID) ?
153
+ attr->ia_gid : inode->i_gid))
96154 attr->ia_mode &= ~S_ISGID;
97155 }
98156
....@@ -114,7 +172,7 @@
114172
115173 return 0;
116174 }
117
-EXPORT_SYMBOL(setattr_prepare);
175
+EXPORT_SYMBOL_NS(setattr_prepare, ANDROID_GKI_VFS_EXPORT_ONLY);
118176
119177 /**
120178 * inode_newsize_ok - may this inode be truncated to a given size
....@@ -134,6 +192,8 @@
134192 */
135193 int inode_newsize_ok(const struct inode *inode, loff_t offset)
136194 {
195
+ if (offset < 0)
196
+ return -EINVAL;
137197 if (inode->i_size < offset) {
138198 unsigned long limit;
139199
....@@ -158,7 +218,7 @@
158218 out_big:
159219 return -EFBIG;
160220 }
161
-EXPORT_SYMBOL(inode_newsize_ok);
221
+EXPORT_SYMBOL_NS(inode_newsize_ok, ANDROID_GKI_VFS_EXPORT_ONLY);
162222
163223 /**
164224 * setattr_copy - copy simple metadata updates into the generic inode
....@@ -184,19 +244,14 @@
184244 if (ia_valid & ATTR_GID)
185245 inode->i_gid = attr->ia_gid;
186246 if (ia_valid & ATTR_ATIME)
187
- inode->i_atime = timespec64_trunc(attr->ia_atime,
188
- inode->i_sb->s_time_gran);
247
+ inode->i_atime = attr->ia_atime;
189248 if (ia_valid & ATTR_MTIME)
190
- inode->i_mtime = timespec64_trunc(attr->ia_mtime,
191
- inode->i_sb->s_time_gran);
249
+ inode->i_mtime = attr->ia_mtime;
192250 if (ia_valid & ATTR_CTIME)
193
- inode->i_ctime = timespec64_trunc(attr->ia_ctime,
194
- inode->i_sb->s_time_gran);
251
+ inode->i_ctime = attr->ia_ctime;
195252 if (ia_valid & ATTR_MODE) {
196253 umode_t mode = attr->ia_mode;
197
-
198
- if (!in_group_p(inode->i_gid) &&
199
- !capable_wrt_inode_uidgid(inode, CAP_FSETID))
254
+ if (!in_group_or_capable(inode, inode->i_gid))
200255 mode &= ~S_ISGID;
201256 inode->i_mode = mode;
202257 }
....@@ -223,7 +278,7 @@
223278 * the file open for write, as there can be no conflicting delegation in
224279 * that case.
225280 */
226
-int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
281
+int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
227282 {
228283 struct inode *inode = dentry->d_inode;
229284 umode_t mode = inode->i_mode;
....@@ -247,16 +302,32 @@
247302 return -EPERM;
248303
249304 if (!inode_owner_or_capable(inode)) {
250
- error = inode_permission2(mnt, inode, MAY_WRITE);
305
+ error = inode_permission(inode, MAY_WRITE);
251306 if (error)
252307 return error;
253308 }
254309 }
255310
256311 if ((ia_valid & ATTR_MODE)) {
257
- umode_t amode = attr->ia_mode;
312
+ /*
313
+ * Don't allow changing the mode of symlinks:
314
+ *
315
+ * (1) The vfs doesn't take the mode of symlinks into account
316
+ * during permission checking.
317
+ * (2) This has never worked correctly. Most major filesystems
318
+ * did return EOPNOTSUPP due to interactions with POSIX ACLs
319
+ * but did still updated the mode of the symlink.
320
+ * This inconsistency led system call wrapper providers such
321
+ * as libc to block changing the mode of symlinks with
322
+ * EOPNOTSUPP already.
323
+ * (3) To even do this in the first place one would have to use
324
+ * specific file descriptors and quite some effort.
325
+ */
326
+ if (S_ISLNK(inode->i_mode))
327
+ return -EOPNOTSUPP;
328
+
258329 /* Flag setting protected by i_mutex */
259
- if (is_sxid(amode))
330
+ if (is_sxid(attr->ia_mode))
260331 inode->i_flags &= ~S_NOSEC;
261332 }
262333
....@@ -265,8 +336,13 @@
265336 attr->ia_ctime = now;
266337 if (!(ia_valid & ATTR_ATIME_SET))
267338 attr->ia_atime = now;
339
+ else
340
+ attr->ia_atime = timestamp_truncate(attr->ia_atime, inode);
268341 if (!(ia_valid & ATTR_MTIME_SET))
269342 attr->ia_mtime = now;
343
+ else
344
+ attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode);
345
+
270346 if (ia_valid & ATTR_KILL_PRIV) {
271347 error = security_inode_need_killpriv(dentry);
272348 if (error < 0)
....@@ -293,7 +369,7 @@
293369 }
294370 }
295371 if (ia_valid & ATTR_KILL_SGID) {
296
- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
372
+ if (mode & S_ISGID) {
297373 if (!(ia_valid & ATTR_MODE)) {
298374 ia_valid = attr->ia_valid |= ATTR_MODE;
299375 attr->ia_mode = inode->i_mode;
....@@ -330,9 +406,7 @@
330406 if (error)
331407 return error;
332408
333
- if (mnt && inode->i_op->setattr2)
334
- error = inode->i_op->setattr2(mnt, dentry, attr);
335
- else if (inode->i_op->setattr)
409
+ if (inode->i_op->setattr)
336410 error = inode->i_op->setattr(dentry, attr);
337411 else
338412 error = simple_setattr(dentry, attr);
....@@ -345,10 +419,4 @@
345419
346420 return error;
347421 }
348
-EXPORT_SYMBOL(notify_change2);
349
-
350
-int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
351
-{
352
- return notify_change2(NULL, dentry, attr, delegated_inode);
353
-}
354
-EXPORT_SYMBOL(notify_change);
422
+EXPORT_SYMBOL_NS(notify_change, ANDROID_GKI_VFS_EXPORT_ONLY);