1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/kernel/capability.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1997 Andrew Main <zefram@fysh.org> 61da177e4SLinus Torvalds * 772c2d582SAndrew Morgan * Integrated into 2.1.97+, Andrew G. Morgan <morgan@kernel.org> 81da177e4SLinus Torvalds * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 11f5645d35SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12f5645d35SJoe Perches 13e68b75a0SEric Paris #include <linux/audit.h> 14c59ede7bSRandy.Dunlap #include <linux/capability.h> 151da177e4SLinus Torvalds #include <linux/mm.h> 169984de1aSPaul Gortmaker #include <linux/export.h> 171da177e4SLinus Torvalds #include <linux/security.h> 181da177e4SLinus Torvalds #include <linux/syscalls.h> 19b460cbc5SSerge E. Hallyn #include <linux/pid_namespace.h> 203486740aSSerge E. Hallyn #include <linux/user_namespace.h> 217c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds /* 24e338d263SAndrew Morgan * Leveraged for setting/resetting capabilities 25e338d263SAndrew Morgan */ 26e338d263SAndrew Morgan 27e338d263SAndrew Morgan const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; 28e338d263SAndrew Morgan EXPORT_SYMBOL(__cap_empty_set); 29e338d263SAndrew Morgan 301f29fae2SSerge E. Hallyn int file_caps_enabled = 1; 311f29fae2SSerge E. Hallyn 321f29fae2SSerge E. Hallyn static int __init file_caps_disable(char *str) 331f29fae2SSerge E. Hallyn { 341f29fae2SSerge E. Hallyn file_caps_enabled = 0; 351f29fae2SSerge E. Hallyn return 1; 361f29fae2SSerge E. Hallyn } 371f29fae2SSerge E. Hallyn __setup("no_file_caps", file_caps_disable); 381f29fae2SSerge E. Hallyn 392813893fSIulia Manda #ifdef CONFIG_MULTIUSER 40e338d263SAndrew Morgan /* 41e338d263SAndrew Morgan * More recent versions of libcap are available from: 42e338d263SAndrew Morgan * 43e338d263SAndrew Morgan * http://www.kernel.org/pub/linux/libs/security/linux-privs/ 44e338d263SAndrew Morgan */ 45e338d263SAndrew Morgan 46e338d263SAndrew Morgan static void warn_legacy_capability_use(void) 47e338d263SAndrew Morgan { 48e338d263SAndrew Morgan char name[sizeof(current->comm)]; 49e338d263SAndrew Morgan 50f5645d35SJoe Perches pr_info_once("warning: `%s' uses 32-bit capabilities (legacy support in use)\n", 51e338d263SAndrew Morgan get_task_comm(name, current)); 52e338d263SAndrew Morgan } 53e338d263SAndrew Morgan 54e338d263SAndrew Morgan /* 55ca05a99aSAndrew G. Morgan * Version 2 capabilities worked fine, but the linux/capability.h file 56ca05a99aSAndrew G. Morgan * that accompanied their introduction encouraged their use without 57ca05a99aSAndrew G. Morgan * the necessary user-space source code changes. As such, we have 58ca05a99aSAndrew G. Morgan * created a version 3 with equivalent functionality to version 2, but 59ca05a99aSAndrew G. Morgan * with a header change to protect legacy source code from using 60ca05a99aSAndrew G. Morgan * version 2 when it wanted to use version 1. If your system has code 61ca05a99aSAndrew G. Morgan * that trips the following warning, it is using version 2 specific 62ca05a99aSAndrew G. Morgan * capabilities and may be doing so insecurely. 63ca05a99aSAndrew G. Morgan * 64ca05a99aSAndrew G. Morgan * The remedy is to either upgrade your version of libcap (to 2.10+, 65ca05a99aSAndrew G. Morgan * if the application is linked against it), or recompile your 66ca05a99aSAndrew G. Morgan * application with modern kernel headers and this warning will go 67ca05a99aSAndrew G. Morgan * away. 68ca05a99aSAndrew G. Morgan */ 69ca05a99aSAndrew G. Morgan 70ca05a99aSAndrew G. Morgan static void warn_deprecated_v2(void) 71ca05a99aSAndrew G. Morgan { 72ca05a99aSAndrew G. Morgan char name[sizeof(current->comm)]; 73ca05a99aSAndrew G. Morgan 74f5645d35SJoe Perches pr_info_once("warning: `%s' uses deprecated v2 capabilities in a way that may be insecure\n", 75ca05a99aSAndrew G. Morgan get_task_comm(name, current)); 76ca05a99aSAndrew G. Morgan } 77ca05a99aSAndrew G. Morgan 78ca05a99aSAndrew G. Morgan /* 79ca05a99aSAndrew G. Morgan * Version check. Return the number of u32s in each capability flag 80ca05a99aSAndrew G. Morgan * array, or a negative value on error. 81ca05a99aSAndrew G. Morgan */ 82ca05a99aSAndrew G. Morgan static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) 83ca05a99aSAndrew G. Morgan { 84ca05a99aSAndrew G. Morgan __u32 version; 85ca05a99aSAndrew G. Morgan 86ca05a99aSAndrew G. Morgan if (get_user(version, &header->version)) 87ca05a99aSAndrew G. Morgan return -EFAULT; 88ca05a99aSAndrew G. Morgan 89ca05a99aSAndrew G. Morgan switch (version) { 90ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_1: 91ca05a99aSAndrew G. Morgan warn_legacy_capability_use(); 92ca05a99aSAndrew G. Morgan *tocopy = _LINUX_CAPABILITY_U32S_1; 93ca05a99aSAndrew G. Morgan break; 94ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_2: 95ca05a99aSAndrew G. Morgan warn_deprecated_v2(); 96ca05a99aSAndrew G. Morgan /* 97ca05a99aSAndrew G. Morgan * fall through - v3 is otherwise equivalent to v2. 98ca05a99aSAndrew G. Morgan */ 99ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_3: 100ca05a99aSAndrew G. Morgan *tocopy = _LINUX_CAPABILITY_U32S_3; 101ca05a99aSAndrew G. Morgan break; 102ca05a99aSAndrew G. Morgan default: 103ca05a99aSAndrew G. Morgan if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version)) 104ca05a99aSAndrew G. Morgan return -EFAULT; 105ca05a99aSAndrew G. Morgan return -EINVAL; 106ca05a99aSAndrew G. Morgan } 107ca05a99aSAndrew G. Morgan 108ca05a99aSAndrew G. Morgan return 0; 109ca05a99aSAndrew G. Morgan } 110ca05a99aSAndrew G. Morgan 111ab763c71SAndrew G. Morgan /* 112d84f4f99SDavid Howells * The only thing that can change the capabilities of the current 113d84f4f99SDavid Howells * process is the current process. As such, we can't be in this code 114d84f4f99SDavid Howells * at the same time as we are in the process of setting capabilities 115d84f4f99SDavid Howells * in this process. The net result is that we can limit our use of 116d84f4f99SDavid Howells * locks to when we are reading the caps of another process. 117ab763c71SAndrew G. Morgan */ 118ab763c71SAndrew G. Morgan static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, 119ab763c71SAndrew G. Morgan kernel_cap_t *pIp, kernel_cap_t *pPp) 120ab763c71SAndrew G. Morgan { 121ab763c71SAndrew G. Morgan int ret; 122ab763c71SAndrew G. Morgan 123ab763c71SAndrew G. Morgan if (pid && (pid != task_pid_vnr(current))) { 124ab763c71SAndrew G. Morgan struct task_struct *target; 125ab763c71SAndrew G. Morgan 12686fc80f1SThomas Gleixner rcu_read_lock(); 127ab763c71SAndrew G. Morgan 128ab763c71SAndrew G. Morgan target = find_task_by_vpid(pid); 129ab763c71SAndrew G. Morgan if (!target) 130ab763c71SAndrew G. Morgan ret = -ESRCH; 131ab763c71SAndrew G. Morgan else 132ab763c71SAndrew G. Morgan ret = security_capget(target, pEp, pIp, pPp); 133ab763c71SAndrew G. Morgan 13486fc80f1SThomas Gleixner rcu_read_unlock(); 135ab763c71SAndrew G. Morgan } else 136ab763c71SAndrew G. Morgan ret = security_capget(current, pEp, pIp, pPp); 137ab763c71SAndrew G. Morgan 138ab763c71SAndrew G. Morgan return ret; 139ab763c71SAndrew G. Morgan } 140ab763c71SAndrew G. Morgan 141207a7ba8SRandy Dunlap /** 1421da177e4SLinus Torvalds * sys_capget - get the capabilities of a given process. 143207a7ba8SRandy Dunlap * @header: pointer to struct that contains capability version and 144207a7ba8SRandy Dunlap * target pid data 145207a7ba8SRandy Dunlap * @dataptr: pointer to struct that contains the effective, permitted, 146207a7ba8SRandy Dunlap * and inheritable capabilities that are returned 147207a7ba8SRandy Dunlap * 148207a7ba8SRandy Dunlap * Returns 0 on success and < 0 on error. 1491da177e4SLinus Torvalds */ 150b290ebe2SHeiko Carstens SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr) 1511da177e4SLinus Torvalds { 1521da177e4SLinus Torvalds int ret = 0; 1531da177e4SLinus Torvalds pid_t pid; 154e338d263SAndrew Morgan unsigned tocopy; 155e338d263SAndrew Morgan kernel_cap_t pE, pI, pP; 1561da177e4SLinus Torvalds 157ca05a99aSAndrew G. Morgan ret = cap_validate_magic(header, &tocopy); 158c4a5af54SAndrew G. Morgan if ((dataptr == NULL) || (ret != 0)) 159c4a5af54SAndrew G. Morgan return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds if (get_user(pid, &header->pid)) 1621da177e4SLinus Torvalds return -EFAULT; 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds if (pid < 0) 1651da177e4SLinus Torvalds return -EINVAL; 1661da177e4SLinus Torvalds 167ab763c71SAndrew G. Morgan ret = cap_get_target_pid(pid, &pE, &pI, &pP); 168e338d263SAndrew Morgan if (!ret) { 169ca05a99aSAndrew G. Morgan struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 170e338d263SAndrew Morgan unsigned i; 171e338d263SAndrew Morgan 172e338d263SAndrew Morgan for (i = 0; i < tocopy; i++) { 173e338d263SAndrew Morgan kdata[i].effective = pE.cap[i]; 174e338d263SAndrew Morgan kdata[i].permitted = pP.cap[i]; 175e338d263SAndrew Morgan kdata[i].inheritable = pI.cap[i]; 176e338d263SAndrew Morgan } 177e338d263SAndrew Morgan 178e338d263SAndrew Morgan /* 179ca05a99aSAndrew G. Morgan * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, 180e338d263SAndrew Morgan * we silently drop the upper capabilities here. This 181e338d263SAndrew Morgan * has the effect of making older libcap 182e338d263SAndrew Morgan * implementations implicitly drop upper capability 183e338d263SAndrew Morgan * bits when they perform a: capget/modify/capset 184e338d263SAndrew Morgan * sequence. 185e338d263SAndrew Morgan * 186e338d263SAndrew Morgan * This behavior is considered fail-safe 187e338d263SAndrew Morgan * behavior. Upgrading the application to a newer 188e338d263SAndrew Morgan * version of libcap will enable access to the newer 189e338d263SAndrew Morgan * capabilities. 190e338d263SAndrew Morgan * 191e338d263SAndrew Morgan * An alternative would be to return an error here 192e338d263SAndrew Morgan * (-ERANGE), but that causes legacy applications to 193a6c8c690SFabian Frederick * unexpectedly fail; the capget/modify/capset aborts 194e338d263SAndrew Morgan * before modification is attempted and the application 195e338d263SAndrew Morgan * fails. 196e338d263SAndrew Morgan */ 197e338d263SAndrew Morgan if (copy_to_user(dataptr, kdata, tocopy 198e338d263SAndrew Morgan * sizeof(struct __user_cap_data_struct))) { 1991da177e4SLinus Torvalds return -EFAULT; 200e338d263SAndrew Morgan } 201e338d263SAndrew Morgan } 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds return ret; 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds 206207a7ba8SRandy Dunlap /** 207ab763c71SAndrew G. Morgan * sys_capset - set capabilities for a process or (*) a group of processes 208207a7ba8SRandy Dunlap * @header: pointer to struct that contains capability version and 209207a7ba8SRandy Dunlap * target pid data 210207a7ba8SRandy Dunlap * @data: pointer to struct that contains the effective, permitted, 211207a7ba8SRandy Dunlap * and inheritable capabilities 212207a7ba8SRandy Dunlap * 2131cdcbec1SDavid Howells * Set capabilities for the current process only. The ability to any other 2141cdcbec1SDavid Howells * process(es) has been deprecated and removed. 2151da177e4SLinus Torvalds * 2161da177e4SLinus Torvalds * The restrictions on setting capabilities are specified as: 2171da177e4SLinus Torvalds * 2181cdcbec1SDavid Howells * I: any raised capabilities must be a subset of the old permitted 2191cdcbec1SDavid Howells * P: any raised capabilities must be a subset of the old permitted 2201cdcbec1SDavid Howells * E: must be set to a subset of new permitted 221207a7ba8SRandy Dunlap * 222207a7ba8SRandy Dunlap * Returns 0 on success and < 0 on error. 2231da177e4SLinus Torvalds */ 224b290ebe2SHeiko Carstens SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) 2251da177e4SLinus Torvalds { 226ca05a99aSAndrew G. Morgan struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 227825332e4SArjan van de Ven unsigned i, tocopy, copybytes; 2281da177e4SLinus Torvalds kernel_cap_t inheritable, permitted, effective; 229d84f4f99SDavid Howells struct cred *new; 2301da177e4SLinus Torvalds int ret; 2311da177e4SLinus Torvalds pid_t pid; 2321da177e4SLinus Torvalds 233ca05a99aSAndrew G. Morgan ret = cap_validate_magic(header, &tocopy); 234ca05a99aSAndrew G. Morgan if (ret != 0) 235ca05a99aSAndrew G. Morgan return ret; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds if (get_user(pid, &header->pid)) 2381da177e4SLinus Torvalds return -EFAULT; 2391da177e4SLinus Torvalds 2401cdcbec1SDavid Howells /* may only affect current now */ 2411cdcbec1SDavid Howells if (pid != 0 && pid != task_pid_vnr(current)) 2421cdcbec1SDavid Howells return -EPERM; 2431cdcbec1SDavid Howells 244825332e4SArjan van de Ven copybytes = tocopy * sizeof(struct __user_cap_data_struct); 245825332e4SArjan van de Ven if (copybytes > sizeof(kdata)) 246825332e4SArjan van de Ven return -EFAULT; 247825332e4SArjan van de Ven 248825332e4SArjan van de Ven if (copy_from_user(&kdata, data, copybytes)) 2491da177e4SLinus Torvalds return -EFAULT; 250e338d263SAndrew Morgan 251e338d263SAndrew Morgan for (i = 0; i < tocopy; i++) { 252e338d263SAndrew Morgan effective.cap[i] = kdata[i].effective; 253e338d263SAndrew Morgan permitted.cap[i] = kdata[i].permitted; 254e338d263SAndrew Morgan inheritable.cap[i] = kdata[i].inheritable; 255e338d263SAndrew Morgan } 256ca05a99aSAndrew G. Morgan while (i < _KERNEL_CAPABILITY_U32S) { 257e338d263SAndrew Morgan effective.cap[i] = 0; 258e338d263SAndrew Morgan permitted.cap[i] = 0; 259e338d263SAndrew Morgan inheritable.cap[i] = 0; 260e338d263SAndrew Morgan i++; 261e338d263SAndrew Morgan } 2621da177e4SLinus Torvalds 2637d8b6c63SEric Paris effective.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 2647d8b6c63SEric Paris permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 2657d8b6c63SEric Paris inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 2667d8b6c63SEric Paris 267d84f4f99SDavid Howells new = prepare_creds(); 268d84f4f99SDavid Howells if (!new) 269d84f4f99SDavid Howells return -ENOMEM; 270d84f4f99SDavid Howells 271d84f4f99SDavid Howells ret = security_capset(new, current_cred(), 272d84f4f99SDavid Howells &effective, &inheritable, &permitted); 273d84f4f99SDavid Howells if (ret < 0) 274d84f4f99SDavid Howells goto error; 275d84f4f99SDavid Howells 276ca24a23eSEric W. Biederman audit_log_capset(new, current_cred()); 277e68b75a0SEric Paris 278d84f4f99SDavid Howells return commit_creds(new); 2791da177e4SLinus Torvalds 280d84f4f99SDavid Howells error: 281d84f4f99SDavid Howells abort_creds(new); 2821da177e4SLinus Torvalds return ret; 2831da177e4SLinus Torvalds } 28412b5989bSChris Wright 2855cd9c58fSDavid Howells /** 28625e75703SEric Paris * has_ns_capability - Does a task have a capability in a specific user ns 2873263245dSSerge E. Hallyn * @t: The task in question 2883263245dSSerge E. Hallyn * @ns: target user namespace 2893263245dSSerge E. Hallyn * @cap: The capability to be tested for 2903263245dSSerge E. Hallyn * 2913263245dSSerge E. Hallyn * Return true if the specified task has the given superior capability 2923263245dSSerge E. Hallyn * currently in effect to the specified user namespace, false if not. 2933263245dSSerge E. Hallyn * 2943263245dSSerge E. Hallyn * Note that this does not set PF_SUPERPRIV on the task. 2953263245dSSerge E. Hallyn */ 2963263245dSSerge E. Hallyn bool has_ns_capability(struct task_struct *t, 2973263245dSSerge E. Hallyn struct user_namespace *ns, int cap) 2983263245dSSerge E. Hallyn { 2992920a840SEric Paris int ret; 3002920a840SEric Paris 3012920a840SEric Paris rcu_read_lock(); 3022920a840SEric Paris ret = security_capable(__task_cred(t), ns, cap); 3032920a840SEric Paris rcu_read_unlock(); 3043263245dSSerge E. Hallyn 3053263245dSSerge E. Hallyn return (ret == 0); 3063263245dSSerge E. Hallyn } 3073263245dSSerge E. Hallyn 3083263245dSSerge E. Hallyn /** 30925e75703SEric Paris * has_capability - Does a task have a capability in init_user_ns 31025e75703SEric Paris * @t: The task in question 31125e75703SEric Paris * @cap: The capability to be tested for 31225e75703SEric Paris * 31325e75703SEric Paris * Return true if the specified task has the given superior capability 31425e75703SEric Paris * currently in effect to the initial user namespace, false if not. 31525e75703SEric Paris * 31625e75703SEric Paris * Note that this does not set PF_SUPERPRIV on the task. 31725e75703SEric Paris */ 31825e75703SEric Paris bool has_capability(struct task_struct *t, int cap) 31925e75703SEric Paris { 32025e75703SEric Paris return has_ns_capability(t, &init_user_ns, cap); 32125e75703SEric Paris } 32219c816e8SJike Song EXPORT_SYMBOL(has_capability); 32325e75703SEric Paris 32425e75703SEric Paris /** 3257b61d648SEric Paris * has_ns_capability_noaudit - Does a task have a capability (unaudited) 3267b61d648SEric Paris * in a specific user ns. 3277b61d648SEric Paris * @t: The task in question 3287b61d648SEric Paris * @ns: target user namespace 3297b61d648SEric Paris * @cap: The capability to be tested for 3307b61d648SEric Paris * 3317b61d648SEric Paris * Return true if the specified task has the given superior capability 3327b61d648SEric Paris * currently in effect to the specified user namespace, false if not. 3337b61d648SEric Paris * Do not write an audit message for the check. 3347b61d648SEric Paris * 3357b61d648SEric Paris * Note that this does not set PF_SUPERPRIV on the task. 3367b61d648SEric Paris */ 3377b61d648SEric Paris bool has_ns_capability_noaudit(struct task_struct *t, 3387b61d648SEric Paris struct user_namespace *ns, int cap) 3397b61d648SEric Paris { 3407b61d648SEric Paris int ret; 3417b61d648SEric Paris 3427b61d648SEric Paris rcu_read_lock(); 3437b61d648SEric Paris ret = security_capable_noaudit(__task_cred(t), ns, cap); 3447b61d648SEric Paris rcu_read_unlock(); 3457b61d648SEric Paris 3467b61d648SEric Paris return (ret == 0); 3477b61d648SEric Paris } 3487b61d648SEric Paris 3497b61d648SEric Paris /** 3507b61d648SEric Paris * has_capability_noaudit - Does a task have a capability (unaudited) in the 3517b61d648SEric Paris * initial user ns 3523263245dSSerge E. Hallyn * @t: The task in question 3533263245dSSerge E. Hallyn * @cap: The capability to be tested for 3543263245dSSerge E. Hallyn * 3553263245dSSerge E. Hallyn * Return true if the specified task has the given superior capability 3563263245dSSerge E. Hallyn * currently in effect to init_user_ns, false if not. Don't write an 3573263245dSSerge E. Hallyn * audit message for the check. 3583263245dSSerge E. Hallyn * 3593263245dSSerge E. Hallyn * Note that this does not set PF_SUPERPRIV on the task. 3603263245dSSerge E. Hallyn */ 3613263245dSSerge E. Hallyn bool has_capability_noaudit(struct task_struct *t, int cap) 3623263245dSSerge E. Hallyn { 3637b61d648SEric Paris return has_ns_capability_noaudit(t, &init_user_ns, cap); 3643263245dSSerge E. Hallyn } 3653263245dSSerge E. Hallyn 36698f368e9STyler Hicks static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit) 36798f368e9STyler Hicks { 36898f368e9STyler Hicks int capable; 36998f368e9STyler Hicks 37098f368e9STyler Hicks if (unlikely(!cap_valid(cap))) { 37198f368e9STyler Hicks pr_crit("capable() called with invalid cap=%u\n", cap); 37298f368e9STyler Hicks BUG(); 37398f368e9STyler Hicks } 37498f368e9STyler Hicks 37598f368e9STyler Hicks capable = audit ? security_capable(current_cred(), ns, cap) : 37698f368e9STyler Hicks security_capable_noaudit(current_cred(), ns, cap); 37798f368e9STyler Hicks if (capable == 0) { 37898f368e9STyler Hicks current->flags |= PF_SUPERPRIV; 37998f368e9STyler Hicks return true; 38098f368e9STyler Hicks } 38198f368e9STyler Hicks return false; 38298f368e9STyler Hicks } 38398f368e9STyler Hicks 3843263245dSSerge E. Hallyn /** 3853486740aSSerge E. Hallyn * ns_capable - Determine if the current task has a superior capability in effect 3863486740aSSerge E. Hallyn * @ns: The usernamespace we want the capability in 3873486740aSSerge E. Hallyn * @cap: The capability to be tested for 3883486740aSSerge E. Hallyn * 3893486740aSSerge E. Hallyn * Return true if the current task has the given superior capability currently 3903486740aSSerge E. Hallyn * available for use, false if not. 3913486740aSSerge E. Hallyn * 3923486740aSSerge E. Hallyn * This sets PF_SUPERPRIV on the task if the capability is available on the 3933486740aSSerge E. Hallyn * assumption that it's about to be used. 3943486740aSSerge E. Hallyn */ 3953486740aSSerge E. Hallyn bool ns_capable(struct user_namespace *ns, int cap) 39612b5989bSChris Wright { 39798f368e9STyler Hicks return ns_capable_common(ns, cap, true); 39812b5989bSChris Wright } 3993486740aSSerge E. Hallyn EXPORT_SYMBOL(ns_capable); 4003486740aSSerge E. Hallyn 40198f368e9STyler Hicks /** 40298f368e9STyler Hicks * ns_capable_noaudit - Determine if the current task has a superior capability 40398f368e9STyler Hicks * (unaudited) in effect 40498f368e9STyler Hicks * @ns: The usernamespace we want the capability in 40598f368e9STyler Hicks * @cap: The capability to be tested for 40698f368e9STyler Hicks * 40798f368e9STyler Hicks * Return true if the current task has the given superior capability currently 40898f368e9STyler Hicks * available for use, false if not. 40998f368e9STyler Hicks * 41098f368e9STyler Hicks * This sets PF_SUPERPRIV on the task if the capability is available on the 41198f368e9STyler Hicks * assumption that it's about to be used. 41298f368e9STyler Hicks */ 41398f368e9STyler Hicks bool ns_capable_noaudit(struct user_namespace *ns, int cap) 41498f368e9STyler Hicks { 41598f368e9STyler Hicks return ns_capable_common(ns, cap, false); 41698f368e9STyler Hicks } 41798f368e9STyler Hicks EXPORT_SYMBOL(ns_capable_noaudit); 4182813893fSIulia Manda 4192813893fSIulia Manda /** 4202813893fSIulia Manda * capable - Determine if the current task has a superior capability in effect 4212813893fSIulia Manda * @cap: The capability to be tested for 4222813893fSIulia Manda * 4232813893fSIulia Manda * Return true if the current task has the given superior capability currently 4242813893fSIulia Manda * available for use, false if not. 4252813893fSIulia Manda * 4262813893fSIulia Manda * This sets PF_SUPERPRIV on the task if the capability is available on the 4272813893fSIulia Manda * assumption that it's about to be used. 4282813893fSIulia Manda */ 4292813893fSIulia Manda bool capable(int cap) 4302813893fSIulia Manda { 4312813893fSIulia Manda return ns_capable(&init_user_ns, cap); 4322813893fSIulia Manda } 4332813893fSIulia Manda EXPORT_SYMBOL(capable); 4342813893fSIulia Manda #endif /* CONFIG_MULTIUSER */ 4352813893fSIulia Manda 4363486740aSSerge E. Hallyn /** 437935d8aabSLinus Torvalds * file_ns_capable - Determine if the file's opener had a capability in effect 438935d8aabSLinus Torvalds * @file: The file we want to check 439935d8aabSLinus Torvalds * @ns: The usernamespace we want the capability in 440935d8aabSLinus Torvalds * @cap: The capability to be tested for 441935d8aabSLinus Torvalds * 442935d8aabSLinus Torvalds * Return true if task that opened the file had a capability in effect 443935d8aabSLinus Torvalds * when the file was opened. 444935d8aabSLinus Torvalds * 445935d8aabSLinus Torvalds * This does not set PF_SUPERPRIV because the caller may not 446935d8aabSLinus Torvalds * actually be privileged. 447935d8aabSLinus Torvalds */ 448a6c8c690SFabian Frederick bool file_ns_capable(const struct file *file, struct user_namespace *ns, 449a6c8c690SFabian Frederick int cap) 450935d8aabSLinus Torvalds { 451935d8aabSLinus Torvalds if (WARN_ON_ONCE(!cap_valid(cap))) 452935d8aabSLinus Torvalds return false; 453935d8aabSLinus Torvalds 454935d8aabSLinus Torvalds if (security_capable(file->f_cred, ns, cap) == 0) 455935d8aabSLinus Torvalds return true; 456935d8aabSLinus Torvalds 457935d8aabSLinus Torvalds return false; 458935d8aabSLinus Torvalds } 459935d8aabSLinus Torvalds EXPORT_SYMBOL(file_ns_capable); 460935d8aabSLinus Torvalds 461935d8aabSLinus Torvalds /** 462f84df2a6SEric W. Biederman * privileged_wrt_inode_uidgid - Do capabilities in the namespace work over the inode? 463f84df2a6SEric W. Biederman * @ns: The user namespace in question 464f84df2a6SEric W. Biederman * @inode: The inode in question 465f84df2a6SEric W. Biederman * 466f84df2a6SEric W. Biederman * Return true if the inode uid and gid are within the namespace. 467f84df2a6SEric W. Biederman */ 468f84df2a6SEric W. Biederman bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode) 469f84df2a6SEric W. Biederman { 470f84df2a6SEric W. Biederman return kuid_has_mapping(ns, inode->i_uid) && 471f84df2a6SEric W. Biederman kgid_has_mapping(ns, inode->i_gid); 472f84df2a6SEric W. Biederman } 473f84df2a6SEric W. Biederman 474f84df2a6SEric W. Biederman /** 47523adbe12SAndy Lutomirski * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped 4761a48e2acSEric W. Biederman * @inode: The inode in question 4771a48e2acSEric W. Biederman * @cap: The capability in question 4781a48e2acSEric W. Biederman * 47923adbe12SAndy Lutomirski * Return true if the current task has the given capability targeted at 48023adbe12SAndy Lutomirski * its own user namespace and that the given inode's uid and gid are 48123adbe12SAndy Lutomirski * mapped into the current user namespace. 4821a48e2acSEric W. Biederman */ 48323adbe12SAndy Lutomirski bool capable_wrt_inode_uidgid(const struct inode *inode, int cap) 4841a48e2acSEric W. Biederman { 4851a48e2acSEric W. Biederman struct user_namespace *ns = current_user_ns(); 4861a48e2acSEric W. Biederman 487f84df2a6SEric W. Biederman return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode); 4881a48e2acSEric W. Biederman } 48923adbe12SAndy Lutomirski EXPORT_SYMBOL(capable_wrt_inode_uidgid); 49064b875f7SEric W. Biederman 49164b875f7SEric W. Biederman /** 49264b875f7SEric W. Biederman * ptracer_capable - Determine if the ptracer holds CAP_SYS_PTRACE in the namespace 49364b875f7SEric W. Biederman * @tsk: The task that may be ptraced 49464b875f7SEric W. Biederman * @ns: The user namespace to search for CAP_SYS_PTRACE in 49564b875f7SEric W. Biederman * 49664b875f7SEric W. Biederman * Return true if the task that is ptracing the current task had CAP_SYS_PTRACE 49764b875f7SEric W. Biederman * in the specified user namespace. 49864b875f7SEric W. Biederman */ 49964b875f7SEric W. Biederman bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns) 50064b875f7SEric W. Biederman { 50164b875f7SEric W. Biederman int ret = 0; /* An absent tracer adds no restrictions */ 50264b875f7SEric W. Biederman const struct cred *cred; 50364b875f7SEric W. Biederman rcu_read_lock(); 50464b875f7SEric W. Biederman cred = rcu_dereference(tsk->ptracer_cred); 50564b875f7SEric W. Biederman if (cred) 50664b875f7SEric W. Biederman ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE); 50764b875f7SEric W. Biederman rcu_read_unlock(); 50864b875f7SEric W. Biederman return (ret == 0); 50964b875f7SEric W. Biederman } 510