Merge with /usr/src/ntfs-2.6.git
This commit is contained in:
commit
450cbfbbbd
|
@ -683,24 +683,18 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
||||||
/* do the secure computing check first */
|
/* do the secure computing check first */
|
||||||
secure_computing(regs->orig_eax);
|
secure_computing(regs->orig_eax);
|
||||||
|
|
||||||
if (unlikely(current->audit_context)) {
|
if (unlikely(current->audit_context) && entryexit)
|
||||||
if (!entryexit)
|
audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
|
||||||
audit_syscall_entry(current, regs->orig_eax,
|
|
||||||
regs->ebx, regs->ecx,
|
|
||||||
regs->edx, regs->esi);
|
|
||||||
else
|
|
||||||
audit_syscall_exit(current, regs->eax);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(current->ptrace & PT_PTRACED))
|
if (!(current->ptrace & PT_PTRACED))
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/* Fake a debug trap */
|
/* Fake a debug trap */
|
||||||
if (test_thread_flag(TIF_SINGLESTEP))
|
if (test_thread_flag(TIF_SINGLESTEP))
|
||||||
send_sigtrap(current, regs, 0);
|
send_sigtrap(current, regs, 0);
|
||||||
|
|
||||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/* the 0x80 provides a way for the tracing parent to distinguish
|
/* the 0x80 provides a way for the tracing parent to distinguish
|
||||||
between a syscall stop and SIGTRAP delivery */
|
between a syscall stop and SIGTRAP delivery */
|
||||||
|
@ -715,4 +709,9 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
||||||
send_sig(current->exit_code, current, 1);
|
send_sig(current->exit_code, current, 1);
|
||||||
current->exit_code = 0;
|
current->exit_code = 0;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
if (unlikely(current->audit_context) && !entryexit)
|
||||||
|
audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
|
||||||
|
regs->ebx, regs->ecx, regs->edx, regs->esi);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1596,20 +1596,25 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
|
||||||
long arg4, long arg5, long arg6, long arg7,
|
long arg4, long arg5, long arg6, long arg7,
|
||||||
struct pt_regs regs)
|
struct pt_regs regs)
|
||||||
{
|
{
|
||||||
long syscall;
|
|
||||||
|
|
||||||
if (unlikely(current->audit_context)) {
|
|
||||||
if (IS_IA32_PROCESS(®s))
|
|
||||||
syscall = regs.r1;
|
|
||||||
else
|
|
||||||
syscall = regs.r15;
|
|
||||||
|
|
||||||
audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
&& (current->ptrace & PT_PTRACED))
|
&& (current->ptrace & PT_PTRACED))
|
||||||
syscall_trace();
|
syscall_trace();
|
||||||
|
|
||||||
|
if (unlikely(current->audit_context)) {
|
||||||
|
long syscall;
|
||||||
|
int arch;
|
||||||
|
|
||||||
|
if (IS_IA32_PROCESS(®s)) {
|
||||||
|
syscall = regs.r1;
|
||||||
|
arch = AUDIT_ARCH_I386;
|
||||||
|
} else {
|
||||||
|
syscall = regs.r15;
|
||||||
|
arch = AUDIT_ARCH_IA64;
|
||||||
|
}
|
||||||
|
|
||||||
|
audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "asmlinkage" so the input arguments are preserved... */
|
/* "asmlinkage" so the input arguments are preserved... */
|
||||||
|
@ -1620,7 +1625,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
|
||||||
struct pt_regs regs)
|
struct pt_regs regs)
|
||||||
{
|
{
|
||||||
if (unlikely(current->audit_context))
|
if (unlikely(current->audit_context))
|
||||||
audit_syscall_exit(current, regs.r8);
|
audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
&& (current->ptrace & PT_PTRACED))
|
&& (current->ptrace & PT_PTRACED))
|
||||||
|
|
|
@ -301,25 +301,38 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int audit_arch(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||||
|
#ifdef CONFIG_MIPS64
|
||||||
|
if (!(current->thread.mflags & MF_32BIT_REGS))
|
||||||
|
return AUDIT_ARCH_MIPSEL64;
|
||||||
|
#endif /* MIPS64 */
|
||||||
|
return AUDIT_ARCH_MIPSEL;
|
||||||
|
|
||||||
|
#else /* big endian... */
|
||||||
|
#ifdef CONFIG_MIPS64
|
||||||
|
if (!(current->thread.mflags & MF_32BIT_REGS))
|
||||||
|
return AUDIT_ARCH_MIPS64;
|
||||||
|
#endif /* MIPS64 */
|
||||||
|
return AUDIT_ARCH_MIPS;
|
||||||
|
|
||||||
|
#endif /* endian */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notification of system call entry/exit
|
* Notification of system call entry/exit
|
||||||
* - triggered by current->work.syscall_trace
|
* - triggered by current->work.syscall_trace
|
||||||
*/
|
*/
|
||||||
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
||||||
{
|
{
|
||||||
if (unlikely(current->audit_context)) {
|
if (unlikely(current->audit_context) && entryexit)
|
||||||
if (!entryexit)
|
audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), regs->regs[2]);
|
||||||
audit_syscall_entry(current, regs->regs[2],
|
|
||||||
regs->regs[4], regs->regs[5],
|
|
||||||
regs->regs[6], regs->regs[7]);
|
|
||||||
else
|
|
||||||
audit_syscall_exit(current, regs->regs[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||||
return;
|
goto out;
|
||||||
if (!(current->ptrace & PT_PTRACED))
|
if (!(current->ptrace & PT_PTRACED))
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/* The 0x80 provides a way for the tracing parent to distinguish
|
/* The 0x80 provides a way for the tracing parent to distinguish
|
||||||
between a syscall stop and SIGTRAP delivery */
|
between a syscall stop and SIGTRAP delivery */
|
||||||
|
@ -335,4 +348,9 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
||||||
send_sig(current->exit_code, current, 1);
|
send_sig(current->exit_code, current, 1);
|
||||||
current->exit_code = 0;
|
current->exit_code = 0;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
if (unlikely(current->audit_context) && !entryexit)
|
||||||
|
audit_syscall_entry(current, audit_arch(), regs->regs[2],
|
||||||
|
regs->regs[4], regs->regs[5],
|
||||||
|
regs->regs[6], regs->regs[7]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,14 +305,17 @@ static void do_syscall_trace(void)
|
||||||
|
|
||||||
void do_syscall_trace_enter(struct pt_regs *regs)
|
void do_syscall_trace_enter(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
if (unlikely(current->audit_context))
|
|
||||||
audit_syscall_entry(current, regs->gpr[0],
|
|
||||||
regs->gpr[3], regs->gpr[4],
|
|
||||||
regs->gpr[5], regs->gpr[6]);
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
&& (current->ptrace & PT_PTRACED))
|
&& (current->ptrace & PT_PTRACED))
|
||||||
do_syscall_trace();
|
do_syscall_trace();
|
||||||
|
|
||||||
|
if (unlikely(current->audit_context))
|
||||||
|
audit_syscall_entry(current,
|
||||||
|
test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
|
||||||
|
regs->gpr[0],
|
||||||
|
regs->gpr[3], regs->gpr[4],
|
||||||
|
regs->gpr[5], regs->gpr[6]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_syscall_trace_leave(struct pt_regs *regs)
|
void do_syscall_trace_leave(struct pt_regs *regs)
|
||||||
|
@ -320,7 +323,9 @@ void do_syscall_trace_leave(struct pt_regs *regs)
|
||||||
secure_computing(regs->gpr[0]);
|
secure_computing(regs->gpr[0]);
|
||||||
|
|
||||||
if (unlikely(current->audit_context))
|
if (unlikely(current->audit_context))
|
||||||
audit_syscall_exit(current, regs->result);
|
audit_syscall_exit(current,
|
||||||
|
(regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
|
||||||
|
regs->result);
|
||||||
|
|
||||||
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
|| test_thread_flag(TIF_SINGLESTEP))
|
|| test_thread_flag(TIF_SINGLESTEP))
|
||||||
|
|
|
@ -712,18 +712,13 @@ out:
|
||||||
asmlinkage void
|
asmlinkage void
|
||||||
syscall_trace(struct pt_regs *regs, int entryexit)
|
syscall_trace(struct pt_regs *regs, int entryexit)
|
||||||
{
|
{
|
||||||
if (unlikely(current->audit_context)) {
|
if (unlikely(current->audit_context) && entryexit)
|
||||||
if (!entryexit)
|
audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
|
||||||
audit_syscall_entry(current, regs->gprs[2],
|
|
||||||
regs->orig_gpr2, regs->gprs[3],
|
|
||||||
regs->gprs[4], regs->gprs[5]);
|
|
||||||
else
|
|
||||||
audit_syscall_exit(current, regs->gprs[2]);
|
|
||||||
}
|
|
||||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||||
return;
|
goto out;
|
||||||
if (!(current->ptrace & PT_PTRACED))
|
if (!(current->ptrace & PT_PTRACED))
|
||||||
return;
|
goto out;
|
||||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||||
? 0x80 : 0));
|
? 0x80 : 0));
|
||||||
|
|
||||||
|
@ -736,4 +731,10 @@ syscall_trace(struct pt_regs *regs, int entryexit)
|
||||||
send_sig(current->exit_code, current, 1);
|
send_sig(current->exit_code, current, 1);
|
||||||
current->exit_code = 0;
|
current->exit_code = 0;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
if (unlikely(current->audit_context) && !entryexit)
|
||||||
|
audit_syscall_entry(current,
|
||||||
|
test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
|
||||||
|
regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
|
||||||
|
regs->gprs[4], regs->gprs[5]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,14 +338,17 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
|
||||||
if (unlikely(current->audit_context)) {
|
if (unlikely(current->audit_context)) {
|
||||||
if (!entryexit)
|
if (!entryexit)
|
||||||
audit_syscall_entry(current,
|
audit_syscall_entry(current,
|
||||||
UPT_SYSCALL_NR(®s->regs),
|
HOST_AUDIT_ARCH,
|
||||||
UPT_SYSCALL_ARG1(®s->regs),
|
UPT_SYSCALL_NR(regs),
|
||||||
UPT_SYSCALL_ARG2(®s->regs),
|
UPT_SYSCALL_ARG1(regs),
|
||||||
UPT_SYSCALL_ARG3(®s->regs),
|
UPT_SYSCALL_ARG2(regs),
|
||||||
UPT_SYSCALL_ARG4(®s->regs));
|
UPT_SYSCALL_ARG3(regs),
|
||||||
else
|
UPT_SYSCALL_ARG4(regs));
|
||||||
audit_syscall_exit(current,
|
else {
|
||||||
UPT_SYSCALL_RET(®s->regs));
|
int res = UPT_SYSCALL_RET(regs);
|
||||||
|
audit_syscall_exit(current, AUDITSC_RESULT(res),
|
||||||
|
res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fake a debug trap */
|
/* Fake a debug trap */
|
||||||
|
|
|
@ -635,20 +635,29 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
|
||||||
/* do the secure computing check first */
|
/* do the secure computing check first */
|
||||||
secure_computing(regs->orig_rax);
|
secure_computing(regs->orig_rax);
|
||||||
|
|
||||||
if (unlikely(current->audit_context))
|
|
||||||
audit_syscall_entry(current, regs->orig_rax,
|
|
||||||
regs->rdi, regs->rsi,
|
|
||||||
regs->rdx, regs->r10);
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
&& (current->ptrace & PT_PTRACED))
|
&& (current->ptrace & PT_PTRACED))
|
||||||
syscall_trace(regs);
|
syscall_trace(regs);
|
||||||
|
|
||||||
|
if (unlikely(current->audit_context)) {
|
||||||
|
if (test_thread_flag(TIF_IA32)) {
|
||||||
|
audit_syscall_entry(current, AUDIT_ARCH_I386,
|
||||||
|
regs->orig_rax,
|
||||||
|
regs->rbx, regs->rcx,
|
||||||
|
regs->rdx, regs->rsi);
|
||||||
|
} else {
|
||||||
|
audit_syscall_entry(current, AUDIT_ARCH_X86_64,
|
||||||
|
regs->orig_rax,
|
||||||
|
regs->rdi, regs->rsi,
|
||||||
|
regs->rdx, regs->r10);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
|
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
if (unlikely(current->audit_context))
|
if (unlikely(current->audit_context))
|
||||||
audit_syscall_exit(current, regs->rax);
|
audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax);
|
||||||
|
|
||||||
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|
||||||
|| test_thread_flag(TIF_SINGLESTEP))
|
|| test_thread_flag(TIF_SINGLESTEP))
|
||||||
|
|
|
@ -405,9 +405,8 @@ void device_release_driver(struct device * dev)
|
||||||
|
|
||||||
static void driver_detach(struct device_driver * drv)
|
static void driver_detach(struct device_driver * drv)
|
||||||
{
|
{
|
||||||
struct list_head * entry, * next;
|
while (!list_empty(&drv->devices)) {
|
||||||
list_for_each_safe(entry, next, &drv->devices) {
|
struct device * dev = container_of(drv->devices.next, struct device, driver_list);
|
||||||
struct device * dev = container_of(entry, struct device, driver_list);
|
|
||||||
device_release_driver(dev);
|
device_release_driver(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
buffer = &buffer[length];
|
buffer = &buffer[length];
|
||||||
buffer_size -= length;
|
buffer_size -= length;
|
||||||
|
|
||||||
if (dev->bus->hotplug) {
|
if (dev->bus && dev->bus->hotplug) {
|
||||||
/* have the bus specific function add its stuff */
|
/* have the bus specific function add its stuff */
|
||||||
retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
|
retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
|
20
fs/namei.c
20
fs/namei.c
|
@ -686,11 +686,11 @@ fail:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name resolution.
|
* Name resolution.
|
||||||
|
* This is the basic name resolution function, turning a pathname into
|
||||||
|
* the final dentry. We expect 'base' to be positive and a directory.
|
||||||
*
|
*
|
||||||
* This is the basic name resolution function, turning a pathname
|
* Returns 0 and nd will have valid dentry and mnt on success.
|
||||||
* into the final dentry.
|
* Returns error and drops reference to input namei data on failure.
|
||||||
*
|
|
||||||
* We expect 'base' to be positive and a directory.
|
|
||||||
*/
|
*/
|
||||||
static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
|
static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
|
@ -929,8 +929,10 @@ int fastcall path_walk(const char * name, struct nameidata *nd)
|
||||||
return link_path_walk(name, nd);
|
return link_path_walk(name, nd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SMP-safe */
|
/*
|
||||||
/* returns 1 if everything is done */
|
* SMP-safe: Returns 1 and nd will have valid dentry and mnt, if
|
||||||
|
* everything is done. Returns 0 and drops input nd, if lookup failed;
|
||||||
|
*/
|
||||||
static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
|
static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
if (path_walk(name, nd))
|
if (path_walk(name, nd))
|
||||||
|
@ -994,9 +996,10 @@ set_it:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
|
||||||
int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
|
int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval = 0;
|
||||||
|
|
||||||
nd->last_type = LAST_ROOT; /* if there are only slashes... */
|
nd->last_type = LAST_ROOT; /* if there are only slashes... */
|
||||||
nd->flags = flags;
|
nd->flags = flags;
|
||||||
|
@ -1009,7 +1012,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
|
||||||
nd->dentry = dget(current->fs->altroot);
|
nd->dentry = dget(current->fs->altroot);
|
||||||
read_unlock(¤t->fs->lock);
|
read_unlock(¤t->fs->lock);
|
||||||
if (__emul_lookup_dentry(name,nd))
|
if (__emul_lookup_dentry(name,nd))
|
||||||
return 0;
|
goto out; /* found in altroot */
|
||||||
read_lock(¤t->fs->lock);
|
read_lock(¤t->fs->lock);
|
||||||
}
|
}
|
||||||
nd->mnt = mntget(current->fs->rootmnt);
|
nd->mnt = mntget(current->fs->rootmnt);
|
||||||
|
@ -1021,6 +1024,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
|
||||||
read_unlock(¤t->fs->lock);
|
read_unlock(¤t->fs->lock);
|
||||||
current->total_link_count = 0;
|
current->total_link_count = 0;
|
||||||
retval = link_path_walk(name, nd);
|
retval = link_path_walk(name, nd);
|
||||||
|
out:
|
||||||
if (unlikely(current->audit_context
|
if (unlikely(current->audit_context
|
||||||
&& nd && nd->dentry && nd->dentry->d_inode))
|
&& nd && nd->dentry && nd->dentry->d_inode))
|
||||||
audit_inode(name, nd->dentry->d_inode);
|
audit_inode(name, nd->dentry->d_inode);
|
||||||
|
|
|
@ -820,7 +820,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
|
||||||
goto out_free_page;
|
goto out_free_page;
|
||||||
|
|
||||||
}
|
}
|
||||||
length = audit_set_loginuid(task->audit_context, loginuid);
|
length = audit_set_loginuid(task, loginuid);
|
||||||
if (likely(length == 0))
|
if (likely(length == 0))
|
||||||
length = count;
|
length = count;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#ifndef __UM_PTRACE_I386_H
|
#ifndef __UM_PTRACE_I386_H
|
||||||
#define __UM_PTRACE_I386_H
|
#define __UM_PTRACE_I386_H
|
||||||
|
|
||||||
|
#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
|
||||||
|
|
||||||
#include "sysdep/ptrace.h"
|
#include "sysdep/ptrace.h"
|
||||||
#include "asm/ptrace-generic.h"
|
#include "asm/ptrace-generic.h"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "asm/ptrace-generic.h"
|
#include "asm/ptrace-generic.h"
|
||||||
#undef signal_fault
|
#undef signal_fault
|
||||||
|
|
||||||
|
#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
|
||||||
|
|
||||||
void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
|
void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
|
||||||
|
|
||||||
#define FS_BASE (21 * sizeof(unsigned long))
|
#define FS_BASE (21 * sizeof(unsigned long))
|
||||||
|
|
|
@ -72,12 +72,14 @@ static inline struct thread_info *current_thread_info(void)
|
||||||
*/
|
*/
|
||||||
#define TIF_RESTART_BLOCK 4
|
#define TIF_RESTART_BLOCK 4
|
||||||
#define TIF_MEMDIE 5
|
#define TIF_MEMDIE 5
|
||||||
|
#define TIF_SYSCALL_AUDIT 6
|
||||||
|
|
||||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||||
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
||||||
#define _TIF_RESTART_BLOCK (1 << TIF_RESTART_BLOCK)
|
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
|
||||||
|
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* audit.h -- Auditing support -*- linux-c -*-
|
/* audit.h -- Auditing support
|
||||||
*
|
*
|
||||||
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
|
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
|
@ -24,6 +24,9 @@
|
||||||
#ifndef _LINUX_AUDIT_H_
|
#ifndef _LINUX_AUDIT_H_
|
||||||
#define _LINUX_AUDIT_H_
|
#define _LINUX_AUDIT_H_
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
|
|
||||||
/* Request and reply types */
|
/* Request and reply types */
|
||||||
#define AUDIT_GET 1000 /* Get status */
|
#define AUDIT_GET 1000 /* Get status */
|
||||||
#define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */
|
#define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */
|
||||||
|
@ -67,6 +70,7 @@
|
||||||
#define AUDIT_FSGID 8
|
#define AUDIT_FSGID 8
|
||||||
#define AUDIT_LOGINUID 9
|
#define AUDIT_LOGINUID 9
|
||||||
#define AUDIT_PERS 10
|
#define AUDIT_PERS 10
|
||||||
|
#define AUDIT_ARCH 11
|
||||||
|
|
||||||
/* These are ONLY useful when checking
|
/* These are ONLY useful when checking
|
||||||
* at syscall exit time (AUDIT_AT_EXIT). */
|
* at syscall exit time (AUDIT_AT_EXIT). */
|
||||||
|
@ -96,6 +100,38 @@
|
||||||
#define AUDIT_FAIL_PRINTK 1
|
#define AUDIT_FAIL_PRINTK 1
|
||||||
#define AUDIT_FAIL_PANIC 2
|
#define AUDIT_FAIL_PANIC 2
|
||||||
|
|
||||||
|
/* distinguish syscall tables */
|
||||||
|
#define __AUDIT_ARCH_64BIT 0x80000000
|
||||||
|
#define __AUDIT_ARCH_LE 0x40000000
|
||||||
|
#define AUDIT_ARCH_ALPHA (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_ARMEB (EM_ARM)
|
||||||
|
#define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_FRV (EM_FRV)
|
||||||
|
#define AUDIT_ARCH_H8300 (EM_H8_300)
|
||||||
|
#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_M32R (EM_M32R)
|
||||||
|
#define AUDIT_ARCH_M68K (EM_68K)
|
||||||
|
#define AUDIT_ARCH_MIPS (EM_MIPS)
|
||||||
|
#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_MIPS64 (EM_MIPS|__AUDIT_ARCH_64BIT)
|
||||||
|
#define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_PARISC (EM_PARISC)
|
||||||
|
#define AUDIT_ARCH_PARISC64 (EM_PARISC|__AUDIT_ARCH_64BIT)
|
||||||
|
#define AUDIT_ARCH_PPC (EM_PPC)
|
||||||
|
#define AUDIT_ARCH_PPC64 (EM_PPC64|__AUDIT_ARCH_64BIT)
|
||||||
|
#define AUDIT_ARCH_S390 (EM_S390)
|
||||||
|
#define AUDIT_ARCH_S390X (EM_S390|__AUDIT_ARCH_64BIT)
|
||||||
|
#define AUDIT_ARCH_SH (EM_SH)
|
||||||
|
#define AUDIT_ARCH_SHEL (EM_SH|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_SH64 (EM_SH|__AUDIT_ARCH_64BIT)
|
||||||
|
#define AUDIT_ARCH_SHEL64 (EM_SH|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_SPARC (EM_SPARC)
|
||||||
|
#define AUDIT_ARCH_SPARC64 (EM_SPARC64|__AUDIT_ARCH_64BIT)
|
||||||
|
#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE)
|
||||||
|
#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
#ifndef __KERNEL__
|
||||||
struct audit_message {
|
struct audit_message {
|
||||||
struct nlmsghdr nlh;
|
struct nlmsghdr nlh;
|
||||||
|
@ -129,32 +165,36 @@ struct audit_buffer;
|
||||||
struct audit_context;
|
struct audit_context;
|
||||||
struct inode;
|
struct inode;
|
||||||
|
|
||||||
|
#define AUDITSC_INVALID 0
|
||||||
|
#define AUDITSC_SUCCESS 1
|
||||||
|
#define AUDITSC_FAILURE 2
|
||||||
|
#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
|
||||||
#ifdef CONFIG_AUDITSYSCALL
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
/* These are defined in auditsc.c */
|
/* These are defined in auditsc.c */
|
||||||
/* Public API */
|
/* Public API */
|
||||||
extern int audit_alloc(struct task_struct *task);
|
extern int audit_alloc(struct task_struct *task);
|
||||||
extern void audit_free(struct task_struct *task);
|
extern void audit_free(struct task_struct *task);
|
||||||
extern void audit_syscall_entry(struct task_struct *task,
|
extern void audit_syscall_entry(struct task_struct *task, int arch,
|
||||||
int major, unsigned long a0, unsigned long a1,
|
int major, unsigned long a0, unsigned long a1,
|
||||||
unsigned long a2, unsigned long a3);
|
unsigned long a2, unsigned long a3);
|
||||||
extern void audit_syscall_exit(struct task_struct *task, int return_code);
|
extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
|
||||||
extern void audit_getname(const char *name);
|
extern void audit_getname(const char *name);
|
||||||
extern void audit_putname(const char *name);
|
extern void audit_putname(const char *name);
|
||||||
extern void audit_inode(const char *name, const struct inode *inode);
|
extern void audit_inode(const char *name, const struct inode *inode);
|
||||||
|
|
||||||
/* Private API (for audit.c only) */
|
/* Private API (for audit.c only) */
|
||||||
extern int audit_receive_filter(int type, int pid, int uid, int seq,
|
extern int audit_receive_filter(int type, int pid, int uid, int seq,
|
||||||
void *data);
|
void *data, uid_t loginuid);
|
||||||
extern void audit_get_stamp(struct audit_context *ctx,
|
extern void audit_get_stamp(struct audit_context *ctx,
|
||||||
struct timespec *t, int *serial);
|
struct timespec *t, unsigned int *serial);
|
||||||
extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
|
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
|
||||||
extern uid_t audit_get_loginuid(struct audit_context *ctx);
|
extern uid_t audit_get_loginuid(struct audit_context *ctx);
|
||||||
extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
|
extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
|
||||||
#else
|
#else
|
||||||
#define audit_alloc(t) ({ 0; })
|
#define audit_alloc(t) ({ 0; })
|
||||||
#define audit_free(t) do { ; } while (0)
|
#define audit_free(t) do { ; } while (0)
|
||||||
#define audit_syscall_entry(t,a,b,c,d,e) do { ; } while (0)
|
#define audit_syscall_entry(t,ta,a,b,c,d,e) do { ; } while (0)
|
||||||
#define audit_syscall_exit(t,r) do { ; } while (0)
|
#define audit_syscall_exit(t,f,r) do { ; } while (0)
|
||||||
#define audit_getname(n) do { ; } while (0)
|
#define audit_getname(n) do { ; } while (0)
|
||||||
#define audit_putname(n) do { ; } while (0)
|
#define audit_putname(n) do { ; } while (0)
|
||||||
#define audit_inode(n,i) do { ; } while (0)
|
#define audit_inode(n,i) do { ; } while (0)
|
||||||
|
@ -174,11 +214,15 @@ extern void audit_log_format(struct audit_buffer *ab,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
__attribute__((format(printf,2,3)));
|
__attribute__((format(printf,2,3)));
|
||||||
extern void audit_log_end(struct audit_buffer *ab);
|
extern void audit_log_end(struct audit_buffer *ab);
|
||||||
|
extern void audit_log_hex(struct audit_buffer *ab,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len);
|
||||||
|
extern void audit_log_untrustedstring(struct audit_buffer *ab,
|
||||||
|
const char *string);
|
||||||
extern void audit_log_d_path(struct audit_buffer *ab,
|
extern void audit_log_d_path(struct audit_buffer *ab,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
struct vfsmount *vfsmnt);
|
struct vfsmount *vfsmnt);
|
||||||
|
|
||||||
/* Private API (for auditsc.c only) */
|
/* Private API (for auditsc.c only) */
|
||||||
extern void audit_send_reply(int pid, int seq, int type,
|
extern void audit_send_reply(int pid, int seq, int type,
|
||||||
int done, int multi,
|
int done, int multi,
|
||||||
|
@ -190,6 +234,8 @@ extern void audit_log_lost(const char *message);
|
||||||
#define audit_log_vformat(b,f,a) do { ; } while (0)
|
#define audit_log_vformat(b,f,a) do { ; } while (0)
|
||||||
#define audit_log_format(b,f,...) do { ; } while (0)
|
#define audit_log_format(b,f,...) do { ; } while (0)
|
||||||
#define audit_log_end(b) do { ; } while (0)
|
#define audit_log_end(b) do { ; } while (0)
|
||||||
|
#define audit_log_hex(a,b,l) do { ; } while (0)
|
||||||
|
#define audit_log_untrustedstring(a,s) do { ; } while (0)
|
||||||
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
|
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -110,6 +110,7 @@ struct netlink_skb_parms
|
||||||
__u32 dst_pid;
|
__u32 dst_pid;
|
||||||
__u32 dst_groups;
|
__u32 dst_groups;
|
||||||
kernel_cap_t eff_cap;
|
kernel_cap_t eff_cap;
|
||||||
|
__u32 loginuid; /* Login (audit) uid */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
|
#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
|
||||||
|
|
|
@ -173,7 +173,7 @@ config AUDIT
|
||||||
|
|
||||||
config AUDITSYSCALL
|
config AUDITSYSCALL
|
||||||
bool "Enable system-call auditing support"
|
bool "Enable system-call auditing support"
|
||||||
depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64)
|
depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64 || UML)
|
||||||
default y if SECURITY_SELINUX
|
default y if SECURITY_SELINUX
|
||||||
help
|
help
|
||||||
Enable low-overhead system-call auditing infrastructure that
|
Enable low-overhead system-call auditing infrastructure that
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* audit.c -- Auditing support -*- linux-c -*-
|
/* audit.c -- Auditing support
|
||||||
* Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
|
* Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
|
||||||
* System-call specific features have moved to auditsc.c
|
* System-call specific features have moved to auditsc.c
|
||||||
*
|
*
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
* 6) Support low-overhead kernel-based filtering to minimize the
|
* 6) Support low-overhead kernel-based filtering to minimize the
|
||||||
* information that must be passed to user-space.
|
* information that must be passed to user-space.
|
||||||
*
|
*
|
||||||
* Example user-space utilities: http://people.redhat.com/faith/audit/
|
* Example user-space utilities: http://people.redhat.com/sgrubb/audit/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -142,7 +142,6 @@ struct audit_buffer {
|
||||||
int total;
|
int total;
|
||||||
int type;
|
int type;
|
||||||
int pid;
|
int pid;
|
||||||
int count; /* Times requeued */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void audit_set_type(struct audit_buffer *ab, int type)
|
void audit_set_type(struct audit_buffer *ab, int type)
|
||||||
|
@ -239,36 +238,36 @@ void audit_log_lost(const char *message)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audit_set_rate_limit(int limit)
|
static int audit_set_rate_limit(int limit, uid_t loginuid)
|
||||||
{
|
{
|
||||||
int old = audit_rate_limit;
|
int old = audit_rate_limit;
|
||||||
audit_rate_limit = limit;
|
audit_rate_limit = limit;
|
||||||
audit_log(current->audit_context, "audit_rate_limit=%d old=%d",
|
audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
|
||||||
audit_rate_limit, old);
|
audit_rate_limit, old, loginuid);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audit_set_backlog_limit(int limit)
|
static int audit_set_backlog_limit(int limit, uid_t loginuid)
|
||||||
{
|
{
|
||||||
int old = audit_backlog_limit;
|
int old = audit_backlog_limit;
|
||||||
audit_backlog_limit = limit;
|
audit_backlog_limit = limit;
|
||||||
audit_log(current->audit_context, "audit_backlog_limit=%d old=%d",
|
audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
|
||||||
audit_backlog_limit, old);
|
audit_backlog_limit, old, loginuid);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audit_set_enabled(int state)
|
static int audit_set_enabled(int state, uid_t loginuid)
|
||||||
{
|
{
|
||||||
int old = audit_enabled;
|
int old = audit_enabled;
|
||||||
if (state != 0 && state != 1)
|
if (state != 0 && state != 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
audit_enabled = state;
|
audit_enabled = state;
|
||||||
audit_log(current->audit_context, "audit_enabled=%d old=%d",
|
audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
|
||||||
audit_enabled, old);
|
audit_enabled, old, loginuid);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audit_set_failure(int state)
|
static int audit_set_failure(int state, uid_t loginuid)
|
||||||
{
|
{
|
||||||
int old = audit_failure;
|
int old = audit_failure;
|
||||||
if (state != AUDIT_FAIL_SILENT
|
if (state != AUDIT_FAIL_SILENT
|
||||||
|
@ -276,8 +275,8 @@ static int audit_set_failure(int state)
|
||||||
&& state != AUDIT_FAIL_PANIC)
|
&& state != AUDIT_FAIL_PANIC)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
audit_failure = state;
|
audit_failure = state;
|
||||||
audit_log(current->audit_context, "audit_failure=%d old=%d",
|
audit_log(NULL, "audit_failure=%d old=%d by auid %u",
|
||||||
audit_failure, old);
|
audit_failure, old, loginuid);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +343,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||||
int err;
|
int err;
|
||||||
struct audit_buffer *ab;
|
struct audit_buffer *ab;
|
||||||
u16 msg_type = nlh->nlmsg_type;
|
u16 msg_type = nlh->nlmsg_type;
|
||||||
|
uid_t loginuid; /* loginuid of sender */
|
||||||
|
|
||||||
err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
|
err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -351,6 +351,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||||
|
|
||||||
pid = NETLINK_CREDS(skb)->pid;
|
pid = NETLINK_CREDS(skb)->pid;
|
||||||
uid = NETLINK_CREDS(skb)->uid;
|
uid = NETLINK_CREDS(skb)->uid;
|
||||||
|
loginuid = NETLINK_CB(skb).loginuid;
|
||||||
seq = nlh->nlmsg_seq;
|
seq = nlh->nlmsg_seq;
|
||||||
data = NLMSG_DATA(nlh);
|
data = NLMSG_DATA(nlh);
|
||||||
|
|
||||||
|
@ -371,34 +372,36 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
status_get = (struct audit_status *)data;
|
status_get = (struct audit_status *)data;
|
||||||
if (status_get->mask & AUDIT_STATUS_ENABLED) {
|
if (status_get->mask & AUDIT_STATUS_ENABLED) {
|
||||||
err = audit_set_enabled(status_get->enabled);
|
err = audit_set_enabled(status_get->enabled, loginuid);
|
||||||
if (err < 0) return err;
|
if (err < 0) return err;
|
||||||
}
|
}
|
||||||
if (status_get->mask & AUDIT_STATUS_FAILURE) {
|
if (status_get->mask & AUDIT_STATUS_FAILURE) {
|
||||||
err = audit_set_failure(status_get->failure);
|
err = audit_set_failure(status_get->failure, loginuid);
|
||||||
if (err < 0) return err;
|
if (err < 0) return err;
|
||||||
}
|
}
|
||||||
if (status_get->mask & AUDIT_STATUS_PID) {
|
if (status_get->mask & AUDIT_STATUS_PID) {
|
||||||
int old = audit_pid;
|
int old = audit_pid;
|
||||||
audit_pid = status_get->pid;
|
audit_pid = status_get->pid;
|
||||||
audit_log(current->audit_context,
|
audit_log(NULL, "audit_pid=%d old=%d by auid %u",
|
||||||
"audit_pid=%d old=%d", audit_pid, old);
|
audit_pid, old, loginuid);
|
||||||
}
|
}
|
||||||
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
|
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
|
||||||
audit_set_rate_limit(status_get->rate_limit);
|
audit_set_rate_limit(status_get->rate_limit, loginuid);
|
||||||
if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
|
if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
|
||||||
audit_set_backlog_limit(status_get->backlog_limit);
|
audit_set_backlog_limit(status_get->backlog_limit,
|
||||||
|
loginuid);
|
||||||
break;
|
break;
|
||||||
case AUDIT_USER:
|
case AUDIT_USER:
|
||||||
ab = audit_log_start(NULL);
|
ab = audit_log_start(NULL);
|
||||||
if (!ab)
|
if (!ab)
|
||||||
break; /* audit_panic has been called */
|
break; /* audit_panic has been called */
|
||||||
audit_log_format(ab,
|
audit_log_format(ab,
|
||||||
"user pid=%d uid=%d length=%d msg='%.1024s'",
|
"user pid=%d uid=%d length=%d loginuid=%u"
|
||||||
|
" msg='%.1024s'",
|
||||||
pid, uid,
|
pid, uid,
|
||||||
(int)(nlh->nlmsg_len
|
(int)(nlh->nlmsg_len
|
||||||
- ((char *)data - (char *)nlh)),
|
- ((char *)data - (char *)nlh)),
|
||||||
(char *)data);
|
loginuid, (char *)data);
|
||||||
ab->type = AUDIT_USER;
|
ab->type = AUDIT_USER;
|
||||||
ab->pid = pid;
|
ab->pid = pid;
|
||||||
audit_log_end(ab);
|
audit_log_end(ab);
|
||||||
|
@ -411,7 +414,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||||
case AUDIT_LIST:
|
case AUDIT_LIST:
|
||||||
#ifdef CONFIG_AUDITSYSCALL
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
|
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
|
||||||
uid, seq, data);
|
uid, seq, data, loginuid);
|
||||||
#else
|
#else
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
|
@ -480,7 +483,7 @@ static void audit_log_move(struct audit_buffer *ab)
|
||||||
if (ab->len == 0)
|
if (ab->len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
skb = skb_peek(&ab->sklist);
|
skb = skb_peek_tail(&ab->sklist);
|
||||||
if (!skb || skb_tailroom(skb) <= ab->len + extra) {
|
if (!skb || skb_tailroom(skb) <= ab->len + extra) {
|
||||||
skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
|
skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
|
@ -519,9 +522,9 @@ static inline int audit_log_drain(struct audit_buffer *ab)
|
||||||
retval = netlink_unicast(audit_sock, skb, audit_pid,
|
retval = netlink_unicast(audit_sock, skb, audit_pid,
|
||||||
MSG_DONTWAIT);
|
MSG_DONTWAIT);
|
||||||
}
|
}
|
||||||
if (retval == -EAGAIN && ab->count < 5) {
|
if (retval == -EAGAIN &&
|
||||||
++ab->count;
|
(atomic_read(&audit_backlog)) < audit_backlog_limit) {
|
||||||
skb_queue_tail(&ab->sklist, skb);
|
skb_queue_head(&ab->sklist, skb);
|
||||||
audit_log_end_irq(ab);
|
audit_log_end_irq(ab);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -537,8 +540,8 @@ static inline int audit_log_drain(struct audit_buffer *ab)
|
||||||
if (!audit_pid) { /* No daemon */
|
if (!audit_pid) { /* No daemon */
|
||||||
int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
|
int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
|
||||||
int len = skb->len - offset;
|
int len = skb->len - offset;
|
||||||
printk(KERN_ERR "%*.*s\n",
|
skb->data[offset + len] = '\0';
|
||||||
len, len, skb->data + offset);
|
printk(KERN_ERR "%s\n", skb->data + offset);
|
||||||
}
|
}
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
ab->nlh = NULL;
|
ab->nlh = NULL;
|
||||||
|
@ -617,7 +620,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx)
|
||||||
struct audit_buffer *ab = NULL;
|
struct audit_buffer *ab = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct timespec t;
|
struct timespec t;
|
||||||
int serial = 0;
|
unsigned int serial;
|
||||||
|
|
||||||
if (!audit_initialized)
|
if (!audit_initialized)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -659,15 +662,16 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx)
|
||||||
ab->total = 0;
|
ab->total = 0;
|
||||||
ab->type = AUDIT_KERNEL;
|
ab->type = AUDIT_KERNEL;
|
||||||
ab->pid = 0;
|
ab->pid = 0;
|
||||||
ab->count = 0;
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDITSYSCALL
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
if (ab->ctx)
|
if (ab->ctx)
|
||||||
audit_get_stamp(ab->ctx, &t, &serial);
|
audit_get_stamp(ab->ctx, &t, &serial);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
t = CURRENT_TIME;
|
t = CURRENT_TIME;
|
||||||
|
serial = 0;
|
||||||
|
}
|
||||||
audit_log_format(ab, "audit(%lu.%03lu:%u): ",
|
audit_log_format(ab, "audit(%lu.%03lu:%u): ",
|
||||||
t.tv_sec, t.tv_nsec/1000000, serial);
|
t.tv_sec, t.tv_nsec/1000000, serial);
|
||||||
return ab;
|
return ab;
|
||||||
|
@ -717,6 +721,29 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<len; i++)
|
||||||
|
audit_log_format(ab, "%02x", buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
|
||||||
|
{
|
||||||
|
const unsigned char *p = string;
|
||||||
|
|
||||||
|
while (*p) {
|
||||||
|
if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) {
|
||||||
|
audit_log_hex(ab, string, strlen(string));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
audit_log_format(ab, "\"%s\"", string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is a helper-function to print the d_path without using a static
|
/* This is a helper-function to print the d_path without using a static
|
||||||
* buffer or allocating another buffer in addition to the one in
|
* buffer or allocating another buffer in addition to the one in
|
||||||
* audit_buffer. */
|
* audit_buffer. */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* auditsc.c -- System-call auditing support -*- linux-c -*-
|
/* auditsc.c -- System-call auditing support
|
||||||
* Handles all system-call specific auditing features.
|
* Handles all system-call specific auditing features.
|
||||||
*
|
*
|
||||||
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
|
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
|
||||||
|
@ -123,7 +123,7 @@ struct audit_context {
|
||||||
int major; /* syscall number */
|
int major; /* syscall number */
|
||||||
unsigned long argv[4]; /* syscall arguments */
|
unsigned long argv[4]; /* syscall arguments */
|
||||||
int return_valid; /* return code is valid */
|
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 auditable; /* 1 if record should be written */
|
||||||
int name_count;
|
int name_count;
|
||||||
struct audit_names names[AUDIT_NAMES];
|
struct audit_names names[AUDIT_NAMES];
|
||||||
|
@ -135,6 +135,7 @@ struct audit_context {
|
||||||
uid_t uid, euid, suid, fsuid;
|
uid_t uid, euid, suid, fsuid;
|
||||||
gid_t gid, egid, sgid, fsgid;
|
gid_t gid, egid, sgid, fsgid;
|
||||||
unsigned long personality;
|
unsigned long personality;
|
||||||
|
int arch;
|
||||||
|
|
||||||
#if AUDIT_DEBUG
|
#if AUDIT_DEBUG
|
||||||
int put_count;
|
int put_count;
|
||||||
|
@ -250,7 +251,8 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
|
int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||||
|
uid_t loginuid)
|
||||||
{
|
{
|
||||||
u32 flags;
|
u32 flags;
|
||||||
struct audit_entry *entry;
|
struct audit_entry *entry;
|
||||||
|
@ -285,6 +287,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
|
||||||
err = audit_add_rule(entry, &audit_entlist);
|
err = audit_add_rule(entry, &audit_entlist);
|
||||||
if (!err && (flags & AUDIT_AT_EXIT))
|
if (!err && (flags & AUDIT_AT_EXIT))
|
||||||
err = audit_add_rule(entry, &audit_extlist);
|
err = audit_add_rule(entry, &audit_extlist);
|
||||||
|
audit_log(NULL, "auid %u added an audit rule\n", loginuid);
|
||||||
break;
|
break;
|
||||||
case AUDIT_DEL:
|
case AUDIT_DEL:
|
||||||
flags =((struct audit_rule *)data)->flags;
|
flags =((struct audit_rule *)data)->flags;
|
||||||
|
@ -294,6 +297,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
|
||||||
err = audit_del_rule(data, &audit_entlist);
|
err = audit_del_rule(data, &audit_entlist);
|
||||||
if (!err && (flags & AUDIT_AT_EXIT))
|
if (!err && (flags & AUDIT_AT_EXIT))
|
||||||
err = audit_del_rule(data, &audit_extlist);
|
err = audit_del_rule(data, &audit_extlist);
|
||||||
|
audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -348,6 +352,10 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||||
case AUDIT_PERS:
|
case AUDIT_PERS:
|
||||||
result = (tsk->personality == value);
|
result = (tsk->personality == value);
|
||||||
break;
|
break;
|
||||||
|
case AUDIT_ARCH:
|
||||||
|
if (ctx)
|
||||||
|
result = (ctx->arch == value);
|
||||||
|
break;
|
||||||
|
|
||||||
case AUDIT_EXIT:
|
case AUDIT_EXIT:
|
||||||
if (ctx && ctx->return_valid)
|
if (ctx && ctx->return_valid)
|
||||||
|
@ -355,7 +363,7 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUCCESS:
|
case AUDIT_SUCCESS:
|
||||||
if (ctx && ctx->return_valid)
|
if (ctx && ctx->return_valid)
|
||||||
result = (ctx->return_code >= 0);
|
result = (ctx->return_valid == AUDITSC_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case AUDIT_DEVMAJOR:
|
case AUDIT_DEVMAJOR:
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
@ -648,8 +656,11 @@ static void audit_log_exit(struct audit_context *context)
|
||||||
audit_log_format(ab, "syscall=%d", context->major);
|
audit_log_format(ab, "syscall=%d", context->major);
|
||||||
if (context->personality != PER_LINUX)
|
if (context->personality != PER_LINUX)
|
||||||
audit_log_format(ab, " per=%lx", context->personality);
|
audit_log_format(ab, " per=%lx", context->personality);
|
||||||
|
audit_log_format(ab, " arch=%x", context->arch);
|
||||||
if (context->return_valid)
|
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,
|
audit_log_format(ab,
|
||||||
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
|
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
|
||||||
" pid=%d loginuid=%d uid=%d gid=%d"
|
" pid=%d loginuid=%d uid=%d gid=%d"
|
||||||
|
@ -696,9 +707,10 @@ static void audit_log_exit(struct audit_context *context)
|
||||||
if (!ab)
|
if (!ab)
|
||||||
continue; /* audit_panic has been called */
|
continue; /* audit_panic has been called */
|
||||||
audit_log_format(ab, "item=%d", i);
|
audit_log_format(ab, "item=%d", i);
|
||||||
if (context->names[i].name)
|
if (context->names[i].name) {
|
||||||
audit_log_format(ab, " name=%s",
|
audit_log_format(ab, " name=");
|
||||||
context->names[i].name);
|
audit_log_untrustedstring(ab, context->names[i].name);
|
||||||
|
}
|
||||||
if (context->names[i].ino != (unsigned long)-1)
|
if (context->names[i].ino != (unsigned long)-1)
|
||||||
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
|
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
|
||||||
" uid=%d gid=%d rdev=%02x:%02x",
|
" uid=%d gid=%d rdev=%02x:%02x",
|
||||||
|
@ -772,7 +784,7 @@ static inline unsigned int audit_serial(void)
|
||||||
* then the record will be written at syscall exit time (otherwise, it
|
* 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
|
* will only be written if another part of the kernel requests that it
|
||||||
* be written). */
|
* 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 a1, unsigned long a2,
|
||||||
unsigned long a3, unsigned long a4)
|
unsigned long a3, unsigned long a4)
|
||||||
{
|
{
|
||||||
|
@ -826,6 +838,7 @@ void audit_syscall_entry(struct task_struct *tsk, int major,
|
||||||
if (!audit_enabled)
|
if (!audit_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
context->arch = arch;
|
||||||
context->major = major;
|
context->major = major;
|
||||||
context->argv[0] = a1;
|
context->argv[0] = a1;
|
||||||
context->argv[1] = a2;
|
context->argv[1] = a2;
|
||||||
|
@ -849,13 +862,13 @@ void audit_syscall_entry(struct task_struct *tsk, int major,
|
||||||
* filtering, or because some other part of the kernel write an audit
|
* filtering, or because some other part of the kernel write an audit
|
||||||
* message), then write out the syscall information. In call cases,
|
* message), then write out the syscall information. In call cases,
|
||||||
* free the names stored from getname(). */
|
* 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;
|
struct audit_context *context;
|
||||||
|
|
||||||
get_task_struct(tsk);
|
get_task_struct(tsk);
|
||||||
task_lock(tsk);
|
task_lock(tsk);
|
||||||
context = audit_get_context(tsk, 1, return_code);
|
context = audit_get_context(tsk, valid, return_code);
|
||||||
task_unlock(tsk);
|
task_unlock(tsk);
|
||||||
|
|
||||||
/* Not having a context here is ok, since the parent may have
|
/* Not having a context here is ok, since the parent may have
|
||||||
|
@ -868,6 +881,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code)
|
||||||
|
|
||||||
context->in_syscall = 0;
|
context->in_syscall = 0;
|
||||||
context->auditable = 0;
|
context->auditable = 0;
|
||||||
|
|
||||||
if (context->previous) {
|
if (context->previous) {
|
||||||
struct audit_context *new_context = context->previous;
|
struct audit_context *new_context = context->previous;
|
||||||
context->previous = NULL;
|
context->previous = NULL;
|
||||||
|
@ -981,7 +995,7 @@ void audit_inode(const char *name, const struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
void audit_get_stamp(struct audit_context *ctx,
|
void audit_get_stamp(struct audit_context *ctx,
|
||||||
struct timespec *t, int *serial)
|
struct timespec *t, unsigned int *serial)
|
||||||
{
|
{
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
t->tv_sec = ctx->ctime.tv_sec;
|
t->tv_sec = ctx->ctime.tv_sec;
|
||||||
|
@ -996,20 +1010,21 @@ void audit_get_stamp(struct audit_context *ctx,
|
||||||
|
|
||||||
extern int audit_set_type(struct audit_buffer *ab, int type);
|
extern int audit_set_type(struct audit_buffer *ab, int type);
|
||||||
|
|
||||||
int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid)
|
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
|
||||||
{
|
{
|
||||||
if (ctx) {
|
if (task->audit_context) {
|
||||||
struct audit_buffer *ab;
|
struct audit_buffer *ab;
|
||||||
|
|
||||||
ab = audit_log_start(NULL);
|
ab = audit_log_start(NULL);
|
||||||
if (ab) {
|
if (ab) {
|
||||||
audit_log_format(ab, "login pid=%d uid=%u "
|
audit_log_format(ab, "login pid=%d uid=%u "
|
||||||
"old loginuid=%u new loginuid=%u",
|
"old loginuid=%u new loginuid=%u",
|
||||||
ctx->pid, ctx->uid, ctx->loginuid, loginuid);
|
task->pid, task->uid,
|
||||||
|
task->audit_context->loginuid, loginuid);
|
||||||
audit_set_type(ab, AUDIT_LOGIN);
|
audit_set_type(ab, AUDIT_LOGIN);
|
||||||
audit_log_end(ab);
|
audit_log_end(ab);
|
||||||
}
|
}
|
||||||
ctx->loginuid = loginuid;
|
task->audit_context->loginuid = loginuid;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/audit.h>
|
||||||
|
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
#include <net/scm.h>
|
#include <net/scm.h>
|
||||||
|
|
||||||
|
@ -904,6 +906,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||||
NETLINK_CB(skb).groups = nlk->groups;
|
NETLINK_CB(skb).groups = nlk->groups;
|
||||||
NETLINK_CB(skb).dst_pid = dst_pid;
|
NETLINK_CB(skb).dst_pid = dst_pid;
|
||||||
NETLINK_CB(skb).dst_groups = dst_groups;
|
NETLINK_CB(skb).dst_groups = dst_groups;
|
||||||
|
NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
|
||||||
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
|
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
|
||||||
|
|
||||||
/* What can I do? Netlink is asynchronous, so that
|
/* What can I do? Netlink is asynchronous, so that
|
||||||
|
|
Loading…
Reference in a new issue