···19#include <asm-generic/audit_read.h>20~0U21};22+23+int ia32_classify_syscall(unsigned syscall)24+{25+ switch(syscall) {26+ case __NR_open:27+ return 2;28+ case __NR_openat:29+ return 3;30+ case __NR_socketcall:31+ return 4;32+ case __NR_execve:33+ return 5;34+ default:35+ return 1;36+ }37+}
+19
arch/x86_64/kernel/audit.c
···23~0U24};25000000000000000000026static int __init audit_classes_init(void)27{28#ifdef CONFIG_IA32_EMULATION
···23~0U24};2526+int audit_classify_syscall(int abi, unsigned syscall)27+{28+#ifdef CONFIG_IA32_EMULATION29+ extern int ia32_classify_syscall(unsigned);30+ if (abi == AUDIT_ARCH_I386)31+ return ia32_classify_syscall(syscall);32+#endif33+ switch(syscall) {34+ case __NR_open:35+ return 2;36+ case __NR_openat:37+ return 3;38+ case __NR_execve:39+ return 5;40+ default:41+ return 0;42+ }43+}44+45static int __init audit_classes_init(void)46{47#ifdef CONFIG_IA32_EMULATION
+7
include/linux/audit.h
···181#define AUDIT_EXIT 103182#define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */183#define AUDIT_WATCH 1050184185#define AUDIT_ARG0 200186#define AUDIT_ARG1 (AUDIT_ARG0+1)···257#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE)258#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)25900000260struct audit_status {261 __u32 mask; /* Bit mask for valid entries */262 __u32 enabled; /* 1 = enabled, 0 = disabled */···324#define AUDITSC_FAILURE 2325#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )326extern int __init audit_register_class(int class, unsigned *list);0327#ifdef CONFIG_AUDITSYSCALL328/* These are defined in auditsc.c */329 /* Public API */
···181#define AUDIT_EXIT 103182#define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */183#define AUDIT_WATCH 105184+#define AUDIT_PERM 106185186#define AUDIT_ARG0 200187#define AUDIT_ARG1 (AUDIT_ARG0+1)···256#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE)257#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)258259+#define AUDIT_PERM_EXEC 1260+#define AUDIT_PERM_WRITE 2261+#define AUDIT_PERM_READ 4262+#define AUDIT_PERM_ATTR 8263+264struct audit_status {265 __u32 mask; /* Bit mask for valid entries */266 __u32 enabled; /* 1 = enabled, 0 = disabled */···318#define AUDITSC_FAILURE 2319#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )320extern int __init audit_register_class(int class, unsigned *list);321+extern int audit_classify_syscall(int abi, unsigned syscall);322#ifdef CONFIG_AUDITSYSCALL323/* These are defined in auditsc.c */324 /* Public API */
+1
kernel/audit.h
···104 return (ino & (AUDIT_INODE_BUCKETS-1));105}1060107extern int audit_comparator(const u32 left, const u32 op, const u32 right);108extern int audit_compare_dname_path(const char *dname, const char *path,109 int *dirlen);
···104 return (ino & (AUDIT_INODE_BUCKETS-1));105}106107+extern int audit_match_class(int class, unsigned syscall);108extern int audit_comparator(const u32 left, const u32 op, const u32 right);109extern int audit_compare_dname_path(const char *dname, const char *path,110 int *dirlen);
+17
kernel/auditfilter.c
···302 return 0;303}304000000000305/* Common user-space to kernel rule translation. */306static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)307{···422 case AUDIT_ARG1:423 case AUDIT_ARG2:424 case AUDIT_ARG3:0000425 break;426 case AUDIT_INODE:427 err = audit_to_inode(&entry->rule, f);···580 goto exit_free;581 entry->rule.buflen += f->val;582 entry->rule.filterkey = str;0000583 break;584 default:585 goto exit_free;
···302 return 0;303}304305+int audit_match_class(int class, unsigned syscall)306+{307+ if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32)))308+ return 0;309+ if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class]))310+ return 0;311+ return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);312+}313+314/* Common user-space to kernel rule translation. */315static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)316{···413 case AUDIT_ARG1:414 case AUDIT_ARG2:415 case AUDIT_ARG3:416+ break;417+ case AUDIT_PERM:418+ if (f->val & ~15)419+ goto exit_free;420 break;421 case AUDIT_INODE:422 err = audit_to_inode(&entry->rule, f);···567 goto exit_free;568 entry->rule.buflen += f->val;569 entry->rule.filterkey = str;570+ break;571+ case AUDIT_PERM:572+ if (f->val & ~15)573+ goto exit_free;574 break;575 default:576 goto exit_free;
+51
kernel/auditsc.c
···209#endif210};211000000000000000000000000000000000000000000000000212/* Determine if any context name data matches a rule's watch data */213/* Compare a task_struct with an audit_rule. Return 1 on match, 0214 * otherwise. */···444 case AUDIT_FILTERKEY:445 /* ignore this field for filtering */446 result = 1;000447 break;448 }449
···209#endif210};211212+#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE])213+static inline int open_arg(int flags, int mask)214+{215+ int n = ACC_MODE(flags);216+ if (flags & (O_TRUNC | O_CREAT))217+ n |= AUDIT_PERM_WRITE;218+ return n & mask;219+}220+221+static int audit_match_perm(struct audit_context *ctx, int mask)222+{223+ unsigned n = ctx->major;224+ switch (audit_classify_syscall(ctx->arch, n)) {225+ case 0: /* native */226+ if ((mask & AUDIT_PERM_WRITE) &&227+ audit_match_class(AUDIT_CLASS_WRITE, n))228+ return 1;229+ if ((mask & AUDIT_PERM_READ) &&230+ audit_match_class(AUDIT_CLASS_READ, n))231+ return 1;232+ if ((mask & AUDIT_PERM_ATTR) &&233+ audit_match_class(AUDIT_CLASS_CHATTR, n))234+ return 1;235+ return 0;236+ case 1: /* 32bit on biarch */237+ if ((mask & AUDIT_PERM_WRITE) &&238+ audit_match_class(AUDIT_CLASS_WRITE_32, n))239+ return 1;240+ if ((mask & AUDIT_PERM_READ) &&241+ audit_match_class(AUDIT_CLASS_READ_32, n))242+ return 1;243+ if ((mask & AUDIT_PERM_ATTR) &&244+ audit_match_class(AUDIT_CLASS_CHATTR_32, n))245+ return 1;246+ return 0;247+ case 2: /* open */248+ return mask & ACC_MODE(ctx->argv[1]);249+ case 3: /* openat */250+ return mask & ACC_MODE(ctx->argv[2]);251+ case 4: /* socketcall */252+ return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);253+ case 5: /* execve */254+ return mask & AUDIT_PERM_EXEC;255+ default:256+ return 0;257+ }258+}259+260/* Determine if any context name data matches a rule's watch data */261/* Compare a task_struct with an audit_rule. Return 1 on match, 0262 * otherwise. */···396 case AUDIT_FILTERKEY:397 /* ignore this field for filtering */398 result = 1;399+ break;400+ case AUDIT_PERM:401+ result = audit_match_perm(ctx, f->val);402 break;403 }404