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 ...
Unified · Split
| @@ -22,6 +22,7 @@ config ALPHA · 21 unmodified lines | ||
| 22 | 22 | select GENERIC_SMP_IDLE_THREAD |
| 23 | 23 | select GENERIC_STRNCPY_FROM_USER |
| 24 | 24 | select GENERIC_STRNLEN_USER |
| 25 | + select HAVE_ARCH_AUDITSYSCALL | |
| 25 | 26 | select HAVE_MOD_ARCH_SPECIFIC |
| 26 | 27 | select MODULES_USE_ELF_RELA |
| 27 | 28 | select ODD_RT_SIGACTION |
| @@ -24,6 +24,7 @@ config ARM · 23 unmodified lines | ||
| 24 | 24 | select GENERIC_STRNCPY_FROM_USER |
| 25 | 25 | select GENERIC_STRNLEN_USER |
| 26 | 26 | select HARDIRQS_SW_RESEND |
| 27 | + select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) | |
| 27 | 28 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL |
| 28 | 29 | select HAVE_ARCH_KGDB |
| 29 | 30 | select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #ifndef _ASM_ARM_SYSCALL_H |
| 8 | 8 | #define _ASM_ARM_SYSCALL_H |
| 9 | 9 | |
| 10 | −#include <linux/audit.h> /* for AUDIT_ARCH_* */ | |
| 10 | +#include <uapi/linux/audit.h> /* for AUDIT_ARCH_* */ | |
| 11 | 11 | #include <linux/elf.h> /* for ELF_EM */ |
| 12 | 12 | #include <linux/err.h> |
| 13 | 13 | #include <linux/sched.h> |
| @@ -103,8 +103,7 @@ static inline void syscall_set_arguments(struct task_struct *task, · 89 unmodified lines | ||
| 103 | 103 | memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0])); |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | −static inline int syscall_get_arch(struct task_struct *task, | |
| 107 | − struct pt_regs *regs) | |
| 106 | +static inline int syscall_get_arch(void) | |
| 108 | 107 | { |
| 109 | 108 | /* ARM tasks don't change audit architectures on the fly. */ |
| 110 | 109 | return AUDIT_ARCH_ARM; |
| @@ -45,6 +45,7 @@ config IA64 · 44 unmodified lines | ||
| 45 | 45 | select HAVE_MOD_ARCH_SPECIFIC |
| 46 | 46 | select MODULES_USE_ELF_RELA |
| 47 | 47 | select ARCH_USE_CMPXCHG_LOCKREF |
| 48 | + select HAVE_ARCH_AUDITSYSCALL | |
| 48 | 49 | default y |
| 49 | 50 | help |
| 50 | 51 | The Itanium Processor Family is Intel's 64-bit successor to |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #define __ASM_MIPS_SYSCALL_H |
| 15 | 15 | |
| 16 | 16 | #include <linux/compiler.h> |
| 17 | −#include <linux/audit.h> | |
| 17 | +#include <uapi/linux/audit.h> | |
| 18 | 18 | #include <linux/elf-em.h> |
| 19 | 19 | #include <linux/kernel.h> |
| 20 | 20 | #include <linux/sched.h> |
| @@ -127,12 +127,11 @@ extern const unsigned long sys_call_table[]; · 106 unmodified lines | ||
| 127 | 127 | extern const unsigned long sys32_call_table[]; |
| 128 | 128 | extern const unsigned long sysn32_call_table[]; |
| 129 | 129 | |
| 130 | −static inline int syscall_get_arch(struct task_struct *task, | |
| 131 | − struct pt_regs *regs) | |
| 130 | +static inline int syscall_get_arch(void) | |
| 132 | 131 | { |
| 133 | 132 | int arch = EM_MIPS; |
| 134 | 133 | #ifdef CONFIG_64BIT |
| 135 | − if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) | |
| 134 | + if (!test_thread_flag(TIF_32BIT_REGS)) | |
| 136 | 135 | arch |= __AUDIT_ARCH_64BIT; |
| 137 | 136 | #endif |
| 138 | 137 | #if defined(__LITTLE_ENDIAN) |
| @@ -649,7 +649,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) · 648 unmodified lines | ||
| 649 | 649 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
| 650 | 650 | trace_sys_enter(regs, regs->regs[2]); |
| 651 | 651 | |
| 652 | − audit_syscall_entry(syscall_get_arch(current, regs), | |
| 652 | + audit_syscall_entry(syscall_get_arch(), | |
| 653 | 653 | syscall, |
| 654 | 654 | regs->regs[4], regs->regs[5], |
| 655 | 655 | regs->regs[6], regs->regs[7]); |
| @@ -28,6 +28,7 @@ config PARISC · 27 unmodified lines | ||
| 28 | 28 | select CLONE_BACKWARDS |
| 29 | 29 | select TTY # Needed for pdc_cons.c |
| 30 | 30 | select HAVE_DEBUG_STACKOVERFLOW |
| 31 | + select HAVE_ARCH_AUDITSYSCALL | |
| 31 | 32 | |
| 32 | 33 | help |
| 33 | 34 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
| @@ -144,6 +144,7 @@ config PPC · 143 unmodified lines | ||
| 144 | 144 | select HAVE_DEBUG_STACKOVERFLOW |
| 145 | 145 | select HAVE_IRQ_EXIT_ON_IRQ_STACK |
| 146 | 146 | select ARCH_USE_CMPXCHG_LOCKREF if PPC64 |
| 147 | + select HAVE_ARCH_AUDITSYSCALL | |
| 147 | 148 | |
| 148 | 149 | config GENERIC_CSUM |
| 149 | 150 | def_bool CPU_LITTLE_ENDIAN |
| @@ -103,6 +103,7 @@ config S390 · 102 unmodified lines | ||
| 103 | 103 | select GENERIC_SMP_IDLE_THREAD |
| 104 | 104 | select GENERIC_TIME_VSYSCALL |
| 105 | 105 | select HAVE_ALIGNED_STRUCT_PAGE if SLUB |
| 106 | + select HAVE_ARCH_AUDITSYSCALL | |
| 106 | 107 | select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 |
| 107 | 108 | select HAVE_ARCH_SECCOMP_FILTER |
| 108 | 109 | select HAVE_ARCH_TRACEHOOK |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #ifndef _ASM_SYSCALL_H |
| 13 | 13 | #define _ASM_SYSCALL_H 1 |
| 14 | 14 | |
| 15 | −#include <linux/audit.h> | |
| 15 | +#include <uapi/linux/audit.h> | |
| 16 | 16 | #include <linux/sched.h> |
| 17 | 17 | #include <linux/err.h> |
| 18 | 18 | #include <asm/ptrace.h> |
| @@ -89,11 +89,10 @@ static inline void syscall_set_arguments(struct task_struct *task, · 70 unmodified lines | ||
| 89 | 89 | regs->orig_gpr2 = args[0]; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | −static inline int syscall_get_arch(struct task_struct *task, | |
| 93 | − struct pt_regs *regs) | |
| 92 | +static inline int syscall_get_arch(void) | |
| 94 | 93 | { |
| 95 | 94 | #ifdef CONFIG_COMPAT |
| 96 | − if (test_tsk_thread_flag(task, TIF_31BIT)) | |
| 95 | + if (test_tsk_thread_flag(current, TIF_31BIT)) | |
| 97 | 96 | return AUDIT_ARCH_S390; |
| 98 | 97 | #endif |
| 99 | 98 | return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; |
| @@ -42,6 +42,7 @@ config SUPERH · 41 unmodified lines | ||
| 42 | 42 | select MODULES_USE_ELF_RELA |
| 43 | 43 | select OLD_SIGSUSPEND |
| 44 | 44 | select OLD_SIGACTION |
| 45 | + select HAVE_ARCH_AUDITSYSCALL | |
| 45 | 46 | help |
| 46 | 47 | The SuperH is a RISC processor targeted for use in embedded systems |
| 47 | 48 | and consumer electronics; it was also used in the Sega Dreamcast |
| @@ -77,6 +77,7 @@ config SPARC64 · 76 unmodified lines | ||
| 77 | 77 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| 78 | 78 | select HAVE_C_RECORDMCOUNT |
| 79 | 79 | select NO_BOOTMEM |
| 80 | + select HAVE_ARCH_AUDITSYSCALL | |
| 80 | 81 | |
| 81 | 82 | config ARCH_DEFCONFIG |
| 82 | 83 | string |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | config UML |
| 2 | 2 | bool |
| 3 | 3 | default y |
| 4 | + select HAVE_ARCH_AUDITSYSCALL | |
| 4 | 5 | select HAVE_UID16 |
| 5 | 6 | select GENERIC_IRQ_SHOW |
| 6 | 7 | select GENERIC_CPU_DEVICES |
| @@ -129,6 +129,7 @@ config X86 · 128 unmodified lines | ||
| 129 | 129 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 |
| 130 | 130 | select HAVE_CC_STACKPROTECTOR |
| 131 | 131 | select GENERIC_CPU_AUTOPROBE |
| 132 | + select HAVE_ARCH_AUDITSYSCALL | |
| 132 | 133 | |
| 133 | 134 | config INSTRUCTION_DECODER |
| 134 | 135 | def_bool y |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #ifndef _ASM_X86_SYSCALL_H |
| 14 | 14 | #define _ASM_X86_SYSCALL_H |
| 15 | 15 | |
| 16 | −#include <linux/audit.h> | |
| 16 | +#include <uapi/linux/audit.h> | |
| 17 | 17 | #include <linux/sched.h> |
| 18 | 18 | #include <linux/err.h> |
| 19 | 19 | #include <asm/asm-offsets.h> /* For NR_syscalls */ |
| @@ -91,8 +91,7 @@ static inline void syscall_set_arguments(struct task_struct *task, · 71 unmodified lines | ||
| 91 | 91 | memcpy(®s->bx + i, args, n * sizeof(args[0])); |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | −static inline int syscall_get_arch(struct task_struct *task, | |
| 95 | − struct pt_regs *regs) | |
| 94 | +static inline int syscall_get_arch(void) | |
| 96 | 95 | { |
| 97 | 96 | return AUDIT_ARCH_I386; |
| 98 | 97 | } |
| @@ -221,8 +220,7 @@ static inline void syscall_set_arguments(struct task_struct *task, · 122 unmodified lines | ||
| 221 | 220 | } |
| 222 | 221 | } |
| 223 | 222 | |
| 224 | −static inline int syscall_get_arch(struct task_struct *task, | |
| 225 | − struct pt_regs *regs) | |
| 223 | +static inline int syscall_get_arch(void) | |
| 226 | 224 | { |
| 227 | 225 | #ifdef CONFIG_IA32_EMULATION |
| 228 | 226 | /* |
| @@ -234,7 +232,7 @@ static inline int syscall_get_arch(struct task_struct *task, · 5 unmodified lines | ||
| 234 | 232 | * |
| 235 | 233 | * x32 tasks should be considered AUDIT_ARCH_X86_64. |
| 236 | 234 | */ |
| 237 | − if (task_thread_info(task)->status & TS_COMPAT) | |
| 235 | + if (task_thread_info(current)->status & TS_COMPAT) | |
| 238 | 236 | return AUDIT_ARCH_I386; |
| 239 | 237 | #endif |
| 240 | 238 | /* 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, · 64 unmodified lines | ||
| 65 | 65 | { |
| 66 | 66 | struct audit_buffer *ab; |
| 67 | 67 | struct task_struct *tsk = current; |
| 68 | + pid_t pid = task_pid_nr(tsk); | |
| 68 | 69 | uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); |
| 69 | 70 | uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); |
| 70 | 71 | unsigned int sessionid = audit_get_sessionid(tsk); |
| @@ -74,7 +75,7 @@ static void tty_audit_log(const char *description, int major, int minor, · 3 unmodified lines | ||
| 74 | 75 | char name[sizeof(tsk->comm)]; |
| 75 | 76 | |
| 76 | 77 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" |
| 77 | − " minor=%d comm=", description, tsk->pid, uid, | |
| 78 | + " minor=%d comm=", description, pid, uid, | |
| 78 | 79 | loginuid, sessionid, major, minor); |
| 79 | 80 | get_task_comm(name, tsk); |
| 80 | 81 | audit_log_untrustedstring(ab, name); |
| @@ -200,41 +200,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path) · 199 unmodified lines | ||
| 200 | 200 | return result; |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | −static int proc_pid_cmdline(struct task_struct *task, char * buffer) | |
| 203 | +static int proc_pid_cmdline(struct task_struct *task, char *buffer) | |
| 204 | 204 | { |
| 205 | − int res = 0; | |
| 206 | − unsigned int len; | |
| 207 | − struct mm_struct *mm = get_task_mm(task); | |
| 208 | − if (!mm) | |
| 209 | − goto out; | |
| 210 | − if (!mm->arg_end) | |
| 211 | − goto out_mm; /* Shh! No looking before we're done */ | |
| 212 | − | |
| 213 | − len = mm->arg_end - mm->arg_start; | |
| 214 | − | |
| 215 | − if (len > PAGE_SIZE) | |
| 216 | − len = PAGE_SIZE; | |
| 217 | − | |
| 218 | − res = access_process_vm(task, mm->arg_start, buffer, len, 0); | |
| 219 | − | |
| 220 | − // If the nul at the end of args has been overwritten, then | |
| 221 | − // assume application is using setproctitle(3). | |
| 222 | − if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) { | |
| 223 | − len = strnlen(buffer, res); | |
| 224 | − if (len < res) { | |
| 225 | − res = len; | |
| 226 | − } else { | |
| 227 | − len = mm->env_end - mm->env_start; | |
| 228 | − if (len > PAGE_SIZE - res) | |
| 229 | − len = PAGE_SIZE - res; | |
| 230 | − res += access_process_vm(task, mm->env_start, buffer+res, len, 0); | |
| 231 | − res = strnlen(buffer, res); | |
| 232 | − } | |
| 233 | − } | |
| 234 | −out_mm: | |
| 235 | − mmput(mm); | |
| 236 | −out: | |
| 237 | − return res; | |
| 205 | + return get_cmdline(task, buffer, PAGE_SIZE); | |
| 238 | 206 | } |
| 239 | 207 | |
| 240 | 208 | 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, · 143 unmodified lines | ||
| 144 | 144 | |
| 145 | 145 | /** |
| 146 | 146 | * syscall_get_arch - return the AUDIT_ARCH for the current system call |
| 147 | − * @task: task of interest, must be in system call entry tracing | |
| 148 | − * @regs: task_pt_regs() of @task | |
| 149 | 147 | * |
| 150 | 148 | * Returns the AUDIT_ARCH_* based on the system call convention in use. |
| 151 | 149 | * |
| @@ -155,5 +153,5 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, · 3 unmodified lines | ||
| 155 | 153 | * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must |
| 156 | 154 | * provide an implementation of this. |
| 157 | 155 | */ |
| 158 | −int syscall_get_arch(struct task_struct *task, struct pt_regs *regs); | |
| 156 | +int syscall_get_arch(void); | |
| 159 | 157 | #endif /* _ASM_SYSCALL_H */ |
| @@ -79,6 +79,14 @@ extern int is_audit_feature_set(int which); · 78 unmodified lines | ||
| 79 | 79 | extern int __init audit_register_class(int class, unsigned *list); |
| 80 | 80 | extern int audit_classify_syscall(int abi, unsigned syscall); |
| 81 | 81 | extern int audit_classify_arch(int arch); |
| 82 | +/* only for compat system calls */ | |
| 83 | +extern unsigned compat_write_class[]; | |
| 84 | +extern unsigned compat_read_class[]; | |
| 85 | +extern unsigned compat_dir_class[]; | |
| 86 | +extern unsigned compat_chattr_class[]; | |
| 87 | +extern unsigned compat_signal_class[]; | |
| 88 | + | |
| 89 | +extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall); | |
| 82 | 90 | |
| 83 | 91 | /* audit_names->type values */ |
| 84 | 92 | #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ |
| @@ -94,6 +102,12 @@ struct filename; · 9 unmodified lines | ||
| 94 | 102 | |
| 95 | 103 | extern void audit_log_session_info(struct audit_buffer *ab); |
| 96 | 104 | |
| 105 | +#ifdef CONFIG_AUDIT_COMPAT_GENERIC | |
| 106 | +#define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT)) | |
| 107 | +#else | |
| 108 | +#define audit_is_compat(arch) false | |
| 109 | +#endif | |
| 110 | + | |
| 97 | 111 | #ifdef CONFIG_AUDITSYSCALL |
| 98 | 112 | /* These are defined in auditsc.c */ |
| 99 | 113 | /* Public API */ |
| @@ -1204,6 +1204,7 @@ void account_page_writeback(struct page *page); · 1203 unmodified lines | ||
| 1204 | 1204 | int set_page_dirty(struct page *page); |
| 1205 | 1205 | int set_page_dirty_lock(struct page *page); |
| 1206 | 1206 | int clear_page_dirty_for_io(struct page *page); |
| 1207 | +int get_cmdline(struct task_struct *task, char *buffer, int buflen); | |
| 1207 | 1208 | |
| 1208 | 1209 | /* Is the vma a continuation of the stack vma above it? */ |
| 1209 | 1210 | 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) · 1718 unmodified lines | ||
| 1719 | 1719 | } |
| 1720 | 1720 | |
| 1721 | 1721 | |
| 1722 | +static inline int pid_alive(const struct task_struct *p); | |
| 1723 | +static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) | |
| 1724 | +{ | |
| 1725 | + pid_t pid = 0; | |
| 1726 | + | |
| 1727 | + rcu_read_lock(); | |
| 1728 | + if (pid_alive(tsk)) | |
| 1729 | + pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns); | |
| 1730 | + rcu_read_unlock(); | |
| 1731 | + | |
| 1732 | + return pid; | |
| 1733 | +} | |
| 1734 | + | |
| 1735 | +static inline pid_t task_ppid_nr(const struct task_struct *tsk) | |
| 1736 | +{ | |
| 1737 | + return task_ppid_nr_ns(tsk, &init_pid_ns); | |
| 1738 | +} | |
| 1739 | + | |
| 1722 | 1740 | static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, |
| 1723 | 1741 | struct pid_namespace *ns) |
| 1724 | 1742 | { |
| @@ -1758,7 +1776,7 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk) · 33 unmodified lines | ||
| 1758 | 1776 | * |
| 1759 | 1777 | * Return: 1 if the process is alive. 0 otherwise. |
| 1760 | 1778 | */ |
| 1761 | −static inline int pid_alive(struct task_struct *p) | |
| 1779 | +static inline int pid_alive(const struct task_struct *p) | |
| 1762 | 1780 | { |
| 1763 | 1781 | return p->pids[PIDTYPE_PID].pid != NULL; |
| 1764 | 1782 | } |
| @@ -70,7 +70,6 @@ · 69 unmodified lines | ||
| 70 | 70 | #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ |
| 71 | 71 | #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ |
| 72 | 72 | #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ |
| 73 | −#define AUDIT_FEATURE_CHANGE 1020 /* audit log listing feature changes */ | |
| 74 | 73 | |
| 75 | 74 | #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ |
| 76 | 75 | #define AUDIT_USER_AVC 1107 /* We filter this differently */ |
| @@ -109,6 +108,8 @@ · 32 unmodified lines | ||
| 109 | 108 | #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ |
| 110 | 109 | #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ |
| 111 | 110 | #define AUDIT_SECCOMP 1326 /* Secure Computing event */ |
| 111 | +#define AUDIT_PROCTITLE 1327 /* Proctitle emit event */ | |
| 112 | +#define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */ | |
| 112 | 113 | |
| 113 | 114 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
| 114 | 115 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
| @@ -308,8 +308,12 @@ struct vfs_cap_data { · 307 unmodified lines | ||
| 308 | 308 | |
| 309 | 309 | #define CAP_LEASE 28 |
| 310 | 310 | |
| 311 | +/* Allow writing the audit log via unicast netlink socket */ | |
| 312 | + | |
| 311 | 313 | #define CAP_AUDIT_WRITE 29 |
| 312 | 314 | |
| 315 | +/* Allow configuration of audit via unicast netlink socket */ | |
| 316 | + | |
| 313 | 317 | #define CAP_AUDIT_CONTROL 30 |
| 314 | 318 | |
| 315 | 319 | #define CAP_SETFCAP 31 |
| @@ -292,9 +292,12 @@ config AUDIT · 291 unmodified lines | ||
| 292 | 292 | logging of avc messages output). Does not do system-call |
| 293 | 293 | auditing without CONFIG_AUDITSYSCALL. |
| 294 | 294 | |
| 295 | +config HAVE_ARCH_AUDITSYSCALL | |
| 296 | + bool | |
| 297 | + | |
| 295 | 298 | config AUDITSYSCALL |
| 296 | 299 | bool "Enable system-call auditing support" |
| 297 | − depends on AUDIT && (X86 || PARISC || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT) || ALPHA) | |
| 300 | + depends on AUDIT && HAVE_ARCH_AUDITSYSCALL | |
| 298 | 301 | default y if SECURITY_SELINUX |
| 299 | 302 | help |
| 300 | 303 | Enable low-overhead system-call auditing infrastructure that |
| @@ -182,7 +182,7 @@ struct audit_buffer { · 181 unmodified lines | ||
| 182 | 182 | |
| 183 | 183 | struct audit_reply { |
| 184 | 184 | __u32 portid; |
| 185 | − struct net *net; | |
| 185 | + struct net *net; | |
| 186 | 186 | struct sk_buff *skb; |
| 187 | 187 | }; |
| 188 | 188 | |
| @@ -396,7 +396,7 @@ static void audit_printk_skb(struct sk_buff *skb) · 207 unmodified lines | ||
| 396 | 396 | if (printk_ratelimit()) |
| 397 | 397 | pr_notice("type=%d %s\n", nlh->nlmsg_type, data); |
| 398 | 398 | else |
| 399 | − audit_log_lost("printk limit exceeded\n"); | |
| 399 | + audit_log_lost("printk limit exceeded"); | |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | 402 | audit_hold_skb(skb); |
| @@ -412,7 +412,7 @@ static void kauditd_send_skb(struct sk_buff *skb) · 9 unmodified lines | ||
| 412 | 412 | BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ |
| 413 | 413 | if (audit_pid) { |
| 414 | 414 | pr_err("*NO* daemon at audit_pid=%d\n", audit_pid); |
| 415 | − audit_log_lost("auditd disappeared\n"); | |
| 415 | + audit_log_lost("auditd disappeared"); | |
| 416 | 416 | audit_pid = 0; |
| 417 | 417 | audit_sock = NULL; |
| 418 | 418 | } |
| @@ -607,7 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) · 188 unmodified lines | ||
| 607 | 607 | { |
| 608 | 608 | int err = 0; |
| 609 | 609 | |
| 610 | − /* Only support the initial namespaces for now. */ | |
| 610 | + /* Only support initial user namespace for now. */ | |
| 611 | 611 | /* |
| 612 | 612 | * We return ECONNREFUSED because it tricks userspace into thinking |
| 613 | 613 | * 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) · 4 unmodified lines | ||
| 618 | 618 | * userspace will reject all logins. This should be removed when we |
| 619 | 619 | * support non init namespaces!! |
| 620 | 620 | */ |
| 621 | − if ((current_user_ns() != &init_user_ns) || | |
| 622 | − (task_active_pid_ns(current) != &init_pid_ns)) | |
| 621 | + if (current_user_ns() != &init_user_ns) | |
| 623 | 622 | return -ECONNREFUSED; |
| 624 | 623 | |
| 625 | 624 | switch (msg_type) { |
| @@ -639,6 +638,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) · 13 unmodified lines | ||
| 639 | 638 | case AUDIT_TTY_SET: |
| 640 | 639 | case AUDIT_TRIM: |
| 641 | 640 | case AUDIT_MAKE_EQUIV: |
| 641 | + /* Only support auditd and auditctl in initial pid namespace | |
| 642 | + * for now. */ | |
| 643 | + if ((task_active_pid_ns(current) != &init_pid_ns)) | |
| 644 | + return -EPERM; | |
| 645 | + | |
| 642 | 646 | if (!capable(CAP_AUDIT_CONTROL)) |
| 643 | 647 | err = -EPERM; |
| 644 | 648 | break; |
| @@ -659,6 +663,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) · 14 unmodified lines | ||
| 659 | 663 | { |
| 660 | 664 | int rc = 0; |
| 661 | 665 | uid_t uid = from_kuid(&init_user_ns, current_uid()); |
| 666 | + pid_t pid = task_tgid_nr(current); | |
| 662 | 667 | |
| 663 | 668 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) { |
| 664 | 669 | *ab = NULL; |
| @@ -668,7 +673,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) · 3 unmodified lines | ||
| 668 | 673 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
| 669 | 674 | if (unlikely(!*ab)) |
| 670 | 675 | return rc; |
| 671 | − audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid); | |
| 676 | + audit_log_format(*ab, "pid=%d uid=%u", pid, uid); | |
| 672 | 677 | audit_log_session_info(*ab); |
| 673 | 678 | audit_log_task_context(*ab); |
| 674 | 679 | |
| @@ -1097,7 +1102,7 @@ static void __net_exit audit_net_exit(struct net *net) · 422 unmodified lines | ||
| 1097 | 1102 | audit_sock = NULL; |
| 1098 | 1103 | } |
| 1099 | 1104 | |
| 1100 | − rcu_assign_pointer(aunet->nlsk, NULL); | |
| 1105 | + RCU_INIT_POINTER(aunet->nlsk, NULL); | |
| 1101 | 1106 | synchronize_net(); |
| 1102 | 1107 | netlink_kernel_release(sock); |
| 1103 | 1108 | } |
| @@ -1829,11 +1834,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) · 725 unmodified lines | ||
| 1829 | 1834 | spin_unlock_irq(&tsk->sighand->siglock); |
| 1830 | 1835 | |
| 1831 | 1836 | audit_log_format(ab, |
| 1832 | − " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | |
| 1837 | + " ppid=%d pid=%d auid=%u uid=%u gid=%u" | |
| 1833 | 1838 | " euid=%u suid=%u fsuid=%u" |
| 1834 | 1839 | " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", |
| 1835 | − sys_getppid(), | |
| 1836 | − tsk->pid, | |
| 1840 | + task_ppid_nr(tsk), | |
| 1841 | + task_pid_nr(tsk), | |
| 1837 | 1842 | from_kuid(&init_user_ns, audit_get_loginuid(tsk)), |
| 1838 | 1843 | from_kuid(&init_user_ns, cred->uid), |
| 1839 | 1844 | from_kgid(&init_user_ns, cred->gid), |
| @@ -106,6 +106,11 @@ struct audit_names { · 105 unmodified lines | ||
| 106 | 106 | bool should_free; |
| 107 | 107 | }; |
| 108 | 108 | |
| 109 | +struct audit_proctitle { | |
| 110 | + int len; /* length of the cmdline field. */ | |
| 111 | + char *value; /* the cmdline field */ | |
| 112 | +}; | |
| 113 | + | |
| 109 | 114 | /* The per-task audit context. */ |
| 110 | 115 | struct audit_context { |
| 111 | 116 | int dummy; /* must be the first element */ |
| @@ -202,6 +207,7 @@ struct audit_context { · 90 unmodified lines | ||
| 202 | 207 | } execve; |
| 203 | 208 | }; |
| 204 | 209 | int fds[2]; |
| 210 | + struct audit_proctitle proctitle; | |
| 205 | 211 | |
| 206 | 212 | #if AUDIT_DEBUG |
| 207 | 213 | int put_count; |
| @@ -19,6 +19,8 @@ · 18 unmodified lines | ||
| 19 | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
| 23 | + | |
| 22 | 24 | #include <linux/kernel.h> |
| 23 | 25 | #include <linux/audit.h> |
| 24 | 26 | #include <linux/kthread.h> |
| @@ -226,7 +228,7 @@ static int audit_match_signal(struct audit_entry *entry) · 201 unmodified lines | ||
| 226 | 228 | #endif |
| 227 | 229 | |
| 228 | 230 | /* Common user-space to kernel rule translation. */ |
| 229 | −static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) | |
| 231 | +static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *rule) | |
| 230 | 232 | { |
| 231 | 233 | unsigned listnr; |
| 232 | 234 | struct audit_entry *entry; |
| @@ -249,7 +251,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) · 16 unmodified lines | ||
| 249 | 251 | ; |
| 250 | 252 | } |
| 251 | 253 | if (unlikely(rule->action == AUDIT_POSSIBLE)) { |
| 252 | − printk(KERN_ERR "AUDIT_POSSIBLE is deprecated\n"); | |
| 254 | + pr_err("AUDIT_POSSIBLE is deprecated\n"); | |
| 253 | 255 | goto exit_err; |
| 254 | 256 | } |
| 255 | 257 | 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, · 147 unmodified lines | ||
| 403 | 405 | int i; |
| 404 | 406 | char *str; |
| 405 | 407 | |
| 406 | − entry = audit_to_entry_common((struct audit_rule *)data); | |
| 408 | + entry = audit_to_entry_common(data); | |
| 407 | 409 | if (IS_ERR(entry)) |
| 408 | 410 | goto exit_nofree; |
| 409 | 411 | |
| @@ -431,6 +433,19 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, · 21 unmodified lines | ||
| 431 | 433 | f->val = 0; |
| 432 | 434 | } |
| 433 | 435 | |
| 436 | + if ((f->type == AUDIT_PID) || (f->type == AUDIT_PPID)) { | |
| 437 | + struct pid *pid; | |
| 438 | + rcu_read_lock(); | |
| 439 | + pid = find_vpid(f->val); | |
| 440 | + if (!pid) { | |
| 441 | + rcu_read_unlock(); | |
| 442 | + err = -ESRCH; | |
| 443 | + goto exit_free; | |
| 444 | + } | |
| 445 | + f->val = pid_nr(pid); | |
| 446 | + rcu_read_unlock(); | |
| 447 | + } | |
| 448 | + | |
| 434 | 449 | err = audit_field_valid(entry, f); |
| 435 | 450 | if (err) |
| 436 | 451 | goto exit_free; |
| @@ -479,8 +494,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, · 42 unmodified lines | ||
| 479 | 494 | /* Keep currently invalid fields around in case they |
| 480 | 495 | * become valid after a policy reload. */ |
| 481 | 496 | if (err == -EINVAL) { |
| 482 | − printk(KERN_WARNING "audit rule for LSM " | |
| 483 | − "\'%s\' is invalid\n", str); | |
| 497 | + pr_warn("audit rule for LSM \'%s\' is invalid\n", | |
| 498 | + str); | |
| 484 | 499 | err = 0; |
| 485 | 500 | } |
| 486 | 501 | if (err) { |
| @@ -709,8 +724,8 @@ static inline int audit_dupe_lsm_field(struct audit_field *df, · 222 unmodified lines | ||
| 709 | 724 | /* Keep currently invalid fields around in case they |
| 710 | 725 | * become valid after a policy reload. */ |
| 711 | 726 | if (ret == -EINVAL) { |
| 712 | − printk(KERN_WARNING "audit rule for LSM \'%s\' is " | |
| 713 | − "invalid\n", df->lsm_str); | |
| 727 | + pr_warn("audit rule for LSM \'%s\' is invalid\n", | |
| 728 | + df->lsm_str); | |
| 714 | 729 | ret = 0; |
| 715 | 730 | } |
| 716 | 731 | |
| @@ -1240,12 +1255,14 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type, · 523 unmodified lines | ||
| 1240 | 1255 | |
| 1241 | 1256 | for (i = 0; i < rule->field_count; i++) { |
| 1242 | 1257 | struct audit_field *f = &rule->fields[i]; |
| 1258 | + pid_t pid; | |
| 1243 | 1259 | int result = 0; |
| 1244 | 1260 | u32 sid; |
| 1245 | 1261 | |
| 1246 | 1262 | switch (f->type) { |
| 1247 | 1263 | case AUDIT_PID: |
| 1248 | − result = audit_comparator(task_pid_vnr(current), f->op, f->val); | |
| 1264 | + pid = task_pid_nr(current); | |
| 1265 | + result = audit_comparator(pid, f->op, f->val); | |
| 1249 | 1266 | break; |
| 1250 | 1267 | case AUDIT_UID: |
| 1251 | 1268 | result = audit_uid_comparator(current_uid(), f->op, f->uid); |
| @@ -42,6 +42,8 @@ · 41 unmodified lines | ||
| 42 | 42 | * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. |
| 43 | 43 | */ |
| 44 | 44 | |
| 45 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
| 46 | + | |
| 45 | 47 | #include <linux/init.h> |
| 46 | 48 | #include <asm/types.h> |
| 47 | 49 | #include <linux/atomic.h> |
| @@ -68,6 +70,7 @@ · 20 unmodified lines | ||
| 68 | 70 | #include <linux/capability.h> |
| 69 | 71 | #include <linux/fs_struct.h> |
| 70 | 72 | #include <linux/compat.h> |
| 73 | +#include <linux/ctype.h> | |
| 71 | 74 | |
| 72 | 75 | #include "audit.h" |
| 73 | 76 | |
| @@ -79,6 +82,9 @@ · 5 unmodified lines | ||
| 79 | 82 | /* no execve audit message should be longer than this (userspace limits) */ |
| 80 | 83 | #define MAX_EXECVE_AUDIT_LEN 7500 |
| 81 | 84 | |
| 85 | +/* max length to print of cmdline/proctitle value during audit */ | |
| 86 | +#define MAX_PROCTITLE_AUDIT_LEN 128 | |
| 87 | + | |
| 82 | 88 | /* number of audit rules */ |
| 83 | 89 | int audit_n_rules; |
| 84 | 90 | |
| @@ -451,15 +457,17 @@ static int audit_filter_rules(struct task_struct *tsk, · 366 unmodified lines | ||
| 451 | 457 | struct audit_field *f = &rule->fields[i]; |
| 452 | 458 | struct audit_names *n; |
| 453 | 459 | int result = 0; |
| 460 | + pid_t pid; | |
| 454 | 461 | |
| 455 | 462 | switch (f->type) { |
| 456 | 463 | case AUDIT_PID: |
| 457 | − result = audit_comparator(tsk->pid, f->op, f->val); | |
| 464 | + pid = task_pid_nr(tsk); | |
| 465 | + result = audit_comparator(pid, f->op, f->val); | |
| 458 | 466 | break; |
| 459 | 467 | case AUDIT_PPID: |
| 460 | 468 | if (ctx) { |
| 461 | 469 | if (!ctx->ppid) |
| 462 | − ctx->ppid = sys_getppid(); | |
| 470 | + ctx->ppid = task_ppid_nr(tsk); | |
| 463 | 471 | result = audit_comparator(ctx->ppid, f->op, f->val); |
| 464 | 472 | } |
| 465 | 473 | break; |
| @@ -805,7 +813,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) · 339 unmodified lines | ||
| 805 | 813 | rcu_read_unlock(); |
| 806 | 814 | } |
| 807 | 815 | |
| 808 | −static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |
| 816 | +/* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */ | |
| 817 | +static inline struct audit_context *audit_take_context(struct task_struct *tsk, | |
| 809 | 818 | int return_valid, |
| 810 | 819 | long return_code) |
| 811 | 820 | { |
| @@ -842,6 +851,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, · 30 unmodified lines | ||
| 842 | 851 | return context; |
| 843 | 852 | } |
| 844 | 853 | |
| 854 | +static inline void audit_proctitle_free(struct audit_context *context) | |
| 855 | +{ | |
| 856 | + kfree(context->proctitle.value); | |
| 857 | + context->proctitle.value = NULL; | |
| 858 | + context->proctitle.len = 0; | |
| 859 | +} | |
| 860 | + | |
| 845 | 861 | static inline void audit_free_names(struct audit_context *context) |
| 846 | 862 | { |
| 847 | 863 | struct audit_names *n, *next; |
| @@ -850,16 +866,15 @@ static inline void audit_free_names(struct audit_context *context) · 2 unmodified lines | ||
| 850 | 866 | if (context->put_count + context->ino_count != context->name_count) { |
| 851 | 867 | int i = 0; |
| 852 | 868 | |
| 853 | − printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" | |
| 854 | − " name_count=%d put_count=%d" | |
| 855 | − " ino_count=%d [NOT freeing]\n", | |
| 856 | − __FILE__, __LINE__, | |
| 869 | + pr_err("%s:%d(:%d): major=%d in_syscall=%d" | |
| 870 | + " name_count=%d put_count=%d ino_count=%d" | |
| 871 | + " [NOT freeing]\n", __FILE__, __LINE__, | |
| 857 | 872 | context->serial, context->major, context->in_syscall, |
| 858 | 873 | context->name_count, context->put_count, |
| 859 | 874 | context->ino_count); |
| 860 | 875 | list_for_each_entry(n, &context->names_list, list) { |
| 861 | − printk(KERN_ERR "names[%d] = %p = %s\n", i++, | |
| 862 | − n->name, n->name->name ?: "(null)"); | |
| 876 | + pr_err("names[%d] = %p = %s\n", i++, n->name, | |
| 877 | + n->name->name ?: "(null)"); | |
| 863 | 878 | } |
| 864 | 879 | dump_stack(); |
| 865 | 880 | return; |
| @@ -955,6 +970,7 @@ static inline void audit_free_context(struct audit_context *context) · 89 unmodified lines | ||
| 955 | 970 | audit_free_aux(context); |
| 956 | 971 | kfree(context->filterkey); |
| 957 | 972 | kfree(context->sockaddr); |
| 973 | + audit_proctitle_free(context); | |
| 958 | 974 | kfree(context); |
| 959 | 975 | } |
| 960 | 976 | |
| @@ -1157,7 +1173,7 @@ static void audit_log_execve_info(struct audit_context *context, · 196 unmodified lines | ||
| 1157 | 1173 | */ |
| 1158 | 1174 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); |
| 1159 | 1175 | if (!buf) { |
| 1160 | − audit_panic("out of memory for argv string\n"); | |
| 1176 | + audit_panic("out of memory for argv string"); | |
| 1161 | 1177 | return; |
| 1162 | 1178 | } |
| 1163 | 1179 | |
| @@ -1271,6 +1287,59 @@ static void show_special(struct audit_context *context, int *call_panic) · 107 unmodified lines | ||
| 1271 | 1287 | audit_log_end(ab); |
| 1272 | 1288 | } |
| 1273 | 1289 | |
| 1290 | +static inline int audit_proctitle_rtrim(char *proctitle, int len) | |
| 1291 | +{ | |
| 1292 | + char *end = proctitle + len - 1; | |
| 1293 | + while (end > proctitle && !isprint(*end)) | |
| 1294 | + end--; | |
| 1295 | + | |
| 1296 | + /* catch the case where proctitle is only 1 non-print character */ | |
| 1297 | + len = end - proctitle + 1; | |
| 1298 | + len -= isprint(proctitle[len-1]) == 0; | |
| 1299 | + return len; | |
| 1300 | +} | |
| 1301 | + | |
| 1302 | +static void audit_log_proctitle(struct task_struct *tsk, | |
| 1303 | + struct audit_context *context) | |
| 1304 | +{ | |
| 1305 | + int res; | |
| 1306 | + char *buf; | |
| 1307 | + char *msg = "(null)"; | |
| 1308 | + int len = strlen(msg); | |
| 1309 | + struct audit_buffer *ab; | |
| 1310 | + | |
| 1311 | + ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); | |
| 1312 | + if (!ab) | |
| 1313 | + return; /* audit_panic or being filtered */ | |
| 1314 | + | |
| 1315 | + audit_log_format(ab, "proctitle="); | |
| 1316 | + | |
| 1317 | + /* Not cached */ | |
| 1318 | + if (!context->proctitle.value) { | |
| 1319 | + buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL); | |
| 1320 | + if (!buf) | |
| 1321 | + goto out; | |
| 1322 | + /* Historically called this from procfs naming */ | |
| 1323 | + res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); | |
| 1324 | + if (res == 0) { | |
| 1325 | + kfree(buf); | |
| 1326 | + goto out; | |
| 1327 | + } | |
| 1328 | + res = audit_proctitle_rtrim(buf, res); | |
| 1329 | + if (res == 0) { | |
| 1330 | + kfree(buf); | |
| 1331 | + goto out; | |
| 1332 | + } | |
| 1333 | + context->proctitle.value = buf; | |
| 1334 | + context->proctitle.len = res; | |
| 1335 | + } | |
| 1336 | + msg = context->proctitle.value; | |
| 1337 | + len = context->proctitle.len; | |
| 1338 | +out: | |
| 1339 | + audit_log_n_untrustedstring(ab, msg, len); | |
| 1340 | + audit_log_end(ab); | |
| 1341 | +} | |
| 1342 | + | |
| 1274 | 1343 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
| 1275 | 1344 | { |
| 1276 | 1345 | int i, call_panic = 0; |
| @@ -1388,6 +1457,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts · 111 unmodified lines | ||
| 1388 | 1457 | audit_log_name(context, n, NULL, i++, &call_panic); |
| 1389 | 1458 | } |
| 1390 | 1459 | |
| 1460 | + audit_log_proctitle(tsk, context); | |
| 1461 | + | |
| 1391 | 1462 | /* Send end of event record to help user space know we are finished */ |
| 1392 | 1463 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
| 1393 | 1464 | if (ab) |
| @@ -1406,7 +1477,7 @@ void __audit_free(struct task_struct *tsk) · 12 unmodified lines | ||
| 1406 | 1477 | { |
| 1407 | 1478 | struct audit_context *context; |
| 1408 | 1479 | |
| 1409 | − context = audit_get_context(tsk, 0, 0); | |
| 1480 | + context = audit_take_context(tsk, 0, 0); | |
| 1410 | 1481 | if (!context) |
| 1411 | 1482 | return; |
| 1412 | 1483 | |
| @@ -1500,7 +1571,7 @@ void __audit_syscall_exit(int success, long return_code) · 87 unmodified lines | ||
| 1500 | 1571 | else |
| 1501 | 1572 | success = AUDITSC_FAILURE; |
| 1502 | 1573 | |
| 1503 | − context = audit_get_context(tsk, success, return_code); | |
| 1574 | + context = audit_take_context(tsk, success, return_code); | |
| 1504 | 1575 | if (!context) |
| 1505 | 1576 | return; |
| 1506 | 1577 | |
| @@ -1550,7 +1621,7 @@ static inline void handle_one(const struct inode *inode) · 43 unmodified lines | ||
| 1550 | 1621 | if (likely(put_tree_ref(context, chunk))) |
| 1551 | 1622 | return; |
| 1552 | 1623 | if (unlikely(!grow_tree_refs(context))) { |
| 1553 | − printk(KERN_WARNING "out of memory, audit has lost a tree reference\n"); | |
| 1624 | + pr_warn("out of memory, audit has lost a tree reference\n"); | |
| 1554 | 1625 | audit_set_auditable(context); |
| 1555 | 1626 | audit_put_chunk(chunk); |
| 1556 | 1627 | unroll_tree_refs(context, p, count); |
| @@ -1609,8 +1680,7 @@ retry: · 52 unmodified lines | ||
| 1609 | 1680 | goto retry; |
| 1610 | 1681 | } |
| 1611 | 1682 | /* too bad */ |
| 1612 | − printk(KERN_WARNING | |
| 1613 | − "out of memory, audit has lost a tree reference\n"); | |
| 1683 | + pr_warn("out of memory, audit has lost a tree reference\n"); | |
| 1614 | 1684 | unroll_tree_refs(context, p, count); |
| 1615 | 1685 | audit_set_auditable(context); |
| 1616 | 1686 | return; |
| @@ -1682,7 +1752,7 @@ void __audit_getname(struct filename *name) · 65 unmodified lines | ||
| 1682 | 1752 | |
| 1683 | 1753 | if (!context->in_syscall) { |
| 1684 | 1754 | #if AUDIT_DEBUG == 2 |
| 1685 | − printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n", | |
| 1755 | + pr_err("%s:%d(:%d): ignoring getname(%p)\n", | |
| 1686 | 1756 | __FILE__, __LINE__, context->serial, name); |
| 1687 | 1757 | dump_stack(); |
| 1688 | 1758 | #endif |
| @@ -1721,15 +1791,15 @@ void audit_putname(struct filename *name) · 32 unmodified lines | ||
| 1721 | 1791 | BUG_ON(!context); |
| 1722 | 1792 | if (!name->aname || !context->in_syscall) { |
| 1723 | 1793 | #if AUDIT_DEBUG == 2 |
| 1724 | − printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", | |
| 1794 | + pr_err("%s:%d(:%d): final_putname(%p)\n", | |
| 1725 | 1795 | __FILE__, __LINE__, context->serial, name); |
| 1726 | 1796 | if (context->name_count) { |
| 1727 | 1797 | struct audit_names *n; |
| 1728 | 1798 | int i = 0; |
| 1729 | 1799 | |
| 1730 | 1800 | list_for_each_entry(n, &context->names_list, list) |
| 1731 | − printk(KERN_ERR "name[%d] = %p = %s\n", i++, | |
| 1732 | − n->name, n->name->name ?: "(null)"); | |
| 1801 | + pr_err("name[%d] = %p = %s\n", i++, n->name, | |
| 1802 | + n->name->name ?: "(null)"); | |
| 1733 | 1803 | } |
| 1734 | 1804 | #endif |
| 1735 | 1805 | final_putname(name); |
| @@ -1738,9 +1808,8 @@ void audit_putname(struct filename *name) · 2 unmodified lines | ||
| 1738 | 1808 | else { |
| 1739 | 1809 | ++context->put_count; |
| 1740 | 1810 | if (context->put_count > context->name_count) { |
| 1741 | − printk(KERN_ERR "%s:%d(:%d): major=%d" | |
| 1742 | − " in_syscall=%d putname(%p) name_count=%d" | |
| 1743 | − " put_count=%d\n", | |
| 1811 | + pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" | |
| 1812 | + " name_count=%d put_count=%d\n", | |
| 1744 | 1813 | __FILE__, __LINE__, |
| 1745 | 1814 | context->serial, context->major, |
| 1746 | 1815 | context->in_syscall, name->name, |
| @@ -1981,12 +2050,10 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, · 234 unmodified lines | ||
| 1981 | 2050 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); |
| 1982 | 2051 | if (!ab) |
| 1983 | 2052 | return; |
| 1984 | − audit_log_format(ab, "pid=%d uid=%u" | |
| 1985 | − " old-auid=%u new-auid=%u old-ses=%u new-ses=%u" | |
| 1986 | − " res=%d", | |
| 1987 | − current->pid, uid, | |
| 1988 | − oldloginuid, loginuid, oldsessionid, sessionid, | |
| 1989 | − !rc); | |
| 2053 | + audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); | |
| 2054 | + audit_log_task_context(ab); | |
| 2055 | + audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", | |
| 2056 | + oldloginuid, loginuid, oldsessionid, sessionid, !rc); | |
| 1990 | 2057 | audit_log_end(ab); |
| 1991 | 2058 | } |
| 1992 | 2059 | |
| @@ -2208,7 +2275,7 @@ void __audit_ptrace(struct task_struct *t) · 215 unmodified lines | ||
| 2208 | 2275 | { |
| 2209 | 2276 | struct audit_context *context = current->audit_context; |
| 2210 | 2277 | |
| 2211 | − context->target_pid = t->pid; | |
| 2278 | + context->target_pid = task_pid_nr(t); | |
| 2212 | 2279 | context->target_auid = audit_get_loginuid(t); |
| 2213 | 2280 | context->target_uid = task_uid(t); |
| 2214 | 2281 | context->target_sessionid = audit_get_sessionid(t); |
| @@ -2233,7 +2300,7 @@ int __audit_signal_info(int sig, struct task_struct *t) · 18 unmodified lines | ||
| 2233 | 2300 | |
| 2234 | 2301 | if (audit_pid && t->tgid == audit_pid) { |
| 2235 | 2302 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { |
| 2236 | − audit_sig_pid = tsk->pid; | |
| 2303 | + audit_sig_pid = task_pid_nr(tsk); | |
| 2237 | 2304 | if (uid_valid(tsk->loginuid)) |
| 2238 | 2305 | audit_sig_uid = tsk->loginuid; |
| 2239 | 2306 | else |
| @@ -2247,7 +2314,7 @@ int __audit_signal_info(int sig, struct task_struct *t) · 7 unmodified lines | ||
| 2247 | 2314 | /* optimize the common case by putting first signal recipient directly |
| 2248 | 2315 | * in audit_context */ |
| 2249 | 2316 | if (!ctx->target_pid) { |
| 2250 | − ctx->target_pid = t->tgid; | |
| 2317 | + ctx->target_pid = task_tgid_nr(t); | |
| 2251 | 2318 | ctx->target_auid = audit_get_loginuid(t); |
| 2252 | 2319 | ctx->target_uid = t_uid; |
| 2253 | 2320 | ctx->target_sessionid = audit_get_sessionid(t); |
| @@ -2268,7 +2335,7 @@ int __audit_signal_info(int sig, struct task_struct *t) · 14 unmodified lines | ||
| 2268 | 2335 | } |
| 2269 | 2336 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); |
| 2270 | 2337 | |
| 2271 | − axp->target_pid[axp->pid_count] = t->tgid; | |
| 2338 | + axp->target_pid[axp->pid_count] = task_tgid_nr(t); | |
| 2272 | 2339 | axp->target_auid[axp->pid_count] = audit_get_loginuid(t); |
| 2273 | 2340 | axp->target_uid[axp->pid_count] = t_uid; |
| 2274 | 2341 | axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); |
| @@ -2368,7 +2435,7 @@ static void audit_log_task(struct audit_buffer *ab) · 93 unmodified lines | ||
| 2368 | 2435 | from_kgid(&init_user_ns, gid), |
| 2369 | 2436 | sessionid); |
| 2370 | 2437 | audit_log_task_context(ab); |
| 2371 | − audit_log_format(ab, " pid=%d comm=", current->pid); | |
| 2438 | + audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); | |
| 2372 | 2439 | audit_log_untrustedstring(ab, current->comm); |
| 2373 | 2440 | if (mm) { |
| 2374 | 2441 | down_read(&mm->mmap_sem); |
| @@ -71,7 +71,7 @@ static void populate_seccomp_data(struct seccomp_data *sd) · 70 unmodified lines | ||
| 71 | 71 | struct pt_regs *regs = task_pt_regs(task); |
| 72 | 72 | |
| 73 | 73 | sd->nr = syscall_get_nr(task, regs); |
| 74 | − sd->arch = syscall_get_arch(task, regs); | |
| 74 | + sd->arch = syscall_get_arch(); | |
| 75 | 75 | |
| 76 | 76 | /* Unroll syscall_get_args to help gcc on arm. */ |
| 77 | 77 | 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) · 270 unmodified lines | ||
| 348 | 348 | info.si_code = SYS_SECCOMP; |
| 349 | 349 | info.si_call_addr = (void __user *)KSTK_EIP(current); |
| 350 | 350 | info.si_errno = reason; |
| 351 | − info.si_arch = syscall_get_arch(current, task_pt_regs(current)); | |
| 351 | + info.si_arch = syscall_get_arch(); | |
| 352 | 352 | info.si_syscall = syscall; |
| 353 | 353 | force_sig_info(SIGSYS, &info, current); |
| 354 | 354 | } |
| @@ -182,6 +182,15 @@ config AUDIT_GENERIC · 181 unmodified lines | ||
| 182 | 182 | depends on AUDIT && !AUDIT_ARCH |
| 183 | 183 | default y |
| 184 | 184 | |
| 185 | +config AUDIT_ARCH_COMPAT_GENERIC | |
| 186 | + bool | |
| 187 | + default n | |
| 188 | + | |
| 189 | +config AUDIT_COMPAT_GENERIC | |
| 190 | + bool | |
| 191 | + depends on AUDIT_GENERIC && AUDIT_ARCH_COMPAT_GENERIC && COMPAT | |
| 192 | + default y | |
| 193 | + | |
| 185 | 194 | config RANDOM32_SELFTEST |
| 186 | 195 | bool "PRNG perform self test on init" |
| 187 | 196 | default n |
| @@ -96,6 +96,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o · 95 unmodified lines | ||
| 96 | 96 | obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o |
| 97 | 97 | obj-$(CONFIG_SMP) += percpu_counter.o |
| 98 | 98 | obj-$(CONFIG_AUDIT_GENERIC) += audit.o |
| 99 | +obj-$(CONFIG_AUDIT_COMPAT_GENERIC) += compat_audit.o | |
| 99 | 100 | |
| 100 | 101 | obj-$(CONFIG_SWIOTLB) += swiotlb.o |
| 101 | 102 | obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o |
| @@ -30,11 +30,17 @@ static unsigned signal_class[] = { · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | int audit_classify_arch(int arch) |
| 32 | 32 | { |
| 33 | − return 0; | |
| 33 | + if (audit_is_compat(arch)) | |
| 34 | + return 1; | |
| 35 | + else | |
| 36 | + return 0; | |
| 34 | 37 | } |
| 35 | 38 | |
| 36 | 39 | int audit_classify_syscall(int abi, unsigned syscall) |
| 37 | 40 | { |
| 41 | + if (audit_is_compat(abi)) | |
| 42 | + return audit_classify_compat_syscall(abi, syscall); | |
| 43 | + | |
| 38 | 44 | switch(syscall) { |
| 39 | 45 | #ifdef __NR_open |
| 40 | 46 | case __NR_open: |
| @@ -57,6 +63,13 @@ int audit_classify_syscall(int abi, unsigned syscall) · 16 unmodified lines | ||
| 57 | 63 | |
| 58 | 64 | static int __init audit_classes_init(void) |
| 59 | 65 | { |
| 66 | +#ifdef CONFIG_AUDIT_COMPAT_GENERIC | |
| 67 | + audit_register_class(AUDIT_CLASS_WRITE_32, compat_write_class); | |
| 68 | + audit_register_class(AUDIT_CLASS_READ_32, compat_read_class); | |
| 69 | + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, compat_dir_class); | |
| 70 | + audit_register_class(AUDIT_CLASS_CHATTR_32, compat_chattr_class); | |
| 71 | + audit_register_class(AUDIT_CLASS_SIGNAL_32, compat_signal_class); | |
| 72 | +#endif | |
| 60 | 73 | audit_register_class(AUDIT_CLASS_WRITE, write_class); |
| 61 | 74 | audit_register_class(AUDIT_CLASS_READ, read_class); |
| 62 | 75 | audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); |
| @@ -0,0 +1,50 @@ | ||
| 1 | +#include <linux/init.h> | |
| 2 | +#include <linux/types.h> | |
| 3 | +#include <asm/unistd32.h> | |
| 4 | + | |
| 5 | +unsigned compat_dir_class[] = { | |
| 6 | +#include <asm-generic/audit_dir_write.h> | |
| 7 | +~0U | |
| 8 | +}; | |
| 9 | + | |
| 10 | +unsigned compat_read_class[] = { | |
| 11 | +#include <asm-generic/audit_read.h> | |
| 12 | +~0U | |
| 13 | +}; | |
| 14 | + | |
| 15 | +unsigned compat_write_class[] = { | |
| 16 | +#include <asm-generic/audit_write.h> | |
| 17 | +~0U | |
| 18 | +}; | |
| 19 | + | |
| 20 | +unsigned compat_chattr_class[] = { | |
| 21 | +#include <asm-generic/audit_change_attr.h> | |
| 22 | +~0U | |
| 23 | +}; | |
| 24 | + | |
| 25 | +unsigned compat_signal_class[] = { | |
| 26 | +#include <asm-generic/audit_signal.h> | |
| 27 | +~0U | |
| 28 | +}; | |
| 29 | + | |
| 30 | +int audit_classify_compat_syscall(int abi, unsigned syscall) | |
| 31 | +{ | |
| 32 | + switch (syscall) { | |
| 33 | +#ifdef __NR_open | |
| 34 | + case __NR_open: | |
| 35 | + return 2; | |
| 36 | +#endif | |
| 37 | +#ifdef __NR_openat | |
| 38 | + case __NR_openat: | |
| 39 | + return 3; | |
| 40 | +#endif | |
| 41 | +#ifdef __NR_socketcall | |
| 42 | + case __NR_socketcall: | |
| 43 | + return 4; | |
| 44 | +#endif | |
| 45 | + case __NR_execve: | |
| 46 | + return 5; | |
| 47 | + default: | |
| 48 | + return 1; | |
| 49 | + } | |
| 50 | +} | |
| @@ -446,6 +446,54 @@ unsigned long vm_commit_limit(void) · 445 unmodified lines | ||
| 446 | 446 | return allowed; |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | +/** | |
| 450 | + * get_cmdline() - copy the cmdline value to a buffer. | |
| 451 | + * @task: the task whose cmdline value to copy. | |
| 452 | + * @buffer: the buffer to copy to. | |
| 453 | + * @buflen: the length of the buffer. Larger cmdline values are truncated | |
| 454 | + * to this length. | |
| 455 | + * Returns the size of the cmdline field copied. Note that the copy does | |
| 456 | + * not guarantee an ending NULL byte. | |
| 457 | + */ | |
| 458 | +int get_cmdline(struct task_struct *task, char *buffer, int buflen) | |
| 459 | +{ | |
| 460 | + int res = 0; | |
| 461 | + unsigned int len; | |
| 462 | + struct mm_struct *mm = get_task_mm(task); | |
| 463 | + if (!mm) | |
| 464 | + goto out; | |
| 465 | + if (!mm->arg_end) | |
| 466 | + goto out_mm; /* Shh! No looking before we're done */ | |
| 467 | + | |
| 468 | + len = mm->arg_end - mm->arg_start; | |
| 469 | + | |
| 470 | + if (len > buflen) | |
| 471 | + len = buflen; | |
| 472 | + | |
| 473 | + res = access_process_vm(task, mm->arg_start, buffer, len, 0); | |
| 474 | + | |
| 475 | + /* | |
| 476 | + * If the nul at the end of args has been overwritten, then | |
| 477 | + * assume application is using setproctitle(3). | |
| 478 | + */ | |
| 479 | + if (res > 0 && buffer[res-1] != '\0' && len < buflen) { | |
| 480 | + len = strnlen(buffer, res); | |
| 481 | + if (len < res) { | |
| 482 | + res = len; | |
| 483 | + } else { | |
| 484 | + len = mm->env_end - mm->env_start; | |
| 485 | + if (len > buflen - res) | |
| 486 | + len = buflen - res; | |
| 487 | + res += access_process_vm(task, mm->env_start, | |
| 488 | + buffer+res, len, 0); | |
| 489 | + res = strnlen(buffer, res); | |
| 490 | + } | |
| 491 | + } | |
| 492 | +out_mm: | |
| 493 | + mmput(mm); | |
| 494 | +out: | |
| 495 | + return res; | |
| 496 | +} | |
| 449 | 497 | |
| 450 | 498 | /* Tracepoints definitions. */ |
| 451 | 499 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); |
| @@ -40,7 +40,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); |
| 42 | 42 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", |
| 43 | − current->pid, | |
| 43 | + task_pid_nr(current), | |
| 44 | 44 | from_kuid(&init_user_ns, current_cred()->uid), |
| 45 | 45 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
| 46 | 46 | audit_get_sessionid(current)); |
| @@ -220,7 +220,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, · 219 unmodified lines | ||
| 220 | 220 | */ |
| 221 | 221 | BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); |
| 222 | 222 | |
| 223 | − audit_log_format(ab, " pid=%d comm=", tsk->pid); | |
| 223 | + audit_log_format(ab, " pid=%d comm=", task_pid_nr(tsk)); | |
| 224 | 224 | audit_log_untrustedstring(ab, tsk->comm); |
| 225 | 225 | |
| 226 | 226 | switch (a->type) { |
| @@ -278,9 +278,12 @@ static void dump_common_audit_data(struct audit_buffer *ab, · 51 unmodified lines | ||
| 278 | 278 | } |
| 279 | 279 | case LSM_AUDIT_DATA_TASK: |
| 280 | 280 | tsk = a->u.tsk; |
| 281 | − if (tsk && tsk->pid) { | |
| 282 | − audit_log_format(ab, " pid=%d comm=", tsk->pid); | |
| 283 | − audit_log_untrustedstring(ab, tsk->comm); | |
| 281 | + if (tsk) { | |
| 282 | + pid_t pid = task_pid_nr(tsk); | |
| 283 | + if (pid) { | |
| 284 | + audit_log_format(ab, " pid=%d comm=", pid); | |
| 285 | + audit_log_untrustedstring(ab, tsk->comm); | |
| 286 | + } | |
| 284 | 287 | } |
| 285 | 288 | break; |
| 286 | 289 | case LSM_AUDIT_DATA_NET: |