11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/kernel/capability.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1997 Andrew Main <zefram@fysh.org> 51da177e4SLinus Torvalds * 672c2d582SAndrew Morgan * Integrated into 2.1.97+, Andrew G. Morgan <morgan@kernel.org> 71da177e4SLinus Torvalds * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds 10e68b75a0SEric Paris #include <linux/audit.h> 11c59ede7bSRandy.Dunlap #include <linux/capability.h> 121da177e4SLinus Torvalds #include <linux/mm.h> 131da177e4SLinus Torvalds #include <linux/module.h> 141da177e4SLinus Torvalds #include <linux/security.h> 151da177e4SLinus Torvalds #include <linux/syscalls.h> 16b460cbc5SSerge E. Hallyn #include <linux/pid_namespace.h> 171da177e4SLinus Torvalds #include <asm/uaccess.h> 18d84f4f99SDavid Howells #include "cred-internals.h" 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds /* 21e338d263SAndrew Morgan * Leveraged for setting/resetting capabilities 22e338d263SAndrew Morgan */ 23e338d263SAndrew Morgan 24e338d263SAndrew Morgan const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; 25e338d263SAndrew Morgan const kernel_cap_t __cap_full_set = CAP_FULL_SET; 26e338d263SAndrew Morgan const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET; 27e338d263SAndrew Morgan 28e338d263SAndrew Morgan EXPORT_SYMBOL(__cap_empty_set); 29e338d263SAndrew Morgan EXPORT_SYMBOL(__cap_full_set); 30e338d263SAndrew Morgan EXPORT_SYMBOL(__cap_init_eff_set); 31e338d263SAndrew Morgan 321f29fae2SSerge E. Hallyn int file_caps_enabled = 1; 331f29fae2SSerge E. Hallyn 341f29fae2SSerge E. Hallyn static int __init file_caps_disable(char *str) 351f29fae2SSerge E. Hallyn { 361f29fae2SSerge E. Hallyn file_caps_enabled = 0; 371f29fae2SSerge E. Hallyn return 1; 381f29fae2SSerge E. Hallyn } 391f29fae2SSerge E. Hallyn __setup("no_file_caps", file_caps_disable); 401f29fae2SSerge E. Hallyn 41e338d263SAndrew Morgan /* 42e338d263SAndrew Morgan * More recent versions of libcap are available from: 43e338d263SAndrew Morgan * 44e338d263SAndrew Morgan * http://www.kernel.org/pub/linux/libs/security/linux-privs/ 45e338d263SAndrew Morgan */ 46e338d263SAndrew Morgan 47e338d263SAndrew Morgan static void warn_legacy_capability_use(void) 48e338d263SAndrew Morgan { 49e338d263SAndrew Morgan static int warned; 50e338d263SAndrew Morgan if (!warned) { 51e338d263SAndrew Morgan char name[sizeof(current->comm)]; 52e338d263SAndrew Morgan 53e338d263SAndrew Morgan printk(KERN_INFO "warning: `%s' uses 32-bit capabilities" 54e338d263SAndrew Morgan " (legacy support in use)\n", 55e338d263SAndrew Morgan get_task_comm(name, current)); 56e338d263SAndrew Morgan warned = 1; 57e338d263SAndrew Morgan } 58e338d263SAndrew Morgan } 59e338d263SAndrew Morgan 60e338d263SAndrew Morgan /* 61ca05a99aSAndrew G. Morgan * Version 2 capabilities worked fine, but the linux/capability.h file 62ca05a99aSAndrew G. Morgan * that accompanied their introduction encouraged their use without 63ca05a99aSAndrew G. Morgan * the necessary user-space source code changes. As such, we have 64ca05a99aSAndrew G. Morgan * created a version 3 with equivalent functionality to version 2, but 65ca05a99aSAndrew G. Morgan * with a header change to protect legacy source code from using 66ca05a99aSAndrew G. Morgan * version 2 when it wanted to use version 1. If your system has code 67ca05a99aSAndrew G. Morgan * that trips the following warning, it is using version 2 specific 68ca05a99aSAndrew G. Morgan * capabilities and may be doing so insecurely. 69ca05a99aSAndrew G. Morgan * 70ca05a99aSAndrew G. Morgan * The remedy is to either upgrade your version of libcap (to 2.10+, 71ca05a99aSAndrew G. Morgan * if the application is linked against it), or recompile your 72ca05a99aSAndrew G. Morgan * application with modern kernel headers and this warning will go 73ca05a99aSAndrew G. Morgan * away. 74ca05a99aSAndrew G. Morgan */ 75ca05a99aSAndrew G. Morgan 76ca05a99aSAndrew G. Morgan static void warn_deprecated_v2(void) 77ca05a99aSAndrew G. Morgan { 78ca05a99aSAndrew G. Morgan static int warned; 79ca05a99aSAndrew G. Morgan 80ca05a99aSAndrew G. Morgan if (!warned) { 81ca05a99aSAndrew G. Morgan char name[sizeof(current->comm)]; 82ca05a99aSAndrew G. Morgan 83ca05a99aSAndrew G. Morgan printk(KERN_INFO "warning: `%s' uses deprecated v2" 84ca05a99aSAndrew G. Morgan " capabilities in a way that may be insecure.\n", 85ca05a99aSAndrew G. Morgan get_task_comm(name, current)); 86ca05a99aSAndrew G. Morgan warned = 1; 87ca05a99aSAndrew G. Morgan } 88ca05a99aSAndrew G. Morgan } 89ca05a99aSAndrew G. Morgan 90ca05a99aSAndrew G. Morgan /* 91ca05a99aSAndrew G. Morgan * Version check. Return the number of u32s in each capability flag 92ca05a99aSAndrew G. Morgan * array, or a negative value on error. 93ca05a99aSAndrew G. Morgan */ 94ca05a99aSAndrew G. Morgan static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) 95ca05a99aSAndrew G. Morgan { 96ca05a99aSAndrew G. Morgan __u32 version; 97ca05a99aSAndrew G. Morgan 98ca05a99aSAndrew G. Morgan if (get_user(version, &header->version)) 99ca05a99aSAndrew G. Morgan return -EFAULT; 100ca05a99aSAndrew G. Morgan 101ca05a99aSAndrew G. Morgan switch (version) { 102ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_1: 103ca05a99aSAndrew G. Morgan warn_legacy_capability_use(); 104ca05a99aSAndrew G. Morgan *tocopy = _LINUX_CAPABILITY_U32S_1; 105ca05a99aSAndrew G. Morgan break; 106ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_2: 107ca05a99aSAndrew G. Morgan warn_deprecated_v2(); 108ca05a99aSAndrew G. Morgan /* 109ca05a99aSAndrew G. Morgan * fall through - v3 is otherwise equivalent to v2. 110ca05a99aSAndrew G. Morgan */ 111ca05a99aSAndrew G. Morgan case _LINUX_CAPABILITY_VERSION_3: 112ca05a99aSAndrew G. Morgan *tocopy = _LINUX_CAPABILITY_U32S_3; 113ca05a99aSAndrew G. Morgan break; 114ca05a99aSAndrew G. Morgan default: 115ca05a99aSAndrew G. Morgan if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version)) 116ca05a99aSAndrew G. Morgan return -EFAULT; 117ca05a99aSAndrew G. Morgan return -EINVAL; 118ca05a99aSAndrew G. Morgan } 119ca05a99aSAndrew G. Morgan 120ca05a99aSAndrew G. Morgan return 0; 121ca05a99aSAndrew G. Morgan } 122ca05a99aSAndrew G. Morgan 123ab763c71SAndrew G. Morgan /* 124d84f4f99SDavid Howells * The only thing that can change the capabilities of the current 125d84f4f99SDavid Howells * process is the current process. As such, we can't be in this code 126d84f4f99SDavid Howells * at the same time as we are in the process of setting capabilities 127d84f4f99SDavid Howells * in this process. The net result is that we can limit our use of 128d84f4f99SDavid Howells * locks to when we are reading the caps of another process. 129ab763c71SAndrew G. Morgan */ 130ab763c71SAndrew G. Morgan static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, 131ab763c71SAndrew G. Morgan kernel_cap_t *pIp, kernel_cap_t *pPp) 132ab763c71SAndrew G. Morgan { 133ab763c71SAndrew G. Morgan int ret; 134ab763c71SAndrew G. Morgan 135ab763c71SAndrew G. Morgan if (pid && (pid != task_pid_vnr(current))) { 136ab763c71SAndrew G. Morgan struct task_struct *target; 137ab763c71SAndrew G. Morgan 13886fc80f1SThomas Gleixner rcu_read_lock(); 139ab763c71SAndrew G. Morgan 140ab763c71SAndrew G. Morgan target = find_task_by_vpid(pid); 141ab763c71SAndrew G. Morgan if (!target) 142ab763c71SAndrew G. Morgan ret = -ESRCH; 143ab763c71SAndrew G. Morgan else 144ab763c71SAndrew G. Morgan ret = security_capget(target, pEp, pIp, pPp); 145ab763c71SAndrew G. Morgan 14686fc80f1SThomas Gleixner rcu_read_unlock(); 147ab763c71SAndrew G. Morgan } else 148ab763c71SAndrew G. Morgan ret = security_capget(current, pEp, pIp, pPp); 149ab763c71SAndrew G. Morgan 150ab763c71SAndrew G. Morgan return ret; 151ab763c71SAndrew G. Morgan } 152ab763c71SAndrew G. Morgan 153207a7ba8SRandy Dunlap /** 1541da177e4SLinus Torvalds * sys_capget - get the capabilities of a given process. 155207a7ba8SRandy Dunlap * @header: pointer to struct that contains capability version and 156207a7ba8SRandy Dunlap * target pid data 157207a7ba8SRandy Dunlap * @dataptr: pointer to struct that contains the effective, permitted, 158207a7ba8SRandy Dunlap * and inheritable capabilities that are returned 159207a7ba8SRandy Dunlap * 160207a7ba8SRandy Dunlap * Returns 0 on success and < 0 on error. 1611da177e4SLinus Torvalds */ 162b290ebe2SHeiko Carstens SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr) 1631da177e4SLinus Torvalds { 1641da177e4SLinus Torvalds int ret = 0; 1651da177e4SLinus Torvalds pid_t pid; 166e338d263SAndrew Morgan unsigned tocopy; 167e338d263SAndrew Morgan kernel_cap_t pE, pI, pP; 1681da177e4SLinus Torvalds 169ca05a99aSAndrew G. Morgan ret = cap_validate_magic(header, &tocopy); 170c4a5af54SAndrew G. Morgan if ((dataptr == NULL) || (ret != 0)) 171c4a5af54SAndrew G. Morgan return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret; 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds if (get_user(pid, &header->pid)) 1741da177e4SLinus Torvalds return -EFAULT; 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds if (pid < 0) 1771da177e4SLinus Torvalds return -EINVAL; 1781da177e4SLinus Torvalds 179ab763c71SAndrew G. Morgan ret = cap_get_target_pid(pid, &pE, &pI, &pP); 180e338d263SAndrew Morgan if (!ret) { 181ca05a99aSAndrew G. Morgan struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 182e338d263SAndrew Morgan unsigned i; 183e338d263SAndrew Morgan 184e338d263SAndrew Morgan for (i = 0; i < tocopy; i++) { 185e338d263SAndrew Morgan kdata[i].effective = pE.cap[i]; 186e338d263SAndrew Morgan kdata[i].permitted = pP.cap[i]; 187e338d263SAndrew Morgan kdata[i].inheritable = pI.cap[i]; 188e338d263SAndrew Morgan } 189e338d263SAndrew Morgan 190e338d263SAndrew Morgan /* 191ca05a99aSAndrew G. Morgan * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, 192e338d263SAndrew Morgan * we silently drop the upper capabilities here. This 193e338d263SAndrew Morgan * has the effect of making older libcap 194e338d263SAndrew Morgan * implementations implicitly drop upper capability 195e338d263SAndrew Morgan * bits when they perform a: capget/modify/capset 196e338d263SAndrew Morgan * sequence. 197e338d263SAndrew Morgan * 198e338d263SAndrew Morgan * This behavior is considered fail-safe 199e338d263SAndrew Morgan * behavior. Upgrading the application to a newer 200e338d263SAndrew Morgan * version of libcap will enable access to the newer 201e338d263SAndrew Morgan * capabilities. 202e338d263SAndrew Morgan * 203e338d263SAndrew Morgan * An alternative would be to return an error here 204e338d263SAndrew Morgan * (-ERANGE), but that causes legacy applications to 205e338d263SAndrew Morgan * unexpectidly fail; the capget/modify/capset aborts 206e338d263SAndrew Morgan * before modification is attempted and the application 207e338d263SAndrew Morgan * fails. 208e338d263SAndrew Morgan */ 209e338d263SAndrew Morgan if (copy_to_user(dataptr, kdata, tocopy 210e338d263SAndrew Morgan * sizeof(struct __user_cap_data_struct))) { 2111da177e4SLinus Torvalds return -EFAULT; 212e338d263SAndrew Morgan } 213e338d263SAndrew Morgan } 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds return ret; 2161da177e4SLinus Torvalds } 2171da177e4SLinus Torvalds 218207a7ba8SRandy Dunlap /** 219ab763c71SAndrew G. Morgan * sys_capset - set capabilities for a process or (*) a group of processes 220207a7ba8SRandy Dunlap * @header: pointer to struct that contains capability version and 221207a7ba8SRandy Dunlap * target pid data 222207a7ba8SRandy Dunlap * @data: pointer to struct that contains the effective, permitted, 223207a7ba8SRandy Dunlap * and inheritable capabilities 224207a7ba8SRandy Dunlap * 2251cdcbec1SDavid Howells * Set capabilities for the current process only. The ability to any other 2261cdcbec1SDavid Howells * process(es) has been deprecated and removed. 2271da177e4SLinus Torvalds * 2281da177e4SLinus Torvalds * The restrictions on setting capabilities are specified as: 2291da177e4SLinus Torvalds * 2301cdcbec1SDavid Howells * I: any raised capabilities must be a subset of the old permitted 2311cdcbec1SDavid Howells * P: any raised capabilities must be a subset of the old permitted 2321cdcbec1SDavid Howells * E: must be set to a subset of new permitted 233207a7ba8SRandy Dunlap * 234207a7ba8SRandy Dunlap * Returns 0 on success and < 0 on error. 2351da177e4SLinus Torvalds */ 236b290ebe2SHeiko Carstens SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) 2371da177e4SLinus Torvalds { 238ca05a99aSAndrew G. Morgan struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 239825332e4SArjan van de Ven unsigned i, tocopy, copybytes; 2401da177e4SLinus Torvalds kernel_cap_t inheritable, permitted, effective; 241d84f4f99SDavid Howells struct cred *new; 2421da177e4SLinus Torvalds int ret; 2431da177e4SLinus Torvalds pid_t pid; 2441da177e4SLinus Torvalds 245ca05a99aSAndrew G. Morgan ret = cap_validate_magic(header, &tocopy); 246ca05a99aSAndrew G. Morgan if (ret != 0) 247ca05a99aSAndrew G. Morgan return ret; 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds if (get_user(pid, &header->pid)) 2501da177e4SLinus Torvalds return -EFAULT; 2511da177e4SLinus Torvalds 2521cdcbec1SDavid Howells /* may only affect current now */ 2531cdcbec1SDavid Howells if (pid != 0 && pid != task_pid_vnr(current)) 2541cdcbec1SDavid Howells return -EPERM; 2551cdcbec1SDavid Howells 256825332e4SArjan van de Ven copybytes = tocopy * sizeof(struct __user_cap_data_struct); 257825332e4SArjan van de Ven if (copybytes > sizeof(kdata)) 258825332e4SArjan van de Ven return -EFAULT; 259825332e4SArjan van de Ven 260825332e4SArjan van de Ven if (copy_from_user(&kdata, data, copybytes)) 2611da177e4SLinus Torvalds return -EFAULT; 262e338d263SAndrew Morgan 263e338d263SAndrew Morgan for (i = 0; i < tocopy; i++) { 264e338d263SAndrew Morgan effective.cap[i] = kdata[i].effective; 265e338d263SAndrew Morgan permitted.cap[i] = kdata[i].permitted; 266e338d263SAndrew Morgan inheritable.cap[i] = kdata[i].inheritable; 267e338d263SAndrew Morgan } 268ca05a99aSAndrew G. Morgan while (i < _KERNEL_CAPABILITY_U32S) { 269e338d263SAndrew Morgan effective.cap[i] = 0; 270e338d263SAndrew Morgan permitted.cap[i] = 0; 271e338d263SAndrew Morgan inheritable.cap[i] = 0; 272e338d263SAndrew Morgan i++; 273e338d263SAndrew Morgan } 2741da177e4SLinus Torvalds 275d84f4f99SDavid Howells new = prepare_creds(); 276d84f4f99SDavid Howells if (!new) 277d84f4f99SDavid Howells return -ENOMEM; 278d84f4f99SDavid Howells 279d84f4f99SDavid Howells ret = security_capset(new, current_cred(), 280d84f4f99SDavid Howells &effective, &inheritable, &permitted); 281d84f4f99SDavid Howells if (ret < 0) 282d84f4f99SDavid Howells goto error; 283d84f4f99SDavid Howells 28457f71a0aSAl Viro audit_log_capset(pid, new, current_cred()); 285e68b75a0SEric Paris 286d84f4f99SDavid Howells return commit_creds(new); 2871da177e4SLinus Torvalds 288d84f4f99SDavid Howells error: 289d84f4f99SDavid Howells abort_creds(new); 2901da177e4SLinus Torvalds return ret; 2911da177e4SLinus Torvalds } 29212b5989bSChris Wright 2935cd9c58fSDavid Howells /** 2945cd9c58fSDavid Howells * capable - Determine if the current task has a superior capability in effect 2955cd9c58fSDavid Howells * @cap: The capability to be tested for 2965cd9c58fSDavid Howells * 2975cd9c58fSDavid Howells * Return true if the current task has the given superior capability currently 2985cd9c58fSDavid Howells * available for use, false if not. 2995cd9c58fSDavid Howells * 3005cd9c58fSDavid Howells * This sets PF_SUPERPRIV on the task if the capability is available on the 3015cd9c58fSDavid Howells * assumption that it's about to be used. 3025cd9c58fSDavid Howells */ 3035cd9c58fSDavid Howells int capable(int cap) 30412b5989bSChris Wright { 305637d32dcSEric Paris if (unlikely(!cap_valid(cap))) { 306637d32dcSEric Paris printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap); 307637d32dcSEric Paris BUG(); 308637d32dcSEric Paris } 309637d32dcSEric Paris 3103699c53cSDavid Howells if (security_capable(cap) == 0) { 3115cd9c58fSDavid Howells current->flags |= PF_SUPERPRIV; 31212b5989bSChris Wright return 1; 31312b5989bSChris Wright } 31412b5989bSChris Wright return 0; 31512b5989bSChris Wright } 31612b5989bSChris Wright EXPORT_SYMBOL(capable); 317