diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-12 12:38:53 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-12 12:38:53 -0700 | 
| commit | 0b747172dce6e0905ab173afbaffebb7a11d89bd (patch) | |
| tree | cef4092aa49bd44d4759b58762bfa221dac45f57 | |
| parent | b7e70ca9c7d7f049bba8047d7ab49966fd5e9e9d (diff) | |
| parent | 312103d64d0fcadb332899a2c84b357ddb18f4e3 (diff) | |
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
  ...
36 files changed, 351 insertions, 119 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index f6c6b345388c..b7ff9a318c31 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -22,6 +22,7 @@ config ALPHA  	select GENERIC_SMP_IDLE_THREAD  	select GENERIC_STRNCPY_FROM_USER  	select GENERIC_STRNLEN_USER +	select HAVE_ARCH_AUDITSYSCALL  	select HAVE_MOD_ARCH_SPECIFIC  	select MODULES_USE_ELF_RELA  	select ODD_RT_SIGACTION diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5db05f6a0412..ab438cb5af55 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -24,6 +24,7 @@ config ARM  	select GENERIC_STRNCPY_FROM_USER  	select GENERIC_STRNLEN_USER  	select HARDIRQS_SW_RESEND +	select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT)  	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL  	select HAVE_ARCH_KGDB  	select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index 73ddd7239b33..4651f6999b7d 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h @@ -7,7 +7,7 @@  #ifndef _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/err.h>  #include <linux/sched.h> @@ -103,8 +103,7 @@ static inline void syscall_set_arguments(struct task_struct *task,  	memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0]));  } -static inline int syscall_get_arch(struct task_struct *task, -				   struct pt_regs *regs) +static inline int syscall_get_arch(void)  {  	/* ARM tasks don't change audit architectures on the fly. */  	return AUDIT_ARCH_ARM; diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 1325c3bc58e1..12c3afee0f6f 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -45,6 +45,7 @@ config IA64  	select HAVE_MOD_ARCH_SPECIFIC  	select MODULES_USE_ELF_RELA  	select ARCH_USE_CMPXCHG_LOCKREF +	select HAVE_ARCH_AUDITSYSCALL  	default y  	help  	  The Itanium Processor Family is Intel's 64-bit successor to diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index 6c488c85d791..c6e9cd2bca8d 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h @@ -14,7 +14,7 @@  #define __ASM_MIPS_SYSCALL_H  #include <linux/compiler.h> -#include <linux/audit.h> +#include <uapi/linux/audit.h>  #include <linux/elf-em.h>  #include <linux/kernel.h>  #include <linux/sched.h> @@ -127,12 +127,11 @@ extern const unsigned long sys_call_table[];  extern const unsigned long sys32_call_table[];  extern const unsigned long sysn32_call_table[]; -static inline int syscall_get_arch(struct task_struct *task, -				   struct pt_regs *regs) +static inline int syscall_get_arch(void)  {  	int arch = EM_MIPS;  #ifdef CONFIG_64BIT -	if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) +	if (!test_thread_flag(TIF_32BIT_REGS))  		arch |= __AUDIT_ARCH_64BIT;  #endif  #if defined(__LITTLE_ENDIAN) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 7271e5a83081..71f85f427034 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -649,7 +649,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)  	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))  		trace_sys_enter(regs, regs->regs[2]); -	audit_syscall_entry(syscall_get_arch(current, regs), +	audit_syscall_entry(syscall_get_arch(),  			    syscall,  			    regs->regs[4], regs->regs[5],  			    regs->regs[6], regs->regs[7]); diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index bb2a8ec440e7..1faefed32749 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -28,6 +28,7 @@ config PARISC  	select CLONE_BACKWARDS  	select TTY # Needed for pdc_cons.c  	select HAVE_DEBUG_STACKOVERFLOW +	select HAVE_ARCH_AUDITSYSCALL  	help  	  The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6c03a94991ad..e0998997943b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -144,6 +144,7 @@ config PPC  	select HAVE_DEBUG_STACKOVERFLOW  	select HAVE_IRQ_EXIT_ON_IRQ_STACK  	select ARCH_USE_CMPXCHG_LOCKREF if PPC64 +	select HAVE_ARCH_AUDITSYSCALL  config GENERIC_CSUM  	def_bool CPU_LITTLE_ENDIAN diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 346d21678ffd..d68fe34799b0 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -103,6 +103,7 @@ config S390  	select GENERIC_SMP_IDLE_THREAD  	select GENERIC_TIME_VSYSCALL  	select HAVE_ALIGNED_STRUCT_PAGE if SLUB +	select HAVE_ARCH_AUDITSYSCALL  	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5  	select HAVE_ARCH_SECCOMP_FILTER  	select HAVE_ARCH_TRACEHOOK diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index cd29d2f4e4f3..777687055e7b 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -12,7 +12,7 @@  #ifndef _ASM_SYSCALL_H  #define _ASM_SYSCALL_H	1 -#include <linux/audit.h> +#include <uapi/linux/audit.h>  #include <linux/sched.h>  #include <linux/err.h>  #include <asm/ptrace.h> @@ -89,11 +89,10 @@ static inline void syscall_set_arguments(struct task_struct *task,  		regs->orig_gpr2 = args[0];  } -static inline int syscall_get_arch(struct task_struct *task, -				   struct pt_regs *regs) +static inline int syscall_get_arch(void)  {  #ifdef CONFIG_COMPAT -	if (test_tsk_thread_flag(task, TIF_31BIT)) +	if (test_tsk_thread_flag(current, TIF_31BIT))  		return AUDIT_ARCH_S390;  #endif  	return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ba55e939a820..834b67c4db5a 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -42,6 +42,7 @@ config SUPERH  	select MODULES_USE_ELF_RELA  	select OLD_SIGSUSPEND  	select OLD_SIGACTION +	select HAVE_ARCH_AUDITSYSCALL  	help  	  The SuperH is a RISC processor targeted for use in embedded systems  	  and consumer electronics; it was also used in the Sega Dreamcast diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 7d8b7e94b93b..29f2e988c56a 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -77,6 +77,7 @@ config SPARC64  	select ARCH_HAVE_NMI_SAFE_CMPXCHG  	select HAVE_C_RECORDMCOUNT  	select NO_BOOTMEM +	select HAVE_ARCH_AUDITSYSCALL  config ARCH_DEFCONFIG  	string diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index 21ca44c4f6d5..6915d28cf118 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common @@ -1,6 +1,7 @@  config UML  	bool  	default y +	select HAVE_ARCH_AUDITSYSCALL  	select HAVE_UID16  	select GENERIC_IRQ_SHOW  	select GENERIC_CPU_DEVICES diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5b8ec0f53b57..25d2c6f7325e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -129,6 +129,7 @@ config X86  	select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64  	select HAVE_CC_STACKPROTECTOR  	select GENERIC_CPU_AUTOPROBE +	select HAVE_ARCH_AUDITSYSCALL  config INSTRUCTION_DECODER  	def_bool y diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index aea284b41312..d6a756ae04c8 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -13,7 +13,7 @@  #ifndef _ASM_X86_SYSCALL_H  #define _ASM_X86_SYSCALL_H -#include <linux/audit.h> +#include <uapi/linux/audit.h>  #include <linux/sched.h>  #include <linux/err.h>  #include <asm/asm-offsets.h>	/* For NR_syscalls */ @@ -91,8 +91,7 @@ static inline void syscall_set_arguments(struct task_struct *task,  	memcpy(®s->bx + i, args, n * sizeof(args[0]));  } -static inline int syscall_get_arch(struct task_struct *task, -				   struct pt_regs *regs) +static inline int syscall_get_arch(void)  {  	return AUDIT_ARCH_I386;  } @@ -221,8 +220,7 @@ static inline void syscall_set_arguments(struct task_struct *task,  		}  } -static inline int syscall_get_arch(struct task_struct *task, -				   struct pt_regs *regs) +static inline int syscall_get_arch(void)  {  #ifdef CONFIG_IA32_EMULATION  	/* @@ -234,7 +232,7 @@ static inline int syscall_get_arch(struct task_struct *task,  	 *  	 * 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;  #endif  	/* Both x32 and x86_64 are considered "64-bit". */ diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index b0e540137e39..90ca082935f6 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -65,6 +65,7 @@ static void tty_audit_log(const char *description, int major, int minor,  {  	struct audit_buffer *ab;  	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 loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));  	unsigned int sessionid = audit_get_sessionid(tsk); @@ -74,7 +75,7 @@ static void tty_audit_log(const char *description, int major, int minor,  		char name[sizeof(tsk->comm)];  		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);  		get_task_comm(name, tsk);  		audit_log_untrustedstring(ab, name); diff --git a/fs/proc/base.c b/fs/proc/base.c index 6b7087e2e8fb..2d696b0c93bf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -200,41 +200,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path)  	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; -	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; +	return get_cmdline(task, buffer, PAGE_SIZE);  }  static int proc_pid_auxv(struct task_struct *task, char *buffer) diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h index 5b09392db673..d401e5463fb0 100644 --- a/include/asm-generic/syscall.h +++ b/include/asm-generic/syscall.h @@ -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 - * @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.   * @@ -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   * 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 */ diff --git a/include/linux/audit.h b/include/linux/audit.h index ec1464df4c60..22cfddb75566 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -79,6 +79,14 @@ extern int is_audit_feature_set(int which);  extern int __init audit_register_class(int class, unsigned *list);  extern int audit_classify_syscall(int abi, unsigned syscall);  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 */  #define	AUDIT_TYPE_UNKNOWN	0	/* we don't know yet */ @@ -94,6 +102,12 @@ struct filename;  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  /* These are defined in auditsc.c */  				/* Public API */ diff --git a/include/linux/mm.h b/include/linux/mm.h index abc848412e3c..bf9811e1321a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1204,6 +1204,7 @@ void account_page_writeback(struct page *page);  int set_page_dirty(struct page *page);  int set_page_dirty_lock(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? */  static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) diff --git a/include/linux/sched.h b/include/linux/sched.h index 075b3056c0c0..25f54c79f757 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -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,  					struct pid_namespace *ns)  { @@ -1758,7 +1776,7 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk)   *   * 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;  } diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 2d48fe1274ca..11917f747cb4 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -70,7 +70,6 @@  #define AUDIT_TTY_SET		1017	/* Set TTY auditing status */  #define AUDIT_SET_FEATURE	1018	/* Turn an audit feature on or off */  #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_USER_AVC		1107	/* We filter this differently */ @@ -109,6 +108,8 @@  #define AUDIT_NETFILTER_PKT	1324	/* Packets traversing netfilter chains */  #define AUDIT_NETFILTER_CFG	1325	/* Netfilter chain modifications */  #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_SELINUX_ERR	1401	/* Internal SE Linux Errors */ diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index ba478fa3012e..154dd6d3c8fe 100644 --- a/include/uapi/linux/capability.h +++ b/include/uapi/linux/capability.h @@ -308,8 +308,12 @@ struct vfs_cap_data {  #define CAP_LEASE            28 +/* Allow writing the audit log via unicast netlink socket */ +  #define CAP_AUDIT_WRITE      29 +/* Allow configuration of audit via unicast netlink socket */ +  #define CAP_AUDIT_CONTROL    30  #define CAP_SETFCAP	     31 diff --git a/init/Kconfig b/init/Kconfig index 427ba60d638f..765018c24cf9 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -292,9 +292,12 @@ config AUDIT  	  logging of avc messages output).  Does not do system-call  	  auditing without CONFIG_AUDITSYSCALL. +config HAVE_ARCH_AUDITSYSCALL +	bool +  config AUDITSYSCALL  	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  	help  	  Enable low-overhead system-call auditing infrastructure that diff --git a/kernel/audit.c b/kernel/audit.c index 95a20f3f52f1..7c2893602d06 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -182,7 +182,7 @@ struct audit_buffer {  struct audit_reply {  	__u32 portid; -	struct net *net;	 +	struct net *net;  	struct sk_buff *skb;  }; @@ -396,7 +396,7 @@ static void audit_printk_skb(struct sk_buff *skb)  		if (printk_ratelimit())  			pr_notice("type=%d %s\n", nlh->nlmsg_type, data);  		else -			audit_log_lost("printk limit exceeded\n"); +			audit_log_lost("printk limit exceeded");  	}  	audit_hold_skb(skb); @@ -412,7 +412,7 @@ static void kauditd_send_skb(struct sk_buff *skb)  		BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */  		if (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_sock = NULL;  		} @@ -607,7 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)  {  	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  	 * 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)  	 * userspace will reject all logins.  This should be removed when we  	 * support non init namespaces!!  	 */ -	if ((current_user_ns() != &init_user_ns) || -	    (task_active_pid_ns(current) != &init_pid_ns)) +	if (current_user_ns() != &init_user_ns)  		return -ECONNREFUSED;  	switch (msg_type) { @@ -639,6 +638,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)  	case AUDIT_TTY_SET:  	case AUDIT_TRIM:  	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))  			err = -EPERM;  		break; @@ -659,6 +663,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)  {  	int rc = 0;  	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) {  		*ab = NULL; @@ -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);  	if (unlikely(!*ab))  		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_task_context(*ab); @@ -1097,7 +1102,7 @@ static void __net_exit audit_net_exit(struct net *net)  		audit_sock = NULL;  	} -	rcu_assign_pointer(aunet->nlsk, NULL); +	RCU_INIT_POINTER(aunet->nlsk, NULL);  	synchronize_net();  	netlink_kernel_release(sock);  } @@ -1829,11 +1834,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)  	spin_unlock_irq(&tsk->sighand->siglock);  	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"  			 " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", -			 sys_getppid(), -			 tsk->pid, +			 task_ppid_nr(tsk), +			 task_pid_nr(tsk),  			 from_kuid(&init_user_ns, audit_get_loginuid(tsk)),  			 from_kuid(&init_user_ns, cred->uid),  			 from_kgid(&init_user_ns, cred->gid), diff --git a/kernel/audit.h b/kernel/audit.h index 8df132214606..7bb65730c890 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -106,6 +106,11 @@ struct audit_names {  	bool			should_free;  }; +struct audit_proctitle { +	int	len;	/* length of the cmdline field. */ +	char	*value;	/* the cmdline field */ +}; +  /* The per-task audit context. */  struct audit_context {  	int		    dummy;	/* must be the first element */ @@ -202,6 +207,7 @@ struct audit_context {  		} execve;  	};  	int fds[2]; +	struct audit_proctitle proctitle;  #if AUDIT_DEBUG  	int		    put_count; diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 92062fd6cc8c..8e9bc9c3dbb7 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -19,6 +19,8 @@   * 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/audit.h>  #include <linux/kthread.h> @@ -226,7 +228,7 @@ static int audit_match_signal(struct audit_entry *entry)  #endif  /* 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;  	struct audit_entry *entry; @@ -249,7 +251,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)  		;  	}  	if (unlikely(rule->action == AUDIT_POSSIBLE)) { -		printk(KERN_ERR "AUDIT_POSSIBLE is deprecated\n"); +		pr_err("AUDIT_POSSIBLE is deprecated\n");  		goto exit_err;  	}  	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,  	int i;  	char *str; -	entry = audit_to_entry_common((struct audit_rule *)data); +	entry = audit_to_entry_common(data);  	if (IS_ERR(entry))  		goto exit_nofree; @@ -431,6 +433,19 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,  			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);  		if (err)  			goto exit_free; @@ -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  			 * become valid after a policy reload. */  			if (err == -EINVAL) { -				printk(KERN_WARNING "audit rule for LSM " -				       "\'%s\' is invalid\n",  str); +				pr_warn("audit rule for LSM \'%s\' is invalid\n", +					str);  				err = 0;  			}  			if (err) { @@ -709,8 +724,8 @@ static inline int audit_dupe_lsm_field(struct audit_field *df,  	/* Keep currently invalid fields around in case they  	 * become valid after a policy reload. */  	if (ret == -EINVAL) { -		printk(KERN_WARNING "audit rule for LSM \'%s\' is " -		       "invalid\n", df->lsm_str); +		pr_warn("audit rule for LSM \'%s\' is invalid\n", +			df->lsm_str);  		ret = 0;  	} @@ -1240,12 +1255,14 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,  	for (i = 0; i < rule->field_count; i++) {  		struct audit_field *f = &rule->fields[i]; +		pid_t pid;  		int result = 0;  		u32 sid;  		switch (f->type) {  		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;  		case AUDIT_UID:  			result = audit_uid_comparator(current_uid(), f->op, f->uid); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 7aef2f4b6c64..f251a5e8d17a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -42,6 +42,8 @@   * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/init.h>  #include <asm/types.h>  #include <linux/atomic.h> @@ -68,6 +70,7 @@  #include <linux/capability.h>  #include <linux/fs_struct.h>  #include <linux/compat.h> +#include <linux/ctype.h>  #include "audit.h" @@ -79,6 +82,9 @@  /* no execve audit message should be longer than this (userspace limits) */  #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 */  int audit_n_rules; @@ -451,15 +457,17 @@ static int audit_filter_rules(struct task_struct *tsk,  		struct audit_field *f = &rule->fields[i];  		struct audit_names *n;  		int result = 0; +		pid_t pid;  		switch (f->type) {  		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;  		case AUDIT_PPID:  			if (ctx) {  				if (!ctx->ppid) -					ctx->ppid = sys_getppid(); +					ctx->ppid = task_ppid_nr(tsk);  				result = audit_comparator(ctx->ppid, f->op, f->val);  			}  			break; @@ -805,7 +813,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)  	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,  						      long return_code)  { @@ -842,6 +851,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,  	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)  {  	struct audit_names *n, *next; @@ -850,16 +866,15 @@ static inline void audit_free_names(struct audit_context *context)  	if (context->put_count + context->ino_count != context->name_count) {  		int i = 0; -		printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" -		       " name_count=%d put_count=%d" -		       " ino_count=%d [NOT freeing]\n", -		       __FILE__, __LINE__, +		pr_err("%s:%d(:%d): major=%d in_syscall=%d" +		       " name_count=%d put_count=%d ino_count=%d" +		       " [NOT freeing]\n", __FILE__, __LINE__,  		       context->serial, context->major, context->in_syscall,  		       context->name_count, context->put_count,  		       context->ino_count);  		list_for_each_entry(n, &context->names_list, list) { -			printk(KERN_ERR "names[%d] = %p = %s\n", i++, -			       n->name, n->name->name ?: "(null)"); +			pr_err("names[%d] = %p = %s\n", i++, n->name, +			       n->name->name ?: "(null)");  		}  		dump_stack();  		return; @@ -955,6 +970,7 @@ static inline void audit_free_context(struct audit_context *context)  	audit_free_aux(context);  	kfree(context->filterkey);  	kfree(context->sockaddr); +	audit_proctitle_free(context);  	kfree(context);  } @@ -1157,7 +1173,7 @@ static void audit_log_execve_info(struct audit_context *context,  	 */  	buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);  	if (!buf) { -		audit_panic("out of memory for argv string\n"); +		audit_panic("out of memory for argv string");  		return;  	} @@ -1271,6 +1287,59 @@ static void show_special(struct audit_context *context, int *call_panic)  	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)  {  	int i, call_panic = 0; @@ -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_proctitle(tsk, context); +  	/* Send end of event record to help user space know we are finished */  	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);  	if (ab) @@ -1406,7 +1477,7 @@ void __audit_free(struct task_struct *tsk)  {  	struct audit_context *context; -	context = audit_get_context(tsk, 0, 0); +	context = audit_take_context(tsk, 0, 0);  	if (!context)  		return; @@ -1500,7 +1571,7 @@ void __audit_syscall_exit(int success, long return_code)  	else  		success = AUDITSC_FAILURE; -	context = audit_get_context(tsk, success, return_code); +	context = audit_take_context(tsk, success, return_code);  	if (!context)  		return; @@ -1550,7 +1621,7 @@ static inline void handle_one(const struct inode *inode)  	if (likely(put_tree_ref(context, chunk)))  		return;  	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_put_chunk(chunk);  		unroll_tree_refs(context, p, count); @@ -1609,8 +1680,7 @@ retry:  			goto retry;  		}  		/* too bad */ -		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");  		unroll_tree_refs(context, p, count);  		audit_set_auditable(context);  		return; @@ -1682,7 +1752,7 @@ void __audit_getname(struct filename *name)  	if (!context->in_syscall) {  #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);  		dump_stack();  #endif @@ -1721,15 +1791,15 @@ void audit_putname(struct filename *name)  	BUG_ON(!context);  	if (!name->aname || !context->in_syscall) {  #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);  		if (context->name_count) {  			struct audit_names *n;  			int i = 0;  			list_for_each_entry(n, &context->names_list, list) -				printk(KERN_ERR "name[%d] = %p = %s\n", i++, -				       n->name, n->name->name ?: "(null)"); +				pr_err("name[%d] = %p = %s\n", i++, n->name, +				       n->name->name ?: "(null)");  			}  #endif  		final_putname(name); @@ -1738,9 +1808,8 @@ void audit_putname(struct filename *name)  	else {  		++context->put_count;  		if (context->put_count > context->name_count) { -			printk(KERN_ERR "%s:%d(:%d): major=%d" -			       " in_syscall=%d putname(%p) name_count=%d" -			       " put_count=%d\n", +			pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" +			       " name_count=%d put_count=%d\n",  			       __FILE__, __LINE__,  			       context->serial, context->major,  			       context->in_syscall, name->name, @@ -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);  	if (!ab)  		return; -	audit_log_format(ab, "pid=%d uid=%u" -			 " old-auid=%u new-auid=%u old-ses=%u new-ses=%u" -			 " res=%d", -			 current->pid, uid, -			 oldloginuid, loginuid, oldsessionid, sessionid, -			 !rc); +	audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); +	audit_log_task_context(ab); +	audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", +			 oldloginuid, loginuid, oldsessionid, sessionid, !rc);  	audit_log_end(ab);  } @@ -2208,7 +2275,7 @@ void __audit_ptrace(struct task_struct *t)  {  	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_uid = task_uid(t);  	context->target_sessionid = audit_get_sessionid(t); @@ -2233,7 +2300,7 @@ int __audit_signal_info(int sig, struct task_struct *t)  	if (audit_pid && t->tgid == audit_pid) {  		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))  				audit_sig_uid = tsk->loginuid;  			else @@ -2247,7 +2314,7 @@ int __audit_signal_info(int sig, struct task_struct *t)  	/* optimize the common case by putting first signal recipient directly  	 * in audit_context */  	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_uid = t_uid;  		ctx->target_sessionid = audit_get_sessionid(t); @@ -2268,7 +2335,7 @@ int __audit_signal_info(int sig, struct task_struct *t)  	}  	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_uid[axp->pid_count] = t_uid;  	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); @@ -2368,7 +2435,7 @@ static void audit_log_task(struct audit_buffer *ab)  			 from_kgid(&init_user_ns, gid),  			 sessionid);  	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);  	if (mm) {  		down_read(&mm->mmap_sem); diff --git a/kernel/seccomp.c b/kernel/seccomp.c index fd609bd9d6dd..d8d046c0726a 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -71,7 +71,7 @@ static void populate_seccomp_data(struct seccomp_data *sd)  	struct pt_regs *regs = task_pt_regs(task);  	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. */  	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)  	info.si_code = SYS_SECCOMP;  	info.si_call_addr = (void __user *)KSTK_EIP(current);  	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;  	force_sig_info(SIGSYS, &info, current);  } diff --git a/lib/Kconfig b/lib/Kconfig index 5d4984c505f8..4771fb3f4da4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -182,6 +182,15 @@ config AUDIT_GENERIC  	depends on AUDIT && !AUDIT_ARCH  	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  	bool "PRNG perform self test on init"  	default n diff --git a/lib/Makefile b/lib/Makefile index 48140e3ba73f..0cd7b68e1382 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o  obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o  obj-$(CONFIG_SMP) += percpu_counter.o  obj-$(CONFIG_AUDIT_GENERIC) += audit.o +obj-$(CONFIG_AUDIT_COMPAT_GENERIC) += compat_audit.o  obj-$(CONFIG_SWIOTLB) += swiotlb.o  obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o diff --git a/lib/audit.c b/lib/audit.c index 76bbed4a20e5..1d726a22565b 100644 --- a/lib/audit.c +++ b/lib/audit.c @@ -30,11 +30,17 @@ static unsigned signal_class[] = {  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)  { +	if (audit_is_compat(abi)) +		return audit_classify_compat_syscall(abi, syscall); +  	switch(syscall) {  #ifdef __NR_open  	case __NR_open: @@ -57,6 +63,13 @@ int audit_classify_syscall(int abi, unsigned syscall)  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_READ, read_class);  	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); diff --git a/lib/compat_audit.c b/lib/compat_audit.c new file mode 100644 index 000000000000..873f75b640ab --- /dev/null +++ b/lib/compat_audit.c @@ -0,0 +1,50 @@ +#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; +	} +} diff --git a/mm/util.c b/mm/util.c index d7813e6d4cc7..f380af7ea779 100644 --- a/mm/util.c +++ b/mm/util.c @@ -446,6 +446,54 @@ unsigned long vm_commit_limit(void)  	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. */  EXPORT_TRACEPOINT_SYMBOL(kmalloc); diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c index aab9fa5a8231..90987d15b6fe 100644 --- a/security/integrity/integrity_audit.c +++ b/security/integrity/integrity_audit.c @@ -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);  	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, audit_get_loginuid(current)),  			 audit_get_sessionid(current)); diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 9a62045e6282..69fdf3bc765b 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -220,7 +220,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,  	 */  	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);  	switch (a->type) { @@ -278,9 +278,12 @@ static void dump_common_audit_data(struct audit_buffer *ab,  	}  	case LSM_AUDIT_DATA_TASK:  		tsk = a->u.tsk; -		if (tsk && tsk->pid) { -			audit_log_format(ab, " pid=%d comm=", tsk->pid); -			audit_log_untrustedstring(ab, tsk->comm); +		if (tsk) { +			pid_t pid = task_pid_nr(tsk); +			if (pid) { +				audit_log_format(ab, " pid=%d comm=", pid); +				audit_log_untrustedstring(ab, tsk->comm); +			}  		}  		break;  	case LSM_AUDIT_DATA_NET:  | 
