00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <linux/audit.h>
00011 #include <linux/capability.h>
00012 #include <linux/mm.h>
00013 #include <linux/module.h>
00014 #include <linux/security.h>
00015 #include <linux/syscalls.h>
00016 #include <linux/pid_namespace.h>
00017 #include <asm/uaccess.h>
00018 #include "cred-internals.h"
00019
00020 #ifndef DDE_LINUX
00021
00022
00023
00024
00025 static DEFINE_SPINLOCK(task_capability_lock);
00026
00027
00028
00029
00030
00031 const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
00032 const kernel_cap_t __cap_full_set = CAP_FULL_SET;
00033 const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
00034
00035 EXPORT_SYMBOL(__cap_empty_set);
00036 EXPORT_SYMBOL(__cap_full_set);
00037 EXPORT_SYMBOL(__cap_init_eff_set);
00038
00039 #ifdef CONFIG_SECURITY_FILE_CAPABILITIES
00040 int file_caps_enabled = 1;
00041
00042 static int __init file_caps_disable(char *str)
00043 {
00044 file_caps_enabled = 0;
00045 return 1;
00046 }
00047 __setup("no_file_caps", file_caps_disable);
00048 #endif
00049
00050
00051
00052
00053
00054
00055
00056 static void warn_legacy_capability_use(void)
00057 {
00058 static int warned;
00059 if (!warned) {
00060 char name[sizeof(current->comm)];
00061
00062 printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
00063 " (legacy support in use)\n",
00064 get_task_comm(name, current));
00065 warned = 1;
00066 }
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static void warn_deprecated_v2(void)
00086 {
00087 static int warned;
00088
00089 if (!warned) {
00090 char name[sizeof(current->comm)];
00091
00092 printk(KERN_INFO "warning: `%s' uses deprecated v2"
00093 " capabilities in a way that may be insecure.\n",
00094 get_task_comm(name, current));
00095 warned = 1;
00096 }
00097 }
00098
00099
00100
00101
00102
00103 static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
00104 {
00105 __u32 version;
00106
00107 if (get_user(version, &header->version))
00108 return -EFAULT;
00109
00110 switch (version) {
00111 case _LINUX_CAPABILITY_VERSION_1:
00112 warn_legacy_capability_use();
00113 *tocopy = _LINUX_CAPABILITY_U32S_1;
00114 break;
00115 case _LINUX_CAPABILITY_VERSION_2:
00116 warn_deprecated_v2();
00117
00118
00119
00120 case _LINUX_CAPABILITY_VERSION_3:
00121 *tocopy = _LINUX_CAPABILITY_U32S_3;
00122 break;
00123 default:
00124 if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version))
00125 return -EFAULT;
00126 return -EINVAL;
00127 }
00128
00129 return 0;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139 static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
00140 kernel_cap_t *pIp, kernel_cap_t *pPp)
00141 {
00142 int ret;
00143
00144 if (pid && (pid != task_pid_vnr(current))) {
00145 struct task_struct *target;
00146
00147 read_lock(&tasklist_lock);
00148
00149 target = find_task_by_vpid(pid);
00150 if (!target)
00151 ret = -ESRCH;
00152 else
00153 ret = security_capget(target, pEp, pIp, pPp);
00154
00155 read_unlock(&tasklist_lock);
00156 } else
00157 ret = security_capget(current, pEp, pIp, pPp);
00158
00159 return ret;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
00172 {
00173 int ret = 0;
00174 pid_t pid;
00175 unsigned tocopy;
00176 kernel_cap_t pE, pI, pP;
00177
00178 ret = cap_validate_magic(header, &tocopy);
00179 if (ret != 0)
00180 return ret;
00181
00182 if (get_user(pid, &header->pid))
00183 return -EFAULT;
00184
00185 if (pid < 0)
00186 return -EINVAL;
00187
00188 ret = cap_get_target_pid(pid, &pE, &pI, &pP);
00189 if (!ret) {
00190 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
00191 unsigned i;
00192
00193 for (i = 0; i < tocopy; i++) {
00194 kdata[i].effective = pE.cap[i];
00195 kdata[i].permitted = pP.cap[i];
00196 kdata[i].inheritable = pI.cap[i];
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 if (copy_to_user(dataptr, kdata, tocopy
00219 * sizeof(struct __user_cap_data_struct))) {
00220 return -EFAULT;
00221 }
00222 }
00223
00224 return ret;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
00246 {
00247 struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
00248 unsigned i, tocopy;
00249 kernel_cap_t inheritable, permitted, effective;
00250 struct cred *new;
00251 int ret;
00252 pid_t pid;
00253
00254 ret = cap_validate_magic(header, &tocopy);
00255 if (ret != 0)
00256 return ret;
00257
00258 if (get_user(pid, &header->pid))
00259 return -EFAULT;
00260
00261
00262 if (pid != 0 && pid != task_pid_vnr(current))
00263 return -EPERM;
00264
00265 if (copy_from_user(&kdata, data,
00266 tocopy * sizeof(struct __user_cap_data_struct)))
00267 return -EFAULT;
00268
00269 for (i = 0; i < tocopy; i++) {
00270 effective.cap[i] = kdata[i].effective;
00271 permitted.cap[i] = kdata[i].permitted;
00272 inheritable.cap[i] = kdata[i].inheritable;
00273 }
00274 while (i < _KERNEL_CAPABILITY_U32S) {
00275 effective.cap[i] = 0;
00276 permitted.cap[i] = 0;
00277 inheritable.cap[i] = 0;
00278 i++;
00279 }
00280
00281 new = prepare_creds();
00282 if (!new)
00283 return -ENOMEM;
00284
00285 ret = security_capset(new, current_cred(),
00286 &effective, &inheritable, &permitted);
00287 if (ret < 0)
00288 goto error;
00289
00290 audit_log_capset(pid, new, current_cred());
00291
00292 return commit_creds(new);
00293
00294 error:
00295 abort_creds(new);
00296 return ret;
00297 }
00298 #endif
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 int capable(int cap)
00311 {
00312 if (unlikely(!cap_valid(cap))) {
00313 printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
00314 BUG();
00315 }
00316
00317 if (security_capable(cap) == 0) {
00318 current->flags |= PF_SUPERPRIV;
00319 return 1;
00320 }
00321 return 0;
00322 }
00323 EXPORT_SYMBOL(capable);