aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c244
1 files changed, 228 insertions, 16 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 0f8a2ce3f3a6..afca6dd4ae69 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -22,6 +22,7 @@
22#include <linux/ptrace.h> 22#include <linux/ptrace.h>
23#include <linux/xattr.h> 23#include <linux/xattr.h>
24#include <linux/hugetlb.h> 24#include <linux/hugetlb.h>
25#include <linux/mount.h>
25 26
26int cap_netlink_send(struct sock *sk, struct sk_buff *skb) 27int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
27{ 28{
@@ -108,14 +109,130 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
108 target->cap_permitted = *permitted; 109 target->cap_permitted = *permitted;
109} 110}
110 111
112static inline void bprm_clear_caps(struct linux_binprm *bprm)
113{
114 cap_clear(bprm->cap_inheritable);
115 cap_clear(bprm->cap_permitted);
116 bprm->cap_effective = false;
117}
118
119#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
120
121int cap_inode_need_killpriv(struct dentry *dentry)
122{
123 struct inode *inode = dentry->d_inode;
124 int error;
125
126 if (!inode->i_op || !inode->i_op->getxattr)
127 return 0;
128
129 error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
130 if (error <= 0)
131 return 0;
132 return 1;
133}
134
135int cap_inode_killpriv(struct dentry *dentry)
136{
137 struct inode *inode = dentry->d_inode;
138
139 if (!inode->i_op || !inode->i_op->removexattr)
140 return 0;
141
142 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
143}
144
145static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm,
146 int size)
147{
148 __u32 magic_etc;
149
150 if (size != XATTR_CAPS_SZ)
151 return -EINVAL;
152
153 magic_etc = le32_to_cpu(caps[0]);
154
155 switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
156 case VFS_CAP_REVISION:
157 if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
158 bprm->cap_effective = true;
159 else
160 bprm->cap_effective = false;
161 bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) );
162 bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) );
163 return 0;
164 default:
165 return -EINVAL;
166 }
167}
168
169/* Locate any VFS capabilities: */
170static int get_file_caps(struct linux_binprm *bprm)
171{
172 struct dentry *dentry;
173 int rc = 0;
174 __le32 v1caps[XATTR_CAPS_SZ];
175 struct inode *inode;
176
177 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
178 bprm_clear_caps(bprm);
179 return 0;
180 }
181
182 dentry = dget(bprm->file->f_dentry);
183 inode = dentry->d_inode;
184 if (!inode->i_op || !inode->i_op->getxattr)
185 goto out;
186
187 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps,
188 XATTR_CAPS_SZ);
189 if (rc == -ENODATA || rc == -EOPNOTSUPP) {
190 /* no data, that's ok */
191 rc = 0;
192 goto out;
193 }
194 if (rc < 0)
195 goto out;
196
197 rc = cap_from_disk(v1caps, bprm, rc);
198 if (rc)
199 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
200 __FUNCTION__, rc, bprm->filename);
201
202out:
203 dput(dentry);
204 if (rc)
205 bprm_clear_caps(bprm);
206
207 return rc;
208}
209
210#else
211int cap_inode_need_killpriv(struct dentry *dentry)
212{
213 return 0;
214}
215
216int cap_inode_killpriv(struct dentry *dentry)
217{
218 return 0;
219}
220
221static inline int get_file_caps(struct linux_binprm *bprm)
222{
223 bprm_clear_caps(bprm);
224 return 0;
225}
226#endif
227
111int cap_bprm_set_security (struct linux_binprm *bprm) 228int cap_bprm_set_security (struct linux_binprm *bprm)
112{ 229{
113 /* Copied from fs/exec.c:prepare_binprm. */ 230 int ret;
114 231
115 /* We don't have VFS support for capabilities yet */ 232 ret = get_file_caps(bprm);
116 cap_clear (bprm->cap_inheritable); 233 if (ret)
117 cap_clear (bprm->cap_permitted); 234 printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
118 cap_clear (bprm->cap_effective); 235 __FUNCTION__, ret, bprm->filename);
119 236
120 /* To support inheritance of root-permissions and suid-root 237 /* To support inheritance of root-permissions and suid-root
121 * executables under compatibility mode, we raise all three 238 * executables under compatibility mode, we raise all three
@@ -131,9 +248,10 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
131 cap_set_full (bprm->cap_permitted); 248 cap_set_full (bprm->cap_permitted);
132 } 249 }
133 if (bprm->e_uid == 0) 250 if (bprm->e_uid == 0)
134 cap_set_full (bprm->cap_effective); 251 bprm->cap_effective = true;
135 } 252 }
136 return 0; 253
254 return ret;
137} 255}
138 256
139void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 257void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
@@ -149,6 +267,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
149 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 267 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
150 !cap_issubset (new_permitted, current->cap_permitted)) { 268 !cap_issubset (new_permitted, current->cap_permitted)) {
151 set_dumpable(current->mm, suid_dumpable); 269 set_dumpable(current->mm, suid_dumpable);
270 current->pdeath_signal = 0;
152 271
153 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { 272 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
154 if (!capable(CAP_SETUID)) { 273 if (!capable(CAP_SETUID)) {
@@ -170,8 +289,8 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
170 * capability rules */ 289 * capability rules */
171 if (!is_init(current)) { 290 if (!is_init(current)) {
172 current->cap_permitted = new_permitted; 291 current->cap_permitted = new_permitted;
173 current->cap_effective = 292 current->cap_effective = bprm->cap_effective ?
174 cap_intersect (new_permitted, bprm->cap_effective); 293 new_permitted : 0;
175 } 294 }
176 295
177 /* AUD: Audit candidate if current->cap_effective is set */ 296 /* AUD: Audit candidate if current->cap_effective is set */
@@ -181,11 +300,15 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
181 300
182int cap_bprm_secureexec (struct linux_binprm *bprm) 301int cap_bprm_secureexec (struct linux_binprm *bprm)
183{ 302{
184 /* If/when this module is enhanced to incorporate capability 303 if (current->uid != 0) {
185 bits on files, the test below should be extended to also perform a 304 if (bprm->cap_effective)
186 test between the old and new capability sets. For now, 305 return 1;
187 it simply preserves the legacy decision algorithm used by 306 if (!cap_isclear(bprm->cap_permitted))
188 the old userland. */ 307 return 1;
308 if (!cap_isclear(bprm->cap_inheritable))
309 return 1;
310 }
311
189 return (current->euid != current->uid || 312 return (current->euid != current->uid ||
190 current->egid != current->gid); 313 current->egid != current->gid);
191} 314}
@@ -193,7 +316,11 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
193int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, 316int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
194 size_t size, int flags) 317 size_t size, int flags)
195{ 318{
196 if (!strncmp(name, XATTR_SECURITY_PREFIX, 319 if (!strcmp(name, XATTR_NAME_CAPS)) {
320 if (!capable(CAP_SETFCAP))
321 return -EPERM;
322 return 0;
323 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
197 sizeof(XATTR_SECURITY_PREFIX) - 1) && 324 sizeof(XATTR_SECURITY_PREFIX) - 1) &&
198 !capable(CAP_SYS_ADMIN)) 325 !capable(CAP_SYS_ADMIN))
199 return -EPERM; 326 return -EPERM;
@@ -202,7 +329,11 @@ int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
202 329
203int cap_inode_removexattr(struct dentry *dentry, char *name) 330int cap_inode_removexattr(struct dentry *dentry, char *name)
204{ 331{
205 if (!strncmp(name, XATTR_SECURITY_PREFIX, 332 if (!strcmp(name, XATTR_NAME_CAPS)) {
333 if (!capable(CAP_SETFCAP))
334 return -EPERM;
335 return 0;
336 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
206 sizeof(XATTR_SECURITY_PREFIX) - 1) && 337 sizeof(XATTR_SECURITY_PREFIX) - 1) &&
207 !capable(CAP_SYS_ADMIN)) 338 !capable(CAP_SYS_ADMIN))
208 return -EPERM; 339 return -EPERM;
@@ -299,6 +430,83 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
299 return 0; 430 return 0;
300} 431}
301 432
433#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
434/*
435 * Rationale: code calling task_setscheduler, task_setioprio, and
436 * task_setnice, assumes that
437 * . if capable(cap_sys_nice), then those actions should be allowed
438 * . if not capable(cap_sys_nice), but acting on your own processes,
439 * then those actions should be allowed
440 * This is insufficient now since you can call code without suid, but
441 * yet with increased caps.
442 * So we check for increased caps on the target process.
443 */
444static inline int cap_safe_nice(struct task_struct *p)
445{
446 if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
447 !__capable(current, CAP_SYS_NICE))
448 return -EPERM;
449 return 0;
450}
451
452int cap_task_setscheduler (struct task_struct *p, int policy,
453 struct sched_param *lp)
454{
455 return cap_safe_nice(p);
456}
457
458int cap_task_setioprio (struct task_struct *p, int ioprio)
459{
460 return cap_safe_nice(p);
461}
462
463int cap_task_setnice (struct task_struct *p, int nice)
464{
465 return cap_safe_nice(p);
466}
467
468int cap_task_kill(struct task_struct *p, struct siginfo *info,
469 int sig, u32 secid)
470{
471 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
472 return 0;
473
474 if (secid)
475 /*
476 * Signal sent as a particular user.
477 * Capabilities are ignored. May be wrong, but it's the
478 * only thing we can do at the moment.
479 * Used only by usb drivers?
480 */
481 return 0;
482 if (cap_issubset(p->cap_permitted, current->cap_permitted))
483 return 0;
484 if (capable(CAP_KILL))
485 return 0;
486
487 return -EPERM;
488}
489#else
490int cap_task_setscheduler (struct task_struct *p, int policy,
491 struct sched_param *lp)
492{
493 return 0;
494}
495int cap_task_setioprio (struct task_struct *p, int ioprio)
496{
497 return 0;
498}
499int cap_task_setnice (struct task_struct *p, int nice)
500{
501 return 0;
502}
503int cap_task_kill(struct task_struct *p, struct siginfo *info,
504 int sig, u32 secid)
505{
506 return 0;
507}
508#endif
509
302void cap_task_reparent_to_init (struct task_struct *p) 510void cap_task_reparent_to_init (struct task_struct *p)
303{ 511{
304 p->cap_effective = CAP_INIT_EFF_SET; 512 p->cap_effective = CAP_INIT_EFF_SET;
@@ -336,6 +544,10 @@ EXPORT_SYMBOL(cap_bprm_secureexec);
336EXPORT_SYMBOL(cap_inode_setxattr); 544EXPORT_SYMBOL(cap_inode_setxattr);
337EXPORT_SYMBOL(cap_inode_removexattr); 545EXPORT_SYMBOL(cap_inode_removexattr);
338EXPORT_SYMBOL(cap_task_post_setuid); 546EXPORT_SYMBOL(cap_task_post_setuid);
547EXPORT_SYMBOL(cap_task_kill);
548EXPORT_SYMBOL(cap_task_setscheduler);
549EXPORT_SYMBOL(cap_task_setioprio);
550EXPORT_SYMBOL(cap_task_setnice);
339EXPORT_SYMBOL(cap_task_reparent_to_init); 551EXPORT_SYMBOL(cap_task_reparent_to_init);
340EXPORT_SYMBOL(cap_syslog); 552EXPORT_SYMBOL(cap_syslog);
341EXPORT_SYMBOL(cap_vm_enough_memory); 553EXPORT_SYMBOL(cap_vm_enough_memory);