From 147d2601d8fabf9451364f2d58098530a37eb3c9 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 27 Jan 2014 18:16:55 -0500 Subject: capabilities: add descriptions for AUDIT_CONTROL and AUDIT_WRITE Fill in missing descriptions for AUDIT_CONTROL and AUDIT_WRITE definitions. Signed-off-by: Richard Guy Briggs --- include/uapi/linux/capability.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index ba478fa3012..154dd6d3c8f 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 -- cgit v1.2.3-70-g09d2 From 3f1c82502c299da08b7b7f08b435212e51166ed9 Mon Sep 17 00:00:00 2001 From: William Roberts Date: Tue, 11 Feb 2014 10:12:01 -0800 Subject: audit: Audit proc//cmdline aka proctitle During an audit event, cache and print the value of the process's proctitle value (proc//cmdline). This is useful in situations where processes are started via fork'd virtual machines where the comm field is incorrect. Often times, setting the comm field still is insufficient as the comm width is not very wide and most virtual machine "package names" do not fit. Also, during execution, many threads have their comm field set as well. By tying it back to the global cmdline value for the process, audit records will be more complete in systems with these properties. An example of where this is useful and applicable is in the realm of Android. With Android, their is no fork/exec for VM instances. The bare, preloaded Dalvik VM listens for a fork and specialize request. When this request comes in, the VM forks, and the loads the specific application (specializing). This was done to take advantage of COW and to not require a load of basic packages by the VM on very app spawn. When this spawn occurs, the package name is set via setproctitle() and shows up in procfs. Many of these package names are longer then 16 bytes, the historical width of task->comm. Having the cmdline in the audit records will couple the application back to the record directly. Also, on my Debian development box, some audit records were more useful then what was printed under comm. The cached proctitle is tied to the life-cycle of the audit_context structure and is built on demand. Proctitle is controllable by userspace, and thus should not be trusted. It is meant as an aid to assist in debugging. The proctitle event is emitted during syscall audits, and can be filtered with auditctl. Example: type=AVC msg=audit(1391217013.924:386): avc: denied { getattr } for pid=1971 comm="mkdir" name="/" dev="selinuxfs" ino=1 scontext=system_u:system_r:consolekit_t:s0-s0:c0.c255 tcontext=system_u:object_r:security_t:s0 tclass=filesystem type=SYSCALL msg=audit(1391217013.924:386): arch=c000003e syscall=137 success=yes exit=0 a0=7f019dfc8bd7 a1=7fffa6aed2c0 a2=fffffffffff4bd25 a3=7fffa6aed050 items=0 ppid=1967 pid=1971 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="mkdir" exe="/bin/mkdir" subj=system_u:system_r:consolekit_t:s0-s0:c0.c255 key=(null) type=UNKNOWN[1327] msg=audit(1391217013.924:386): proctitle=6D6B646972002D70002F7661722F72756E2F636F6E736F6C65 Acked-by: Steve Grubb (wrt record formating) Signed-off-by: William Roberts Signed-off-by: Eric Paris --- include/uapi/linux/audit.h | 1 + kernel/audit.h | 6 +++++ kernel/auditsc.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 2d48fe1274c..4315ee99b96 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -109,6 +109,7 @@ #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_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/kernel/audit.h b/kernel/audit.h index 57cc64d6771..38c967d28de 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/auditsc.c b/kernel/auditsc.c index 6874c1fd453..043d1ef9362 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -70,6 +70,7 @@ #include #include #include +#include #include "audit.h" @@ -81,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; @@ -844,6 +848,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; @@ -956,6 +967,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); } @@ -1272,6 +1284,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; @@ -1389,6 +1454,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) -- cgit v1.2.3-70-g09d2 From 4b58841149dcaa500ceba1d5378ae70622fe4899 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Sat, 15 Mar 2014 14:48:00 +0900 Subject: audit: Add generic compat syscall support lib/audit.c provides a generic function for auditing system calls. This patch extends it for compat syscall support on bi-architectures (32/64-bit) by adding lib/compat_audit.c. What is required to support this feature are: * add asm/unistd32.h for compat system call names * select CONFIG_AUDIT_ARCH_COMPAT_GENERIC Signed-off-by: AKASHI Takahiro Acked-by: Richard Guy Briggs Signed-off-by: Eric Paris --- include/linux/audit.h | 8 ++++++++ include/uapi/linux/audit.h | 6 ++++++ lib/Kconfig | 9 +++++++++ lib/Makefile | 1 + lib/audit.c | 15 +++++++++++++- lib/compat_audit.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 lib/compat_audit.c (limited to 'include/uapi') diff --git a/include/linux/audit.h b/include/linux/audit.h index ec1464df4c6..4b2983e25ce 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 */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4315ee99b96..9af01d77dc4 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -362,6 +362,12 @@ enum { #define AUDIT_ARCH_SPARC64 (EM_SPARCV9|__AUDIT_ARCH_64BIT) #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#ifdef CONFIG_COMPAT +#define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT)) +#else +#define audit_is_compat(arch) false +#endif + #define AUDIT_PERM_EXEC 1 #define AUDIT_PERM_WRITE 2 #define AUDIT_PERM_READ 4 diff --git a/lib/Kconfig b/lib/Kconfig index 991c98bc4a3..1e80cb3c77a 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 a459c31e8c6..972552b39cf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -93,6 +93,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 76bbed4a20e..1d726a22565 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 00000000000..873f75b640a --- /dev/null +++ b/lib/compat_audit.c @@ -0,0 +1,50 @@ +#include +#include +#include + +unsigned compat_dir_class[] = { +#include +~0U +}; + +unsigned compat_read_class[] = { +#include +~0U +}; + +unsigned compat_write_class[] = { +#include +~0U +}; + +unsigned compat_chattr_class[] = { +#include +~0U +}; + +unsigned compat_signal_class[] = { +#include +~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; + } +} -- cgit v1.2.3-70-g09d2 From 356750e35e86485c464704c0a32c1d8dc77590d7 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 24 Mar 2014 12:13:48 -0400 Subject: audit: define audit_is_compat in kernel internal header We were exposing a function based on kernel config options to userspace. This is wrong. Move it to the audit internal header. Suggested-by: Chris Metcalf Signed-off-by: Eric Paris --- include/linux/audit.h | 6 ++++++ include/uapi/linux/audit.h | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include/uapi') diff --git a/include/linux/audit.h b/include/linux/audit.h index 4b2983e25ce..611a59a56f1 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -102,6 +102,12 @@ struct filename; extern void audit_log_session_info(struct audit_buffer *ab); +#ifdef CONFIG_COMPAT +#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/uapi/linux/audit.h b/include/uapi/linux/audit.h index 9af01d77dc4..4315ee99b96 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -362,12 +362,6 @@ enum { #define AUDIT_ARCH_SPARC64 (EM_SPARCV9|__AUDIT_ARCH_64BIT) #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) -#ifdef CONFIG_COMPAT -#define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT)) -#else -#define audit_is_compat(arch) false -#endif - #define AUDIT_PERM_EXEC 1 #define AUDIT_PERM_WRITE 2 #define AUDIT_PERM_READ 4 -- cgit v1.2.3-70-g09d2 From ab9705f34ce92b4f0da494859e69688e1e34e387 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 2 Apr 2014 16:21:24 -0400 Subject: audit: renumber AUDIT_FEATURE_CHANGE into the 1300 range 1000-1099 is for configuring things. So auditd ignored such messages. This is about actually logging what was configured. Move it into the range for such types of messages. Reported-by: Steve Grubb Signed-off-by: Eric Paris --- include/uapi/linux/audit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/uapi') diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4315ee99b96..11917f747cb 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 */ @@ -110,6 +109,7 @@ #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 */ -- cgit v1.2.3-70-g09d2