Commit 0b747172 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.infradead.org/users/eparis/audit

Pull audit updates from Eric Paris.

* git://git.infradead.org/users/eparis/audit: (28 commits)
  AUDIT: make audit_is_compat depend on CONFIG_AUDIT_COMPAT_GENERIC
  audit: renumber AUDIT_FEATURE_CHANGE into the 1300 range
  audit: do not cast audit_rule_data pointers pointlesly
  AUDIT: Allow login in non-init namespaces
  audit: define audit_is_compat in kernel internal header
  kernel: Use RCU_INIT_POINTER(x, NULL) in audit.c
  sched: declare pid_alive as inline
  audit: use uapi/linux/audit.h for AUDIT_ARCH declarations
  syscall_get_arch: remove useless function arguments
  audit: remove stray newline from audit_log_execve_info() audit_panic() call
  audit: remove stray newlines from audit_log_lost messages
  audit: include subject in login records
  audit: remove superfluous new- prefix in AUDIT_LOGIN messages
  audit: allow user processes to log from another PID namespace
  audit: anchor all pid references in the initial pid namespace
  audit: convert PPIDs to the inital PID namespace.
  pid: get pid_t ppid of task in init_pid_ns
  audit: rename the misleading audit_get_context() to audit_take_context()
  audit: Add generic compat syscall support
  audit: Add CONFIG_HAVE_ARCH_AUDITSYSCALL
  ...
parents b7e70ca9 312103d6
...@@ -22,6 +22,7 @@ config ALPHA ...@@ -22,6 +22,7 @@ config ALPHA
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER select GENERIC_STRNLEN_USER
select HAVE_ARCH_AUDITSYSCALL
select HAVE_MOD_ARCH_SPECIFIC select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select ODD_RT_SIGACTION select ODD_RT_SIGACTION
......
...@@ -24,6 +24,7 @@ config ARM ...@@ -24,6 +24,7 @@ config ARM
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER select GENERIC_STRNLEN_USER
select HARDIRQS_SW_RESEND select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT)
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
select HAVE_ARCH_KGDB select HAVE_ARCH_KGDB
select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#ifndef _ASM_ARM_SYSCALL_H #ifndef _ASM_ARM_SYSCALL_H
#define _ASM_ARM_SYSCALL_H #define _ASM_ARM_SYSCALL_H
#include <linux/audit.h> /* for AUDIT_ARCH_* */ #include <uapi/linux/audit.h> /* for AUDIT_ARCH_* */
#include <linux/elf.h> /* for ELF_EM */ #include <linux/elf.h> /* for ELF_EM */
#include <linux/err.h> #include <linux/err.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -103,8 +103,7 @@ static inline void syscall_set_arguments(struct task_struct *task, ...@@ -103,8 +103,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0])); memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0]));
} }
static inline int syscall_get_arch(struct task_struct *task, static inline int syscall_get_arch(void)
struct pt_regs *regs)
{ {
/* ARM tasks don't change audit architectures on the fly. */ /* ARM tasks don't change audit architectures on the fly. */
return AUDIT_ARCH_ARM; return AUDIT_ARCH_ARM;
......
...@@ -45,6 +45,7 @@ config IA64 ...@@ -45,6 +45,7 @@ config IA64
select HAVE_MOD_ARCH_SPECIFIC select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select ARCH_USE_CMPXCHG_LOCKREF select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_ARCH_AUDITSYSCALL
default y default y
help help
The Itanium Processor Family is Intel's 64-bit successor to The Itanium Processor Family is Intel's 64-bit successor to
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#define __ASM_MIPS_SYSCALL_H #define __ASM_MIPS_SYSCALL_H
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/audit.h> #include <uapi/linux/audit.h>
#include <linux/elf-em.h> #include <linux/elf-em.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -127,12 +127,11 @@ extern const unsigned long sys_call_table[]; ...@@ -127,12 +127,11 @@ extern const unsigned long sys_call_table[];
extern const unsigned long sys32_call_table[]; extern const unsigned long sys32_call_table[];
extern const unsigned long sysn32_call_table[]; extern const unsigned long sysn32_call_table[];
static inline int syscall_get_arch(struct task_struct *task, static inline int syscall_get_arch(void)
struct pt_regs *regs)
{ {
int arch = EM_MIPS; int arch = EM_MIPS;
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) if (!test_thread_flag(TIF_32BIT_REGS))
arch |= __AUDIT_ARCH_64BIT; arch |= __AUDIT_ARCH_64BIT;
#endif #endif
#if defined(__LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN)
......
...@@ -649,7 +649,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) ...@@ -649,7 +649,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_enter(regs, regs->regs[2]); trace_sys_enter(regs, regs->regs[2]);
audit_syscall_entry(syscall_get_arch(current, regs), audit_syscall_entry(syscall_get_arch(),
syscall, syscall,
regs->regs[4], regs->regs[5], regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]); regs->regs[6], regs->regs[7]);
......
...@@ -28,6 +28,7 @@ config PARISC ...@@ -28,6 +28,7 @@ config PARISC
select CLONE_BACKWARDS select CLONE_BACKWARDS
select TTY # Needed for pdc_cons.c select TTY # Needed for pdc_cons.c
select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_STACKOVERFLOW
select HAVE_ARCH_AUDITSYSCALL
help help
The PA-RISC microprocessor is designed by Hewlett-Packard and used The PA-RISC microprocessor is designed by Hewlett-Packard and used
......
...@@ -144,6 +144,7 @@ config PPC ...@@ -144,6 +144,7 @@ config PPC
select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_STACKOVERFLOW
select HAVE_IRQ_EXIT_ON_IRQ_STACK select HAVE_IRQ_EXIT_ON_IRQ_STACK
select ARCH_USE_CMPXCHG_LOCKREF if PPC64 select ARCH_USE_CMPXCHG_LOCKREF if PPC64
select HAVE_ARCH_AUDITSYSCALL
config GENERIC_CSUM config GENERIC_CSUM
def_bool CPU_LITTLE_ENDIAN def_bool CPU_LITTLE_ENDIAN
......
...@@ -103,6 +103,7 @@ config S390 ...@@ -103,6 +103,7 @@ config S390
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL
select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#ifndef _ASM_SYSCALL_H #ifndef _ASM_SYSCALL_H
#define _ASM_SYSCALL_H 1 #define _ASM_SYSCALL_H 1
#include <linux/audit.h> #include <uapi/linux/audit.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/err.h> #include <linux/err.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
...@@ -89,11 +89,10 @@ static inline void syscall_set_arguments(struct task_struct *task, ...@@ -89,11 +89,10 @@ static inline void syscall_set_arguments(struct task_struct *task,
regs->orig_gpr2 = args[0]; regs->orig_gpr2 = args[0];
} }
static inline int syscall_get_arch(struct task_struct *task, static inline int syscall_get_arch(void)
struct pt_regs *regs)
{ {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (test_tsk_thread_flag(task, TIF_31BIT)) if (test_tsk_thread_flag(current, TIF_31BIT))
return AUDIT_ARCH_S390; return AUDIT_ARCH_S390;
#endif #endif
return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390;
......
...@@ -42,6 +42,7 @@ config SUPERH ...@@ -42,6 +42,7 @@ config SUPERH
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select OLD_SIGSUSPEND select OLD_SIGSUSPEND
select OLD_SIGACTION select OLD_SIGACTION
select HAVE_ARCH_AUDITSYSCALL
help help
The SuperH is a RISC processor targeted for use in embedded systems The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast and consumer electronics; it was also used in the Sega Dreamcast
......
...@@ -77,6 +77,7 @@ config SPARC64 ...@@ -77,6 +77,7 @@ config SPARC64
select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_HAVE_NMI_SAFE_CMPXCHG
select HAVE_C_RECORDMCOUNT select HAVE_C_RECORDMCOUNT
select NO_BOOTMEM select NO_BOOTMEM
select HAVE_ARCH_AUDITSYSCALL
config ARCH_DEFCONFIG config ARCH_DEFCONFIG
string string
......
config UML config UML
bool bool
default y default y
select HAVE_ARCH_AUDITSYSCALL
select HAVE_UID16 select HAVE_UID16
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
......
...@@ -129,6 +129,7 @@ config X86 ...@@ -129,6 +129,7 @@ config X86
select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
select HAVE_CC_STACKPROTECTOR select HAVE_CC_STACKPROTECTOR
select GENERIC_CPU_AUTOPROBE select GENERIC_CPU_AUTOPROBE
select HAVE_ARCH_AUDITSYSCALL
config INSTRUCTION_DECODER config INSTRUCTION_DECODER
def_bool y def_bool y
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#ifndef _ASM_X86_SYSCALL_H #ifndef _ASM_X86_SYSCALL_H
#define _ASM_X86_SYSCALL_H #define _ASM_X86_SYSCALL_H
#include <linux/audit.h> #include <uapi/linux/audit.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/err.h> #include <linux/err.h>
#include <asm/asm-offsets.h> /* For NR_syscalls */ #include <asm/asm-offsets.h> /* For NR_syscalls */
...@@ -91,8 +91,7 @@ static inline void syscall_set_arguments(struct task_struct *task, ...@@ -91,8 +91,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
memcpy(&regs->bx + i, args, n * sizeof(args[0])); memcpy(&regs->bx + i, args, n * sizeof(args[0]));
} }
static inline int syscall_get_arch(struct task_struct *task, static inline int syscall_get_arch(void)
struct pt_regs *regs)
{ {
return AUDIT_ARCH_I386; return AUDIT_ARCH_I386;
} }
...@@ -221,8 +220,7 @@ static inline void syscall_set_arguments(struct task_struct *task, ...@@ -221,8 +220,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
} }
} }
static inline int syscall_get_arch(struct task_struct *task, static inline int syscall_get_arch(void)
struct pt_regs *regs)
{ {
#ifdef CONFIG_IA32_EMULATION #ifdef CONFIG_IA32_EMULATION
/* /*
...@@ -234,7 +232,7 @@ static inline int syscall_get_arch(struct task_struct *task, ...@@ -234,7 +232,7 @@ static inline int syscall_get_arch(struct task_struct *task,
* *
* x32 tasks should be considered AUDIT_ARCH_X86_64. * x32 tasks should be considered AUDIT_ARCH_X86_64.
*/ */
if (task_thread_info(task)->status & TS_COMPAT) if (task_thread_info(current)->status & TS_COMPAT)
return AUDIT_ARCH_I386; return AUDIT_ARCH_I386;
#endif #endif
/* Both x32 and x86_64 are considered "64-bit". */ /* Both x32 and x86_64 are considered "64-bit". */
......
...@@ -65,6 +65,7 @@ static void tty_audit_log(const char *description, int major, int minor, ...@@ -65,6 +65,7 @@ static void tty_audit_log(const char *description, int major, int minor,
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
struct task_struct *tsk = current; struct task_struct *tsk = current;
pid_t pid = task_pid_nr(tsk);
uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); uid_t uid = from_kuid(&init_user_ns, task_uid(tsk));
uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));
unsigned int sessionid = audit_get_sessionid(tsk); unsigned int sessionid = audit_get_sessionid(tsk);
...@@ -74,7 +75,7 @@ static void tty_audit_log(const char *description, int major, int minor, ...@@ -74,7 +75,7 @@ static void tty_audit_log(const char *description, int major, int minor,
char name[sizeof(tsk->comm)]; char name[sizeof(tsk->comm)];
audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d"
" minor=%d comm=", description, tsk->pid, uid, " minor=%d comm=", description, pid, uid,
loginuid, sessionid, major, minor); loginuid, sessionid, major, minor);
get_task_comm(name, tsk); get_task_comm(name, tsk);
audit_log_untrustedstring(ab, name); audit_log_untrustedstring(ab, name);
......
...@@ -200,41 +200,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path) ...@@ -200,41 +200,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
return result; return result;
} }
static int proc_pid_cmdline(struct task_struct *task, char * buffer) static int proc_pid_cmdline(struct task_struct *task, char *buffer)
{ {
int res = 0; return get_cmdline(task, buffer, PAGE_SIZE);
unsigned int len;
struct mm_struct *mm = get_task_mm(task);
if (!mm)
goto out;
if (!mm->arg_end)
goto out_mm; /* Shh! No looking before we're done */
len = mm->arg_end - mm->arg_start;
if (len > PAGE_SIZE)
len = PAGE_SIZE;
res = access_process_vm(task, mm->arg_start, buffer, len, 0);
// If the nul at the end of args has been overwritten, then
// assume application is using setproctitle(3).
if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
len = strnlen(buffer, res);
if (len < res) {
res = len;
} else {
len = mm->env_end - mm->env_start;
if (len > PAGE_SIZE - res)
len = PAGE_SIZE - res;
res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
res = strnlen(buffer, res);
}
}
out_mm:
mmput(mm);
out:
return res;
} }
static int proc_pid_auxv(struct task_struct *task, char *buffer) static int proc_pid_auxv(struct task_struct *task, char *buffer)
......
...@@ -144,8 +144,6 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, ...@@ -144,8 +144,6 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
/** /**
* syscall_get_arch - return the AUDIT_ARCH for the current system call * syscall_get_arch - return the AUDIT_ARCH for the current system call
* @task: task of interest, must be in system call entry tracing
* @regs: task_pt_regs() of @task
* *
* Returns the AUDIT_ARCH_* based on the system call convention in use. * Returns the AUDIT_ARCH_* based on the system call convention in use.
* *
...@@ -155,5 +153,5 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, ...@@ -155,5 +153,5 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
* Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must
* provide an implementation of this. * provide an implementation of this.
*/ */
int syscall_get_arch(struct task_struct *task, struct pt_regs *regs); int syscall_get_arch(void);
#endif /* _ASM_SYSCALL_H */ #endif /* _ASM_SYSCALL_H */
...@@ -79,6 +79,14 @@ extern int is_audit_feature_set(int which); ...@@ -79,6 +79,14 @@ extern int is_audit_feature_set(int which);
extern int __init audit_register_class(int class, unsigned *list); extern int __init audit_register_class(int class, unsigned *list);
extern int audit_classify_syscall(int abi, unsigned syscall); extern int audit_classify_syscall(int abi, unsigned syscall);
extern int audit_classify_arch(int arch); extern int audit_classify_arch(int arch);
/* only for compat system calls */
extern unsigned compat_write_class[];
extern unsigned compat_read_class[];
extern unsigned compat_dir_class[];
extern unsigned compat_chattr_class[];
extern unsigned compat_signal_class[];
extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall);
/* audit_names->type values */ /* audit_names->type values */
#define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */
...@@ -94,6 +102,12 @@ struct filename; ...@@ -94,6 +102,12 @@ struct filename;
extern void audit_log_session_info(struct audit_buffer *ab); extern void audit_log_session_info(struct audit_buffer *ab);
#ifdef CONFIG_AUDIT_COMPAT_GENERIC
#define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT))
#else
#define audit_is_compat(arch) false
#endif
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */ /* These are defined in auditsc.c */
/* Public API */ /* Public API */
......
...@@ -1204,6 +1204,7 @@ void account_page_writeback(struct page *page); ...@@ -1204,6 +1204,7 @@ void account_page_writeback(struct page *page);
int set_page_dirty(struct page *page); int set_page_dirty(struct page *page);
int set_page_dirty_lock(struct page *page); int set_page_dirty_lock(struct page *page);
int clear_page_dirty_for_io(struct page *page); int clear_page_dirty_for_io(struct page *page);
int get_cmdline(struct task_struct *task, char *buffer, int buflen);
/* Is the vma a continuation of the stack vma above it? */ /* Is the vma a continuation of the stack vma above it? */
static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
......
...@@ -1719,6 +1719,24 @@ static inline pid_t task_tgid_vnr(struct task_struct *tsk) ...@@ -1719,6 +1719,24 @@ static inline pid_t task_tgid_vnr(struct task_struct *tsk)
} }
static inline int pid_alive(const struct task_struct *p);
static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
{
pid_t pid = 0;
rcu_read_lock();
if (pid_alive(tsk))
pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns);
rcu_read_unlock();
return pid;
}
static inline pid_t task_ppid_nr(const struct task_struct *tsk)
{
return task_ppid_nr_ns(tsk, &init_pid_ns);
}
static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk,
struct pid_namespace *ns) struct pid_namespace *ns)
{ {
...@@ -1758,7 +1776,7 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk) ...@@ -1758,7 +1776,7 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk)
* *
* Return: 1 if the process is alive. 0 otherwise. * Return: 1 if the process is alive. 0 otherwise.
*/ */
static inline int pid_alive(struct task_struct *p) static inline int pid_alive(const struct task_struct *p)
{ {
return p->pids[PIDTYPE_PID].pid != NULL; return p->pids[PIDTYPE_PID].pid != NULL;
} }
......
...@@ -70,7 +70,6 @@ ...@@ -70,7 +70,6 @@
#define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */
#define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */
#define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */
#define AUDIT_FEATURE_CHANGE 1020 /* audit log listing feature changes */
#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */ #define AUDIT_USER_AVC 1107 /* We filter this differently */
...@@ -109,6 +108,8 @@ ...@@ -109,6 +108,8 @@
#define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */
#define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */
#define AUDIT_SECCOMP 1326 /* Secure Computing event */ #define AUDIT_SECCOMP 1326 /* Secure Computing event */
#define AUDIT_PROCTITLE 1327 /* Proctitle emit event */
#define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
......
...@@ -308,8 +308,12 @@ struct vfs_cap_data { ...@@ -308,8 +308,12 @@ struct vfs_cap_data {
#define CAP_LEASE 28 #define CAP_LEASE 28
/* Allow writing the audit log via unicast netlink socket */
#define CAP_AUDIT_WRITE 29 #define CAP_AUDIT_WRITE 29
/* Allow configuration of audit via unicast netlink socket */
#define CAP_AUDIT_CONTROL 30 #define CAP_AUDIT_CONTROL 30
#define CAP_SETFCAP 31 #define CAP_SETFCAP 31
......
...@@ -292,9 +292,12 @@ config AUDIT ...@@ -292,9 +292,12 @@ config AUDIT
logging of avc messages output). Does not do system-call logging of avc messages output). Does not do system-call
auditing without CONFIG_AUDITSYSCALL. auditing without CONFIG_AUDITSYSCALL.
config HAVE_ARCH_AUDITSYSCALL
bool
config AUDITSYSCALL config AUDITSYSCALL
bool "Enable system-call auditing support" bool "Enable system-call auditing support"
depends on AUDIT && (X86 || PARISC || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT) || ALPHA) depends on AUDIT && HAVE_ARCH_AUDITSYSCALL
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
......
...@@ -182,7 +182,7 @@ struct audit_buffer { ...@@ -182,7 +182,7 @@ struct audit_buffer {
struct audit_reply { struct audit_reply {
__u32 portid; __u32 portid;
struct net *net; struct net *net;
struct sk_buff *skb; struct sk_buff *skb;
}; };
...@@ -396,7 +396,7 @@ static void audit_printk_skb(struct sk_buff *skb) ...@@ -396,7 +396,7 @@ static void audit_printk_skb(struct sk_buff *skb)
if (printk_ratelimit()) if (printk_ratelimit())
pr_notice("type=%d %s\n", nlh->nlmsg_type, data); pr_notice("type=%d %s\n", nlh->nlmsg_type, data);
else else
audit_log_lost("printk limit exceeded\n"); audit_log_lost("printk limit exceeded");
} }
audit_hold_skb(skb); audit_hold_skb(skb);
...@@ -412,7 +412,7 @@ static void kauditd_send_skb(struct sk_buff *skb) ...@@ -412,7 +412,7 @@ static void kauditd_send_skb(struct sk_buff *skb)
BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */
if (audit_pid) { if (audit_pid) {
pr_err("*NO* daemon at audit_pid=%d\n", audit_pid); pr_err("*NO* daemon at audit_pid=%d\n", audit_pid);
audit_log_lost("auditd disappeared\n"); audit_log_lost("auditd disappeared");
audit_pid = 0; audit_pid = 0;
audit_sock = NULL; audit_sock = NULL;
} }
...@@ -607,7 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) ...@@ -607,7 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
{ {
int err = 0; int err = 0;
/* Only support the initial namespaces for now. */ /* Only support initial user namespace for now. */
/* /*
* We return ECONNREFUSED because it tricks userspace into thinking * We return ECONNREFUSED because it tricks userspace into thinking
* that audit was not configured into the kernel. Lots of users * that audit was not configured into the kernel. Lots of users
...@@ -618,8 +618,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) ...@@ -618,8 +618,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
* userspace will reject all logins. This should be removed when we * userspace will reject all logins. This should be removed when we
* support non init namespaces!! * support non init namespaces!!
*/ */
if ((current_user_ns() != &init_user_ns) || if (current_user_ns() != &init_user_ns)
(task_active_pid_ns(current) != &init_pid_ns))
return -ECONNREFUSED; return -ECONNREFUSED;
switch (msg_type) { switch (msg_type) {
...@@ -639,6 +638,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) ...@@ -639,6 +638,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
case AUDIT_TTY_SET: case AUDIT_TTY_SET:
case AUDIT_TRIM: case AUDIT_TRIM:
case AUDIT_MAKE_EQUIV: case AUDIT_MAKE_EQUIV:
/* Only support auditd and auditctl in initial pid namespace
* for now. */
if ((task_active_pid_ns(current) != &init_pid_ns))
return -EPERM;
if (!capable(CAP_AUDIT_CONTROL)) if (!capable(CAP_AUDIT_CONTROL))
err = -EPERM; err = -EPERM;
break; break;
...@@ -659,6 +663,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) ...@@ -659,6 +663,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
{ {
int rc = 0; int rc = 0;
uid_t uid = from_kuid(&init_user_ns, current_uid()); uid_t uid = from_kuid(&init_user_ns, current_uid());
pid_t pid = task_tgid_nr(current);
if (!audit_enabled && msg_type != AUDIT_USER_AVC) { if (!audit_enabled && msg_type != AUDIT_USER_AVC) {
*ab = NULL; *ab = NULL;
...@@ -668,7 +673,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) ...@@ -668,7 +673,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
*ab = audit_log_start(NULL, GFP_KERNEL, msg_type); *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
if (unlikely(!*ab)) if (unlikely(!*ab))
return rc; return rc;
audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid); audit_log_format(*ab, "pid=%d uid=%u", pid, uid);
audit_log_session_info(*ab); audit_log_session_info(*ab);
audit_log_task_context(*ab); audit_log_task_context(*ab);
...@@ -1097,7 +1102,7 @@ static void __net_exit audit_net_exit(struct net *net) ...@@ -1097,7 +1102,7 @@ static void __net_exit audit_net_exit(struct net *net)
audit_sock = NULL; audit_sock = NULL;
} }
rcu_assign_pointer(aunet->nlsk, NULL); RCU_INIT_POINTER(aunet->nlsk, NULL);
synchronize_net(); synchronize_net();
netlink_kernel_release(sock); netlink_kernel_release(sock);
} }
...@@ -1829,11 +1834,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) ...@@ -1829,11 +1834,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
spin_unlock_irq(&tsk->sighand->siglock); spin_unlock_irq(&tsk->sighand->siglock);
audit_log_format(ab, audit_log_format(ab,
" ppid=%ld pid=%d auid=%u uid=%u gid=%u" " ppid=%d pid=%d auid=%u uid=%u gid=%u"
" euid=%u suid=%u fsuid=%u" " euid=%u suid=%u fsuid=%u"
" egid=%u sgid=%u fsgid=%u tty=%s ses=%u", " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
sys_getppid(), task_ppid_nr(tsk),
tsk->pid, task_pid_nr(tsk),
from_kuid(&init_user_ns, audit_get_loginuid(tsk)), from_kuid(&init_user_ns, audit_get_loginuid(tsk)),
from_kuid(&init_user_ns, cred->uid), from_kuid(&init_user_ns, cred->uid),
from_kgid(&init_user_ns, cred->gid), from_kgid(&init_user_ns, cred->gid),
......
...@@ -106,6 +106,11 @@ struct audit_names { ...@@ -106,6 +106,11 @@ struct audit_names {
bool should_free; bool should_free;
}; };
struct audit_proctitle {
int len; /* length of the cmdline field. */
char *value; /* the cmdline field */
};
/* The per-task audit context. */ /* The per-task audit context. */
struct audit_context { struct audit_context {
int dummy; /* must be the first element */ int dummy; /* must be the first element */
...@@ -202,6 +207,7 @@ struct audit_context { ...@@ -202,6 +207,7 @@ struct audit_context {
} execve; } execve;
}; };
int fds[2]; int fds[2];
struct audit_proctitle proctitle;
#if AUDIT_DEBUG #if AUDIT_DEBUG
int put_count; int put_count;
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/kthread.h> #include <linux/kthread.h>
...@@ -226,7 +228,7 @@ static int audit_match_signal(struct audit_entry *entry) ...@@ -226,7 +228,7 @@ static int audit_match_signal(struct audit_entry *entry)
#endif #endif
/* Common user-space to kernel rule translation. */ /* Common user-space to kernel rule translation. */
static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *rule)
{ {
unsigned listnr; unsigned listnr;
struct audit_entry *entry; struct audit_entry *entry;
...@@ -249,7 +251,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) ...@@ -249,7 +251,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
; ;
} }
if (unlikely(rule->action == AUDIT_POSSIBLE)) { if (unlikely(rule->action == AUDIT_POSSIBLE)) {
printk(KERN_ERR "AUDIT_POSSIBLE is deprecated\n"); pr_err("AUDIT_POSSIBLE is deprecated\n");
goto exit_err; goto exit_err;
} }
if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS) if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS)
...@@ -403,7 +405,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, ...@@ -403,7 +405,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
int i; int i;
char *str; char *str;
entry = audit_to_entry_common((struct audit_rule *)data); entry = audit_to_entry_common(data);
if (IS_ERR(entry)) if (IS_ERR(entry))
goto exit_nofree; goto exit_nofree;
...@@ -431,6 +433,19 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, ...@@ -431,6 +433,19 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
f->val = 0; f->val = 0;
} }
if ((f->type == AUDIT_PID) || (f->type == AUDIT_PPID)) {
struct pid *pid;
rcu_read_lock();
pid = find_vpid(f->val);
if (!pid) {
rcu_read_unlock();
err = -ESRCH;
goto exit_free;
}
f->val = pid_nr(pid);
rcu_read_unlock();
}
err = audit_field_valid(entry, f); err = audit_field_valid(entry, f);
if (err) if (err)
goto exit_free; goto exit_free;
...@@ -479,8 +494,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, ...@@ -479,8 +494,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
/* Keep currently invalid fields around in case they /* Keep currently invalid fields around in case they
* become valid after a policy reload. */ * become valid after a policy reload. */
if (err == -EINVAL) { if (err == -EINVAL) {
printk(KERN_WARNING "audit rule for LSM " pr_warn("audit rule for LSM \'%s\' is invalid\n",
"\'%s\' is invalid\n", str); str);
err = 0; err = 0;
} }
if (err) { if (err) {
...@@ -709,8 +724,8 @@ static inline int audit_dupe_lsm_field(struct audit_field *df, ...@@ -709,8 +724,8 @@ static inline int audit_dupe_lsm_field(struct audit_field *df,
/* Keep currently invalid fields around in case they /* Keep currently invalid fields around in case they
* become valid after a policy reload. */ * become valid after a policy reload. */
if (ret == -EINVAL) { if (ret == -EINVAL) {
printk(KERN_WARNING "audit rule for LSM \'%s\' is " pr_warn("audit rule for LSM \'%s\' is invalid\n",
"invalid\n", df->lsm_str); df->lsm_str);
ret = 0; ret = 0;
} }
...@@ -1240,12 +1255,14 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type, ...@@ -1240,12 +1255,14 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,
for (i = 0; i < rule->field_count; i++) { for (i = 0; i < rule->field_count; i++) {
struct audit_field *f = &rule->fields[i]; struct audit_field *f = &rule->fields[i];
pid_t pid;
int result = 0; int result = 0;
u32 sid; u32 sid;
switch (f->type) { switch (f->type) {
case AUDIT_PID: case AUDIT_PID:
result = audit_comparator(task_pid_vnr(current), f->op, f->val); pid = task_pid_nr(current);
result = audit_comparator(pid, f->op, f->val);
break; break;
case AUDIT_UID: case AUDIT_UID:
result = audit_uid_comparator(current_uid(), f->op, f->uid); result = audit_uid_comparator(current_uid(), f->op, f->uid);
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
* and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h> #include <linux/init.h>
#include <asm/types.h> #include <asm/types.h>
#include <linux/atomic.h> #include <linux/atomic.h>
...@@ -68,6 +70,7 @@ ...@@ -68,6 +70,7 @@
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/fs_struct.h> #include <linux/fs_struct.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/ctype.h>
#include "audit.h" #include "audit.h"
...@@ -79,6 +82,9 @@ ...@@ -79,6 +82,9 @@
/* no execve audit message should be longer than this (userspace limits) */ /* no execve audit message should be longer than this (userspace limits) */
#define MAX_EXECVE_AUDIT_LEN 7500 #define MAX_EXECVE_AUDIT_LEN 7500
/* max length to print of cmdline/proctitle value during audit */
#define MAX_PROCTITLE_AUDIT_LEN 128
/* number of audit rules */ /* number of audit rules */
int audit_n_rules; int audit_n_rules;
...@@ -451,15 +457,17 @@ static int audit_filter_rules(struct task_struct *tsk, ...@@ -451,15 +457,17 @@ static int audit_filter_rules(struct task_struct *tsk,
struct audit_field *f = &rule->fields[i]; struct audit_field *f = &rule->fields[i];
struct audit_names *n; struct audit_names *n;
int result = 0; int result = 0;
pid_t pid;
switch (f->type) { switch (f->type) {
case AUDIT_PID: case AUDIT_PID:
result = audit_comparator(tsk->pid, f->op, f->val); pid = task_pid_nr(tsk);
result = audit_comparator(pid, f->op, f->val);
break; break;
case AUDIT_PPID: case AUDIT_PPID:
if (ctx) { if (ctx) {
if (!ctx->ppid) if (!ctx->ppid)
ctx->ppid = sys_getppid(); ctx->ppid = task_ppid_nr(tsk);
result = audit_comparator(ctx->ppid, f->op, f->val); result = audit_comparator(ctx->ppid, f->op, f->val);
} }
break; break;
...@@ -805,7 +813,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) ...@@ -805,7 +813,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
rcu_read_unlock(); rcu_read_unlock();
} }
static inline struct audit_context *audit_get_context(struct task_struct *tsk, /* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */
static inline struct audit_context *audit_take_context(struct task_struct *tsk,
int return_valid, int return_valid,
long return_code) long return_code)
{ {
...@@ -842,6 +851,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, ...@@ -842,6 +851,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
return context; return context;
} }
static inline void audit_proctitle_free(struct audit_context *context)
{
kfree(context->proctitle.value);
context->proctitle.value = NULL;
context->proctitle.len = 0;
}
static inline void audit_free_names(struct audit_context *context) static inline void audit_free_names(struct audit_context *context)
{ {
struct audit_names *n, *next; struct audit_names *n, *next;
...@@ -850,16 +866,15 @@ static inline void audit_free_names(struct audit_context *context) ...@@ -850,16 +866,15 @@ static inline void audit_free_names(struct audit_context *context)
if (context->put_count + context->ino_count != context->name_count) { if (context->put_count + context->ino_count != context->name_count) {
int i = 0; int i = 0;
printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" pr_err("%s:%d(:%d): major=%d in_syscall=%d"
" name_count=%d put_count=%d" " name_count=%d put_count=%d ino_count=%d"
" ino_count=%d [NOT freeing]\n", " [NOT freeing]\n", __FILE__, __LINE__,
__FILE__, __LINE__,
context->serial, context->major, context->in_syscall, context->serial, context->major, context->in_syscall,
context->name_count, context->put_count, context->name_count, context->put_count,
context->ino_count); context->ino_count);
list_for_each_entry(n, &context->names_list, list) { list_for_each_entry(n, &context->names_list, list) {
printk(KERN_ERR "names[%d] = %p = %s\n", i++, pr_err("names[%d] = %p = %s\n", i++, n->name,
n->name, n->name->name ?: "(null)"); n->name->name ?: "(null)");
} }
dump_stack(); dump_stack();
return; return;
...@@ -955,6 +970,7 @@ static inline void audit_free_context(struct audit_context *context) ...@@ -955,6 +970,7 @@ static inline void audit_free_context(struct audit_context *context)
audit_free_aux(context); audit_free_aux(context);
kfree(context->filterkey); kfree(context->filterkey);
kfree(context->sockaddr); kfree(context->sockaddr);
audit_proctitle_free(context);
kfree(context); kfree(context);
} }
...@@ -1157,7 +1173,7 @@ static void audit_log_execve_info(struct audit_context *context, ...@@ -1157,7 +1173,7 @@ static void audit_log_execve_info(struct audit_context *context,
*/ */
buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
if (!buf) { if (!buf) {
audit_panic("out of memory for argv string\n"); audit_panic("out of memory for argv string");
return; return;
} }
...@@ -1271,6 +1287,59 @@ static void show_special(struct audit_context *context, int *call_panic) ...@@ -1271,6 +1287,59 @@ static void show_special(struct audit_context *context, int *call_panic)
audit_log_end(ab); audit_log_end(ab);
} }
static inline int audit_proctitle_rtrim(char *proctitle, int len)
{
char *end = proctitle + len - 1;
while (end > proctitle && !isprint(*end))
end--;
/* catch the case where proctitle is only 1 non-print character */
len = end - proctitle + 1;
len -= isprint(proctitle[len-1]) == 0;
return len;
}
static void audit_log_proctitle(struct task_struct *tsk,
struct audit_context *context)
{
int res;
char *buf;
char *msg = "(null)";
int len = strlen(msg);
struct audit_buffer *ab;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
if (!ab)
return; /* audit_panic or being filtered */
audit_log_format(ab, "proctitle=");
/* Not cached */
if (!context->proctitle.value) {
buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
if (!buf)
goto out;
/* Historically called this from procfs naming */
res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN);
if (res == 0) {
kfree(buf);
goto out;
}
res = audit_proctitle_rtrim(buf, res);
if (res == 0) {
kfree(buf);
goto out;
}
context->proctitle.value = buf;
context->proctitle.len = res;
}
msg = context->proctitle.value;
len = context->proctitle.len;
out:
audit_log_n_untrustedstring(ab, msg, len);
audit_log_end(ab);
}
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{ {
int i, call_panic = 0; int i, call_panic = 0;
...@@ -1388,6 +1457,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts ...@@ -1388,6 +1457,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_name(context, n, NULL, i++, &call_panic); audit_log_name(context, n, NULL, i++, &call_panic);
} }
audit_log_proctitle(tsk, context);
/* Send end of event record to help user space know we are finished */ /* Send end of event record to help user space know we are finished */
ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
if (ab) if (ab)
...@@ -1406,7 +1477,7 @@ void __audit_free(struct task_struct *tsk) ...@@ -1406,7 +1477,7 @@ void __audit_free(struct task_struct *tsk)
{ {
struct audit_context *context; struct audit_context *context;
context = audit_get_context(tsk, 0, 0); context = audit_take_context(tsk, 0, 0);
if (!context) if (!context)
return; return;
...@@ -1500,7 +1571,7 @@ void __audit_syscall_exit(int success, long return_code) ...@@ -1500,7 +1571,7 @@ void __audit_syscall_exit(int success, long return_code)
else else
success = AUDITSC_FAILURE; success = AUDITSC_FAILURE;
context = audit_get_context(tsk, success, return_code); context = audit_take_context(tsk, success, return_code);
if (!context) if (!context)
return; return;
...@@ -1550,7 +1621,7 @@ static inline void handle_one(const struct inode *inode) ...@@ -1550,7 +1621,7 @@ static inline void handle_one(const struct inode *inode)
if (likely(put_tree_ref(context, chunk))) if (likely(put_tree_ref(context, chunk)))
return; return;
if (unlikely(!grow_tree_refs(context))) { if (unlikely(!grow_tree_refs(context))) {
printk(KERN_WARNING "out of memory, audit has lost a tree reference\n"); pr_warn("out of memory, audit has lost a tree reference\n");
audit_set_auditable(context); audit_set_auditable(context);
audit_put_chunk(chunk); audit_put_chunk(chunk);
unroll_tree_refs(context, p, count); unroll_tree_refs(context, p, count);
...@@ -1609,8 +1680,7 @@ static void handle_path(const struct dentry *dentry) ...@@ -1609,8 +1680,7 @@ static void handle_path(const struct dentry *dentry)
goto retry; goto retry;
} }
/* too bad */ /* too bad */
printk(KERN_WARNING pr_warn("out of memory, audit has lost a tree reference\n");
"out of memory, audit has lost a tree reference\n");
unroll_tree_refs(context, p, count); unroll_tree_refs(context, p, count);
audit_set_auditable(context); audit_set_auditable(context);
return; return;
...@@ -1682,7 +1752,7 @@ void __audit_getname(struct filename *name) ...@@ -1682,7 +1752,7 @@ void __audit_getname(struct filename *name)
if (!context->in_syscall) { if (!context->in_syscall) {
#if AUDIT_DEBUG == 2 #if AUDIT_DEBUG == 2
printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n", pr_err("%s:%d(:%d): ignoring getname(%p)\n",
__FILE__, __LINE__, context->serial, name); __FILE__, __LINE__, context->serial, name);
dump_stack(); dump_stack();
#endif #endif
...@@ -1721,15 +1791,15 @@ void audit_putname(struct filename *name) ...@@ -1721,15 +1791,15 @@ void audit_putname(struct filename *name)
BUG_ON(!context); BUG_ON(!context);
if (!name->aname || !context->in_syscall) { if (!name->aname || !context->in_syscall) {
#if AUDIT_DEBUG == 2 #if AUDIT_DEBUG == 2
printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", pr_err("%s:%d(:%d): final_putname(%p)\n",
__FILE__, __LINE__, context->serial, name); __FILE__, __LINE__, context->serial, name);
if (context->name_count) { if (context->name_count) {
struct audit_names *n; struct audit_names *n;
int i = 0; int i = 0;
list_for_each_entry(n, &context->names_list, list) list_for_each_entry(n, &context->names_list, list)
printk(KERN_ERR "name[%d] = %p = %s\n", i++, pr_err("name[%d] = %p = %s\n", i++, n->name,
n->name, n->name->name ?: "(null)"); n->name->name ?: "(null)");
} }
#endif #endif
final_putname(name); final_putname(name);
...@@ -1738,9 +1808,8 @@ void audit_putname(struct filename *name) ...@@ -1738,9 +1808,8 @@ void audit_putname(struct filename *name)
else { else {
++context->put_count; ++context->put_count;
if (context->put_count > context->name_count) { if (context->put_count > context->name_count) {
printk(KERN_ERR "%s:%d(:%d): major=%d" pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)"
" in_syscall=%d putname(%p) name_count=%d" " name_count=%d put_count=%d\n",
" put_count=%d\n",
__FILE__, __LINE__, __FILE__, __LINE__,
context->serial, context->major, context->serial, context->major,
context->in_syscall, name->name, context->in_syscall, name->name,
...@@ -1981,12 +2050,10 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, ...@@ -1981,12 +2050,10 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
if (!ab) if (!ab)
return; return;
audit_log_format(ab, "pid=%d uid=%u" audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid);
" old-auid=%u new-auid=%u old-ses=%u new-ses=%u" audit_log_task_context(ab);
" res=%d", audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d",
current->pid, uid, oldloginuid, loginuid, oldsessionid, sessionid, !rc);
oldloginuid, loginuid, oldsessionid, sessionid,
!rc);
audit_log_end(ab); audit_log_end(ab);
} }
...@@ -2208,7 +2275,7 @@ void __audit_ptrace(struct task_struct *t) ...@@ -2208,7 +2275,7 @@ void __audit_ptrace(struct task_struct *t)
{ {
struct audit_context *context = current->audit_context; struct audit_context *context = current->audit_context;
context->target_pid = t->pid; context->target_pid = task_pid_nr(t);
context->target_auid = audit_get_loginuid(t); context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t); context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t); context->target_sessionid = audit_get_sessionid(t);
...@@ -2233,7 +2300,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2233,7 +2300,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
if (audit_pid && t->tgid == audit_pid) { if (audit_pid && t->tgid == audit_pid) {
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
audit_sig_pid = tsk->pid; audit_sig_pid = task_pid_nr(tsk);
if (uid_valid(tsk->loginuid)) if (uid_valid(tsk->loginuid))
audit_sig_uid = tsk->loginuid; audit_sig_uid = tsk->loginuid;
else else
...@@ -2247,7 +2314,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2247,7 +2314,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
/* optimize the common case by putting first signal recipient directly /* optimize the common case by putting first signal recipient directly
* in audit_context */ * in audit_context */
if (!ctx->target_pid) { if (!ctx->target_pid) {
ctx->target_pid = t->tgid; ctx->target_pid = task_tgid_nr(t);
ctx->target_auid = audit_get_loginuid(t); ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid; ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t); ctx->target_sessionid = audit_get_sessionid(t);
...@@ -2268,7 +2335,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2268,7 +2335,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
} }
BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
axp->target_pid[axp->pid_count] = t->tgid; axp->target_pid[axp->pid_count] = task_tgid_nr(t);
axp->target_auid[axp->pid_count] = audit_get_loginuid(t); axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
axp->target_uid[axp->pid_count] = t_uid; axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
...@@ -2368,7 +2435,7 @@ static void audit_log_task(struct audit_buffer *ab) ...@@ -2368,7 +2435,7 @@ static void audit_log_task(struct audit_buffer *ab)
from_kgid(&init_user_ns, gid), from_kgid(&init_user_ns, gid),
sessionid); sessionid);
audit_log_task_context(ab); audit_log_task_context(ab);
audit_log_format(ab, " pid=%d comm=", current->pid); audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
audit_log_untrustedstring(ab, current->comm); audit_log_untrustedstring(ab, current->comm);
if (mm) { if (mm) {
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
......
...@@ -71,7 +71,7 @@ static void populate_seccomp_data(struct seccomp_data *sd) ...@@ -71,7 +71,7 @@ static void populate_seccomp_data(struct seccomp_data *sd)
struct pt_regs *regs = task_pt_regs(task); struct pt_regs *regs = task_pt_regs(task);
sd->nr = syscall_get_nr(task, regs); sd->nr = syscall_get_nr(task, regs);
sd->arch = syscall_get_arch(task, regs); sd->arch = syscall_get_arch();
/* Unroll syscall_get_args to help gcc on arm. */ /* Unroll syscall_get_args to help gcc on arm. */
syscall_get_arguments(task, regs, 0, 1, (unsigned long *) &sd->args[0]); syscall_get_arguments(task, regs, 0, 1, (unsigned long *) &sd->args[0]);
...@@ -348,7 +348,7 @@ static void seccomp_send_sigsys(int syscall, int reason) ...@@ -348,7 +348,7 @@ static void seccomp_send_sigsys(int syscall, int reason)
info.si_code = SYS_SECCOMP; info.si_code = SYS_SECCOMP;
info.si_call_addr = (void __user *)KSTK_EIP(current); info.si_call_addr = (void __user *)KSTK_EIP(current);
info.si_errno = reason; info.si_errno = reason;
info.si_arch = syscall_get_arch(current, task_pt_regs(current)); info.si_arch = syscall_get_arch();
info.si_syscall = syscall; info.si_syscall = syscall;
force_sig_info(SIGSYS, &info, current); force_sig_info(SIGSYS, &info, current);
} }
......
...@@ -182,6 +182,15 @@ config AUDIT_GENERIC ...@@ -182,6 +182,15 @@ config AUDIT_GENERIC
depends on AUDIT && !AUDIT_ARCH depends on AUDIT && !AUDIT_ARCH
default y default y
config AUDIT_ARCH_COMPAT_GENERIC
bool
default n
config AUDIT_COMPAT_GENERIC
bool
depends on AUDIT_GENERIC && AUDIT_ARCH_COMPAT_GENERIC && COMPAT
default y
config RANDOM32_SELFTEST config RANDOM32_SELFTEST
bool "PRNG perform self test on init" bool "PRNG perform self test on init"
default n default n
......
...@@ -96,6 +96,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o ...@@ -96,6 +96,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
obj-$(CONFIG_SMP) += percpu_counter.o obj-$(CONFIG_SMP) += percpu_counter.o
obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_AUDIT_GENERIC) += audit.o
obj-$(CONFIG_AUDIT_COMPAT_GENERIC) += compat_audit.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_SWIOTLB) += swiotlb.o
obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o
......
...@@ -30,11 +30,17 @@ static unsigned signal_class[] = { ...@@ -30,11 +30,17 @@ static unsigned signal_class[] = {
int audit_classify_arch(int arch) int audit_classify_arch(int arch)
{ {
return 0; if (audit_is_compat(arch))
return 1;
else
return 0;
} }
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
if (audit_is_compat(abi))
return audit_classify_compat_syscall(abi, syscall);
switch(syscall) { switch(syscall) {
#ifdef __NR_open #ifdef __NR_open
case __NR_open: case __NR_open:
...@@ -57,6 +63,13 @@ int audit_classify_syscall(int abi, unsigned syscall) ...@@ -57,6 +63,13 @@ int audit_classify_syscall(int abi, unsigned syscall)
static int __init audit_classes_init(void) static int __init audit_classes_init(void)
{ {
#ifdef CONFIG_AUDIT_COMPAT_GENERIC
audit_register_class(AUDIT_CLASS_WRITE_32, compat_write_class);
audit_register_class(AUDIT_CLASS_READ_32, compat_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, compat_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, compat_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, compat_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
......
#include <linux/init.h>
#include <linux/types.h>
#include <asm/unistd32.h>
unsigned compat_dir_class[] = {
#include <asm-generic/audit_dir_write.h>
~0U
};
unsigned compat_read_class[] = {
#include <asm-generic/audit_read.h>
~0U
};
unsigned compat_write_class[] = {
#include <asm-generic/audit_write.h>
~0U
};
unsigned compat_chattr_class[] = {
#include <asm-generic/audit_change_attr.h>
~0U
};
unsigned compat_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_compat_syscall(int abi, unsigned syscall)
{
switch (syscall) {
#ifdef __NR_open
case __NR_open:
return 2;
#endif
#ifdef __NR_openat
case __NR_openat:
return 3;
#endif
#ifdef __NR_socketcall
case __NR_socketcall:
return 4;
#endif
case __NR_execve:
return 5;
default:
return 1;
}
}
...@@ -446,6 +446,54 @@ unsigned long vm_commit_limit(void) ...@@ -446,6 +446,54 @@ unsigned long vm_commit_limit(void)
return allowed; return allowed;
} }
/**
* get_cmdline() - copy the cmdline value to a buffer.
* @task: the task whose cmdline value to copy.
* @buffer: the buffer to copy to.
* @buflen: the length of the buffer. Larger cmdline values are truncated
* to this length.
* Returns the size of the cmdline field copied. Note that the copy does
* not guarantee an ending NULL byte.
*/
int get_cmdline(struct task_struct *task, char *buffer, int buflen)
{
int res = 0;
unsigned int len;
struct mm_struct *mm = get_task_mm(task);
if (!mm)
goto out;
if (!mm->arg_end)
goto out_mm; /* Shh! No looking before we're done */
len = mm->arg_end - mm->arg_start;
if (len > buflen)
len = buflen;
res = access_process_vm(task, mm->arg_start, buffer, len, 0);
/*
* If the nul at the end of args has been overwritten, then
* assume application is using setproctitle(3).
*/
if (res > 0 && buffer[res-1] != '\0' && len < buflen) {
len = strnlen(buffer, res);
if (len < res) {
res = len;
} else {
len = mm->env_end - mm->env_start;
if (len > buflen - res)
len = buflen - res;
res += access_process_vm(task, mm->env_start,
buffer+res, len, 0);
res = strnlen(buffer, res);
}
}
out_mm:
mmput(mm);
out:
return res;
}
/* Tracepoints definitions. */ /* Tracepoints definitions. */
EXPORT_TRACEPOINT_SYMBOL(kmalloc); EXPORT_TRACEPOINT_SYMBOL(kmalloc);
......
...@@ -40,7 +40,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, ...@@ -40,7 +40,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u",
current->pid, task_pid_nr(current),
from_kuid(&init_user_ns, current_cred()->uid), from_kuid(&init_user_ns, current_cred()->uid),
from_kuid(&init_user_ns, audit_get_loginuid(current)), from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current)); audit_get_sessionid(current));
......
...@@ -220,7 +220,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -220,7 +220,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
*/ */
BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
audit_log_format(ab, " pid=%d comm=", tsk->pid); audit_log_format(ab, " pid=%d comm=", task_pid_nr(tsk));
audit_log_untrustedstring(ab, tsk->comm); audit_log_untrustedstring(ab, tsk->comm);
switch (a->type) { switch (a->type) {
...@@ -278,9 +278,12 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -278,9 +278,12 @@ static void dump_common_audit_data(struct audit_buffer *ab,
} }
case LSM_AUDIT_DATA_TASK: case LSM_AUDIT_DATA_TASK:
tsk = a->u.tsk; tsk = a->u.tsk;
if (tsk && tsk->pid) { if (tsk) {
audit_log_format(ab, " pid=%d comm=", tsk->pid); pid_t pid = task_pid_nr(tsk);
audit_log_untrustedstring(ab, tsk->comm); if (pid) {
audit_log_format(ab, " pid=%d comm=", pid);
audit_log_untrustedstring(ab, tsk->comm);
}
} }
break; break;
case LSM_AUDIT_DATA_NET: case LSM_AUDIT_DATA_NET:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment