Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'audit.b22' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current

* 'audit.b22' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current:
[PATCH] audit syscall classes
[PATCH] audit: support for object context filters
[PATCH] audit: rename AUDIT_SE_* constants
[PATCH] add rule filterkey

+403 -87
+1
arch/i386/kernel/Makefile
··· 38 38 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 39 39 obj-$(CONFIG_HPET_TIMER) += hpet.o 40 40 obj-$(CONFIG_K8_NB) += k8.o 41 + obj-$(CONFIG_AUDIT) += audit.o 41 42 42 43 EXTRA_AFLAGS := -traditional 43 44
+23
arch/i386/kernel/audit.c
··· 1 + #include <linux/init.h> 2 + #include <linux/types.h> 3 + #include <linux/audit.h> 4 + #include <asm/unistd.h> 5 + 6 + static unsigned dir_class[] = { 7 + #include <asm-generic/audit_dir_write.h> 8 + ~0U 9 + }; 10 + 11 + static unsigned chattr_class[] = { 12 + #include <asm-generic/audit_change_attr.h> 13 + ~0U 14 + }; 15 + 16 + static int __init audit_classes_init(void) 17 + { 18 + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); 19 + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); 20 + return 0; 21 + } 22 + 23 + __initcall(audit_classes_init);
+1
arch/ia64/ia32/Makefile
··· 4 4 5 5 obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \ 6 6 ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o 7 + obj-$(CONFIG_AUDIT) += audit.o 7 8 8 9 # Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and 9 10 # restore_ia32_fpstate_live() can be sure the live register contain user-level state.
+11
arch/ia64/ia32/audit.c
··· 1 + #include <asm-i386/unistd.h> 2 + 3 + unsigned ia32_dir_class[] = { 4 + #include <asm-generic/audit_dir_write.h> 5 + ~0U 6 + }; 7 + 8 + unsigned ia32_chattr_class[] = { 9 + #include <asm-generic/audit_change_attr.h> 10 + ~0U 11 + };
+1
arch/ia64/kernel/Makefile
··· 29 29 obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o 30 30 obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o 31 31 obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o 32 + obj-$(CONFIG_AUDIT) += audit.o 32 33 mca_recovery-y += mca_drv.o mca_drv_asm.o 33 34 34 35 # The gate DSO image is built using a special linker script.
+29
arch/ia64/kernel/audit.c
··· 1 + #include <linux/init.h> 2 + #include <linux/types.h> 3 + #include <linux/audit.h> 4 + #include <asm/unistd.h> 5 + 6 + static unsigned dir_class[] = { 7 + #include <asm-generic/audit_dir_write.h> 8 + ~0U 9 + }; 10 + 11 + static unsigned chattr_class[] = { 12 + #include <asm-generic/audit_change_attr.h> 13 + ~0U 14 + }; 15 + 16 + static int __init audit_classes_init(void) 17 + { 18 + #ifdef CONFIG_IA32_SUPPORT 19 + extern __u32 ia32_dir_class[]; 20 + extern __u32 ia32_chattr_class[]; 21 + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); 22 + audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); 23 + #endif 24 + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); 25 + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); 26 + return 0; 27 + } 28 + 29 + __initcall(audit_classes_init);
+3
arch/x86_64/ia32/Makefile
··· 11 11 12 12 obj-$(CONFIG_IA32_AOUT) += ia32_aout.o 13 13 14 + audit-class-$(CONFIG_AUDIT) := audit.o 15 + obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y) 16 + 14 17 $(obj)/syscall32_syscall.o: \ 15 18 $(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so) 16 19
+11
arch/x86_64/ia32/audit.c
··· 1 + #include <asm-i386/unistd.h> 2 + 3 + unsigned ia32_dir_class[] = { 4 + #include <asm-generic/audit_dir_write.h> 5 + ~0U 6 + }; 7 + 8 + unsigned ia32_chattr_class[] = { 9 + #include <asm-generic/audit_change_attr.h> 10 + ~0U 11 + };
+1
arch/x86_64/kernel/Makefile
··· 35 35 obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o 36 36 obj-$(CONFIG_X86_VSMP) += vsmp.o 37 37 obj-$(CONFIG_K8_NB) += k8.o 38 + obj-$(CONFIG_AUDIT) += audit.o 38 39 39 40 obj-$(CONFIG_MODULES) += module.o 40 41
+29
arch/x86_64/kernel/audit.c
··· 1 + #include <linux/init.h> 2 + #include <linux/types.h> 3 + #include <linux/audit.h> 4 + #include <asm/unistd.h> 5 + 6 + static unsigned dir_class[] = { 7 + #include <asm-generic/audit_dir_write.h> 8 + ~0U 9 + }; 10 + 11 + static unsigned chattr_class[] = { 12 + #include <asm-generic/audit_change_attr.h> 13 + ~0U 14 + }; 15 + 16 + static int __init audit_classes_init(void) 17 + { 18 + #ifdef CONFIG_IA32_EMULATION 19 + extern __u32 ia32_dir_class[]; 20 + extern __u32 ia32_chattr_class[]; 21 + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); 22 + audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); 23 + #endif 24 + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); 25 + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); 26 + return 0; 27 + } 28 + 29 + __initcall(audit_classes_init);
+18
include/asm-generic/audit_change_attr.h
··· 1 + __NR_chmod, 2 + __NR_fchmod, 3 + __NR_chown, 4 + __NR_fchown, 5 + __NR_lchown, 6 + __NR_setxattr, 7 + __NR_lsetxattr, 8 + __NR_fsetxattr, 9 + __NR_removexattr, 10 + __NR_lremovexattr, 11 + __NR_fremovexattr, 12 + __NR_fchownat, 13 + __NR_fchmodat, 14 + #ifdef __NR_chown32 15 + __NR_chown32, 16 + __NR_fchown32, 17 + __NR_lchown32, 18 + #endif
+14
include/asm-generic/audit_dir_write.h
··· 1 + __NR_rename, 2 + __NR_mkdir, 3 + __NR_rmdir, 4 + __NR_creat, 5 + __NR_link, 6 + __NR_unlink, 7 + __NR_symlink, 8 + __NR_mknod, 9 + __NR_mkdirat, 10 + __NR_mknodat, 11 + __NR_unlinkat, 12 + __NR_renameat, 13 + __NR_linkat, 14 + __NR_symlinkat,
+20 -5
include/linux/audit.h
··· 122 122 /* Rule structure sizes -- if these change, different AUDIT_ADD and 123 123 * AUDIT_LIST commands must be implemented. */ 124 124 #define AUDIT_MAX_FIELDS 64 125 + #define AUDIT_MAX_KEY_LEN 32 125 126 #define AUDIT_BITMASK_SIZE 64 126 127 #define AUDIT_WORD(nr) ((__u32)((nr)/32)) 127 128 #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) 129 + 130 + #define AUDIT_SYSCALL_CLASSES 16 131 + #define AUDIT_CLASS_DIR_WRITE 0 132 + #define AUDIT_CLASS_DIR_WRITE_32 1 133 + #define AUDIT_CLASS_CHATTR 2 134 + #define AUDIT_CLASS_CHATTR_32 3 128 135 129 136 /* This bitmask is used to validate user input. It represents all bits that 130 137 * are currently used in an audit field constant understood by the kernel. ··· 157 150 #define AUDIT_PERS 10 158 151 #define AUDIT_ARCH 11 159 152 #define AUDIT_MSGTYPE 12 160 - #define AUDIT_SE_USER 13 /* security label user */ 161 - #define AUDIT_SE_ROLE 14 /* security label role */ 162 - #define AUDIT_SE_TYPE 15 /* security label type */ 163 - #define AUDIT_SE_SEN 16 /* security label sensitivity label */ 164 - #define AUDIT_SE_CLR 17 /* security label clearance label */ 153 + #define AUDIT_SUBJ_USER 13 /* security label user */ 154 + #define AUDIT_SUBJ_ROLE 14 /* security label role */ 155 + #define AUDIT_SUBJ_TYPE 15 /* security label type */ 156 + #define AUDIT_SUBJ_SEN 16 /* security label sensitivity label */ 157 + #define AUDIT_SUBJ_CLR 17 /* security label clearance label */ 165 158 #define AUDIT_PPID 18 159 + #define AUDIT_OBJ_USER 19 160 + #define AUDIT_OBJ_ROLE 20 161 + #define AUDIT_OBJ_TYPE 21 162 + #define AUDIT_OBJ_LEV_LOW 22 163 + #define AUDIT_OBJ_LEV_HIGH 23 166 164 167 165 /* These are ONLY useful when checking 168 166 * at syscall exit time (AUDIT_AT_EXIT). */ ··· 182 170 #define AUDIT_ARG1 (AUDIT_ARG0+1) 183 171 #define AUDIT_ARG2 (AUDIT_ARG0+2) 184 172 #define AUDIT_ARG3 (AUDIT_ARG0+3) 173 + 174 + #define AUDIT_FILTERKEY 210 185 175 186 176 #define AUDIT_NEGATE 0x80000000 187 177 ··· 313 299 #define AUDITSC_SUCCESS 1 314 300 #define AUDITSC_FAILURE 2 315 301 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) 302 + extern int __init audit_register_class(int class, unsigned *list); 316 303 #ifdef CONFIG_AUDITSYSCALL 317 304 /* These are defined in auditsc.c */ 318 305 /* Public API */
+1
kernel/audit.h
··· 81 81 u32 mask[AUDIT_BITMASK_SIZE]; 82 82 u32 buflen; /* for data alloc on list rules */ 83 83 u32 field_count; 84 + char *filterkey; /* ties events to rules */ 84 85 struct audit_field *fields; 85 86 struct audit_field *inode_f; /* quick access to an inode field */ 86 87 struct audit_watch *watch; /* associated watch */
+148 -61
kernel/auditfilter.c
··· 141 141 selinux_audit_rule_free(f->se_rule); 142 142 } 143 143 kfree(e->rule.fields); 144 + kfree(e->rule.filterkey); 144 145 kfree(e); 145 146 } 146 147 ··· 279 278 return 0; 280 279 } 281 280 281 + static __u32 *classes[AUDIT_SYSCALL_CLASSES]; 282 + 283 + int __init audit_register_class(int class, unsigned *list) 284 + { 285 + __u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL); 286 + if (!p) 287 + return -ENOMEM; 288 + while (*list != ~0U) { 289 + unsigned n = *list++; 290 + if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) { 291 + kfree(p); 292 + return -EINVAL; 293 + } 294 + p[AUDIT_WORD(n)] |= AUDIT_BIT(n); 295 + } 296 + if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) { 297 + kfree(p); 298 + return -EINVAL; 299 + } 300 + classes[class] = p; 301 + return 0; 302 + } 303 + 282 304 /* Common user-space to kernel rule translation. */ 283 305 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) 284 306 { ··· 344 320 345 321 for (i = 0; i < AUDIT_BITMASK_SIZE; i++) 346 322 entry->rule.mask[i] = rule->mask[i]; 323 + 324 + for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) { 325 + int bit = AUDIT_BITMASK_SIZE * 32 - i - 1; 326 + __u32 *p = &entry->rule.mask[AUDIT_WORD(bit)]; 327 + __u32 *class; 328 + 329 + if (!(*p & AUDIT_BIT(bit))) 330 + continue; 331 + *p &= ~AUDIT_BIT(bit); 332 + class = classes[i]; 333 + if (class) { 334 + int j; 335 + for (j = 0; j < AUDIT_BITMASK_SIZE; j++) 336 + entry->rule.mask[j] |= class[j]; 337 + } 338 + } 347 339 348 340 return entry; 349 341 ··· 509 469 case AUDIT_ARG2: 510 470 case AUDIT_ARG3: 511 471 break; 512 - case AUDIT_SE_USER: 513 - case AUDIT_SE_ROLE: 514 - case AUDIT_SE_TYPE: 515 - case AUDIT_SE_SEN: 516 - case AUDIT_SE_CLR: 472 + case AUDIT_SUBJ_USER: 473 + case AUDIT_SUBJ_ROLE: 474 + case AUDIT_SUBJ_TYPE: 475 + case AUDIT_SUBJ_SEN: 476 + case AUDIT_SUBJ_CLR: 477 + case AUDIT_OBJ_USER: 478 + case AUDIT_OBJ_ROLE: 479 + case AUDIT_OBJ_TYPE: 480 + case AUDIT_OBJ_LEV_LOW: 481 + case AUDIT_OBJ_LEV_HIGH: 517 482 str = audit_unpack_string(&bufp, &remain, f->val); 518 483 if (IS_ERR(str)) 519 484 goto exit_free; ··· 555 510 err = audit_to_inode(&entry->rule, f); 556 511 if (err) 557 512 goto exit_free; 513 + break; 514 + case AUDIT_FILTERKEY: 515 + err = -EINVAL; 516 + if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN) 517 + goto exit_free; 518 + str = audit_unpack_string(&bufp, &remain, f->val); 519 + if (IS_ERR(str)) 520 + goto exit_free; 521 + entry->rule.buflen += f->val; 522 + entry->rule.filterkey = str; 558 523 break; 559 524 default: 560 525 goto exit_free; ··· 655 600 data->fields[i] = f->type; 656 601 data->fieldflags[i] = f->op; 657 602 switch(f->type) { 658 - case AUDIT_SE_USER: 659 - case AUDIT_SE_ROLE: 660 - case AUDIT_SE_TYPE: 661 - case AUDIT_SE_SEN: 662 - case AUDIT_SE_CLR: 603 + case AUDIT_SUBJ_USER: 604 + case AUDIT_SUBJ_ROLE: 605 + case AUDIT_SUBJ_TYPE: 606 + case AUDIT_SUBJ_SEN: 607 + case AUDIT_SUBJ_CLR: 608 + case AUDIT_OBJ_USER: 609 + case AUDIT_OBJ_ROLE: 610 + case AUDIT_OBJ_TYPE: 611 + case AUDIT_OBJ_LEV_LOW: 612 + case AUDIT_OBJ_LEV_HIGH: 663 613 data->buflen += data->values[i] = 664 614 audit_pack_string(&bufp, f->se_str); 665 615 break; 666 616 case AUDIT_WATCH: 667 617 data->buflen += data->values[i] = 668 618 audit_pack_string(&bufp, krule->watch->path); 619 + break; 620 + case AUDIT_FILTERKEY: 621 + data->buflen += data->values[i] = 622 + audit_pack_string(&bufp, krule->filterkey); 669 623 break; 670 624 default: 671 625 data->values[i] = f->val; ··· 703 639 return 1; 704 640 705 641 switch(a->fields[i].type) { 706 - case AUDIT_SE_USER: 707 - case AUDIT_SE_ROLE: 708 - case AUDIT_SE_TYPE: 709 - case AUDIT_SE_SEN: 710 - case AUDIT_SE_CLR: 642 + case AUDIT_SUBJ_USER: 643 + case AUDIT_SUBJ_ROLE: 644 + case AUDIT_SUBJ_TYPE: 645 + case AUDIT_SUBJ_SEN: 646 + case AUDIT_SUBJ_CLR: 647 + case AUDIT_OBJ_USER: 648 + case AUDIT_OBJ_ROLE: 649 + case AUDIT_OBJ_TYPE: 650 + case AUDIT_OBJ_LEV_LOW: 651 + case AUDIT_OBJ_LEV_HIGH: 711 652 if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) 712 653 return 1; 713 654 break; 714 655 case AUDIT_WATCH: 715 656 if (strcmp(a->watch->path, b->watch->path)) 657 + return 1; 658 + break; 659 + case AUDIT_FILTERKEY: 660 + /* both filterkeys exist based on above type compare */ 661 + if (strcmp(a->filterkey, b->filterkey)) 716 662 return 1; 717 663 break; 718 664 default: ··· 804 730 u32 fcount = old->field_count; 805 731 struct audit_entry *entry; 806 732 struct audit_krule *new; 733 + char *fk; 807 734 int i, err = 0; 808 735 809 736 entry = audit_init_entry(fcount); ··· 828 753 * the originals will all be freed when the old rule is freed. */ 829 754 for (i = 0; i < fcount; i++) { 830 755 switch (new->fields[i].type) { 831 - case AUDIT_SE_USER: 832 - case AUDIT_SE_ROLE: 833 - case AUDIT_SE_TYPE: 834 - case AUDIT_SE_SEN: 835 - case AUDIT_SE_CLR: 756 + case AUDIT_SUBJ_USER: 757 + case AUDIT_SUBJ_ROLE: 758 + case AUDIT_SUBJ_TYPE: 759 + case AUDIT_SUBJ_SEN: 760 + case AUDIT_SUBJ_CLR: 761 + case AUDIT_OBJ_USER: 762 + case AUDIT_OBJ_ROLE: 763 + case AUDIT_OBJ_TYPE: 764 + case AUDIT_OBJ_LEV_LOW: 765 + case AUDIT_OBJ_LEV_HIGH: 836 766 err = audit_dupe_selinux_field(&new->fields[i], 837 767 &old->fields[i]); 768 + break; 769 + case AUDIT_FILTERKEY: 770 + fk = kstrdup(old->filterkey, GFP_KERNEL); 771 + if (unlikely(!fk)) 772 + err = -ENOMEM; 773 + else 774 + new->filterkey = fk; 838 775 } 839 776 if (err) { 840 777 audit_free_rule(entry); ··· 1332 1245 skb_queue_tail(q, skb); 1333 1246 } 1334 1247 1248 + /* Log rule additions and removals */ 1249 + static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, 1250 + struct audit_krule *rule, int res) 1251 + { 1252 + struct audit_buffer *ab; 1253 + 1254 + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 1255 + if (!ab) 1256 + return; 1257 + audit_log_format(ab, "auid=%u", loginuid); 1258 + if (sid) { 1259 + char *ctx = NULL; 1260 + u32 len; 1261 + if (selinux_ctxid_to_string(sid, &ctx, &len)) 1262 + audit_log_format(ab, " ssid=%u", sid); 1263 + else 1264 + audit_log_format(ab, " subj=%s", ctx); 1265 + kfree(ctx); 1266 + } 1267 + audit_log_format(ab, " %s rule key=", action); 1268 + if (rule->filterkey) 1269 + audit_log_untrustedstring(ab, rule->filterkey); 1270 + else 1271 + audit_log_format(ab, "(null)"); 1272 + audit_log_format(ab, " list=%d res=%d", rule->listnr, res); 1273 + audit_log_end(ab); 1274 + } 1275 + 1335 1276 /** 1336 1277 * audit_receive_filter - apply all rules to the specified message type 1337 1278 * @type: audit message type ··· 1419 1304 1420 1305 err = audit_add_rule(entry, 1421 1306 &audit_filter_list[entry->rule.listnr]); 1422 - 1423 - if (sid) { 1424 - char *ctx = NULL; 1425 - u32 len; 1426 - if (selinux_ctxid_to_string(sid, &ctx, &len)) { 1427 - /* Maybe call audit_panic? */ 1428 - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 1429 - "auid=%u ssid=%u add rule to list=%d res=%d", 1430 - loginuid, sid, entry->rule.listnr, !err); 1431 - } else 1432 - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 1433 - "auid=%u subj=%s add rule to list=%d res=%d", 1434 - loginuid, ctx, entry->rule.listnr, !err); 1435 - kfree(ctx); 1436 - } else 1437 - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 1438 - "auid=%u add rule to list=%d res=%d", 1439 - loginuid, entry->rule.listnr, !err); 1307 + audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err); 1440 1308 1441 1309 if (err) 1442 1310 audit_free_rule(entry); ··· 1435 1337 1436 1338 err = audit_del_rule(entry, 1437 1339 &audit_filter_list[entry->rule.listnr]); 1438 - 1439 - if (sid) { 1440 - char *ctx = NULL; 1441 - u32 len; 1442 - if (selinux_ctxid_to_string(sid, &ctx, &len)) { 1443 - /* Maybe call audit_panic? */ 1444 - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 1445 - "auid=%u ssid=%u remove rule from list=%d res=%d", 1446 - loginuid, sid, entry->rule.listnr, !err); 1447 - } else 1448 - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 1449 - "auid=%u subj=%s remove rule from list=%d res=%d", 1450 - loginuid, ctx, entry->rule.listnr, !err); 1451 - kfree(ctx); 1452 - } else 1453 - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 1454 - "auid=%u remove rule from list=%d res=%d", 1455 - loginuid, entry->rule.listnr, !err); 1340 + audit_log_rule_change(loginuid, sid, "remove", &entry->rule, 1341 + !err); 1456 1342 1457 1343 audit_free_rule(entry); 1458 1344 break; ··· 1596 1514 for (i = 0; i < rule->field_count; i++) { 1597 1515 struct audit_field *f = &rule->fields[i]; 1598 1516 switch (f->type) { 1599 - case AUDIT_SE_USER: 1600 - case AUDIT_SE_ROLE: 1601 - case AUDIT_SE_TYPE: 1602 - case AUDIT_SE_SEN: 1603 - case AUDIT_SE_CLR: 1517 + case AUDIT_SUBJ_USER: 1518 + case AUDIT_SUBJ_ROLE: 1519 + case AUDIT_SUBJ_TYPE: 1520 + case AUDIT_SUBJ_SEN: 1521 + case AUDIT_SUBJ_CLR: 1522 + case AUDIT_OBJ_USER: 1523 + case AUDIT_OBJ_ROLE: 1524 + case AUDIT_OBJ_TYPE: 1525 + case AUDIT_OBJ_LEV_LOW: 1526 + case AUDIT_OBJ_LEV_HIGH: 1604 1527 return 1; 1605 1528 } 1606 1529 }
+60 -5
kernel/auditsc.c
··· 186 186 int auditable; /* 1 if record should be written */ 187 187 int name_count; 188 188 struct audit_names names[AUDIT_NAMES]; 189 + char * filterkey; /* key for rule that triggered record */ 189 190 struct dentry * pwd; 190 191 struct vfsmount * pwdmnt; 191 192 struct audit_context *previous; /* For nested syscalls */ ··· 321 320 if (ctx) 322 321 result = audit_comparator(ctx->loginuid, f->op, f->val); 323 322 break; 324 - case AUDIT_SE_USER: 325 - case AUDIT_SE_ROLE: 326 - case AUDIT_SE_TYPE: 327 - case AUDIT_SE_SEN: 328 - case AUDIT_SE_CLR: 323 + case AUDIT_SUBJ_USER: 324 + case AUDIT_SUBJ_ROLE: 325 + case AUDIT_SUBJ_TYPE: 326 + case AUDIT_SUBJ_SEN: 327 + case AUDIT_SUBJ_CLR: 329 328 /* NOTE: this may return negative values indicating 330 329 a temporary error. We simply treat this as a 331 330 match for now to avoid losing information that ··· 342 341 ctx); 343 342 } 344 343 break; 344 + case AUDIT_OBJ_USER: 345 + case AUDIT_OBJ_ROLE: 346 + case AUDIT_OBJ_TYPE: 347 + case AUDIT_OBJ_LEV_LOW: 348 + case AUDIT_OBJ_LEV_HIGH: 349 + /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR 350 + also applies here */ 351 + if (f->se_rule) { 352 + /* Find files that match */ 353 + if (name) { 354 + result = selinux_audit_rule_match( 355 + name->osid, f->type, f->op, 356 + f->se_rule, ctx); 357 + } else if (ctx) { 358 + for (j = 0; j < ctx->name_count; j++) { 359 + if (selinux_audit_rule_match( 360 + ctx->names[j].osid, 361 + f->type, f->op, 362 + f->se_rule, ctx)) { 363 + ++result; 364 + break; 365 + } 366 + } 367 + } 368 + /* Find ipc objects that match */ 369 + if (ctx) { 370 + struct audit_aux_data *aux; 371 + for (aux = ctx->aux; aux; 372 + aux = aux->next) { 373 + if (aux->type == AUDIT_IPC) { 374 + struct audit_aux_data_ipcctl *axi = (void *)aux; 375 + if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { 376 + ++result; 377 + break; 378 + } 379 + } 380 + } 381 + } 382 + } 383 + break; 345 384 case AUDIT_ARG0: 346 385 case AUDIT_ARG1: 347 386 case AUDIT_ARG2: ··· 389 348 if (ctx) 390 349 result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); 391 350 break; 351 + case AUDIT_FILTERKEY: 352 + /* ignore this field for filtering */ 353 + result = 1; 354 + break; 392 355 } 393 356 394 357 if (!result) 395 358 return 0; 396 359 } 360 + if (rule->filterkey) 361 + ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); 397 362 switch (rule->action) { 398 363 case AUDIT_NEVER: *state = AUDIT_DISABLED; break; 399 364 case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; ··· 674 627 } 675 628 audit_free_names(context); 676 629 audit_free_aux(context); 630 + kfree(context->filterkey); 677 631 kfree(context); 678 632 context = previous; 679 633 } while (context); ··· 783 735 context->euid, context->suid, context->fsuid, 784 736 context->egid, context->sgid, context->fsgid, tty); 785 737 audit_log_task_info(ab, tsk); 738 + if (context->filterkey) { 739 + audit_log_format(ab, " key="); 740 + audit_log_untrustedstring(ab, context->filterkey); 741 + } else 742 + audit_log_format(ab, " key=(null)"); 786 743 audit_log_end(ab); 787 744 788 745 for (aux = context->aux; aux; aux = aux->next) { ··· 1113 1060 } else { 1114 1061 audit_free_names(context); 1115 1062 audit_free_aux(context); 1063 + kfree(context->filterkey); 1064 + context->filterkey = NULL; 1116 1065 tsk->audit_context = context; 1117 1066 } 1118 1067 }
+32 -16
security/selinux/ss/services.c
··· 1845 1845 return -ENOTSUPP; 1846 1846 1847 1847 switch (field) { 1848 - case AUDIT_SE_USER: 1849 - case AUDIT_SE_ROLE: 1850 - case AUDIT_SE_TYPE: 1848 + case AUDIT_SUBJ_USER: 1849 + case AUDIT_SUBJ_ROLE: 1850 + case AUDIT_SUBJ_TYPE: 1851 + case AUDIT_OBJ_USER: 1852 + case AUDIT_OBJ_ROLE: 1853 + case AUDIT_OBJ_TYPE: 1851 1854 /* only 'equals' and 'not equals' fit user, role, and type */ 1852 1855 if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) 1853 1856 return -EINVAL; 1854 1857 break; 1855 - case AUDIT_SE_SEN: 1856 - case AUDIT_SE_CLR: 1858 + case AUDIT_SUBJ_SEN: 1859 + case AUDIT_SUBJ_CLR: 1860 + case AUDIT_OBJ_LEV_LOW: 1861 + case AUDIT_OBJ_LEV_HIGH: 1857 1862 /* we do not allow a range, indicated by the presense of '-' */ 1858 1863 if (strchr(rulestr, '-')) 1859 1864 return -EINVAL; ··· 1879 1874 tmprule->au_seqno = latest_granting; 1880 1875 1881 1876 switch (field) { 1882 - case AUDIT_SE_USER: 1877 + case AUDIT_SUBJ_USER: 1878 + case AUDIT_OBJ_USER: 1883 1879 userdatum = hashtab_search(policydb.p_users.table, rulestr); 1884 1880 if (!userdatum) 1885 1881 rc = -EINVAL; 1886 1882 else 1887 1883 tmprule->au_ctxt.user = userdatum->value; 1888 1884 break; 1889 - case AUDIT_SE_ROLE: 1885 + case AUDIT_SUBJ_ROLE: 1886 + case AUDIT_OBJ_ROLE: 1890 1887 roledatum = hashtab_search(policydb.p_roles.table, rulestr); 1891 1888 if (!roledatum) 1892 1889 rc = -EINVAL; 1893 1890 else 1894 1891 tmprule->au_ctxt.role = roledatum->value; 1895 1892 break; 1896 - case AUDIT_SE_TYPE: 1893 + case AUDIT_SUBJ_TYPE: 1894 + case AUDIT_OBJ_TYPE: 1897 1895 typedatum = hashtab_search(policydb.p_types.table, rulestr); 1898 1896 if (!typedatum) 1899 1897 rc = -EINVAL; 1900 1898 else 1901 1899 tmprule->au_ctxt.type = typedatum->value; 1902 1900 break; 1903 - case AUDIT_SE_SEN: 1904 - case AUDIT_SE_CLR: 1901 + case AUDIT_SUBJ_SEN: 1902 + case AUDIT_SUBJ_CLR: 1903 + case AUDIT_OBJ_LEV_LOW: 1904 + case AUDIT_OBJ_LEV_HIGH: 1905 1905 rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); 1906 1906 break; 1907 1907 } ··· 1958 1948 /* a field/op pair that is not caught here will simply fall through 1959 1949 without a match */ 1960 1950 switch (field) { 1961 - case AUDIT_SE_USER: 1951 + case AUDIT_SUBJ_USER: 1952 + case AUDIT_OBJ_USER: 1962 1953 switch (op) { 1963 1954 case AUDIT_EQUAL: 1964 1955 match = (ctxt->user == rule->au_ctxt.user); ··· 1969 1958 break; 1970 1959 } 1971 1960 break; 1972 - case AUDIT_SE_ROLE: 1961 + case AUDIT_SUBJ_ROLE: 1962 + case AUDIT_OBJ_ROLE: 1973 1963 switch (op) { 1974 1964 case AUDIT_EQUAL: 1975 1965 match = (ctxt->role == rule->au_ctxt.role); ··· 1980 1968 break; 1981 1969 } 1982 1970 break; 1983 - case AUDIT_SE_TYPE: 1971 + case AUDIT_SUBJ_TYPE: 1972 + case AUDIT_OBJ_TYPE: 1984 1973 switch (op) { 1985 1974 case AUDIT_EQUAL: 1986 1975 match = (ctxt->type == rule->au_ctxt.type); ··· 1991 1978 break; 1992 1979 } 1993 1980 break; 1994 - case AUDIT_SE_SEN: 1995 - case AUDIT_SE_CLR: 1996 - level = (field == AUDIT_SE_SEN ? 1981 + case AUDIT_SUBJ_SEN: 1982 + case AUDIT_SUBJ_CLR: 1983 + case AUDIT_OBJ_LEV_LOW: 1984 + case AUDIT_OBJ_LEV_HIGH: 1985 + level = ((field == AUDIT_SUBJ_SEN || 1986 + field == AUDIT_OBJ_LEV_LOW) ? 1997 1987 &ctxt->range.level[0] : &ctxt->range.level[1]); 1998 1988 switch (op) { 1999 1989 case AUDIT_EQUAL: