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

[PATCH] audit syscall classes

Allow to tie upper bits of syscall bitmap in audit rules to kernel-defined
sets of syscalls. Infrastructure, a couple of classes (with 32bit counterparts
for biarch targets) and actual tie-in on i386, amd64 and ia64.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro b915543b 6e5a2d1d

+188
+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,
+7
include/linux/audit.h
··· 127 127 #define AUDIT_WORD(nr) ((__u32)((nr)/32)) 128 128 #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) 129 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 135 + 130 136 /* This bitmask is used to validate user input. It represents all bits that 131 137 * are currently used in an audit field constant understood by the kernel. 132 138 * If you are adding a new #define AUDIT_<whatever>, please ensure that ··· 313 307 #define AUDITSC_SUCCESS 1 314 308 #define AUDITSC_FAILURE 2 315 309 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) 310 + extern int __init audit_register_class(int class, unsigned *list); 316 311 #ifdef CONFIG_AUDITSYSCALL 317 312 /* These are defined in auditsc.c */ 318 313 /* Public API */
+39
kernel/auditfilter.c
··· 279 279 return 0; 280 280 } 281 281 282 + static __u32 *classes[AUDIT_SYSCALL_CLASSES]; 283 + 284 + int __init audit_register_class(int class, unsigned *list) 285 + { 286 + __u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL); 287 + if (!p) 288 + return -ENOMEM; 289 + while (*list != ~0U) { 290 + unsigned n = *list++; 291 + if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) { 292 + kfree(p); 293 + return -EINVAL; 294 + } 295 + p[AUDIT_WORD(n)] |= AUDIT_BIT(n); 296 + } 297 + if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) { 298 + kfree(p); 299 + return -EINVAL; 300 + } 301 + classes[class] = p; 302 + return 0; 303 + } 304 + 282 305 /* Common user-space to kernel rule translation. */ 283 306 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) 284 307 { ··· 344 321 345 322 for (i = 0; i < AUDIT_BITMASK_SIZE; i++) 346 323 entry->rule.mask[i] = rule->mask[i]; 324 + 325 + for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) { 326 + int bit = AUDIT_BITMASK_SIZE * 32 - i - 1; 327 + __u32 *p = &entry->rule.mask[AUDIT_WORD(bit)]; 328 + __u32 *class; 329 + 330 + if (!(*p & AUDIT_BIT(bit))) 331 + continue; 332 + *p &= ~AUDIT_BIT(bit); 333 + class = classes[i]; 334 + if (class) { 335 + int j; 336 + for (j = 0; j < AUDIT_BITMASK_SIZE; j++) 337 + entry->rule.mask[j] |= class[j]; 338 + } 339 + } 347 340 348 341 return entry; 349 342