diff options
author | <dwmw2@shinybook.infradead.org> | 2005-04-29 11:08:28 -0400 |
---|---|---|
committer | <dwmw2@shinybook.infradead.org> | 2005-04-29 11:08:28 -0400 |
commit | 2fd6f58ba6efc82ea2c9c2630f7ff5ed9eeaf34a (patch) | |
tree | 87cf236a78ad242ae01f1b71c289131e6d1c0662 /kernel | |
parent | ea3834d9fb348fb1144ad3affea22df933eaf62e (diff) |
[AUDIT] Don't allow ptrace to fool auditing, log arch of audited syscalls.
We were calling ptrace_notify() after auditing the syscall and arguments,
but the debugger could have _changed_ them before the syscall was actually
invoked. Reorder the calls to fix that.
While we're touching ever call to audit_syscall_entry(), we also make it
take an extra argument: the architecture of the syscall which was made,
because some architectures allow more than one type of syscall.
Also add an explicit success/failure flag to audit_syscall_exit(), for
the benefit of architectures which return that in a condition register
rather than only returning a single register.
Change type of syscall return value to 'long' not 'int'.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/auditsc.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 00e87ffff13b..77e92592de57 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -123,7 +123,7 @@ struct audit_context { | |||
123 | int major; /* syscall number */ | 123 | int major; /* syscall number */ |
124 | unsigned long argv[4]; /* syscall arguments */ | 124 | unsigned long argv[4]; /* syscall arguments */ |
125 | int return_valid; /* return code is valid */ | 125 | int return_valid; /* return code is valid */ |
126 | int return_code;/* syscall return code */ | 126 | long return_code;/* syscall return code */ |
127 | int auditable; /* 1 if record should be written */ | 127 | int auditable; /* 1 if record should be written */ |
128 | int name_count; | 128 | int name_count; |
129 | struct audit_names names[AUDIT_NAMES]; | 129 | struct audit_names names[AUDIT_NAMES]; |
@@ -135,6 +135,7 @@ struct audit_context { | |||
135 | uid_t uid, euid, suid, fsuid; | 135 | uid_t uid, euid, suid, fsuid; |
136 | gid_t gid, egid, sgid, fsgid; | 136 | gid_t gid, egid, sgid, fsgid; |
137 | unsigned long personality; | 137 | unsigned long personality; |
138 | int arch; | ||
138 | 139 | ||
139 | #if AUDIT_DEBUG | 140 | #if AUDIT_DEBUG |
140 | int put_count; | 141 | int put_count; |
@@ -348,6 +349,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
348 | case AUDIT_PERS: | 349 | case AUDIT_PERS: |
349 | result = (tsk->personality == value); | 350 | result = (tsk->personality == value); |
350 | break; | 351 | break; |
352 | case AUDIT_ARCH: | ||
353 | if (ctx) | ||
354 | result = (ctx->arch == value); | ||
355 | break; | ||
351 | 356 | ||
352 | case AUDIT_EXIT: | 357 | case AUDIT_EXIT: |
353 | if (ctx && ctx->return_valid) | 358 | if (ctx && ctx->return_valid) |
@@ -355,7 +360,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
355 | break; | 360 | break; |
356 | case AUDIT_SUCCESS: | 361 | case AUDIT_SUCCESS: |
357 | if (ctx && ctx->return_valid) | 362 | if (ctx && ctx->return_valid) |
358 | result = (ctx->return_code >= 0); | 363 | result = (ctx->return_valid == AUDITSC_SUCCESS); |
359 | break; | 364 | break; |
360 | case AUDIT_DEVMAJOR: | 365 | case AUDIT_DEVMAJOR: |
361 | if (ctx) { | 366 | if (ctx) { |
@@ -648,8 +653,11 @@ static void audit_log_exit(struct audit_context *context) | |||
648 | audit_log_format(ab, "syscall=%d", context->major); | 653 | audit_log_format(ab, "syscall=%d", context->major); |
649 | if (context->personality != PER_LINUX) | 654 | if (context->personality != PER_LINUX) |
650 | audit_log_format(ab, " per=%lx", context->personality); | 655 | audit_log_format(ab, " per=%lx", context->personality); |
656 | audit_log_format(ab, " arch=%x", context->arch); | ||
651 | if (context->return_valid) | 657 | if (context->return_valid) |
652 | audit_log_format(ab, " exit=%d", context->return_code); | 658 | audit_log_format(ab, " success=%s exit=%ld", |
659 | (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", | ||
660 | context->return_code); | ||
653 | audit_log_format(ab, | 661 | audit_log_format(ab, |
654 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" | 662 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" |
655 | " pid=%d loginuid=%d uid=%d gid=%d" | 663 | " pid=%d loginuid=%d uid=%d gid=%d" |
@@ -773,7 +781,7 @@ static inline unsigned int audit_serial(void) | |||
773 | * then the record will be written at syscall exit time (otherwise, it | 781 | * then the record will be written at syscall exit time (otherwise, it |
774 | * will only be written if another part of the kernel requests that it | 782 | * will only be written if another part of the kernel requests that it |
775 | * be written). */ | 783 | * be written). */ |
776 | void audit_syscall_entry(struct task_struct *tsk, int major, | 784 | void audit_syscall_entry(struct task_struct *tsk, int arch, int major, |
777 | unsigned long a1, unsigned long a2, | 785 | unsigned long a1, unsigned long a2, |
778 | unsigned long a3, unsigned long a4) | 786 | unsigned long a3, unsigned long a4) |
779 | { | 787 | { |
@@ -827,6 +835,7 @@ void audit_syscall_entry(struct task_struct *tsk, int major, | |||
827 | if (!audit_enabled) | 835 | if (!audit_enabled) |
828 | return; | 836 | return; |
829 | 837 | ||
838 | context->arch = arch; | ||
830 | context->major = major; | 839 | context->major = major; |
831 | context->argv[0] = a1; | 840 | context->argv[0] = a1; |
832 | context->argv[1] = a2; | 841 | context->argv[1] = a2; |
@@ -850,13 +859,13 @@ void audit_syscall_entry(struct task_struct *tsk, int major, | |||
850 | * filtering, or because some other part of the kernel write an audit | 859 | * filtering, or because some other part of the kernel write an audit |
851 | * message), then write out the syscall information. In call cases, | 860 | * message), then write out the syscall information. In call cases, |
852 | * free the names stored from getname(). */ | 861 | * free the names stored from getname(). */ |
853 | void audit_syscall_exit(struct task_struct *tsk, int return_code) | 862 | void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code) |
854 | { | 863 | { |
855 | struct audit_context *context; | 864 | struct audit_context *context; |
856 | 865 | ||
857 | get_task_struct(tsk); | 866 | get_task_struct(tsk); |
858 | task_lock(tsk); | 867 | task_lock(tsk); |
859 | context = audit_get_context(tsk, 1, return_code); | 868 | context = audit_get_context(tsk, valid, return_code); |
860 | task_unlock(tsk); | 869 | task_unlock(tsk); |
861 | 870 | ||
862 | /* Not having a context here is ok, since the parent may have | 871 | /* Not having a context here is ok, since the parent may have |
@@ -869,6 +878,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code) | |||
869 | 878 | ||
870 | context->in_syscall = 0; | 879 | context->in_syscall = 0; |
871 | context->auditable = 0; | 880 | context->auditable = 0; |
881 | |||
872 | if (context->previous) { | 882 | if (context->previous) { |
873 | struct audit_context *new_context = context->previous; | 883 | struct audit_context *new_context = context->previous; |
874 | context->previous = NULL; | 884 | context->previous = NULL; |