[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>
This commit is contained in:
parent
6e5a2d1d32
commit
b915543b46
14 changed files with 188 additions and 0 deletions
|
@ -38,6 +38,7 @@ obj-$(CONFIG_VM86) += vm86.o
|
|||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_HPET_TIMER) += hpet.o
|
||||
obj-$(CONFIG_K8_NB) += k8.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
|
||||
EXTRA_AFLAGS := -traditional
|
||||
|
||||
|
|
23
arch/i386/kernel/audit.c
Normal file
23
arch/i386/kernel/audit.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/audit.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
static unsigned dir_class[] = {
|
||||
#include <asm-generic/audit_dir_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
static unsigned chattr_class[] = {
|
||||
#include <asm-generic/audit_change_attr.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
static int __init audit_classes_init(void)
|
||||
{
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
|
||||
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(audit_classes_init);
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \
|
||||
ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
|
||||
# Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and
|
||||
# restore_ia32_fpstate_live() can be sure the live register contain user-level state.
|
||||
|
|
11
arch/ia64/ia32/audit.c
Normal file
11
arch/ia64/ia32/audit.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <asm-i386/unistd.h>
|
||||
|
||||
unsigned ia32_dir_class[] = {
|
||||
#include <asm-generic/audit_dir_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
unsigned ia32_chattr_class[] = {
|
||||
#include <asm-generic/audit_change_attr.h>
|
||||
~0U
|
||||
};
|
|
@ -29,6 +29,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
|
|||
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
|
||||
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
mca_recovery-y += mca_drv.o mca_drv_asm.o
|
||||
|
||||
# The gate DSO image is built using a special linker script.
|
||||
|
|
29
arch/ia64/kernel/audit.c
Normal file
29
arch/ia64/kernel/audit.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/audit.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
static unsigned dir_class[] = {
|
||||
#include <asm-generic/audit_dir_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
static unsigned chattr_class[] = {
|
||||
#include <asm-generic/audit_change_attr.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
static int __init audit_classes_init(void)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
extern __u32 ia32_dir_class[];
|
||||
extern __u32 ia32_chattr_class[];
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
|
||||
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
|
||||
#endif
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
|
||||
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(audit_classes_init);
|
|
@ -11,6 +11,9 @@ obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
|
|||
|
||||
obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
|
||||
|
||||
audit-class-$(CONFIG_AUDIT) := audit.o
|
||||
obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
|
||||
|
||||
$(obj)/syscall32_syscall.o: \
|
||||
$(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so)
|
||||
|
||||
|
|
11
arch/x86_64/ia32/audit.c
Normal file
11
arch/x86_64/ia32/audit.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <asm-i386/unistd.h>
|
||||
|
||||
unsigned ia32_dir_class[] = {
|
||||
#include <asm-generic/audit_dir_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
unsigned ia32_chattr_class[] = {
|
||||
#include <asm-generic/audit_change_attr.h>
|
||||
~0U
|
||||
};
|
|
@ -35,6 +35,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o
|
|||
obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
|
||||
obj-$(CONFIG_X86_VSMP) += vsmp.o
|
||||
obj-$(CONFIG_K8_NB) += k8.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
||||
|
|
29
arch/x86_64/kernel/audit.c
Normal file
29
arch/x86_64/kernel/audit.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/audit.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
static unsigned dir_class[] = {
|
||||
#include <asm-generic/audit_dir_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
static unsigned chattr_class[] = {
|
||||
#include <asm-generic/audit_change_attr.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
static int __init audit_classes_init(void)
|
||||
{
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
extern __u32 ia32_dir_class[];
|
||||
extern __u32 ia32_chattr_class[];
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
|
||||
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
|
||||
#endif
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
|
||||
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(audit_classes_init);
|
18
include/asm-generic/audit_change_attr.h
Normal file
18
include/asm-generic/audit_change_attr.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
__NR_chmod,
|
||||
__NR_fchmod,
|
||||
__NR_chown,
|
||||
__NR_fchown,
|
||||
__NR_lchown,
|
||||
__NR_setxattr,
|
||||
__NR_lsetxattr,
|
||||
__NR_fsetxattr,
|
||||
__NR_removexattr,
|
||||
__NR_lremovexattr,
|
||||
__NR_fremovexattr,
|
||||
__NR_fchownat,
|
||||
__NR_fchmodat,
|
||||
#ifdef __NR_chown32
|
||||
__NR_chown32,
|
||||
__NR_fchown32,
|
||||
__NR_lchown32,
|
||||
#endif
|
14
include/asm-generic/audit_dir_write.h
Normal file
14
include/asm-generic/audit_dir_write.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
__NR_rename,
|
||||
__NR_mkdir,
|
||||
__NR_rmdir,
|
||||
__NR_creat,
|
||||
__NR_link,
|
||||
__NR_unlink,
|
||||
__NR_symlink,
|
||||
__NR_mknod,
|
||||
__NR_mkdirat,
|
||||
__NR_mknodat,
|
||||
__NR_unlinkat,
|
||||
__NR_renameat,
|
||||
__NR_linkat,
|
||||
__NR_symlinkat,
|
|
@ -127,6 +127,12 @@
|
|||
#define AUDIT_WORD(nr) ((__u32)((nr)/32))
|
||||
#define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32))
|
||||
|
||||
#define AUDIT_SYSCALL_CLASSES 16
|
||||
#define AUDIT_CLASS_DIR_WRITE 0
|
||||
#define AUDIT_CLASS_DIR_WRITE_32 1
|
||||
#define AUDIT_CLASS_CHATTR 2
|
||||
#define AUDIT_CLASS_CHATTR_32 3
|
||||
|
||||
/* This bitmask is used to validate user input. It represents all bits that
|
||||
* are currently used in an audit field constant understood by the kernel.
|
||||
* If you are adding a new #define AUDIT_<whatever>, please ensure that
|
||||
|
@ -307,6 +313,7 @@ struct mqstat;
|
|||
#define AUDITSC_SUCCESS 1
|
||||
#define AUDITSC_FAILURE 2
|
||||
#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
|
||||
extern int __init audit_register_class(int class, unsigned *list);
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
/* These are defined in auditsc.c */
|
||||
/* Public API */
|
||||
|
|
|
@ -279,6 +279,29 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __u32 *classes[AUDIT_SYSCALL_CLASSES];
|
||||
|
||||
int __init audit_register_class(int class, unsigned *list)
|
||||
{
|
||||
__u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
while (*list != ~0U) {
|
||||
unsigned n = *list++;
|
||||
if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) {
|
||||
kfree(p);
|
||||
return -EINVAL;
|
||||
}
|
||||
p[AUDIT_WORD(n)] |= AUDIT_BIT(n);
|
||||
}
|
||||
if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) {
|
||||
kfree(p);
|
||||
return -EINVAL;
|
||||
}
|
||||
classes[class] = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Common user-space to kernel rule translation. */
|
||||
static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
|
||||
{
|
||||
|
@ -322,6 +345,22 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
|
|||
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
|
||||
entry->rule.mask[i] = rule->mask[i];
|
||||
|
||||
for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) {
|
||||
int bit = AUDIT_BITMASK_SIZE * 32 - i - 1;
|
||||
__u32 *p = &entry->rule.mask[AUDIT_WORD(bit)];
|
||||
__u32 *class;
|
||||
|
||||
if (!(*p & AUDIT_BIT(bit)))
|
||||
continue;
|
||||
*p &= ~AUDIT_BIT(bit);
|
||||
class = classes[i];
|
||||
if (class) {
|
||||
int j;
|
||||
for (j = 0; j < AUDIT_BITMASK_SIZE; j++)
|
||||
entry->rule.mask[j] |= class[j];
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
|
||||
exit_err:
|
||||
|
|
Loading…
Reference in a new issue