aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/audit.h26
-rw-r--r--kernel/auditsc.c68
-rw-r--r--security/commoncap.c23
3 files changed, 116 insertions, 1 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6272a395d43c..8cfb9feb2a05 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -99,6 +99,7 @@
99#define AUDIT_OBJ_PID 1318 /* ptrace target */ 99#define AUDIT_OBJ_PID 1318 /* ptrace target */
100#define AUDIT_TTY 1319 /* Input on an administrative TTY */ 100#define AUDIT_TTY 1319 /* Input on an administrative TTY */
101#define AUDIT_EOE 1320 /* End of multi-record event */ 101#define AUDIT_EOE 1320 /* End of multi-record event */
102#define AUDIT_BPRM_FCAPS 1321 /* Information about fcaps increasing perms */
102 103
103#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 104#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
104#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ 105#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -452,6 +453,7 @@ extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_pr
452extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout); 453extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
453extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification); 454extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
454extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); 455extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
456extern void __audit_log_bprm_fcaps(struct linux_binprm *bprm, kernel_cap_t *pP, kernel_cap_t *pE);
455 457
456static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) 458static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
457{ 459{
@@ -501,6 +503,29 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
501 return __audit_mq_getsetattr(mqdes, mqstat); 503 return __audit_mq_getsetattr(mqdes, mqstat);
502 return 0; 504 return 0;
503} 505}
506
507/*
508 * ieieeeeee, an audit function without a return code!
509 *
510 * This function might fail! I decided that it didn't matter. We are too late
511 * to fail the syscall and the information isn't REQUIRED for any purpose. It's
512 * just nice to have. We should be able to look at past audit logs to figure
513 * out this process's current cap set along with the fcaps from the PATH record
514 * and use that to come up with the final set. Yeah, its ugly, but all the info
515 * is still in the audit log. So I'm not going to bother mentioning we failed
516 * if we couldn't allocate memory.
517 *
518 * If someone changes their mind they could create the aux record earlier and
519 * then search here and use that earlier allocation. But I don't wanna.
520 *
521 * -Eric
522 */
523static inline void audit_log_bprm_fcaps(struct linux_binprm *bprm, kernel_cap_t *pP, kernel_cap_t *pE)
524{
525 if (unlikely(!audit_dummy_context()))
526 __audit_log_bprm_fcaps(bprm, pP, pE);
527}
528
504extern int audit_n_rules; 529extern int audit_n_rules;
505extern int audit_signals; 530extern int audit_signals;
506#else 531#else
@@ -532,6 +557,7 @@ extern int audit_signals;
532#define audit_mq_timedreceive(d,l,p,t) ({ 0; }) 557#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
533#define audit_mq_notify(d,n) ({ 0; }) 558#define audit_mq_notify(d,n) ({ 0; })
534#define audit_mq_getsetattr(d,s) ({ 0; }) 559#define audit_mq_getsetattr(d,s) ({ 0; })
560#define audit_log_bprm_fcaps(b, p, e) do { ; } while (0)
535#define audit_ptrace(t) ((void)0) 561#define audit_ptrace(t) ((void)0)
536#define audit_n_rules 0 562#define audit_n_rules 0
537#define audit_signals 0 563#define audit_signals 0
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index de7e9bcba9ae..3229cd4206f5 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -196,6 +196,14 @@ struct audit_aux_data_pids {
196 int pid_count; 196 int pid_count;
197}; 197};
198 198
199struct audit_aux_data_bprm_fcaps {
200 struct audit_aux_data d;
201 struct audit_cap_data fcap;
202 unsigned int fcap_ver;
203 struct audit_cap_data old_pcap;
204 struct audit_cap_data new_pcap;
205};
206
199struct audit_tree_refs { 207struct audit_tree_refs {
200 struct audit_tree_refs *next; 208 struct audit_tree_refs *next;
201 struct audit_chunk *c[31]; 209 struct audit_chunk *c[31];
@@ -1375,6 +1383,20 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
1375 audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]); 1383 audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
1376 break; } 1384 break; }
1377 1385
1386 case AUDIT_BPRM_FCAPS: {
1387 struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
1388 audit_log_format(ab, "fver=%x", axs->fcap_ver);
1389 audit_log_cap(ab, "fp", &axs->fcap.permitted);
1390 audit_log_cap(ab, "fi", &axs->fcap.inheritable);
1391 audit_log_format(ab, " fe=%d", axs->fcap.fE);
1392 audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
1393 audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
1394 audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
1395 audit_log_cap(ab, "new_pp", &axs->new_pcap.permitted);
1396 audit_log_cap(ab, "new_pi", &axs->new_pcap.inheritable);
1397 audit_log_cap(ab, "new_pe", &axs->new_pcap.effective);
1398 break; }
1399
1378 } 1400 }
1379 audit_log_end(ab); 1401 audit_log_end(ab);
1380 } 1402 }
@@ -2502,6 +2524,52 @@ int __audit_signal_info(int sig, struct task_struct *t)
2502} 2524}
2503 2525
2504/** 2526/**
2527 * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
2528 * @bprm pointer to the bprm being processed
2529 * @caps the caps read from the disk
2530 *
2531 * Simply check if the proc already has the caps given by the file and if not
2532 * store the priv escalation info for later auditing at the end of the syscall
2533 *
2534 * this can fail and we don't care. See the note in audit.h for
2535 * audit_log_bprm_fcaps() for my explaination....
2536 *
2537 * -Eric
2538 */
2539void __audit_log_bprm_fcaps(struct linux_binprm *bprm, kernel_cap_t *pP, kernel_cap_t *pE)
2540{
2541 struct audit_aux_data_bprm_fcaps *ax;
2542 struct audit_context *context = current->audit_context;
2543 struct cpu_vfs_cap_data vcaps;
2544 struct dentry *dentry;
2545
2546 ax = kmalloc(sizeof(*ax), GFP_KERNEL);
2547 if (!ax)
2548 return;
2549
2550 ax->d.type = AUDIT_BPRM_FCAPS;
2551 ax->d.next = context->aux;
2552 context->aux = (void *)ax;
2553
2554 dentry = dget(bprm->file->f_dentry);
2555 get_vfs_caps_from_disk(dentry, &vcaps);
2556 dput(dentry);
2557
2558 ax->fcap.permitted = vcaps.permitted;
2559 ax->fcap.inheritable = vcaps.inheritable;
2560 ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
2561 ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
2562
2563 ax->old_pcap.permitted = *pP;
2564 ax->old_pcap.inheritable = current->cap_inheritable;
2565 ax->old_pcap.effective = *pE;
2566
2567 ax->new_pcap.permitted = current->cap_permitted;
2568 ax->new_pcap.inheritable = current->cap_inheritable;
2569 ax->new_pcap.effective = current->cap_effective;
2570}
2571
2572/**
2505 * audit_core_dumps - record information about processes that end abnormally 2573 * audit_core_dumps - record information about processes that end abnormally
2506 * @signr: signal value 2574 * @signr: signal value
2507 * 2575 *
diff --git a/security/commoncap.c b/security/commoncap.c
index d7eff5797b91..d45393380997 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -8,6 +8,7 @@
8 */ 8 */
9 9
10#include <linux/capability.h> 10#include <linux/capability.h>
11#include <linux/audit.h>
11#include <linux/module.h> 12#include <linux/module.h>
12#include <linux/init.h> 13#include <linux/init.h>
13#include <linux/kernel.h> 14#include <linux/kernel.h>
@@ -376,6 +377,9 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
376 377
377void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 378void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
378{ 379{
380 kernel_cap_t pP = current->cap_permitted;
381 kernel_cap_t pE = current->cap_effective;
382
379 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 383 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
380 !cap_issubset(bprm->cap_post_exec_permitted, 384 !cap_issubset(bprm->cap_post_exec_permitted,
381 current->cap_permitted)) { 385 current->cap_permitted)) {
@@ -409,7 +413,24 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
409 cap_clear(current->cap_effective); 413 cap_clear(current->cap_effective);
410 } 414 }
411 415
412 /* AUD: Audit candidate if current->cap_effective is set */ 416 /*
417 * Audit candidate if current->cap_effective is set
418 *
419 * We do not bother to audit if 3 things are true:
420 * 1) cap_effective has all caps
421 * 2) we are root
422 * 3) root is supposed to have all caps (SECURE_NOROOT)
423 * Since this is just a normal root execing a process.
424 *
425 * Number 1 above might fail if you don't have a full bset, but I think
426 * that is interesting information to audit.
427 */
428 if (!cap_isclear(current->cap_effective)) {
429 if (!cap_issubset(CAP_FULL_SET, current->cap_effective) ||
430 (bprm->e_uid != 0) || (current->uid != 0) ||
431 issecure(SECURE_NOROOT))
432 audit_log_bprm_fcaps(bprm, &pP, &pE);
433 }
413 434
414 current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); 435 current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
415} 436}