From fc47e7b592dc45b03c27b0a4c8f2d215dae9944d Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Wed, 6 Sep 2006 00:03:39 -0700 Subject: [PATCH] lockdep ifdef fix With CONFIG_SMP=y CONFIG_PREEMPT=y CONFIG_LOCKDEP=y CONFIG_DEBUG_LOCK_ALLOC=y # CONFIG_PROVE_LOCKING is not set spin_unlock_irqrestore() goes through lockdep but spin_lock_irqsave() doesn't. Apparently, bad things happen. Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/spinlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/spinlock.c b/kernel/spinlock.c index bfd6ad9c0330..fb524b009eef 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c @@ -72,7 +72,7 @@ EXPORT_SYMBOL(_write_trylock); * not re-enabled during lock-acquire (which the preempt-spin-ops do): */ #if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) || \ - defined(CONFIG_PROVE_LOCKING) + defined(CONFIG_DEBUG_LOCK_ALLOC) void __lockfunc _read_lock(rwlock_t *lock) { -- cgit v1.3-14-g43fede From 471b40d0dfc17bf0161629950b82524d41bc37ce Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 6 Sep 2006 00:03:43 -0700 Subject: [PATCH] prevent swsusp with PAE PAE + swsusp results in hard-to-debug crash about 50% of time during resume. Cause is known, fix needs to be ported from x86-64 (but we can't make it to 2.6.18, and I'd like this to be worked around in 2.6.18). Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index ae44a70aae8a..619ecabf7c58 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -56,7 +56,7 @@ config PM_TRACE config SOFTWARE_SUSPEND bool "Software Suspend" - depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) + depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP) && !X86_PAE) || ((FRV || PPC32) && !SMP)) ---help--- Enable the possibility of suspending the machine. It doesn't need ACPI or APM. @@ -78,6 +78,10 @@ config SOFTWARE_SUSPEND For more information take a look at . + (For now, swsusp is incompatible with PAE aka HIGHMEM_64G on i386. + we need identity mapping for resume to work, and that is trivial + to get with 4MB pages, but less than trivial on PAE). + config PM_STD_PARTITION string "Default resume partition" depends on SOFTWARE_SUSPEND -- cgit v1.3-14-g43fede From 068c4579fe5c21e84c7cb2ba89db80899e25104e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 6 Sep 2006 00:03:44 -0700 Subject: [PATCH] lockdep: do not touch console state when tainting the kernel Remove an unintended console_verbose() side-effect from add_taint(). Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/panic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/panic.c b/kernel/panic.c index 9b8dcfd1ca93..8010b9b17aca 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -173,7 +173,7 @@ const char *print_tainted(void) void add_taint(unsigned flag) { - debug_locks_off(); /* can't trust the integrity of the kernel anymore */ + debug_locks = 0; /* can't trust the integrity of the kernel anymore */ tainted |= flag; } EXPORT_SYMBOL(add_taint); -- cgit v1.3-14-g43fede From c5780e976e19faff345fcef4a01db87108b51a44 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 8 Sep 2006 09:47:15 -0700 Subject: [PATCH] Use the correct restart option for futex_lock_pi The current implementation of futex_lock_pi returns -ERESTART_RESTARTBLOCK in case that the lock operation has been interrupted by a signal. This results in a return of -EINTR to userspace in case there is an handler for the signal. This is wrong, because userspace expects that the lock function does not return in any case of signal delivery. This was not caught by my insufficient test case, but triggered a nasty userspace problem in an high load application scenario. Unfortunately also glibc does not check for this invalid return value. Using -ERSTARTNOINTR makes sure, that the interrupted syscall is restarted. The restart block related code can be safely removed, as the possible timeout argument is an absolute time value. Signed-off-by: Thomas Gleixner Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/futex.c | 84 ++++++++-------------------------------------------------- 1 file changed, 11 insertions(+), 73 deletions(-) (limited to 'kernel') diff --git a/kernel/futex.c b/kernel/futex.c index b9b8aea5389e..9d260e838cff 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1120,9 +1120,10 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) * if there are waiters then it will block, it does PI, etc. (Due to * races the kernel might see a 0 value of the futex too.) */ -static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, - struct hrtimer_sleeper *to) +static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, + long nsec, int trylock) { + struct hrtimer_sleeper timeout, *to = NULL; struct task_struct *curr = current; struct futex_hash_bucket *hb; u32 uval, newval, curval; @@ -1132,6 +1133,13 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, if (refill_pi_state_cache()) return -ENOMEM; + if (sec != MAX_SCHEDULE_TIMEOUT) { + to = &timeout; + hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); + hrtimer_init_sleeper(to, current); + to->timer.expires = ktime_set(sec, nsec); + } + q.pi_state = NULL; retry: down_read(&curr->mm->mmap_sem); @@ -1307,7 +1315,7 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, if (!detect && ret == -EDEADLK && 0) force_sig(SIGKILL, current); - return ret; + return ret != -EINTR ? ret : -ERESTARTNOINTR; out_unlock_release_sem: queue_unlock(&q, hb); @@ -1341,76 +1349,6 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, return ret; } -/* - * Restart handler - */ -static long futex_lock_pi_restart(struct restart_block *restart) -{ - struct hrtimer_sleeper timeout, *to = NULL; - int ret; - - restart->fn = do_no_restart_syscall; - - if (restart->arg2 || restart->arg3) { - to = &timeout; - hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); - hrtimer_init_sleeper(to, current); - to->timer.expires.tv64 = ((u64)restart->arg1 << 32) | - (u64) restart->arg0; - } - - pr_debug("lock_pi restart: %p, %d (%d)\n", - (u32 __user *)restart->arg0, current->pid); - - ret = do_futex_lock_pi((u32 __user *)restart->arg0, restart->arg1, - 0, to); - - if (ret != -EINTR) - return ret; - - restart->fn = futex_lock_pi_restart; - - /* The other values are filled in */ - return -ERESTART_RESTARTBLOCK; -} - -/* - * Called from the syscall entry below. - */ -static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, - long nsec, int trylock) -{ - struct hrtimer_sleeper timeout, *to = NULL; - struct restart_block *restart; - int ret; - - if (sec != MAX_SCHEDULE_TIMEOUT) { - to = &timeout; - hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); - hrtimer_init_sleeper(to, current); - to->timer.expires = ktime_set(sec, nsec); - } - - ret = do_futex_lock_pi(uaddr, detect, trylock, to); - - if (ret != -EINTR) - return ret; - - pr_debug("lock_pi interrupted: %p, %d (%d)\n", uaddr, current->pid); - - restart = ¤t_thread_info()->restart_block; - restart->fn = futex_lock_pi_restart; - restart->arg0 = (unsigned long) uaddr; - restart->arg1 = detect; - if (to) { - restart->arg2 = to->timer.expires.tv64 & 0xFFFFFFFF; - restart->arg3 = to->timer.expires.tv64 >> 32; - } else - restart->arg2 = restart->arg3 = 0; - - return -ERESTART_RESTARTBLOCK; -} - /* * Userspace attempted a TID -> 0 atomic transition, and failed. * This is the in-kernel slowpath: we look up the PI state (if any), -- cgit v1.3-14-g43fede From 3b33ac3182a4554742757a0c61ee1df162cf8225 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Sat, 26 Aug 2006 14:06:20 -0400 Subject: [PATCH] fix ppid bug in 2.6.18 kernel Hello, During some troubleshooting, I found that ppid was accidentally omitted from the legacy rule section. This resulted in EINVAL for any rule with ppid sent with AUDIT_ADD. Signed-off-by: Steve Grubb Signed-off-by: Al Viro --- kernel/auditfilter.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel') diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 6a9a5c5a4e7d..0d6a8fc21f17 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -404,6 +404,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_PERS: case AUDIT_ARCH: case AUDIT_MSGTYPE: + case AUDIT_PPID: case AUDIT_DEVMAJOR: case AUDIT_DEVMINOR: case AUDIT_EXIT: -- cgit v1.3-14-g43fede From 8ef2d3040e5cf38f7d64a408038f576b4a5ec987 Mon Sep 17 00:00:00 2001 From: Amy Griffis Date: Thu, 7 Sep 2006 17:03:02 -0400 Subject: [PATCH] sanity check audit_buffer Add sanity checks for NULL audit_buffer consistent with other audit_log* routines. Signed-off-by: Amy Griffis Signed-off-by: Al Viro --- kernel/audit.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'kernel') diff --git a/kernel/audit.c b/kernel/audit.c index 0a36091ed712..963fd15c9621 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1028,6 +1028,9 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, struct sk_buff *skb; static const unsigned char *hex = "0123456789ABCDEF"; + if (!ab) + return; + BUG_ON(!ab->skb); skb = ab->skb; avail = skb_tailroom(skb); @@ -1060,6 +1063,9 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, unsigned char *ptr; struct sk_buff *skb; + if (!ab) + return; + BUG_ON(!ab->skb); skb = ab->skb; avail = skb_tailroom(skb); -- cgit v1.3-14-g43fede From 5974501e2d44546748e67c635cec20ba66619a3d Mon Sep 17 00:00:00 2001 From: Amy Griffis Date: Thu, 7 Sep 2006 17:46:18 -0400 Subject: [PATCH] update audit rule change messages Make the audit message for implicit rule removal more informative. Make the rule update message consistent with other messages. Signed-off-by: Amy Griffis Signed-off-by: Al Viro --- kernel/auditfilter.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 0d6a8fc21f17..e4cafc11c510 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -914,7 +914,7 @@ static void audit_update_watch(struct audit_parent *parent, } ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, "audit updated rules specifying watch="); + audit_log_format(ab, "audit updated rules specifying path="); audit_log_untrustedstring(ab, owatch->path); audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); audit_log_end(ab); @@ -937,19 +937,28 @@ static void audit_remove_parent_watches(struct audit_parent *parent) struct audit_watch *w, *nextw; struct audit_krule *r, *nextr; struct audit_entry *e; + struct audit_buffer *ab; mutex_lock(&audit_filter_mutex); parent->flags |= AUDIT_PARENT_INVALID; list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { list_for_each_entry_safe(r, nextr, &w->rules, rlist) { e = container_of(r, struct audit_entry, rule); + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + audit_log_format(ab, "audit implicitly removed rule path="); + audit_log_untrustedstring(ab, w->path); + if (r->filterkey) { + audit_log_format(ab, " key="); + audit_log_untrustedstring(ab, r->filterkey); + } else + audit_log_format(ab, " key=(null)"); + audit_log_format(ab, " list=%d", r->listnr); + audit_log_end(ab); + list_del(&r->rlist); list_del_rcu(&e->list); call_rcu(&e->rcu, audit_free_rule_rcu); - - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit implicitly removed rule from list=%d\n", - AUDIT_FILTER_EXIT); } audit_remove_watch(w); } -- cgit v1.3-14-g43fede From 55669bfa141b488be865341ed12e188967d11308 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Aug 2006 19:26:40 -0400 Subject: [PATCH] audit: AUDIT_PERM support add support for AUDIT_PERM predicate Signed-off-by: Al Viro --- arch/i386/kernel/audit.c | 16 ++++++++++++ arch/ia64/ia32/audit.c | 16 ++++++++++++ arch/ia64/kernel/audit.c | 19 ++++++++++++++ arch/powerpc/kernel/audit.c | 21 ++++++++++++++++ arch/powerpc/kernel/compat_audit.c | 16 ++++++++++++ arch/s390/kernel/audit.c | 21 ++++++++++++++++ arch/s390/kernel/compat_audit.c | 16 ++++++++++++ arch/x86_64/ia32/audit.c | 16 ++++++++++++ arch/x86_64/kernel/audit.c | 19 ++++++++++++++ include/linux/audit.h | 7 ++++++ kernel/audit.h | 1 + kernel/auditfilter.c | 17 +++++++++++++ kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 236 insertions(+) (limited to 'kernel') diff --git a/arch/i386/kernel/audit.c b/arch/i386/kernel/audit.c index 28bbc46f75c2..3b97cff41549 100644 --- a/arch/i386/kernel/audit.c +++ b/arch/i386/kernel/audit.c @@ -23,6 +23,22 @@ static unsigned chattr_class[] = { ~0U }; +int audit_classify_syscall(int abi, unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + static int __init audit_classes_init(void) { audit_register_class(AUDIT_CLASS_WRITE, write_class); diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c index 798501994bd9..92d7d0c8d93f 100644 --- a/arch/ia64/ia32/audit.c +++ b/arch/ia64/ia32/audit.c @@ -19,3 +19,19 @@ unsigned ia32_read_class[] = { #include ~0U }; + +int ia32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c index 99488cdbf5cd..04682555a28c 100644 --- a/arch/ia64/kernel/audit.c +++ b/arch/ia64/kernel/audit.c @@ -23,6 +23,25 @@ static unsigned chattr_class[] = { ~0U }; +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_IA32_SUPPORT + extern int ia32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_I386) + return ia32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_execve: + return 5; + default: + return 0; + } +} + static int __init audit_classes_init(void) { #ifdef CONFIG_IA32_SUPPORT diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c index 24a65e3724e1..7fe5e6300e9a 100644 --- a/arch/powerpc/kernel/audit.c +++ b/arch/powerpc/kernel/audit.c @@ -23,6 +23,27 @@ static unsigned chattr_class[] = { ~0U }; +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_PPC64 + extern int ppc32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_PPC) + return ppc32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + static int __init audit_classes_init(void) { #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c index ddc0a64896a2..640d4bb29321 100644 --- a/arch/powerpc/kernel/compat_audit.c +++ b/arch/powerpc/kernel/compat_audit.c @@ -20,3 +20,19 @@ unsigned ppc32_read_class[] = { #include ~0U }; + +int ppc32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c index cde57039334c..0741d9193390 100644 --- a/arch/s390/kernel/audit.c +++ b/arch/s390/kernel/audit.c @@ -23,6 +23,27 @@ static unsigned chattr_class[] = { ~0U }; +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_COMPAT + extern int s390_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_S390) + return s390_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + static int __init audit_classes_init(void) { #ifdef CONFIG_COMPAT diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c index d9e5f3540d48..16d9436bfa91 100644 --- a/arch/s390/kernel/compat_audit.c +++ b/arch/s390/kernel/compat_audit.c @@ -20,3 +20,19 @@ unsigned s390_read_class[] = { #include ~0U }; + +int s390_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c index 798501994bd9..92d7d0c8d93f 100644 --- a/arch/x86_64/ia32/audit.c +++ b/arch/x86_64/ia32/audit.c @@ -19,3 +19,19 @@ unsigned ia32_read_class[] = { #include ~0U }; + +int ia32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c index 36840acb6513..21f33387bef3 100644 --- a/arch/x86_64/kernel/audit.c +++ b/arch/x86_64/kernel/audit.c @@ -23,6 +23,25 @@ static unsigned chattr_class[] = { ~0U }; +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_IA32_EMULATION + extern int ia32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_I386) + return ia32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_execve: + return 5; + default: + return 0; + } +} + static int __init audit_classes_init(void) { #ifdef CONFIG_IA32_EMULATION diff --git a/include/linux/audit.h b/include/linux/audit.h index 1077362a2efb..40a6c26294ae 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -181,6 +181,7 @@ #define AUDIT_EXIT 103 #define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */ #define AUDIT_WATCH 105 +#define AUDIT_PERM 106 #define AUDIT_ARG0 200 #define AUDIT_ARG1 (AUDIT_ARG0+1) @@ -256,6 +257,11 @@ #define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE) #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_PERM_EXEC 1 +#define AUDIT_PERM_WRITE 2 +#define AUDIT_PERM_READ 4 +#define AUDIT_PERM_ATTR 8 + struct audit_status { __u32 mask; /* Bit mask for valid entries */ __u32 enabled; /* 1 = enabled, 0 = disabled */ @@ -318,6 +324,7 @@ struct mqstat; #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); +extern int audit_classify_syscall(int abi, unsigned syscall); #ifdef CONFIG_AUDITSYSCALL /* These are defined in auditsc.c */ /* Public API */ diff --git a/kernel/audit.h b/kernel/audit.h index 6aa33b848cf2..a3370232a390 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -104,6 +104,7 @@ static inline int audit_hash_ino(u32 ino) return (ino & (AUDIT_INODE_BUCKETS-1)); } +extern int audit_match_class(int class, unsigned syscall); extern int audit_comparator(const u32 left, const u32 op, const u32 right); extern int audit_compare_dname_path(const char *dname, const char *path, int *dirlen); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index e4cafc11c510..a44879b0c72f 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -302,6 +302,15 @@ int __init audit_register_class(int class, unsigned *list) return 0; } +int audit_match_class(int class, unsigned syscall) +{ + if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) + return 0; + if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) + return 0; + return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall); +} + /* Common user-space to kernel rule translation. */ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) { @@ -414,6 +423,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_ARG2: case AUDIT_ARG3: break; + case AUDIT_PERM: + if (f->val & ~15) + goto exit_free; + break; case AUDIT_INODE: err = audit_to_inode(&entry->rule, f); if (err) @@ -568,6 +581,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, entry->rule.buflen += f->val; entry->rule.filterkey = str; break; + case AUDIT_PERM: + if (f->val & ~15) + goto exit_free; + break; default: goto exit_free; } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index efc1b74bebf3..1bd8827a0102 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -209,6 +209,54 @@ struct audit_context { #endif }; +#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) +static inline int open_arg(int flags, int mask) +{ + int n = ACC_MODE(flags); + if (flags & (O_TRUNC | O_CREAT)) + n |= AUDIT_PERM_WRITE; + return n & mask; +} + +static int audit_match_perm(struct audit_context *ctx, int mask) +{ + unsigned n = ctx->major; + switch (audit_classify_syscall(ctx->arch, n)) { + case 0: /* native */ + if ((mask & AUDIT_PERM_WRITE) && + audit_match_class(AUDIT_CLASS_WRITE, n)) + return 1; + if ((mask & AUDIT_PERM_READ) && + audit_match_class(AUDIT_CLASS_READ, n)) + return 1; + if ((mask & AUDIT_PERM_ATTR) && + audit_match_class(AUDIT_CLASS_CHATTR, n)) + return 1; + return 0; + case 1: /* 32bit on biarch */ + if ((mask & AUDIT_PERM_WRITE) && + audit_match_class(AUDIT_CLASS_WRITE_32, n)) + return 1; + if ((mask & AUDIT_PERM_READ) && + audit_match_class(AUDIT_CLASS_READ_32, n)) + return 1; + if ((mask & AUDIT_PERM_ATTR) && + audit_match_class(AUDIT_CLASS_CHATTR_32, n)) + return 1; + return 0; + case 2: /* open */ + return mask & ACC_MODE(ctx->argv[1]); + case 3: /* openat */ + return mask & ACC_MODE(ctx->argv[2]); + case 4: /* socketcall */ + return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND); + case 5: /* execve */ + return mask & AUDIT_PERM_EXEC; + default: + return 0; + } +} + /* Determine if any context name data matches a rule's watch data */ /* Compare a task_struct with an audit_rule. Return 1 on match, 0 * otherwise. */ @@ -397,6 +445,9 @@ static int audit_filter_rules(struct task_struct *tsk, /* ignore this field for filtering */ result = 1; break; + case AUDIT_PERM: + result = audit_match_perm(ctx, f->val); + break; } if (!result) -- cgit v1.3-14-g43fede