aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/audit.h
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2012-01-03 14:23:06 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-17 16:16:56 -0500
commitd7e7528bcd456f5c36ad4a202ccfb43c5aa98bc4 (patch)
treeef49503b1dc52c52102e728dbd979c9309d5756b /include/linux/audit.h
parent85e7bac33b8d5edafc4e219c7dfdb3d48e0b4e31 (diff)
Audit: push audit success and retcode into arch ptrace.h
The audit system previously expected arches calling to audit_syscall_exit to supply as arguments if the syscall was a success and what the return code was. Audit also provides a helper AUDITSC_RESULT which was supposed to simplify things by converting from negative retcodes to an audit internal magic value stating success or failure. This helper was wrong and could indicate that a valid pointer returned to userspace was a failed syscall. The fix is to fix the layering foolishness. We now pass audit_syscall_exit a struct pt_reg and it in turns calls back into arch code to collect the return value and to determine if the syscall was a success or failure. We also define a generic is_syscall_success() macro which determines success/failure based on if the value is < -MAX_ERRNO. This works for arches like x86 which do not use a separate mechanism to indicate syscall failure. We make both the is_syscall_success() and regs_return_value() static inlines instead of macros. The reason is because the audit function must take a void* for the regs. (uml calls theirs struct uml_pt_regs instead of just struct pt_regs so audit_syscall_exit can't take a struct pt_regs). Since the audit function takes a void* we need to use static inlines to cast it back to the arch correct structure to dereference it. The other major change is that on some arches, like ia64, MIPS and ppc, we change regs_return_value() to give us the negative value on syscall failure. THE only other user of this macro, kretprobe_example.c, won't notice and it makes the value signed consistently for the audit functions across all archs. In arch/sh/kernel/ptrace_64.c I see that we were using regs[9] in the old audit code as the return value. But the ptrace_64.h code defined the macro regs_return_value() as regs[3]. I have no idea which one is correct, but this patch now uses the regs_return_value() function, so it now uses regs[3]. For powerpc we previously used regs->result but now use the regs_return_value() function which uses regs->gprs[3]. regs->gprs[3] is always positive so the regs_return_value(), much like ia64 makes it negative before calling the audit code when appropriate. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: H. Peter Anvin <hpa@zytor.com> [for x86 portion] Acked-by: Tony Luck <tony.luck@intel.com> [for ia64] Acked-by: Richard Weinberger <richard@nod.at> [for uml] Acked-by: David S. Miller <davem@davemloft.net> [for sparc] Acked-by: Ralf Baechle <ralf@linux-mips.org> [for mips] Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [for ppc]
Diffstat (limited to 'include/linux/audit.h')
-rw-r--r--include/linux/audit.h22
1 files changed, 14 insertions, 8 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6e1c533f9b46..3d65e4b3ba06 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
26 26
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/elf-em.h> 28#include <linux/elf-em.h>
29#include <linux/ptrace.h>
29 30
30/* The netlink messages for the audit system is divided into blocks: 31/* The netlink messages for the audit system is divided into blocks:
31 * 1000 - 1099 are for commanding the audit system 32 * 1000 - 1099 are for commanding the audit system
@@ -408,10 +409,6 @@ struct audit_field {
408 void *lsm_rule; 409 void *lsm_rule;
409}; 410};
410 411
411#define AUDITSC_INVALID 0
412#define AUDITSC_SUCCESS 1
413#define AUDITSC_FAILURE 2
414#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
415extern int __init audit_register_class(int class, unsigned *list); 412extern int __init audit_register_class(int class, unsigned *list);
416extern int audit_classify_syscall(int abi, unsigned syscall); 413extern int audit_classify_syscall(int abi, unsigned syscall);
417extern int audit_classify_arch(int arch); 414extern int audit_classify_arch(int arch);
@@ -424,7 +421,7 @@ extern void audit_free(struct task_struct *task);
424extern void audit_syscall_entry(int arch, 421extern void audit_syscall_entry(int arch,
425 int major, unsigned long a0, unsigned long a1, 422 int major, unsigned long a0, unsigned long a1,
426 unsigned long a2, unsigned long a3); 423 unsigned long a2, unsigned long a3);
427extern void audit_syscall_exit(int failed, long return_code); 424extern void __audit_syscall_exit(int ret_success, long ret_value);
428extern void __audit_getname(const char *name); 425extern void __audit_getname(const char *name);
429extern void audit_putname(const char *name); 426extern void audit_putname(const char *name);
430extern void __audit_inode(const char *name, const struct dentry *dentry); 427extern void __audit_inode(const char *name, const struct dentry *dentry);
@@ -438,6 +435,15 @@ static inline int audit_dummy_context(void)
438 void *p = current->audit_context; 435 void *p = current->audit_context;
439 return !p || *(int *)p; 436 return !p || *(int *)p;
440} 437}
438static inline void audit_syscall_exit(void *pt_regs)
439{
440 if (unlikely(current->audit_context)) {
441 int success = is_syscall_success(pt_regs);
442 int return_code = regs_return_value(pt_regs);
443
444 __audit_syscall_exit(success, return_code);
445 }
446}
441static inline void audit_getname(const char *name) 447static inline void audit_getname(const char *name)
442{ 448{
443 if (unlikely(!audit_dummy_context())) 449 if (unlikely(!audit_dummy_context()))
@@ -551,12 +557,12 @@ static inline void audit_mmap_fd(int fd, int flags)
551 557
552extern int audit_n_rules; 558extern int audit_n_rules;
553extern int audit_signals; 559extern int audit_signals;
554#else 560#else /* CONFIG_AUDITSYSCALL */
555#define audit_finish_fork(t) 561#define audit_finish_fork(t)
556#define audit_alloc(t) ({ 0; }) 562#define audit_alloc(t) ({ 0; })
557#define audit_free(t) do { ; } while (0) 563#define audit_free(t) do { ; } while (0)
558#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0) 564#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
559#define audit_syscall_exit(f,r) do { ; } while (0) 565#define audit_syscall_exit(r) do { ; } while (0)
560#define audit_dummy_context() 1 566#define audit_dummy_context() 1
561#define audit_getname(n) do { ; } while (0) 567#define audit_getname(n) do { ; } while (0)
562#define audit_putname(n) do { ; } while (0) 568#define audit_putname(n) do { ; } while (0)
@@ -587,7 +593,7 @@ extern int audit_signals;
587#define audit_ptrace(t) ((void)0) 593#define audit_ptrace(t) ((void)0)
588#define audit_n_rules 0 594#define audit_n_rules 0
589#define audit_signals 0 595#define audit_signals 0
590#endif 596#endif /* CONFIG_AUDITSYSCALL */
591 597
592#ifdef CONFIG_AUDIT 598#ifdef CONFIG_AUDIT
593/* These are defined in audit.c */ 599/* These are defined in audit.c */