mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 14:11:20 +00:00
[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>
This commit is contained in:
parent
ea3834d9fb
commit
2fd6f58ba6
8 changed files with 146 additions and 65 deletions
|
@ -123,7 +123,7 @@ struct audit_context {
|
|||
int major; /* syscall number */
|
||||
unsigned long argv[4]; /* syscall arguments */
|
||||
int return_valid; /* return code is valid */
|
||||
int return_code;/* syscall return code */
|
||||
long return_code;/* syscall return code */
|
||||
int auditable; /* 1 if record should be written */
|
||||
int name_count;
|
||||
struct audit_names names[AUDIT_NAMES];
|
||||
|
@ -135,6 +135,7 @@ struct audit_context {
|
|||
uid_t uid, euid, suid, fsuid;
|
||||
gid_t gid, egid, sgid, fsgid;
|
||||
unsigned long personality;
|
||||
int arch;
|
||||
|
||||
#if AUDIT_DEBUG
|
||||
int put_count;
|
||||
|
@ -348,6 +349,10 @@ static int audit_filter_rules(struct task_struct *tsk,
|
|||
case AUDIT_PERS:
|
||||
result = (tsk->personality == value);
|
||||
break;
|
||||
case AUDIT_ARCH:
|
||||
if (ctx)
|
||||
result = (ctx->arch == value);
|
||||
break;
|
||||
|
||||
case AUDIT_EXIT:
|
||||
if (ctx && ctx->return_valid)
|
||||
|
@ -355,7 +360,7 @@ static int audit_filter_rules(struct task_struct *tsk,
|
|||
break;
|
||||
case AUDIT_SUCCESS:
|
||||
if (ctx && ctx->return_valid)
|
||||
result = (ctx->return_code >= 0);
|
||||
result = (ctx->return_valid == AUDITSC_SUCCESS);
|
||||
break;
|
||||
case AUDIT_DEVMAJOR:
|
||||
if (ctx) {
|
||||
|
@ -648,8 +653,11 @@ static void audit_log_exit(struct audit_context *context)
|
|||
audit_log_format(ab, "syscall=%d", context->major);
|
||||
if (context->personality != PER_LINUX)
|
||||
audit_log_format(ab, " per=%lx", context->personality);
|
||||
audit_log_format(ab, " arch=%x", context->arch);
|
||||
if (context->return_valid)
|
||||
audit_log_format(ab, " exit=%d", context->return_code);
|
||||
audit_log_format(ab, " success=%s exit=%ld",
|
||||
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
|
||||
context->return_code);
|
||||
audit_log_format(ab,
|
||||
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
|
||||
" pid=%d loginuid=%d uid=%d gid=%d"
|
||||
|
@ -773,7 +781,7 @@ static inline unsigned int audit_serial(void)
|
|||
* then the record will be written at syscall exit time (otherwise, it
|
||||
* will only be written if another part of the kernel requests that it
|
||||
* be written). */
|
||||
void audit_syscall_entry(struct task_struct *tsk, int major,
|
||||
void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
|
||||
unsigned long a1, unsigned long a2,
|
||||
unsigned long a3, unsigned long a4)
|
||||
{
|
||||
|
@ -827,6 +835,7 @@ void audit_syscall_entry(struct task_struct *tsk, int major,
|
|||
if (!audit_enabled)
|
||||
return;
|
||||
|
||||
context->arch = arch;
|
||||
context->major = major;
|
||||
context->argv[0] = a1;
|
||||
context->argv[1] = a2;
|
||||
|
@ -850,13 +859,13 @@ void audit_syscall_entry(struct task_struct *tsk, int major,
|
|||
* filtering, or because some other part of the kernel write an audit
|
||||
* message), then write out the syscall information. In call cases,
|
||||
* free the names stored from getname(). */
|
||||
void audit_syscall_exit(struct task_struct *tsk, int return_code)
|
||||
void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
|
||||
{
|
||||
struct audit_context *context;
|
||||
|
||||
get_task_struct(tsk);
|
||||
task_lock(tsk);
|
||||
context = audit_get_context(tsk, 1, return_code);
|
||||
context = audit_get_context(tsk, valid, return_code);
|
||||
task_unlock(tsk);
|
||||
|
||||
/* 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)
|
|||
|
||||
context->in_syscall = 0;
|
||||
context->auditable = 0;
|
||||
|
||||
if (context->previous) {
|
||||
struct audit_context *new_context = context->previous;
|
||||
context->previous = NULL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue