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
This commit is contained in:
commit
fc25465f09
17 changed files with 403 additions and 87 deletions
arch
i386/kernel
ia64
x86_64
include
kernel
security/selinux/ss
|
@ -38,6 +38,7 @@ obj-$(CONFIG_VM86) += vm86.o
|
||||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
obj-$(CONFIG_HPET_TIMER) += hpet.o
|
obj-$(CONFIG_HPET_TIMER) += hpet.o
|
||||||
obj-$(CONFIG_K8_NB) += k8.o
|
obj-$(CONFIG_K8_NB) += k8.o
|
||||||
|
obj-$(CONFIG_AUDIT) += audit.o
|
||||||
|
|
||||||
EXTRA_AFLAGS := -traditional
|
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 \
|
obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \
|
||||||
ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.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
|
# 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.
|
# 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_IA64_MCA_RECOVERY) += mca_recovery.o
|
||||||
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
|
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
|
||||||
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
|
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
|
||||||
|
obj-$(CONFIG_AUDIT) += audit.o
|
||||||
mca_recovery-y += mca_drv.o mca_drv_asm.o
|
mca_recovery-y += mca_drv.o mca_drv_asm.o
|
||||||
|
|
||||||
# The gate DSO image is built using a special linker script.
|
# 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
|
obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
|
||||||
|
|
||||||
|
audit-class-$(CONFIG_AUDIT) := audit.o
|
||||||
|
obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
|
||||||
|
|
||||||
$(obj)/syscall32_syscall.o: \
|
$(obj)/syscall32_syscall.o: \
|
||||||
$(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so)
|
$(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_PM_TIMER) += pmtimer.o
|
||||||
obj-$(CONFIG_X86_VSMP) += vsmp.o
|
obj-$(CONFIG_X86_VSMP) += vsmp.o
|
||||||
obj-$(CONFIG_K8_NB) += k8.o
|
obj-$(CONFIG_K8_NB) += k8.o
|
||||||
|
obj-$(CONFIG_AUDIT) += audit.o
|
||||||
|
|
||||||
obj-$(CONFIG_MODULES) += module.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,
|
|
@ -122,10 +122,17 @@
|
||||||
/* Rule structure sizes -- if these change, different AUDIT_ADD and
|
/* Rule structure sizes -- if these change, different AUDIT_ADD and
|
||||||
* AUDIT_LIST commands must be implemented. */
|
* AUDIT_LIST commands must be implemented. */
|
||||||
#define AUDIT_MAX_FIELDS 64
|
#define AUDIT_MAX_FIELDS 64
|
||||||
|
#define AUDIT_MAX_KEY_LEN 32
|
||||||
#define AUDIT_BITMASK_SIZE 64
|
#define AUDIT_BITMASK_SIZE 64
|
||||||
#define AUDIT_WORD(nr) ((__u32)((nr)/32))
|
#define AUDIT_WORD(nr) ((__u32)((nr)/32))
|
||||||
#define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(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
|
/* 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.
|
* are currently used in an audit field constant understood by the kernel.
|
||||||
* If you are adding a new #define AUDIT_<whatever>, please ensure that
|
* If you are adding a new #define AUDIT_<whatever>, please ensure that
|
||||||
|
@ -150,12 +157,17 @@
|
||||||
#define AUDIT_PERS 10
|
#define AUDIT_PERS 10
|
||||||
#define AUDIT_ARCH 11
|
#define AUDIT_ARCH 11
|
||||||
#define AUDIT_MSGTYPE 12
|
#define AUDIT_MSGTYPE 12
|
||||||
#define AUDIT_SE_USER 13 /* security label user */
|
#define AUDIT_SUBJ_USER 13 /* security label user */
|
||||||
#define AUDIT_SE_ROLE 14 /* security label role */
|
#define AUDIT_SUBJ_ROLE 14 /* security label role */
|
||||||
#define AUDIT_SE_TYPE 15 /* security label type */
|
#define AUDIT_SUBJ_TYPE 15 /* security label type */
|
||||||
#define AUDIT_SE_SEN 16 /* security label sensitivity label */
|
#define AUDIT_SUBJ_SEN 16 /* security label sensitivity label */
|
||||||
#define AUDIT_SE_CLR 17 /* security label clearance label */
|
#define AUDIT_SUBJ_CLR 17 /* security label clearance label */
|
||||||
#define AUDIT_PPID 18
|
#define AUDIT_PPID 18
|
||||||
|
#define AUDIT_OBJ_USER 19
|
||||||
|
#define AUDIT_OBJ_ROLE 20
|
||||||
|
#define AUDIT_OBJ_TYPE 21
|
||||||
|
#define AUDIT_OBJ_LEV_LOW 22
|
||||||
|
#define AUDIT_OBJ_LEV_HIGH 23
|
||||||
|
|
||||||
/* These are ONLY useful when checking
|
/* These are ONLY useful when checking
|
||||||
* at syscall exit time (AUDIT_AT_EXIT). */
|
* at syscall exit time (AUDIT_AT_EXIT). */
|
||||||
|
@ -171,6 +183,8 @@
|
||||||
#define AUDIT_ARG2 (AUDIT_ARG0+2)
|
#define AUDIT_ARG2 (AUDIT_ARG0+2)
|
||||||
#define AUDIT_ARG3 (AUDIT_ARG0+3)
|
#define AUDIT_ARG3 (AUDIT_ARG0+3)
|
||||||
|
|
||||||
|
#define AUDIT_FILTERKEY 210
|
||||||
|
|
||||||
#define AUDIT_NEGATE 0x80000000
|
#define AUDIT_NEGATE 0x80000000
|
||||||
|
|
||||||
/* These are the supported operators.
|
/* These are the supported operators.
|
||||||
|
@ -299,6 +313,7 @@ struct mqstat;
|
||||||
#define AUDITSC_SUCCESS 1
|
#define AUDITSC_SUCCESS 1
|
||||||
#define AUDITSC_FAILURE 2
|
#define AUDITSC_FAILURE 2
|
||||||
#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
|
#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
|
||||||
|
extern int __init audit_register_class(int class, unsigned *list);
|
||||||
#ifdef CONFIG_AUDITSYSCALL
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
/* These are defined in auditsc.c */
|
/* These are defined in auditsc.c */
|
||||||
/* Public API */
|
/* Public API */
|
||||||
|
|
|
@ -81,6 +81,7 @@ struct audit_krule {
|
||||||
u32 mask[AUDIT_BITMASK_SIZE];
|
u32 mask[AUDIT_BITMASK_SIZE];
|
||||||
u32 buflen; /* for data alloc on list rules */
|
u32 buflen; /* for data alloc on list rules */
|
||||||
u32 field_count;
|
u32 field_count;
|
||||||
|
char *filterkey; /* ties events to rules */
|
||||||
struct audit_field *fields;
|
struct audit_field *fields;
|
||||||
struct audit_field *inode_f; /* quick access to an inode field */
|
struct audit_field *inode_f; /* quick access to an inode field */
|
||||||
struct audit_watch *watch; /* associated watch */
|
struct audit_watch *watch; /* associated watch */
|
||||||
|
|
|
@ -141,6 +141,7 @@ static inline void audit_free_rule(struct audit_entry *e)
|
||||||
selinux_audit_rule_free(f->se_rule);
|
selinux_audit_rule_free(f->se_rule);
|
||||||
}
|
}
|
||||||
kfree(e->rule.fields);
|
kfree(e->rule.fields);
|
||||||
|
kfree(e->rule.filterkey);
|
||||||
kfree(e);
|
kfree(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,6 +279,29 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
|
||||||
return 0;
|
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. */
|
/* Common user-space to kernel rule translation. */
|
||||||
static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
|
static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
|
||||||
{
|
{
|
||||||
|
@ -321,6 +345,22 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
|
||||||
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
|
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
|
||||||
entry->rule.mask[i] = rule->mask[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;
|
return entry;
|
||||||
|
|
||||||
exit_err:
|
exit_err:
|
||||||
|
@ -469,11 +509,16 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||||
case AUDIT_ARG2:
|
case AUDIT_ARG2:
|
||||||
case AUDIT_ARG3:
|
case AUDIT_ARG3:
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
str = audit_unpack_string(&bufp, &remain, f->val);
|
str = audit_unpack_string(&bufp, &remain, f->val);
|
||||||
if (IS_ERR(str))
|
if (IS_ERR(str))
|
||||||
goto exit_free;
|
goto exit_free;
|
||||||
|
@ -511,6 +556,16 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||||
if (err)
|
if (err)
|
||||||
goto exit_free;
|
goto exit_free;
|
||||||
break;
|
break;
|
||||||
|
case AUDIT_FILTERKEY:
|
||||||
|
err = -EINVAL;
|
||||||
|
if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
|
||||||
|
goto exit_free;
|
||||||
|
str = audit_unpack_string(&bufp, &remain, f->val);
|
||||||
|
if (IS_ERR(str))
|
||||||
|
goto exit_free;
|
||||||
|
entry->rule.buflen += f->val;
|
||||||
|
entry->rule.filterkey = str;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto exit_free;
|
goto exit_free;
|
||||||
}
|
}
|
||||||
|
@ -600,11 +655,16 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
|
||||||
data->fields[i] = f->type;
|
data->fields[i] = f->type;
|
||||||
data->fieldflags[i] = f->op;
|
data->fieldflags[i] = f->op;
|
||||||
switch(f->type) {
|
switch(f->type) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
data->buflen += data->values[i] =
|
data->buflen += data->values[i] =
|
||||||
audit_pack_string(&bufp, f->se_str);
|
audit_pack_string(&bufp, f->se_str);
|
||||||
break;
|
break;
|
||||||
|
@ -612,6 +672,10 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
|
||||||
data->buflen += data->values[i] =
|
data->buflen += data->values[i] =
|
||||||
audit_pack_string(&bufp, krule->watch->path);
|
audit_pack_string(&bufp, krule->watch->path);
|
||||||
break;
|
break;
|
||||||
|
case AUDIT_FILTERKEY:
|
||||||
|
data->buflen += data->values[i] =
|
||||||
|
audit_pack_string(&bufp, krule->filterkey);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
data->values[i] = f->val;
|
data->values[i] = f->val;
|
||||||
}
|
}
|
||||||
|
@ -639,11 +703,16 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
switch(a->fields[i].type) {
|
switch(a->fields[i].type) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
|
if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
@ -651,6 +720,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
|
||||||
if (strcmp(a->watch->path, b->watch->path))
|
if (strcmp(a->watch->path, b->watch->path))
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
case AUDIT_FILTERKEY:
|
||||||
|
/* both filterkeys exist based on above type compare */
|
||||||
|
if (strcmp(a->filterkey, b->filterkey))
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (a->fields[i].val != b->fields[i].val)
|
if (a->fields[i].val != b->fields[i].val)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -730,6 +804,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
|
||||||
u32 fcount = old->field_count;
|
u32 fcount = old->field_count;
|
||||||
struct audit_entry *entry;
|
struct audit_entry *entry;
|
||||||
struct audit_krule *new;
|
struct audit_krule *new;
|
||||||
|
char *fk;
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
|
|
||||||
entry = audit_init_entry(fcount);
|
entry = audit_init_entry(fcount);
|
||||||
|
@ -753,13 +828,25 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
|
||||||
* the originals will all be freed when the old rule is freed. */
|
* the originals will all be freed when the old rule is freed. */
|
||||||
for (i = 0; i < fcount; i++) {
|
for (i = 0; i < fcount; i++) {
|
||||||
switch (new->fields[i].type) {
|
switch (new->fields[i].type) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
err = audit_dupe_selinux_field(&new->fields[i],
|
err = audit_dupe_selinux_field(&new->fields[i],
|
||||||
&old->fields[i]);
|
&old->fields[i]);
|
||||||
|
break;
|
||||||
|
case AUDIT_FILTERKEY:
|
||||||
|
fk = kstrdup(old->filterkey, GFP_KERNEL);
|
||||||
|
if (unlikely(!fk))
|
||||||
|
err = -ENOMEM;
|
||||||
|
else
|
||||||
|
new->filterkey = fk;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
audit_free_rule(entry);
|
audit_free_rule(entry);
|
||||||
|
@ -1245,6 +1332,34 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
|
||||||
skb_queue_tail(q, skb);
|
skb_queue_tail(q, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Log rule additions and removals */
|
||||||
|
static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
|
||||||
|
struct audit_krule *rule, int res)
|
||||||
|
{
|
||||||
|
struct audit_buffer *ab;
|
||||||
|
|
||||||
|
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
|
||||||
|
if (!ab)
|
||||||
|
return;
|
||||||
|
audit_log_format(ab, "auid=%u", loginuid);
|
||||||
|
if (sid) {
|
||||||
|
char *ctx = NULL;
|
||||||
|
u32 len;
|
||||||
|
if (selinux_ctxid_to_string(sid, &ctx, &len))
|
||||||
|
audit_log_format(ab, " ssid=%u", sid);
|
||||||
|
else
|
||||||
|
audit_log_format(ab, " subj=%s", ctx);
|
||||||
|
kfree(ctx);
|
||||||
|
}
|
||||||
|
audit_log_format(ab, " %s rule key=", action);
|
||||||
|
if (rule->filterkey)
|
||||||
|
audit_log_untrustedstring(ab, rule->filterkey);
|
||||||
|
else
|
||||||
|
audit_log_format(ab, "(null)");
|
||||||
|
audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
|
||||||
|
audit_log_end(ab);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* audit_receive_filter - apply all rules to the specified message type
|
* audit_receive_filter - apply all rules to the specified message type
|
||||||
* @type: audit message type
|
* @type: audit message type
|
||||||
|
@ -1304,24 +1419,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||||
|
|
||||||
err = audit_add_rule(entry,
|
err = audit_add_rule(entry,
|
||||||
&audit_filter_list[entry->rule.listnr]);
|
&audit_filter_list[entry->rule.listnr]);
|
||||||
|
audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err);
|
||||||
if (sid) {
|
|
||||||
char *ctx = NULL;
|
|
||||||
u32 len;
|
|
||||||
if (selinux_ctxid_to_string(sid, &ctx, &len)) {
|
|
||||||
/* Maybe call audit_panic? */
|
|
||||||
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
|
|
||||||
"auid=%u ssid=%u add rule to list=%d res=%d",
|
|
||||||
loginuid, sid, entry->rule.listnr, !err);
|
|
||||||
} else
|
|
||||||
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
|
|
||||||
"auid=%u subj=%s add rule to list=%d res=%d",
|
|
||||||
loginuid, ctx, entry->rule.listnr, !err);
|
|
||||||
kfree(ctx);
|
|
||||||
} else
|
|
||||||
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
|
|
||||||
"auid=%u add rule to list=%d res=%d",
|
|
||||||
loginuid, entry->rule.listnr, !err);
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
audit_free_rule(entry);
|
audit_free_rule(entry);
|
||||||
|
@ -1337,24 +1435,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||||
|
|
||||||
err = audit_del_rule(entry,
|
err = audit_del_rule(entry,
|
||||||
&audit_filter_list[entry->rule.listnr]);
|
&audit_filter_list[entry->rule.listnr]);
|
||||||
|
audit_log_rule_change(loginuid, sid, "remove", &entry->rule,
|
||||||
if (sid) {
|
!err);
|
||||||
char *ctx = NULL;
|
|
||||||
u32 len;
|
|
||||||
if (selinux_ctxid_to_string(sid, &ctx, &len)) {
|
|
||||||
/* Maybe call audit_panic? */
|
|
||||||
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
|
|
||||||
"auid=%u ssid=%u remove rule from list=%d res=%d",
|
|
||||||
loginuid, sid, entry->rule.listnr, !err);
|
|
||||||
} else
|
|
||||||
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
|
|
||||||
"auid=%u subj=%s remove rule from list=%d res=%d",
|
|
||||||
loginuid, ctx, entry->rule.listnr, !err);
|
|
||||||
kfree(ctx);
|
|
||||||
} else
|
|
||||||
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
|
|
||||||
"auid=%u remove rule from list=%d res=%d",
|
|
||||||
loginuid, entry->rule.listnr, !err);
|
|
||||||
|
|
||||||
audit_free_rule(entry);
|
audit_free_rule(entry);
|
||||||
break;
|
break;
|
||||||
|
@ -1514,11 +1596,16 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule)
|
||||||
for (i = 0; i < rule->field_count; i++) {
|
for (i = 0; i < rule->field_count; i++) {
|
||||||
struct audit_field *f = &rule->fields[i];
|
struct audit_field *f = &rule->fields[i];
|
||||||
switch (f->type) {
|
switch (f->type) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,7 @@ struct audit_context {
|
||||||
int auditable; /* 1 if record should be written */
|
int auditable; /* 1 if record should be written */
|
||||||
int name_count;
|
int name_count;
|
||||||
struct audit_names names[AUDIT_NAMES];
|
struct audit_names names[AUDIT_NAMES];
|
||||||
|
char * filterkey; /* key for rule that triggered record */
|
||||||
struct dentry * pwd;
|
struct dentry * pwd;
|
||||||
struct vfsmount * pwdmnt;
|
struct vfsmount * pwdmnt;
|
||||||
struct audit_context *previous; /* For nested syscalls */
|
struct audit_context *previous; /* For nested syscalls */
|
||||||
|
@ -320,11 +321,11 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||||
if (ctx)
|
if (ctx)
|
||||||
result = audit_comparator(ctx->loginuid, f->op, f->val);
|
result = audit_comparator(ctx->loginuid, f->op, f->val);
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
/* NOTE: this may return negative values indicating
|
/* NOTE: this may return negative values indicating
|
||||||
a temporary error. We simply treat this as a
|
a temporary error. We simply treat this as a
|
||||||
match for now to avoid losing information that
|
match for now to avoid losing information that
|
||||||
|
@ -341,6 +342,46 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||||
ctx);
|
ctx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
|
/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
|
||||||
|
also applies here */
|
||||||
|
if (f->se_rule) {
|
||||||
|
/* Find files that match */
|
||||||
|
if (name) {
|
||||||
|
result = selinux_audit_rule_match(
|
||||||
|
name->osid, f->type, f->op,
|
||||||
|
f->se_rule, ctx);
|
||||||
|
} else if (ctx) {
|
||||||
|
for (j = 0; j < ctx->name_count; j++) {
|
||||||
|
if (selinux_audit_rule_match(
|
||||||
|
ctx->names[j].osid,
|
||||||
|
f->type, f->op,
|
||||||
|
f->se_rule, ctx)) {
|
||||||
|
++result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Find ipc objects that match */
|
||||||
|
if (ctx) {
|
||||||
|
struct audit_aux_data *aux;
|
||||||
|
for (aux = ctx->aux; aux;
|
||||||
|
aux = aux->next) {
|
||||||
|
if (aux->type == AUDIT_IPC) {
|
||||||
|
struct audit_aux_data_ipcctl *axi = (void *)aux;
|
||||||
|
if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
|
||||||
|
++result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case AUDIT_ARG0:
|
case AUDIT_ARG0:
|
||||||
case AUDIT_ARG1:
|
case AUDIT_ARG1:
|
||||||
case AUDIT_ARG2:
|
case AUDIT_ARG2:
|
||||||
|
@ -348,11 +389,17 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||||
if (ctx)
|
if (ctx)
|
||||||
result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
|
result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
|
||||||
break;
|
break;
|
||||||
|
case AUDIT_FILTERKEY:
|
||||||
|
/* ignore this field for filtering */
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (rule->filterkey)
|
||||||
|
ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
|
||||||
switch (rule->action) {
|
switch (rule->action) {
|
||||||
case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
|
case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
|
||||||
case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
|
case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
|
||||||
|
@ -627,6 +674,7 @@ static inline void audit_free_context(struct audit_context *context)
|
||||||
}
|
}
|
||||||
audit_free_names(context);
|
audit_free_names(context);
|
||||||
audit_free_aux(context);
|
audit_free_aux(context);
|
||||||
|
kfree(context->filterkey);
|
||||||
kfree(context);
|
kfree(context);
|
||||||
context = previous;
|
context = previous;
|
||||||
} while (context);
|
} while (context);
|
||||||
|
@ -735,6 +783,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
|
||||||
context->euid, context->suid, context->fsuid,
|
context->euid, context->suid, context->fsuid,
|
||||||
context->egid, context->sgid, context->fsgid, tty);
|
context->egid, context->sgid, context->fsgid, tty);
|
||||||
audit_log_task_info(ab, tsk);
|
audit_log_task_info(ab, tsk);
|
||||||
|
if (context->filterkey) {
|
||||||
|
audit_log_format(ab, " key=");
|
||||||
|
audit_log_untrustedstring(ab, context->filterkey);
|
||||||
|
} else
|
||||||
|
audit_log_format(ab, " key=(null)");
|
||||||
audit_log_end(ab);
|
audit_log_end(ab);
|
||||||
|
|
||||||
for (aux = context->aux; aux; aux = aux->next) {
|
for (aux = context->aux; aux; aux = aux->next) {
|
||||||
|
@ -1060,6 +1113,8 @@ void audit_syscall_exit(int valid, long return_code)
|
||||||
} else {
|
} else {
|
||||||
audit_free_names(context);
|
audit_free_names(context);
|
||||||
audit_free_aux(context);
|
audit_free_aux(context);
|
||||||
|
kfree(context->filterkey);
|
||||||
|
context->filterkey = NULL;
|
||||||
tsk->audit_context = context;
|
tsk->audit_context = context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1845,15 +1845,20 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
/* only 'equals' and 'not equals' fit user, role, and type */
|
/* only 'equals' and 'not equals' fit user, role, and type */
|
||||||
if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
|
if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
/* we do not allow a range, indicated by the presense of '-' */
|
/* we do not allow a range, indicated by the presense of '-' */
|
||||||
if (strchr(rulestr, '-'))
|
if (strchr(rulestr, '-'))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1874,29 +1879,34 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||||
tmprule->au_seqno = latest_granting;
|
tmprule->au_seqno = latest_granting;
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
userdatum = hashtab_search(policydb.p_users.table, rulestr);
|
userdatum = hashtab_search(policydb.p_users.table, rulestr);
|
||||||
if (!userdatum)
|
if (!userdatum)
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
else
|
else
|
||||||
tmprule->au_ctxt.user = userdatum->value;
|
tmprule->au_ctxt.user = userdatum->value;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
roledatum = hashtab_search(policydb.p_roles.table, rulestr);
|
roledatum = hashtab_search(policydb.p_roles.table, rulestr);
|
||||||
if (!roledatum)
|
if (!roledatum)
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
else
|
else
|
||||||
tmprule->au_ctxt.role = roledatum->value;
|
tmprule->au_ctxt.role = roledatum->value;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
typedatum = hashtab_search(policydb.p_types.table, rulestr);
|
typedatum = hashtab_search(policydb.p_types.table, rulestr);
|
||||||
if (!typedatum)
|
if (!typedatum)
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
else
|
else
|
||||||
tmprule->au_ctxt.type = typedatum->value;
|
tmprule->au_ctxt.type = typedatum->value;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
|
rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1948,7 +1958,8 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
|
||||||
/* a field/op pair that is not caught here will simply fall through
|
/* a field/op pair that is not caught here will simply fall through
|
||||||
without a match */
|
without a match */
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case AUDIT_SE_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
|
case AUDIT_OBJ_USER:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case AUDIT_EQUAL:
|
case AUDIT_EQUAL:
|
||||||
match = (ctxt->user == rule->au_ctxt.user);
|
match = (ctxt->user == rule->au_ctxt.user);
|
||||||
|
@ -1958,7 +1969,8 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
|
case AUDIT_OBJ_ROLE:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case AUDIT_EQUAL:
|
case AUDIT_EQUAL:
|
||||||
match = (ctxt->role == rule->au_ctxt.role);
|
match = (ctxt->role == rule->au_ctxt.role);
|
||||||
|
@ -1968,7 +1980,8 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
|
case AUDIT_OBJ_TYPE:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case AUDIT_EQUAL:
|
case AUDIT_EQUAL:
|
||||||
match = (ctxt->type == rule->au_ctxt.type);
|
match = (ctxt->type == rule->au_ctxt.type);
|
||||||
|
@ -1978,9 +1991,12 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIT_SE_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SE_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
level = (field == AUDIT_SE_SEN ?
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
|
level = ((field == AUDIT_SUBJ_SEN ||
|
||||||
|
field == AUDIT_OBJ_LEV_LOW) ?
|
||||||
&ctxt->range.level[0] : &ctxt->range.level[1]);
|
&ctxt->range.level[0] : &ctxt->range.level[1]);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case AUDIT_EQUAL:
|
case AUDIT_EQUAL:
|
||||||
|
|
Loading…
Add table
Reference in a new issue