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 231f29fae2SSerge E. Hallyn int file_caps_enabled = 1; 241f29fae2SSerge E. Hallyn 251f29fae2SSerge E. Hallyn static int __init file_caps_disable(char *str) 261f29fae2SSerge E. Hallyn { 271f29fae2SSerge E. Hallyn file_caps_enabled = 0; 281f29fae2SSerge E. Hallyn return 1; 291f29fae2SSerge E. Hallyn } 301f29fae2SSerge E. Hallyn __setup("no_file_caps", file_caps_disable); 311f29fae2SSerge E. Hallyn 322813893fSIulia Manda #ifdef CONFIG_MULTIUSER 33e338d263SAndrew Morgan /* 34e338d263SAndrew Morgan * More recent versions of libcap are available from: 35e338d263SAndrew Morgan * 36e338d263SAndrew Morgan * http://www.kernel.org/pub/linux/libs/security/linux-privs/ 37e338d263SAndrew Morgan */ 38e338d263SAndrew Morgan 39e338d263SAndrew Morgan static void warn_legacy_capability_use(void) 40e338d263SAndrew Morgan { 41e338d263SAndrew Morgan char name[sizeof(current->comm)]; 42e338d263SAndrew Morgan 43f5645d35SJoe Perches pr_info_once("warning: `%s' uses 32-bit capabilities (legacy support in use)\n", 44e338d263SAndrew Morgan get_task_comm(name, current)); 45e338d263SAndrew Morgan } 46e338d263SAndrew Morgan 47e338d263SAndrew Morgan /* 48ca05a99aSAndrew G. Morgan * Version 2 capabilities worked fine, but the linux/capability.h file 49ca05a99aSAndrew G. Morgan * that accompanied their introduction encouraged their use without 50ca05a99aSAndrew G. Morgan * the necessary user-space source code changes. As such, we have 51ca05a99aSAndrew G. Morgan * created a version 3 with equivalent functionality to version 2, but 52ca05a99aSAndrew G. Morgan * with a header change to protect legacy source code from using 53ca05a99aSAndrew G. Morgan * version 2 when it wanted to use version 1. If your system has code 54ca05a99aSAndrew G. Morgan * that trips the following warning, it is using version 2 specific 55ca05a99aSAndrew G. Morgan * capabilities and may be doing so insecurely. 56ca05a99aSAndrew G. Morgan * 57ca05a99aSAndrew G. Morgan * The remedy is to either upgrade your version of libcap (to 2.10+, 58ca05a99aSAndrew G. Morgan * if the application is linked against it), or recompile your 59ca05a99aSAndrew G. Morgan * application with modern kernel headers and this warning will go 60ca05a99aSAndrew G. Morgan * away. 61ca05a99aSAndrew G. Morgan */ 62ca05a99aSAndrew G. Morgan 63ca05a99aSAndrew G. Morgan static void warn_deprecated_v2(void) 64ca05a99aSAndrew G. Morgan { 65ca05a99aSAndrew G. Morgan char name[sizeof(current->comm)]; 66ca05a99aSAndrew G. Morgan 67f5645d35SJoe Perches pr_info_once("warning: `%s' uses deprecated v2 capabilities in a way that may be insecure\n", 68ca05a99aSAndrew G. Morgan get_task_comm(name, current)); 69ca05a99aSAndrew G. Morgan } 70ca05a99aSAndrew G. Morgan 71ca05a99aSAndrew G. Morgan /* 72ca05a99aSAndrew G. Morgan * Version check. Return the number of u32s in each capability flag 73ca05a99aSAndrew G. Morgan * array, or a negative value on error. 74ca05a99aSAndrew G. Morgan */ 75ca05a99aSAndrew G. Morgan static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) 76ca05a99aSAndrew G. Morgan { 77ca05a99aSAndrew G. Morgan __u32 version; 78ca05a99aSAndrew G. Morgan 79ca05a99aSAndrew G. Morgan if (get_user(version, &header->version)) 80ca05a99aSAndrew G. Morgan return -EFAULT; 81ca05a99aSAndrew G. Morgan 82ca05a99aSAndrew G. Morgan switch (version) { 83ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_1: 84ca05a99aSAndrew G. Morgan warn_legacy_capability_use(); 85ca05a99aSAndrew G. Morgan *tocopy = _LINUX_CAPABILITY_U32S_1; 86ca05a99aSAndrew G. Morgan break; 87ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_2: 88ca05a99aSAndrew G. Morgan warn_deprecated_v2(); 89df561f66SGustavo A. R. Silva fallthrough; /* v3 is otherwise equivalent to v2 */ 90ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_3: 91ca05a99aSAndrew G. Morgan *tocopy = _LINUX_CAPABILITY_U32S_3; 92ca05a99aSAndrew G. Morgan break; 93ca05a99aSAndrew G. Morgan default: 94ca05a99aSAndrew G. Morgan if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version)) 95ca05a99aSAndrew G. Morgan return -EFAULT; 96ca05a99aSAndrew G. Morgan return -EINVAL; 97ca05a99aSAndrew G. Morgan } 98ca05a99aSAndrew G. Morgan 99ca05a99aSAndrew G. Morgan return 0; 100ca05a99aSAndrew G. Morgan } 101ca05a99aSAndrew G. Morgan 102ab763c71SAndrew G. Morgan /* 103d84f4f99SDavid Howells * The only thing that can change the capabilities of the current 104d84f4f99SDavid Howells * process is the current process. As such, we can't be in this code 105d84f4f99SDavid Howells * at the same time as we are in the process of setting capabilities 106d84f4f99SDavid Howells * in this process. The net result is that we can limit our use of 107d84f4f99SDavid Howells * locks to when we are reading the caps of another process. 108ab763c71SAndrew G. Morgan */ 109ab763c71SAndrew G. Morgan static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, 110ab763c71SAndrew G. Morgan kernel_cap_t *pIp, kernel_cap_t *pPp) 111ab763c71SAndrew G. Morgan { 112ab763c71SAndrew G. Morgan int ret; 113ab763c71SAndrew G. Morgan 114ab763c71SAndrew G. Morgan if (pid && (pid != task_pid_vnr(current))) { 115ab763c71SAndrew G. Morgan struct task_struct *target; 116ab763c71SAndrew G. Morgan 11786fc80f1SThomas Gleixner rcu_read_lock(); 118ab763c71SAndrew G. Morgan 119ab763c71SAndrew G. Morgan target = find_task_by_vpid(pid); 120ab763c71SAndrew G. Morgan if (!target) 121ab763c71SAndrew G. Morgan ret = -ESRCH; 122ab763c71SAndrew G. Morgan else 123ab763c71SAndrew G. Morgan ret = security_capget(target, pEp, pIp, pPp); 124ab763c71SAndrew G. Morgan 12586fc80f1SThomas Gleixner rcu_read_unlock(); 126ab763c71SAndrew G. Morgan } else 127ab763c71SAndrew G. Morgan ret = security_capget(current, pEp, pIp, pPp); 128ab763c71SAndrew G. Morgan 129ab763c71SAndrew G. Morgan return ret; 130ab763c71SAndrew G. Morgan } 131ab763c71SAndrew G. Morgan 132207a7ba8SRandy Dunlap /** 1331da177e4SLinus Torvalds * sys_capget - get the capabilities of a given process. 134207a7ba8SRandy Dunlap * @header: pointer to struct that contains capability version and 135207a7ba8SRandy Dunlap * target pid data 136207a7ba8SRandy Dunlap * @dataptr: pointer to struct that contains the effective, permitted, 137207a7ba8SRandy Dunlap * and inheritable capabilities that are returned 138207a7ba8SRandy Dunlap * 139207a7ba8SRandy Dunlap * Returns 0 on success and < 0 on error. 1401da177e4SLinus Torvalds */ 141b290ebe2SHeiko Carstens SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr) 1421da177e4SLinus Torvalds { 1431da177e4SLinus Torvalds int ret = 0; 1441da177e4SLinus Torvalds pid_t pid; 145e338d263SAndrew Morgan unsigned tocopy; 146e338d263SAndrew Morgan kernel_cap_t pE, pI, pP; 147*f122a08bSLinus Torvalds struct __user_cap_data_struct kdata[2]; 1481da177e4SLinus Torvalds 149ca05a99aSAndrew G. Morgan ret = cap_validate_magic(header, &tocopy); 150c4a5af54SAndrew G. Morgan if ((dataptr == NULL) || (ret != 0)) 151c4a5af54SAndrew G. Morgan return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds if (get_user(pid, &header->pid)) 1541da177e4SLinus Torvalds return -EFAULT; 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds if (pid < 0) 1571da177e4SLinus Torvalds return -EINVAL; 1581da177e4SLinus Torvalds 159ab763c71SAndrew G. Morgan ret = cap_get_target_pid(pid, &pE, &pI, &pP); 160*f122a08bSLinus Torvalds if (ret) 161*f122a08bSLinus Torvalds return ret; 162e338d263SAndrew Morgan 163*f122a08bSLinus Torvalds /* 164*f122a08bSLinus Torvalds * Annoying legacy format with 64-bit capabilities exposed 165*f122a08bSLinus Torvalds * as two sets of 32-bit fields, so we need to split the 166*f122a08bSLinus Torvalds * capability values up. 167*f122a08bSLinus Torvalds */ 168*f122a08bSLinus Torvalds kdata[0].effective = pE.val; kdata[1].effective = pE.val >> 32; 169*f122a08bSLinus Torvalds kdata[0].permitted = pP.val; kdata[1].permitted = pP.val >> 32; 170*f122a08bSLinus Torvalds kdata[0].inheritable = pI.val; kdata[1].inheritable = pI.val >> 32; 171e338d263SAndrew Morgan 172e338d263SAndrew Morgan /* 173ca05a99aSAndrew G. Morgan * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, 174e338d263SAndrew Morgan * we silently drop the upper capabilities here. This 175e338d263SAndrew Morgan * has the effect of making older libcap 176e338d263SAndrew Morgan * implementations implicitly drop upper capability 177e338d263SAndrew Morgan * bits when they perform a: capget/modify/capset 178e338d263SAndrew Morgan * sequence. 179e338d263SAndrew Morgan * 180e338d263SAndrew Morgan * This behavior is considered fail-safe 181e338d263SAndrew Morgan * behavior. Upgrading the application to a newer 182e338d263SAndrew Morgan * version of libcap will enable access to the newer 183e338d263SAndrew Morgan * capabilities. 184e338d263SAndrew Morgan * 185e338d263SAndrew Morgan * An alternative would be to return an error here 186e338d263SAndrew Morgan * (-ERANGE), but that causes legacy applications to 187a6c8c690SFabian Frederick * unexpectedly fail; the capget/modify/capset aborts 188e338d263SAndrew Morgan * before modification is attempted and the application 189e338d263SAndrew Morgan * fails. 190e338d263SAndrew Morgan */ 191*f122a08bSLinus Torvalds if (copy_to_user(dataptr, kdata, tocopy * sizeof(kdata[0]))) 1921da177e4SLinus Torvalds return -EFAULT; 193*f122a08bSLinus Torvalds 194*f122a08bSLinus Torvalds return 0; 195e338d263SAndrew Morgan } 1961da177e4SLinus Torvalds 197*f122a08bSLinus Torvalds static kernel_cap_t mk_kernel_cap(u32 low, u32 high) 198*f122a08bSLinus Torvalds { 199*f122a08bSLinus Torvalds return (kernel_cap_t) { (low | ((u64)high << 32)) & CAP_VALID_MASK }; 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds 202207a7ba8SRandy Dunlap /** 203ab763c71SAndrew G. Morgan * sys_capset - set capabilities for a process or (*) a group of processes 204207a7ba8SRandy Dunlap * @header: pointer to struct that contains capability version and 205207a7ba8SRandy Dunlap * target pid data 206207a7ba8SRandy Dunlap * @data: pointer to struct that contains the effective, permitted, 207207a7ba8SRandy Dunlap * and inheritable capabilities 208207a7ba8SRandy Dunlap * 2091cdcbec1SDavid Howells * Set capabilities for the current process only. The ability to any other 2101cdcbec1SDavid Howells * process(es) has been deprecated and removed. 2111da177e4SLinus Torvalds * 2121da177e4SLinus Torvalds * The restrictions on setting capabilities are specified as: 2131da177e4SLinus Torvalds * 2141cdcbec1SDavid Howells * I: any raised capabilities must be a subset of the old permitted 2151cdcbec1SDavid Howells * P: any raised capabilities must be a subset of the old permitted 2161cdcbec1SDavid Howells * E: must be set to a subset of new permitted 217207a7ba8SRandy Dunlap * 218207a7ba8SRandy Dunlap * Returns 0 on success and < 0 on error. 2191da177e4SLinus Torvalds */ 220b290ebe2SHeiko Carstens SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) 2211da177e4SLinus Torvalds { 222*f122a08bSLinus Torvalds struct __user_cap_data_struct kdata[2] = { { 0, }, }; 223*f122a08bSLinus Torvalds unsigned tocopy, copybytes; 2241da177e4SLinus Torvalds kernel_cap_t inheritable, permitted, effective; 225d84f4f99SDavid Howells struct cred *new; 2261da177e4SLinus Torvalds int ret; 2271da177e4SLinus Torvalds pid_t pid; 2281da177e4SLinus Torvalds 229ca05a99aSAndrew G. Morgan ret = cap_validate_magic(header, &tocopy); 230ca05a99aSAndrew G. Morgan if (ret != 0) 231ca05a99aSAndrew G. Morgan return ret; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds if (get_user(pid, &header->pid)) 2341da177e4SLinus Torvalds return -EFAULT; 2351da177e4SLinus Torvalds 2361cdcbec1SDavid Howells /* may only affect current now */ 2371cdcbec1SDavid Howells if (pid != 0 && pid != task_pid_vnr(current)) 2381cdcbec1SDavid Howells return -EPERM; 2391cdcbec1SDavid Howells 240825332e4SArjan van de Ven copybytes = tocopy * sizeof(struct __user_cap_data_struct); 241825332e4SArjan van de Ven if (copybytes > sizeof(kdata)) 242825332e4SArjan van de Ven return -EFAULT; 243825332e4SArjan van de Ven 244825332e4SArjan van de Ven if (copy_from_user(&kdata, data, copybytes)) 2451da177e4SLinus Torvalds return -EFAULT; 246e338d263SAndrew Morgan 247*f122a08bSLinus Torvalds effective = mk_kernel_cap(kdata[0].effective, kdata[1].effective); 248*f122a08bSLinus Torvalds permitted = mk_kernel_cap(kdata[0].permitted, kdata[1].permitted); 249*f122a08bSLinus Torvalds inheritable = mk_kernel_cap(kdata[0].inheritable, kdata[1].inheritable); 2507d8b6c63SEric Paris 251d84f4f99SDavid Howells new = prepare_creds(); 252d84f4f99SDavid Howells if (!new) 253d84f4f99SDavid Howells return -ENOMEM; 254d84f4f99SDavid Howells 255d84f4f99SDavid Howells ret = security_capset(new, current_cred(), 256d84f4f99SDavid Howells &effective, &inheritable, &permitted); 257d84f4f99SDavid Howells if (ret < 0) 258d84f4f99SDavid Howells goto error; 259d84f4f99SDavid Howells 260ca24a23eSEric W. Biederman audit_log_capset(new, current_cred()); 261e68b75a0SEric Paris 262d84f4f99SDavid Howells return commit_creds(new); 2631da177e4SLinus Torvalds 264d84f4f99SDavid Howells error: 265d84f4f99SDavid Howells abort_creds(new); 2661da177e4SLinus Torvalds return ret; 2671da177e4SLinus Torvalds } 26812b5989bSChris Wright 2695cd9c58fSDavid Howells /** 27025e75703SEric Paris * has_ns_capability - Does a task have a capability in a specific user ns 2713263245dSSerge E. Hallyn * @t: The task in question 2723263245dSSerge E. Hallyn * @ns: target user namespace 2733263245dSSerge E. Hallyn * @cap: The capability to be tested for 2743263245dSSerge E. Hallyn * 2753263245dSSerge E. Hallyn * Return true if the specified task has the given superior capability 2763263245dSSerge E. Hallyn * currently in effect to the specified user namespace, false if not. 2773263245dSSerge E. Hallyn * 2783263245dSSerge E. Hallyn * Note that this does not set PF_SUPERPRIV on the task. 2793263245dSSerge E. Hallyn */ 2803263245dSSerge E. Hallyn bool has_ns_capability(struct task_struct *t, 2813263245dSSerge E. Hallyn struct user_namespace *ns, int cap) 2823263245dSSerge E. Hallyn { 2832920a840SEric Paris int ret; 2842920a840SEric Paris 2852920a840SEric Paris rcu_read_lock(); 286c1a85a00SMicah Morton ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE); 2872920a840SEric Paris rcu_read_unlock(); 2883263245dSSerge E. Hallyn 2893263245dSSerge E. Hallyn return (ret == 0); 2903263245dSSerge E. Hallyn } 2913263245dSSerge E. Hallyn 2923263245dSSerge E. Hallyn /** 29325e75703SEric Paris * has_capability - Does a task have a capability in init_user_ns 29425e75703SEric Paris * @t: The task in question 29525e75703SEric Paris * @cap: The capability to be tested for 29625e75703SEric Paris * 29725e75703SEric Paris * Return true if the specified task has the given superior capability 29825e75703SEric Paris * currently in effect to the initial user namespace, false if not. 29925e75703SEric Paris * 30025e75703SEric Paris * Note that this does not set PF_SUPERPRIV on the task. 30125e75703SEric Paris */ 30225e75703SEric Paris bool has_capability(struct task_struct *t, int cap) 30325e75703SEric Paris { 30425e75703SEric Paris return has_ns_capability(t, &init_user_ns, cap); 30525e75703SEric Paris } 30619c816e8SJike Song EXPORT_SYMBOL(has_capability); 30725e75703SEric Paris 30825e75703SEric Paris /** 3097b61d648SEric Paris * has_ns_capability_noaudit - Does a task have a capability (unaudited) 3107b61d648SEric Paris * in a specific user ns. 3117b61d648SEric Paris * @t: The task in question 3127b61d648SEric Paris * @ns: target user namespace 3137b61d648SEric Paris * @cap: The capability to be tested for 3147b61d648SEric Paris * 3157b61d648SEric Paris * Return true if the specified task has the given superior capability 3167b61d648SEric Paris * currently in effect to the specified user namespace, false if not. 3177b61d648SEric Paris * Do not write an audit message for the check. 3187b61d648SEric Paris * 3197b61d648SEric Paris * Note that this does not set PF_SUPERPRIV on the task. 3207b61d648SEric Paris */ 3217b61d648SEric Paris bool has_ns_capability_noaudit(struct task_struct *t, 3227b61d648SEric Paris struct user_namespace *ns, int cap) 3237b61d648SEric Paris { 3247b61d648SEric Paris int ret; 3257b61d648SEric Paris 3267b61d648SEric Paris rcu_read_lock(); 327c1a85a00SMicah Morton ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT); 3287b61d648SEric Paris rcu_read_unlock(); 3297b61d648SEric Paris 3307b61d648SEric Paris return (ret == 0); 3317b61d648SEric Paris } 3327b61d648SEric Paris 3337b61d648SEric Paris /** 3347b61d648SEric Paris * has_capability_noaudit - Does a task have a capability (unaudited) in the 3357b61d648SEric Paris * initial user ns 3363263245dSSerge E. Hallyn * @t: The task in question 3373263245dSSerge E. Hallyn * @cap: The capability to be tested for 3383263245dSSerge E. Hallyn * 3393263245dSSerge E. Hallyn * Return true if the specified task has the given superior capability 3403263245dSSerge E. Hallyn * currently in effect to init_user_ns, false if not. Don't write an 3413263245dSSerge E. Hallyn * audit message for the check. 3423263245dSSerge E. Hallyn * 3433263245dSSerge E. Hallyn * Note that this does not set PF_SUPERPRIV on the task. 3443263245dSSerge E. Hallyn */ 3453263245dSSerge E. Hallyn bool has_capability_noaudit(struct task_struct *t, int cap) 3463263245dSSerge E. Hallyn { 3477b61d648SEric Paris return has_ns_capability_noaudit(t, &init_user_ns, cap); 3483263245dSSerge E. Hallyn } 349eba0549bSDarrick J. Wong EXPORT_SYMBOL(has_capability_noaudit); 3503263245dSSerge E. Hallyn 351c1a85a00SMicah Morton static bool ns_capable_common(struct user_namespace *ns, 352c1a85a00SMicah Morton int cap, 353c1a85a00SMicah Morton unsigned int opts) 35498f368e9STyler Hicks { 35598f368e9STyler Hicks int capable; 35698f368e9STyler Hicks 35798f368e9STyler Hicks if (unlikely(!cap_valid(cap))) { 35898f368e9STyler Hicks pr_crit("capable() called with invalid cap=%u\n", cap); 35998f368e9STyler Hicks BUG(); 36098f368e9STyler Hicks } 36198f368e9STyler Hicks 362c1a85a00SMicah Morton capable = security_capable(current_cred(), ns, cap, opts); 36398f368e9STyler Hicks if (capable == 0) { 36498f368e9STyler Hicks current->flags |= PF_SUPERPRIV; 36598f368e9STyler Hicks return true; 36698f368e9STyler Hicks } 36798f368e9STyler Hicks return false; 36898f368e9STyler Hicks } 36998f368e9STyler Hicks 3703263245dSSerge E. Hallyn /** 3713486740aSSerge E. Hallyn * ns_capable - Determine if the current task has a superior capability in effect 3723486740aSSerge E. Hallyn * @ns: The usernamespace we want the capability in 3733486740aSSerge E. Hallyn * @cap: The capability to be tested for 3743486740aSSerge E. Hallyn * 3753486740aSSerge E. Hallyn * Return true if the current task has the given superior capability currently 3763486740aSSerge E. Hallyn * available for use, false if not. 3773486740aSSerge E. Hallyn * 3783486740aSSerge E. Hallyn * This sets PF_SUPERPRIV on the task if the capability is available on the 3793486740aSSerge E. Hallyn * assumption that it's about to be used. 3803486740aSSerge E. Hallyn */ 3813486740aSSerge E. Hallyn bool ns_capable(struct user_namespace *ns, int cap) 38212b5989bSChris Wright { 383c1a85a00SMicah Morton return ns_capable_common(ns, cap, CAP_OPT_NONE); 38412b5989bSChris Wright } 3853486740aSSerge E. Hallyn EXPORT_SYMBOL(ns_capable); 3863486740aSSerge E. Hallyn 38798f368e9STyler Hicks /** 38898f368e9STyler Hicks * ns_capable_noaudit - Determine if the current task has a superior capability 38998f368e9STyler Hicks * (unaudited) in effect 39098f368e9STyler Hicks * @ns: The usernamespace we want the capability in 39198f368e9STyler Hicks * @cap: The capability to be tested for 39298f368e9STyler Hicks * 39398f368e9STyler Hicks * Return true if the current task has the given superior capability currently 39498f368e9STyler Hicks * available for use, false if not. 39598f368e9STyler Hicks * 39698f368e9STyler Hicks * This sets PF_SUPERPRIV on the task if the capability is available on the 39798f368e9STyler Hicks * assumption that it's about to be used. 39898f368e9STyler Hicks */ 39998f368e9STyler Hicks bool ns_capable_noaudit(struct user_namespace *ns, int cap) 40098f368e9STyler Hicks { 401c1a85a00SMicah Morton return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT); 40298f368e9STyler Hicks } 40398f368e9STyler Hicks EXPORT_SYMBOL(ns_capable_noaudit); 4042813893fSIulia Manda 4052813893fSIulia Manda /** 40640852275SMicah Morton * ns_capable_setid - Determine if the current task has a superior capability 40740852275SMicah Morton * in effect, while signalling that this check is being done from within a 408111767c1SThomas Cedeno * setid or setgroups syscall. 40940852275SMicah Morton * @ns: The usernamespace we want the capability in 41040852275SMicah Morton * @cap: The capability to be tested for 41140852275SMicah Morton * 41240852275SMicah Morton * Return true if the current task has the given superior capability currently 41340852275SMicah Morton * available for use, false if not. 41440852275SMicah Morton * 41540852275SMicah Morton * This sets PF_SUPERPRIV on the task if the capability is available on the 41640852275SMicah Morton * assumption that it's about to be used. 41740852275SMicah Morton */ 41840852275SMicah Morton bool ns_capable_setid(struct user_namespace *ns, int cap) 41940852275SMicah Morton { 42040852275SMicah Morton return ns_capable_common(ns, cap, CAP_OPT_INSETID); 42140852275SMicah Morton } 42240852275SMicah Morton EXPORT_SYMBOL(ns_capable_setid); 42340852275SMicah Morton 42440852275SMicah Morton /** 4252813893fSIulia Manda * capable - Determine if the current task has a superior capability in effect 4262813893fSIulia Manda * @cap: The capability to be tested for 4272813893fSIulia Manda * 4282813893fSIulia Manda * Return true if the current task has the given superior capability currently 4292813893fSIulia Manda * available for use, false if not. 4302813893fSIulia Manda * 4312813893fSIulia Manda * This sets PF_SUPERPRIV on the task if the capability is available on the 4322813893fSIulia Manda * assumption that it's about to be used. 4332813893fSIulia Manda */ 4342813893fSIulia Manda bool capable(int cap) 4352813893fSIulia Manda { 4362813893fSIulia Manda return ns_capable(&init_user_ns, cap); 4372813893fSIulia Manda } 4382813893fSIulia Manda EXPORT_SYMBOL(capable); 4392813893fSIulia Manda #endif /* CONFIG_MULTIUSER */ 4402813893fSIulia Manda 4413486740aSSerge E. Hallyn /** 442935d8aabSLinus Torvalds * file_ns_capable - Determine if the file's opener had a capability in effect 443935d8aabSLinus Torvalds * @file: The file we want to check 444935d8aabSLinus Torvalds * @ns: The usernamespace we want the capability in 445935d8aabSLinus Torvalds * @cap: The capability to be tested for 446935d8aabSLinus Torvalds * 447935d8aabSLinus Torvalds * Return true if task that opened the file had a capability in effect 448935d8aabSLinus Torvalds * when the file was opened. 449935d8aabSLinus Torvalds * 450935d8aabSLinus Torvalds * This does not set PF_SUPERPRIV because the caller may not 451935d8aabSLinus Torvalds * actually be privileged. 452935d8aabSLinus Torvalds */ 453a6c8c690SFabian Frederick bool file_ns_capable(const struct file *file, struct user_namespace *ns, 454a6c8c690SFabian Frederick int cap) 455935d8aabSLinus Torvalds { 456c1a85a00SMicah Morton 457935d8aabSLinus Torvalds if (WARN_ON_ONCE(!cap_valid(cap))) 458935d8aabSLinus Torvalds return false; 459935d8aabSLinus Torvalds 460c1a85a00SMicah Morton if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE) == 0) 461935d8aabSLinus Torvalds return true; 462935d8aabSLinus Torvalds 463935d8aabSLinus Torvalds return false; 464935d8aabSLinus Torvalds } 465935d8aabSLinus Torvalds EXPORT_SYMBOL(file_ns_capable); 466935d8aabSLinus Torvalds 467935d8aabSLinus Torvalds /** 468f84df2a6SEric W. Biederman * privileged_wrt_inode_uidgid - Do capabilities in the namespace work over the inode? 469f84df2a6SEric W. Biederman * @ns: The user namespace in question 470f84df2a6SEric W. Biederman * @inode: The inode in question 471f84df2a6SEric W. Biederman * 472f84df2a6SEric W. Biederman * Return true if the inode uid and gid are within the namespace. 473f84df2a6SEric W. Biederman */ 4740558c1bfSChristian Brauner bool privileged_wrt_inode_uidgid(struct user_namespace *ns, 4759452e93eSChristian Brauner struct mnt_idmap *idmap, 4760558c1bfSChristian Brauner const struct inode *inode) 477f84df2a6SEric W. Biederman { 478e67fe633SChristian Brauner return vfsuid_has_mapping(ns, i_uid_into_vfsuid(idmap, inode)) && 479e67fe633SChristian Brauner vfsgid_has_mapping(ns, i_gid_into_vfsgid(idmap, inode)); 480f84df2a6SEric W. Biederman } 481f84df2a6SEric W. Biederman 482f84df2a6SEric W. Biederman /** 48323adbe12SAndy Lutomirski * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped 4841a48e2acSEric W. Biederman * @inode: The inode in question 4851a48e2acSEric W. Biederman * @cap: The capability in question 4861a48e2acSEric W. Biederman * 48723adbe12SAndy Lutomirski * Return true if the current task has the given capability targeted at 48823adbe12SAndy Lutomirski * its own user namespace and that the given inode's uid and gid are 48923adbe12SAndy Lutomirski * mapped into the current user namespace. 4901a48e2acSEric W. Biederman */ 4919452e93eSChristian Brauner bool capable_wrt_inode_uidgid(struct mnt_idmap *idmap, 4920558c1bfSChristian Brauner const struct inode *inode, int cap) 4931a48e2acSEric W. Biederman { 4941a48e2acSEric W. Biederman struct user_namespace *ns = current_user_ns(); 4951a48e2acSEric W. Biederman 4960558c1bfSChristian Brauner return ns_capable(ns, cap) && 4979452e93eSChristian Brauner privileged_wrt_inode_uidgid(ns, idmap, inode); 4981a48e2acSEric W. Biederman } 49923adbe12SAndy Lutomirski EXPORT_SYMBOL(capable_wrt_inode_uidgid); 50064b875f7SEric W. Biederman 50164b875f7SEric W. Biederman /** 50264b875f7SEric W. Biederman * ptracer_capable - Determine if the ptracer holds CAP_SYS_PTRACE in the namespace 50364b875f7SEric W. Biederman * @tsk: The task that may be ptraced 50464b875f7SEric W. Biederman * @ns: The user namespace to search for CAP_SYS_PTRACE in 50564b875f7SEric W. Biederman * 50664b875f7SEric W. Biederman * Return true if the task that is ptracing the current task had CAP_SYS_PTRACE 50764b875f7SEric W. Biederman * in the specified user namespace. 50864b875f7SEric W. Biederman */ 50964b875f7SEric W. Biederman bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns) 51064b875f7SEric W. Biederman { 51164b875f7SEric W. Biederman int ret = 0; /* An absent tracer adds no restrictions */ 51264b875f7SEric W. Biederman const struct cred *cred; 513c1a85a00SMicah Morton 51464b875f7SEric W. Biederman rcu_read_lock(); 51564b875f7SEric W. Biederman cred = rcu_dereference(tsk->ptracer_cred); 51664b875f7SEric W. Biederman if (cred) 517c1a85a00SMicah Morton ret = security_capable(cred, ns, CAP_SYS_PTRACE, 518c1a85a00SMicah Morton CAP_OPT_NOAUDIT); 51964b875f7SEric W. Biederman rcu_read_unlock(); 52064b875f7SEric W. Biederman return (ret == 0); 52164b875f7SEric W. Biederman } 522