hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/inode.c
....@@ -1016,6 +1016,48 @@
10161016 EXPORT_SYMBOL(discard_new_inode);
10171017
10181018 /**
1019
+ * lock_two_inodes - lock two inodes (may be regular files but also dirs)
1020
+ *
1021
+ * Lock any non-NULL argument. The caller must make sure that if he is passing
1022
+ * in two directories, one is not ancestor of the other. Zero, one or two
1023
+ * objects may be locked by this function.
1024
+ *
1025
+ * @inode1: first inode to lock
1026
+ * @inode2: second inode to lock
1027
+ * @subclass1: inode lock subclass for the first lock obtained
1028
+ * @subclass2: inode lock subclass for the second lock obtained
1029
+ */
1030
+void lock_two_inodes(struct inode *inode1, struct inode *inode2,
1031
+ unsigned subclass1, unsigned subclass2)
1032
+{
1033
+ if (!inode1 || !inode2) {
1034
+ /*
1035
+ * Make sure @subclass1 will be used for the acquired lock.
1036
+ * This is not strictly necessary (no current caller cares) but
1037
+ * let's keep things consistent.
1038
+ */
1039
+ if (!inode1)
1040
+ swap(inode1, inode2);
1041
+ goto lock;
1042
+ }
1043
+
1044
+ /*
1045
+ * If one object is directory and the other is not, we must make sure
1046
+ * to lock directory first as the other object may be its child.
1047
+ */
1048
+ if (S_ISDIR(inode2->i_mode) == S_ISDIR(inode1->i_mode)) {
1049
+ if (inode1 > inode2)
1050
+ swap(inode1, inode2);
1051
+ } else if (!S_ISDIR(inode1->i_mode))
1052
+ swap(inode1, inode2);
1053
+lock:
1054
+ if (inode1)
1055
+ inode_lock_nested(inode1, subclass1);
1056
+ if (inode2 && inode2 != inode1)
1057
+ inode_lock_nested(inode2, subclass2);
1058
+}
1059
+
1060
+/**
10191061 * lock_two_nondirectories - take two i_mutexes on non-directory objects
10201062 *
10211063 * Lock any non-NULL argument that is not a directory.
....@@ -1855,35 +1897,6 @@
18551897 EXPORT_SYMBOL_NS(touch_atime, ANDROID_GKI_VFS_EXPORT_ONLY);
18561898
18571899 /*
1858
- * The logic we want is
1859
- *
1860
- * if suid or (sgid and xgrp)
1861
- * remove privs
1862
- */
1863
-int should_remove_suid(struct dentry *dentry)
1864
-{
1865
- umode_t mode = d_inode(dentry)->i_mode;
1866
- int kill = 0;
1867
-
1868
- /* suid always must be killed */
1869
- if (unlikely(mode & S_ISUID))
1870
- kill = ATTR_KILL_SUID;
1871
-
1872
- /*
1873
- * sgid without any exec bits is just a mandatory locking mark; leave
1874
- * it alone. If some exec bits are set, it's a real sgid; kill it.
1875
- */
1876
- if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
1877
- kill |= ATTR_KILL_SGID;
1878
-
1879
- if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
1880
- return kill;
1881
-
1882
- return 0;
1883
-}
1884
-EXPORT_SYMBOL(should_remove_suid);
1885
-
1886
-/*
18871900 * Return mask of changes for notify_change() that need to be done as a
18881901 * response to write or truncate. Return 0 if nothing has to be changed.
18891902 * Negative value on error (change should be denied).
....@@ -1897,7 +1910,7 @@
18971910 if (IS_NOSEC(inode))
18981911 return 0;
18991912
1900
- mask = should_remove_suid(dentry);
1913
+ mask = setattr_should_drop_suidgid(inode);
19011914 ret = security_inode_need_killpriv(dentry);
19021915 if (ret < 0)
19031916 return ret;
....@@ -2147,10 +2160,6 @@
21472160 /* Directories are special, and always inherit S_ISGID */
21482161 if (S_ISDIR(mode))
21492162 mode |= S_ISGID;
2150
- else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) &&
2151
- !in_group_p(inode->i_gid) &&
2152
- !capable_wrt_inode_uidgid(dir, CAP_FSETID))
2153
- mode &= ~S_ISGID;
21542163 } else
21552164 inode->i_gid = current_fsgid();
21562165 inode->i_mode = mode;
....@@ -2382,3 +2391,48 @@
23822391 return 0;
23832392 }
23842393 EXPORT_SYMBOL(vfs_ioc_fssetxattr_check);
2394
+
2395
+/**
2396
+ * in_group_or_capable - check whether caller is CAP_FSETID privileged
2397
+ * @inode: inode to check
2398
+ * @gid: the new/current gid of @inode
2399
+ *
2400
+ * Check wether @gid is in the caller's group list or if the caller is
2401
+ * privileged with CAP_FSETID over @inode. This can be used to determine
2402
+ * whether the setgid bit can be kept or must be dropped.
2403
+ *
2404
+ * Return: true if the caller is sufficiently privileged, false if not.
2405
+ */
2406
+bool in_group_or_capable(const struct inode *inode, kgid_t gid)
2407
+{
2408
+ if (in_group_p(gid))
2409
+ return true;
2410
+ if (capable_wrt_inode_uidgid(inode, CAP_FSETID))
2411
+ return true;
2412
+ return false;
2413
+}
2414
+
2415
+/**
2416
+ * mode_strip_sgid - handle the sgid bit for non-directories
2417
+ * @dir: parent directory inode
2418
+ * @mode: mode of the file to be created in @dir
2419
+ *
2420
+ * If the @mode of the new file has both the S_ISGID and S_IXGRP bit
2421
+ * raised and @dir has the S_ISGID bit raised ensure that the caller is
2422
+ * either in the group of the parent directory or they have CAP_FSETID
2423
+ * in their user namespace and are privileged over the parent directory.
2424
+ * In all other cases, strip the S_ISGID bit from @mode.
2425
+ *
2426
+ * Return: the new mode to use for the file
2427
+ */
2428
+umode_t mode_strip_sgid(const struct inode *dir, umode_t mode)
2429
+{
2430
+ if ((mode & (S_ISGID | S_IXGRP)) != (S_ISGID | S_IXGRP))
2431
+ return mode;
2432
+ if (S_ISDIR(mode) || !dir || !(dir->i_mode & S_ISGID))
2433
+ return mode;
2434
+ if (in_group_or_capable(dir, dir->i_gid))
2435
+ return mode;
2436
+ return mode & ~S_ISGID;
2437
+}
2438
+EXPORT_SYMBOL(mode_strip_sgid);