1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * This is <linux/capability.h> 41da177e4SLinus Torvalds * 5b5376771SSerge E. Hallyn * Andrew G. Morgan <[email protected]> 61da177e4SLinus Torvalds * Alexander Kjeldaas <[email protected]> 71da177e4SLinus Torvalds * with help from Aleph1, Roland Buresund and Andrew Main. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * See here for the libcap library ("POSIX draft" compliance): 101da177e4SLinus Torvalds * 11bcf56442SGeunSik Lim * ftp://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/ 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds #ifndef _LINUX_CAPABILITY_H 141da177e4SLinus Torvalds #define _LINUX_CAPABILITY_H 151da177e4SLinus Torvalds 16607ca46eSDavid Howells #include <uapi/linux/capability.h> 172fec30e2SRichard Guy Briggs #include <linux/uidgid.h> 18ca05a99aSAndrew G. Morgan 19ca05a99aSAndrew G. Morgan #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 20ca05a99aSAndrew G. Morgan #define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 211da177e4SLinus Torvalds 229fa91d99SJaswinder Singh Rajput extern int file_caps_enabled; 239fa91d99SJaswinder Singh Rajput 241da177e4SLinus Torvalds typedef struct kernel_cap_struct { 25ca05a99aSAndrew G. Morgan __u32 cap[_KERNEL_CAPABILITY_U32S]; 261da177e4SLinus Torvalds } kernel_cap_t; 271da177e4SLinus Torvalds 282fec30e2SRichard Guy Briggs /* same as vfs_ns_cap_data but in cpu endian and always filled completely */ 29c0b00441SEric Paris struct cpu_vfs_cap_data { 30c0b00441SEric Paris __u32 magic_etc; 31c0b00441SEric Paris kernel_cap_t permitted; 32c0b00441SEric Paris kernel_cap_t inheritable; 332fec30e2SRichard Guy Briggs kuid_t rootid; 34c0b00441SEric Paris }; 35c0b00441SEric Paris 36e338d263SAndrew Morgan #define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) 371da177e4SLinus Torvalds #define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t)) 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds 40935d8aabSLinus Torvalds struct file; 411a48e2acSEric W. Biederman struct inode; 423486740aSSerge E. Hallyn struct dentry; 43db3f6001SAlexey Dobriyan struct task_struct; 443486740aSSerge E. Hallyn struct user_namespace; 4539f60c1cSChristian Brauner struct mnt_idmap; 463486740aSSerge E. Hallyn 473486740aSSerge E. Hallyn extern const kernel_cap_t __cap_empty_set; 483486740aSSerge E. Hallyn extern const kernel_cap_t __cap_init_eff_set; 493486740aSSerge E. Hallyn 501da177e4SLinus Torvalds /* 511da177e4SLinus Torvalds * Internal kernel functions only 521da177e4SLinus Torvalds */ 531da177e4SLinus Torvalds 54e338d263SAndrew Morgan #define CAP_FOR_EACH_U32(__capi) \ 55ca05a99aSAndrew G. Morgan for (__capi = 0; __capi < _KERNEL_CAPABILITY_U32S; ++__capi) 561da177e4SLinus Torvalds 570ad30b8fSSerge E. Hallyn /* 580ad30b8fSSerge E. Hallyn * CAP_FS_MASK and CAP_NFSD_MASKS: 590ad30b8fSSerge E. Hallyn * 600ad30b8fSSerge E. Hallyn * The fs mask is all the privileges that fsuid==0 historically meant. 610ad30b8fSSerge E. Hallyn * At one time in the past, that included CAP_MKNOD and CAP_LINUX_IMMUTABLE. 620ad30b8fSSerge E. Hallyn * 630ad30b8fSSerge E. Hallyn * It has never meant setting security.* and trusted.* xattrs. 640ad30b8fSSerge E. Hallyn * 650ad30b8fSSerge E. Hallyn * We could also define fsmask as follows: 660ad30b8fSSerge E. Hallyn * 1. CAP_FS_MASK is the privilege to bypass all fs-related DAC permissions 670ad30b8fSSerge E. Hallyn * 2. The security.* and trusted.* xattrs are fs-related MAC permissions 680ad30b8fSSerge E. Hallyn */ 690ad30b8fSSerge E. Hallyn 70e338d263SAndrew Morgan # define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ 710ad30b8fSSerge E. Hallyn | CAP_TO_MASK(CAP_MKNOD) \ 72e338d263SAndrew Morgan | CAP_TO_MASK(CAP_DAC_OVERRIDE) \ 73e338d263SAndrew Morgan | CAP_TO_MASK(CAP_DAC_READ_SEARCH) \ 74e338d263SAndrew Morgan | CAP_TO_MASK(CAP_FOWNER) \ 75e338d263SAndrew Morgan | CAP_TO_MASK(CAP_FSETID)) 761da177e4SLinus Torvalds 77e114e473SCasey Schaufler # define CAP_FS_MASK_B1 (CAP_TO_MASK(CAP_MAC_OVERRIDE)) 78e114e473SCasey Schaufler 79ca05a99aSAndrew G. Morgan #if _KERNEL_CAPABILITY_U32S != 2 80e338d263SAndrew Morgan # error Fix up hand-coded capability macro initializers 81e338d263SAndrew Morgan #else /* HAND-CODED capability initializers */ 821da177e4SLinus Torvalds 837d8b6c63SEric Paris #define CAP_LAST_U32 ((_KERNEL_CAPABILITY_U32S) - 1) 847d8b6c63SEric Paris #define CAP_LAST_U32_VALID_MASK (CAP_TO_MASK(CAP_LAST_CAP + 1) -1) 857d8b6c63SEric Paris 8625f2ea9fSDavid Howells # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) 877d8b6c63SEric Paris # define CAP_FULL_SET ((kernel_cap_t){{ ~0, CAP_LAST_U32_VALID_MASK }}) 880ad30b8fSSerge E. Hallyn # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ 890ad30b8fSSerge E. Hallyn | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ 900ad30b8fSSerge E. Hallyn CAP_FS_MASK_B1 } }) 9176a67ec6SJ. Bruce Fields # define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ 920ad30b8fSSerge E. Hallyn | CAP_TO_MASK(CAP_SYS_RESOURCE), \ 9325f2ea9fSDavid Howells CAP_FS_MASK_B1 } }) 941da177e4SLinus Torvalds 95ca05a99aSAndrew G. Morgan #endif /* _KERNEL_CAPABILITY_U32S != 2 */ 961da177e4SLinus Torvalds 97e338d263SAndrew Morgan # define cap_clear(c) do { (c) = __cap_empty_set; } while (0) 981da177e4SLinus Torvalds 99e338d263SAndrew Morgan #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) 100e338d263SAndrew Morgan #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) 101e338d263SAndrew Morgan #define cap_raised(c, flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag)) 102e338d263SAndrew Morgan 103e338d263SAndrew Morgan #define CAP_BOP_ALL(c, a, b, OP) \ 104e338d263SAndrew Morgan do { \ 105e338d263SAndrew Morgan unsigned __capi; \ 106e338d263SAndrew Morgan CAP_FOR_EACH_U32(__capi) { \ 107e338d263SAndrew Morgan c.cap[__capi] = a.cap[__capi] OP b.cap[__capi]; \ 108e338d263SAndrew Morgan } \ 109e338d263SAndrew Morgan } while (0) 110e338d263SAndrew Morgan 111e338d263SAndrew Morgan #define CAP_UOP_ALL(c, a, OP) \ 112e338d263SAndrew Morgan do { \ 113e338d263SAndrew Morgan unsigned __capi; \ 114e338d263SAndrew Morgan CAP_FOR_EACH_U32(__capi) { \ 115e338d263SAndrew Morgan c.cap[__capi] = OP a.cap[__capi]; \ 116e338d263SAndrew Morgan } \ 117e338d263SAndrew Morgan } while (0) 118e338d263SAndrew Morgan 119e338d263SAndrew Morgan static inline kernel_cap_t cap_combine(const kernel_cap_t a, 120e338d263SAndrew Morgan const kernel_cap_t b) 1211da177e4SLinus Torvalds { 1221da177e4SLinus Torvalds kernel_cap_t dest; 123e338d263SAndrew Morgan CAP_BOP_ALL(dest, a, b, |); 1241da177e4SLinus Torvalds return dest; 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds 127e338d263SAndrew Morgan static inline kernel_cap_t cap_intersect(const kernel_cap_t a, 128e338d263SAndrew Morgan const kernel_cap_t b) 1291da177e4SLinus Torvalds { 1301da177e4SLinus Torvalds kernel_cap_t dest; 131e338d263SAndrew Morgan CAP_BOP_ALL(dest, a, b, &); 1321da177e4SLinus Torvalds return dest; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds 135e338d263SAndrew Morgan static inline kernel_cap_t cap_drop(const kernel_cap_t a, 136e338d263SAndrew Morgan const kernel_cap_t drop) 1371da177e4SLinus Torvalds { 1381da177e4SLinus Torvalds kernel_cap_t dest; 139e338d263SAndrew Morgan CAP_BOP_ALL(dest, a, drop, &~); 1401da177e4SLinus Torvalds return dest; 1411da177e4SLinus Torvalds } 1421da177e4SLinus Torvalds 143e338d263SAndrew Morgan static inline kernel_cap_t cap_invert(const kernel_cap_t c) 1441da177e4SLinus Torvalds { 1451da177e4SLinus Torvalds kernel_cap_t dest; 146e338d263SAndrew Morgan CAP_UOP_ALL(dest, c, ~); 1471da177e4SLinus Torvalds return dest; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 150e42852bfSYaowei Bai static inline bool cap_isclear(const kernel_cap_t a) 151e338d263SAndrew Morgan { 152e338d263SAndrew Morgan unsigned __capi; 153e338d263SAndrew Morgan CAP_FOR_EACH_U32(__capi) { 154e338d263SAndrew Morgan if (a.cap[__capi] != 0) 155e42852bfSYaowei Bai return false; 156e338d263SAndrew Morgan } 157e42852bfSYaowei Bai return true; 158e338d263SAndrew Morgan } 1591da177e4SLinus Torvalds 160*a4eecbaeSMateusz Guzik static inline bool cap_isidentical(const kernel_cap_t a, const kernel_cap_t b) 161*a4eecbaeSMateusz Guzik { 162*a4eecbaeSMateusz Guzik unsigned __capi; 163*a4eecbaeSMateusz Guzik CAP_FOR_EACH_U32(__capi) { 164*a4eecbaeSMateusz Guzik if (a.cap[__capi] != b.cap[__capi]) 165*a4eecbaeSMateusz Guzik return false; 166*a4eecbaeSMateusz Guzik } 167*a4eecbaeSMateusz Guzik return true; 168*a4eecbaeSMateusz Guzik } 169*a4eecbaeSMateusz Guzik 1709d36be76SEric Paris /* 1719d36be76SEric Paris * Check if "a" is a subset of "set". 172e42852bfSYaowei Bai * return true if ALL of the capabilities in "a" are also in "set" 173e42852bfSYaowei Bai * cap_issubset(0101, 1111) will return true 174e42852bfSYaowei Bai * return false if ANY of the capabilities in "a" are not in "set" 175e42852bfSYaowei Bai * cap_issubset(1111, 0101) will return false 1769d36be76SEric Paris */ 177e42852bfSYaowei Bai static inline bool cap_issubset(const kernel_cap_t a, const kernel_cap_t set) 178e338d263SAndrew Morgan { 179e338d263SAndrew Morgan kernel_cap_t dest; 180e338d263SAndrew Morgan dest = cap_drop(a, set); 181e338d263SAndrew Morgan return cap_isclear(dest); 182e338d263SAndrew Morgan } 1831da177e4SLinus Torvalds 184e338d263SAndrew Morgan /* Used to decide between falling back on the old suser() or fsuser(). */ 185e338d263SAndrew Morgan 186e338d263SAndrew Morgan static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a) 187e338d263SAndrew Morgan { 188e338d263SAndrew Morgan const kernel_cap_t __cap_fs_set = CAP_FS_SET; 189e338d263SAndrew Morgan return cap_drop(a, __cap_fs_set); 190e338d263SAndrew Morgan } 191e338d263SAndrew Morgan 192e338d263SAndrew Morgan static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a, 193e338d263SAndrew Morgan const kernel_cap_t permitted) 194e338d263SAndrew Morgan { 195e338d263SAndrew Morgan const kernel_cap_t __cap_fs_set = CAP_FS_SET; 196e338d263SAndrew Morgan return cap_combine(a, 197e338d263SAndrew Morgan cap_intersect(permitted, __cap_fs_set)); 198e338d263SAndrew Morgan } 199e338d263SAndrew Morgan 200e338d263SAndrew Morgan static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a) 201e338d263SAndrew Morgan { 202e338d263SAndrew Morgan const kernel_cap_t __cap_fs_set = CAP_NFSD_SET; 203e338d263SAndrew Morgan return cap_drop(a, __cap_fs_set); 204e338d263SAndrew Morgan } 205e338d263SAndrew Morgan 206e338d263SAndrew Morgan static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a, 207e338d263SAndrew Morgan const kernel_cap_t permitted) 208e338d263SAndrew Morgan { 209e338d263SAndrew Morgan const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET; 210e338d263SAndrew Morgan return cap_combine(a, 211e338d263SAndrew Morgan cap_intersect(permitted, __cap_nfsd_set)); 212e338d263SAndrew Morgan } 213e338d263SAndrew Morgan 2142813893fSIulia Manda #ifdef CONFIG_MULTIUSER 2153263245dSSerge E. Hallyn extern bool has_capability(struct task_struct *t, int cap); 2163263245dSSerge E. Hallyn extern bool has_ns_capability(struct task_struct *t, 2173263245dSSerge E. Hallyn struct user_namespace *ns, int cap); 2183263245dSSerge E. Hallyn extern bool has_capability_noaudit(struct task_struct *t, int cap); 2197b61d648SEric Paris extern bool has_ns_capability_noaudit(struct task_struct *t, 2207b61d648SEric Paris struct user_namespace *ns, int cap); 2213486740aSSerge E. Hallyn extern bool capable(int cap); 2223486740aSSerge E. Hallyn extern bool ns_capable(struct user_namespace *ns, int cap); 22398f368e9STyler Hicks extern bool ns_capable_noaudit(struct user_namespace *ns, int cap); 22440852275SMicah Morton extern bool ns_capable_setid(struct user_namespace *ns, int cap); 2252813893fSIulia Manda #else 2262813893fSIulia Manda static inline bool has_capability(struct task_struct *t, int cap) 2272813893fSIulia Manda { 2282813893fSIulia Manda return true; 2292813893fSIulia Manda } 2302813893fSIulia Manda static inline bool has_ns_capability(struct task_struct *t, 2312813893fSIulia Manda struct user_namespace *ns, int cap) 2322813893fSIulia Manda { 2332813893fSIulia Manda return true; 2342813893fSIulia Manda } 2352813893fSIulia Manda static inline bool has_capability_noaudit(struct task_struct *t, int cap) 2362813893fSIulia Manda { 2372813893fSIulia Manda return true; 2382813893fSIulia Manda } 2392813893fSIulia Manda static inline bool has_ns_capability_noaudit(struct task_struct *t, 2402813893fSIulia Manda struct user_namespace *ns, int cap) 2412813893fSIulia Manda { 2422813893fSIulia Manda return true; 2432813893fSIulia Manda } 2442813893fSIulia Manda static inline bool capable(int cap) 2452813893fSIulia Manda { 2462813893fSIulia Manda return true; 2472813893fSIulia Manda } 2482813893fSIulia Manda static inline bool ns_capable(struct user_namespace *ns, int cap) 2492813893fSIulia Manda { 2502813893fSIulia Manda return true; 2512813893fSIulia Manda } 25298f368e9STyler Hicks static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap) 25398f368e9STyler Hicks { 25498f368e9STyler Hicks return true; 25598f368e9STyler Hicks } 25640852275SMicah Morton static inline bool ns_capable_setid(struct user_namespace *ns, int cap) 25740852275SMicah Morton { 25840852275SMicah Morton return true; 25940852275SMicah Morton } 2602813893fSIulia Manda #endif /* CONFIG_MULTIUSER */ 2610558c1bfSChristian Brauner bool privileged_wrt_inode_uidgid(struct user_namespace *ns, 2629452e93eSChristian Brauner struct mnt_idmap *idmap, 2630558c1bfSChristian Brauner const struct inode *inode); 2649452e93eSChristian Brauner bool capable_wrt_inode_uidgid(struct mnt_idmap *idmap, 2650558c1bfSChristian Brauner const struct inode *inode, int cap); 266935d8aabSLinus Torvalds extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); 26764b875f7SEric W. Biederman extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns); 26898073728SAlexey Budankov static inline bool perfmon_capable(void) 26998073728SAlexey Budankov { 27098073728SAlexey Budankov return capable(CAP_PERFMON) || capable(CAP_SYS_ADMIN); 27198073728SAlexey Budankov } 272c59ede7bSRandy.Dunlap 273a17b53c4SAlexei Starovoitov static inline bool bpf_capable(void) 274a17b53c4SAlexei Starovoitov { 275a17b53c4SAlexei Starovoitov return capable(CAP_BPF) || capable(CAP_SYS_ADMIN); 276a17b53c4SAlexei Starovoitov } 277a17b53c4SAlexei Starovoitov 278124ea650SAdrian Reber static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns) 279124ea650SAdrian Reber { 280124ea650SAdrian Reber return ns_capable(ns, CAP_CHECKPOINT_RESTORE) || 281124ea650SAdrian Reber ns_capable(ns, CAP_SYS_ADMIN); 282124ea650SAdrian Reber } 283124ea650SAdrian Reber 284851f7ff5SEric Paris /* audit system wants to get cap info from files as well */ 28539f60c1cSChristian Brauner int get_vfs_caps_from_disk(struct mnt_idmap *idmap, 28671bc356fSChristian Brauner const struct dentry *dentry, 28771bc356fSChristian Brauner struct cpu_vfs_cap_data *cpu_caps); 288851f7ff5SEric Paris 28939f60c1cSChristian Brauner int cap_convert_nscap(struct mnt_idmap *idmap, struct dentry *dentry, 290e65ce2a5SChristian Brauner const void **ivalue, size_t size); 2918db6c34fSSerge E. Hallyn 2921da177e4SLinus Torvalds #endif /* !_LINUX_CAPABILITY_H */ 293