[PATCH 1/1] Added exe field to audit core dump signal log
by Paul Davies C
Currently when the coredump signals are logged by the audit system , the
actual path to the executable is not logged. Without details of exe , the
system admin may not have an exact idea on what program failed.
This patch changes the audit_log_task() so that the path to the exe is also
logged.
Signed-off-by: Paul Davies C <pauldaviesc(a)gmail.com>
---
kernel/auditsc.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 9845cb3..988de72 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2353,6 +2353,7 @@ static void audit_log_task(struct audit_buffer *ab)
kuid_t auid, uid;
kgid_t gid;
unsigned int sessionid;
+ struct mm_struct *mm = current->mm;
auid = audit_get_loginuid(current);
sessionid = audit_get_sessionid(current);
@@ -2366,6 +2367,12 @@ static void audit_log_task(struct audit_buffer *ab)
audit_log_task_context(ab);
audit_log_format(ab, " pid=%d comm=", current->pid);
audit_log_untrustedstring(ab, current->comm);
+ if (mm) {
+ down_read(&mm->mmap_sem);
+ if (mm->exe_file)
+ audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
+ up_read(&mm->mmap_sem);
+ }
}
static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
--
1.7.9.5
9 years, 3 months
[PATCH v10 0/3] arm64: Add audit support
by AKASHI Takahiro
(This patchset was already acked by the maintainers, and
re-targeting v3.17. See change history.)
(I don't think that discussions below about ptrace() have impact on
this patchset.
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/268923.html
)
This patchset adds system call audit support on arm64.
Both 32-bit (AUDIT_ARCH_ARM) and 64-bit tasks (AUDIT_ARCH_AARCH64)
are supported. Since arm64 has the exact same set of system calls
on LE and BE, we don't care about endianness (or more specifically
__AUDIT_ARCH_64BIT bit in AUDIT_ARCH_*).
This patch should work correctly with:
* userspace audit tool (v2.3.6 or later)
This code was tested on both 32-bit and 64-bit LE userland
in the following two ways:
1) basic operations with auditctl/autrace
# auditctl -a exit,always -S openat -F path=/etc/inittab
# auditctl -a exit,always -F dir=/tmp -F perm=rw
# auditctl -a task,always
# autrace /bin/ls
by comparing output from autrace with one from strace
2) audit-test-code (+ my workarounds for arm/arm64)
by running "audit-tool", "filter" and "syscalls" test categories.
Changes v9 -> v10:
* rebased on 3.16-rc3
* included Catalin's patch[1/3] and added more syscall definitions for 3.16
Changes v8 -> v9:
* rebased on 3.15-rc, especially due to the change of syscall_get_arch()
interface [1,2/2]
Changes v7 -> v8:
* aligned with the change in "audit: generic compat system call audit
support" v5 [1/2]
* aligned with the change in "arm64: split syscall_trace() into separate
functions for enter/exit" v5 [2/2]
Changes v6 -> v7:
* changed an include file in syscall.h from <linux/audit.h> to
<uapi/linux/audit.h> [1/2]
* aligned with the patch, "arm64: split syscall_trace() into separate
functions for enter/exit" [2/2]
Changes v5 -> v6:
* removed and put "arm64: Add regs_return_value() in syscall.h" patch into
a separate set
* aligned with the change in "arm64: make a single hook to syscall_trace()
for all syscall features" v3 [1/2]
Changes v4 -> v5:
* rebased to 3.14-rcX
* added a guard against TIF_SYSCALL_AUDIT [3/3]
* aligned with the change in "arm64: make a single hook to syscall_trace()
for all syscall features" v2 [3/3]
Changes v3 -> v4:
* Modified to sync with the patch, "make a single hook to syscall_trace()
for all syscall features"
* aligned with "audit: Add CONFIG_HAVE_ARCH_AUDITSYSCALL" patch
Changes v2 -> v3:
* Remove asm/audit.h.
See "generic compat syscall audit support" patch v4
* Remove endianness dependency, ie. AUDIT_ARCH_ARMEB/AARCH64EB.
* Remove kernel/syscalls/Makefile which was used to create unistd32.h.
See Catalin's "Add __NR_* definitions for compat syscalls" patch
Changes v1 -> v2:
* Modified to utilize "generic compat system call audit" [3/6, 4/6, 5/6]
Please note that a required header, unistd_32.h, is automatically
generated from unistd32.h.
* Refer to regs->orig_x0 instead of regs->x0 as the first argument of
system call in audit_syscall_entry() [6/6]
* Include "Add regs_return_value() in syscall.h" patch [2/6],
which was not intentionally included in v1 because it could be added
by "kprobes support".
AKASHI Takahiro (2):
arm64: Add audit support
arm64: audit: Add audit hook in syscall_trace_enter/exit()
Catalin Marinas (1):
arm64: Add __NR_* definitions for compat syscalls
arch/arm64/Kconfig | 2 +
arch/arm64/include/asm/syscall.h | 14 +
arch/arm64/include/asm/unistd.h | 17 +
arch/arm64/include/asm/unistd32.h | 1166 ++++++++++++++++++++++++-------------
arch/arm64/kernel/entry.S | 1 -
arch/arm64/kernel/kuser32.S | 2 +-
arch/arm64/kernel/ptrace.c | 7 +
arch/arm64/kernel/signal32.c | 2 +-
arch/arm64/kernel/sys_compat.c | 2 +-
include/uapi/linux/audit.h | 1 +
10 files changed, 810 insertions(+), 404 deletions(-)
--
1.7.9.5
9 years, 9 months
[PATCH] TaskTracker : Simplified thread information tracker.
by Tetsuo Handa
Yesterday I went to LinuxCon Japan 2014 and stopped at Red Hat's booth
and Oracle's booth. I explained about this module ( using page 92 of
http://I-love.SAKURA.ne.jp/tomoyo/LCJ2014-en.pdf ) and got positive
responses from persons who have experienced troubleshooting jobs.
I was convinced that I am not the only person who is bothered by lack of
process history information in the logs. Therefore, I repost this module
toward inclusion into mainline Linux kernel.
Changes from previous version ( http://lwn.net/Articles/575044/ ):
(1) Assign a value to "u32 *seclen" in addition to "char *secdata"
at security_task_getsecid() hook.
(2) Make calculation of time stamp a bit faster.
Background:
When an unexpected system event (e.g. reboot) occurs, the administrator may
want to identify which application triggered the event. System call auditing
could be used for recording such event. However, the audit log may not be
able to provide sufficient information for identifying the application
because the audit log does not reflect how the program was executed.
I sometimes receive "which application triggered the event" questions on RHEL
systems. TOMOYO security module can track how the program was executed, but
TOMOYO is not yet available in Fedora/RHEL distributions.
Although subj= field is added to the audit log if SELinux is not disabled,
SELinux is too difficult to customize as fine grained as I expect in order to
reflect how the program was executed. Therefore, I'm currently using AKARI
and SystemTap for emulating TOMOYO-like tracing.
But AKARI and SystemTap do not help unless the kernel module is loaded before
the unexpected system event occurs. Generally, the administrator is failing
to record the first event, and has to wait for the same event to occur again
after loading the kernel module and/or configuring auditing. I came to think
that we want a built-in kernel routine which is automatically started upon
boot so that we don't fail to record the first event.
What I did:
Assuming that multiple concurrent LSM support comes in the near future,
I wrote a trivial LSM module which emits TOMOYO-like information into the
audit logs.
Usage:
Just register this LSM module. No configuration is needed. You will get
history of current thread in the form of comm name and time stamp pairs
in the subj= field of audit logs like examples shown in the patch
description.
----------
>From ff68d3a4cd496bd263d2939848777fffc30cbc0b Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin-kernel(a)I-love.SAKURA.ne.jp>
Date: Fri, 23 May 2014 21:31:56 +0900
Subject: [PATCH] TaskTracker : Simplified thread information tracker.
Existing audit logs generated via system call auditing functionality include
current thread's comm name. But it is not always sufficient for identifying
which application has requested specific operations because comm name does not
reflect history of current thread.
This security module adds functionality for adding current thread's history
information like TOMOYO security module does, expecting that this module can
help us getting more information from system call auditing functionality.
type=USER_LOGIN msg=audit(1400879947.084:24): pid=4308 uid=0 auid=0 ses=2
subj="swapper/0(2014/05/23-21:17:30)=>init(2014/05/23-21:17:33)=>
switch_root(2014/05/23-21:17:34)=>init(2014/05/23-21:17:34)=>
sh(2014/05/23-21:17:56)=>mingetty(2014/05/23-21:17:56)=>
login(2014/05/23-21:19:05)" msg='op=login id=0 exe="/bin/login" hostname=?
addr=? terminal=tty1 res=success'
type=SYSCALL msg=audit(1400880014.444:26): arch=40000003 syscall=11
success=yes exit=0 a0=8140f78 a1=812b7d8 a2=812b248 a3=812b7d8 items=2
ppid=4323 pid=4355 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0
fsgid=0 tty=pts0 ses=1 comm="tail" exe="/usr/bin/tail"
subj="swapper/0(2014/05/23-21:17:30)=>init(2014/05/23-21:17:33)=>
switch_root(2014/05/23-21:17:34)=>init(2014/05/23-21:17:34)=>
sh(2014/05/23-21:17:37)=>rc(2014/05/23-21:17:37)=>
S55sshd(2014/05/23-21:17:53)=>sshd(2014/05/23-21:17:53)=>
sshd(2014/05/23-21:18:17)=>bash(2014/05/23-21:18:21)=>
tail(2014/05/23-21:20:14)" key=(null)
Signed-off-by: Tetsuo Handa <penguin-kernel(a)I-love.SAKURA.ne.jp>
---
security/Kconfig | 6 +
security/Makefile | 2 +
security/tasktracker/Kconfig | 35 +++++
security/tasktracker/Makefile | 1 +
security/tasktracker/tasktracker.c | 282 ++++++++++++++++++++++++++++++++++++
5 files changed, 326 insertions(+), 0 deletions(-)
create mode 100644 security/tasktracker/Kconfig
create mode 100644 security/tasktracker/Makefile
create mode 100644 security/tasktracker/tasktracker.c
diff --git a/security/Kconfig b/security/Kconfig
index beb86b5..14e7d27 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -122,6 +122,7 @@ source security/smack/Kconfig
source security/tomoyo/Kconfig
source security/apparmor/Kconfig
source security/yama/Kconfig
+source security/tasktracker/Kconfig
source security/integrity/Kconfig
@@ -132,6 +133,7 @@ choice
default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
default DEFAULT_SECURITY_YAMA if SECURITY_YAMA
+ default DEFAULT_SECURITY_TT if SECURITY_TT
default DEFAULT_SECURITY_DAC
help
@@ -153,6 +155,9 @@ choice
config DEFAULT_SECURITY_YAMA
bool "Yama" if SECURITY_YAMA=y
+ config DEFAULT_SECURITY_TT
+ bool "TaskTracker" if SECURITY_TT=y
+
config DEFAULT_SECURITY_DAC
bool "Unix Discretionary Access Controls"
@@ -165,6 +170,7 @@ config DEFAULT_SECURITY
default "tomoyo" if DEFAULT_SECURITY_TOMOYO
default "apparmor" if DEFAULT_SECURITY_APPARMOR
default "yama" if DEFAULT_SECURITY_YAMA
+ default "tt" if DEFAULT_SECURITY_TT
default "" if DEFAULT_SECURITY_DAC
endmenu
diff --git a/security/Makefile b/security/Makefile
index 05f1c93..28a90ed 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -8,6 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack
subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
subdir-$(CONFIG_SECURITY_YAMA) += yama
+subdir-$(CONFIG_SECURITY_TT) += tasktracker
# always enable default capabilities
obj-y += commoncap.o
@@ -22,6 +23,7 @@ obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
obj-$(CONFIG_SECURITY_YAMA) += yama/
+obj-$(CONFIG_SECURITY_TT) += tasktracker/
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
# Object integrity file lists
diff --git a/security/tasktracker/Kconfig b/security/tasktracker/Kconfig
new file mode 100644
index 0000000..6de5354
--- /dev/null
+++ b/security/tasktracker/Kconfig
@@ -0,0 +1,35 @@
+config SECURITY_TT
+ bool "TaskTracker support"
+ depends on SECURITY
+ default n
+ help
+ Existing audit logs generated via system call auditing functionality
+ include current thread's comm name. But it is not always sufficient
+ for identifying which application has requested specific operations
+ because comm name does not reflect history of current thread.
+
+ This security module adds functionality for adding current thread's
+ history information like TOMOYO security module does, expecting that
+ this module can help us getting more information from system call
+ auditing functionality.
+
+ If you are unsure how to answer this question, answer N.
+
+ Usage:
+
+ Just register this module. No configuration is needed.
+
+ You will get history of current thread in the form of
+ comm name and time stamp pairs in the subj= field of audit logs
+ like an example shown below.
+
+ type=SYSCALL msg=audit(1400880014.444:26): arch=40000003 syscall=11
+ success=yes exit=0 a0=8140f78 a1=812b7d8 a2=812b248 a3=812b7d8
+ items=2 ppid=4323 pid=4355 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0
+ egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="tail"
+ exe="/usr/bin/tail" subj="swapper/0(2014/05/23-21:17:30)=>
+ init(2014/05/23-21:17:33)=>switch_root(2014/05/23-21:17:34)=>
+ init(2014/05/23-21:17:34)=>sh(2014/05/23-21:17:37)=>
+ rc(2014/05/23-21:17:37)=>S55sshd(2014/05/23-21:17:53)=>
+ sshd(2014/05/23-21:17:53)=>sshd(2014/05/23-21:18:17)=>
+ bash(2014/05/23-21:18:21)=>tail(2014/05/23-21:20:14)" key=(null)
diff --git a/security/tasktracker/Makefile b/security/tasktracker/Makefile
new file mode 100644
index 0000000..15d03ce
--- /dev/null
+++ b/security/tasktracker/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SECURITY_TT) := tasktracker.o
diff --git a/security/tasktracker/tasktracker.c b/security/tasktracker/tasktracker.c
new file mode 100644
index 0000000..ec4eb0c
--- /dev/null
+++ b/security/tasktracker/tasktracker.c
@@ -0,0 +1,282 @@
+/*
+ * tasktracker.c - Simplified thread information tracker.
+ *
+ * Copyright (C) 2010-2014 Tetsuo Handa <penguin-kernel(a)I-love.SAKURA.ne.jp>
+ */
+#include <linux/security.h>
+#include <linux/binfmts.h>
+
+/* Wrapper structure for passing string buffer. */
+struct tt_record {
+ char history[1024];
+};
+
+/* Structure for representing YYYY/MM/DD hh/mm/ss. */
+struct tt_time {
+ u16 year;
+ u8 month;
+ u8 day;
+ u8 hour;
+ u8 min;
+ u8 sec;
+};
+
+/**
+ * tt_get_time - Get current time in YYYY/MM/DD hh/mm/ss format.
+ *
+ * @stamp: Pointer to "struct tt_time".
+ *
+ * Returns nothing.
+ *
+ * This function does not handle Y2038 problem.
+ */
+static void tt_get_time(struct tt_time *stamp)
+{
+ struct timeval tv;
+ static const u16 tt_eom[2][12] = {
+ { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+ u16 y = 1970;
+ u8 m;
+ bool r;
+ time_t time;
+ do_gettimeofday(&tv);
+ time = tv.tv_sec;
+ stamp->sec = time % 60;
+ time /= 60;
+ stamp->min = time % 60;
+ time /= 60;
+ stamp->hour = time % 24;
+ time /= 24;
+ if (time >= 16071) {
+ /* Start from 2014/01/01 rather than 1970/01/01. */
+ time -= 16071;
+ y += 44;
+ }
+ while (1) {
+ const unsigned short days = (y & 3) ? 365 : 366;
+ if (time < days)
+ break;
+ time -= days;
+ y++;
+ }
+ r = (y & 3) == 0;
+ for (m = 0; m < 11 && time >= tt_eom[r][m]; m++)
+ ;
+ if (m)
+ time -= tt_eom[r][m - 1];
+ stamp->year = y;
+ stamp->month = ++m;
+ stamp->day = ++time;
+}
+
+/**
+ * tt_update_record - Update "struct tt_record" for given credential.
+ *
+ * @record: Pointer to "struct tt_record".
+ *
+ * Returns nothing.
+ */
+static void tt_update_record(struct tt_record *record)
+{
+ char *cp;
+ int i;
+ struct tt_time stamp;
+ tt_get_time(&stamp);
+ /*
+ * Lockless update because current thread's record is not concurrently
+ * accessible, for "struct cred"->security is not visible from other
+ * threads because this function is called upon only boot up and
+ * successful execve() operation.
+ */
+ cp = record->history;
+ i = strlen(cp);
+ while (i >= sizeof(record->history) - (TASK_COMM_LEN * 4 + 30)) {
+ /*
+ * Since this record is not for making security decision,
+ * I don't care by-chance matching "=>" in task's commname.
+ */
+ char *cp2 = strstr(cp + 2, "=>");
+ if (!cp2)
+ return;
+ memmove(cp + 1, cp2, strlen(cp2) + 1);
+ i = strlen(cp);
+ }
+ if (!i)
+ *cp++ = '"';
+ else {
+ cp += i - 1;
+ *cp++ = '=';
+ *cp++ = '>';
+ }
+ /*
+ * Lockless read because this is current thread and being unexpectedly
+ * modified by other thread is not a fatal problem.
+ */
+ for (i = 0; i < TASK_COMM_LEN; i++) {
+ const unsigned char c = current->comm[i];
+ if (!c)
+ break;
+ else if (c == '"' || c == '\\' || c < 0x21 || c > 0x7e) {
+ *cp++ = '\\';
+ *cp++ = (c >> 6) + '0';
+ *cp++ = ((c >> 3) & 7) + '0';
+ *cp++ = (c & 7) + '0';
+ } else
+ *cp++ = c;
+ }
+ sprintf(cp, "(%04u/%02u/%02u-%02u:%02u:%02u)\"", stamp.year,
+ stamp.month, stamp.day, stamp.hour, stamp.min, stamp.sec);
+}
+
+/**
+ * tt_find_record - Find "struct tt_record" for given credential.
+ *
+ * @cred: Pointer to "struct cred".
+ *
+ * Returns pointer to "struct tt_record".
+ */
+static inline struct tt_record *tt_find_record(const struct cred *cred)
+{
+ return cred->security;
+}
+
+/**
+ * tt_cred_alloc_blank - Allocate memory for new credentials.
+ *
+ * @new: Pointer to "struct cred".
+ * @gfp: Memory allocation flags.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tt_cred_alloc_blank(struct cred *new, gfp_t gfp)
+{
+ new->security = kzalloc(sizeof(struct tt_record), gfp);
+ return new->security ? 0 : -ENOMEM;
+}
+
+/**
+ * tt_cred_prepare - Allocate memory for new credentials.
+ *
+ * @new: Pointer to "struct cred".
+ * @old: Pointer to "struct cred".
+ * @gfp: Memory allocation flags.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tt_cred_prepare(struct cred *new, const struct cred *old,
+ gfp_t gfp)
+{
+ if (tt_cred_alloc_blank(new, gfp))
+ return -ENOMEM;
+ strcpy(tt_find_record(new)->history, tt_find_record(old)->history);
+ return 0;
+}
+
+/**
+ * tt_cred_free - Release memory used by credentials.
+ *
+ * @cred: Pointer to "struct cred".
+ *
+ * Returns nothing.
+ */
+static void tt_cred_free(struct cred *cred)
+{
+ kfree(cred->security);
+}
+
+/**
+ * tt_cred_transfer - Transfer "struct tt_record" between credentials.
+ *
+ * @new: Pointer to "struct cred".
+ * @old: Pointer to "struct cred".
+ *
+ * Returns nothing.
+ */
+static void tt_cred_transfer(struct cred *new, const struct cred *old)
+{
+ strcpy(tt_find_record(new)->history, tt_find_record(old)->history);
+}
+
+/**
+ * tt_bprm_committing_creds - A hook which is called when do_execve() succeeded.
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ *
+ * Returns nothing.
+ */
+static void tt_bprm_committing_creds(struct linux_binprm *bprm)
+{
+ tt_update_record(tt_find_record(bprm->cred));
+}
+
+/**
+ * tt_task_getsecid - Check whether to audit or not.
+ *
+ * @p: Pointer to "struct task_struct".
+ * @secid: Pointer to flag.
+ */
+static void tt_task_getsecid(struct task_struct *p, u32 *secid)
+{
+ *secid = (p == current);
+}
+
+/**
+ * tt_secid_to_secctx - Allocate memory used for auditing.
+ *
+ * @secid: Bool flag to allocate.
+ * @secdata: Pointer to allocate memory.
+ * @seclen: Size of allocated memory.
+ *
+ * Returns 0 on success, -EINVAL otherwise.
+ */
+static int tt_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+ struct tt_record *record;
+ /* Ignore unless current thread's record is requested. */
+ if (secid != 1)
+ return -EINVAL;
+ /*
+ * We don't need to duplicate the string because current thread's
+ * record is updated upon only boot up and successful execve()
+ * operation, even if current thread's record is shared between
+ * multiple threads.
+ */
+ record = tt_find_record(current->real_cred);
+ *secdata = record->history;
+ *seclen = strlen(record->history);
+ return 0;
+}
+
+/* List of hooks. */
+static struct security_operations tasktracker_ops = {
+ .name = "tt",
+ .secid_to_secctx = tt_secid_to_secctx,
+ .task_getsecid = tt_task_getsecid,
+ .cred_prepare = tt_cred_prepare,
+ .cred_free = tt_cred_free,
+ .cred_alloc_blank = tt_cred_alloc_blank,
+ .cred_transfer = tt_cred_transfer,
+ .bprm_committing_creds = tt_bprm_committing_creds,
+};
+
+/**
+ * tt_init - Initialize this module.
+ *
+ * Returns 0 on success, panic otherwise.
+ */
+static int __init tt_init(void)
+{
+ struct cred *cred = (struct cred *) current_cred();
+ if (!security_module_enable(&tasktracker_ops))
+ return 0;
+ if (tt_cred_alloc_blank(cred, GFP_ATOMIC) ||
+ register_security(&tasktracker_ops))
+ panic("Failure registering TaskTracker");
+ tt_update_record(tt_find_record(cred));
+ pr_info("TaskTracker initialized\n");
+ return 0;
+}
+
+security_initcall(tt_init);
--
1.7.1
9 years, 9 months
[PATCH] audit: restore AUDIT_LOGINUID unset ABI
by Richard Guy Briggs
A regression was caused by commit 780a7654cee8:
audit: Make testing for a valid loginuid explicit.
(which in turn attempted to fix a regression caused by e1760bd)
When audit_krule_to_data() fills in the rules to get a listing, there was a
missing clause to convert back from AUDIT_LOGINUID_SET to AUDIT_LOGINUID.
This broke userspace by not returning the same information that was sent and
expected.
The rule:
auditctl -a exit,never -F auid=-1
gives:
auditctl -l
LIST_RULES: exit,never f24=0 syscall=all
when it should give:
LIST_RULES: exit,never auid=-1 (0xffffffff) syscall=all
Tag it so that it is reported the same way it was set.
Note: move the field validation call ahead of the mutation code to have it work
on the original field set.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
include/uapi/linux/audit.h | 3 +++
kernel/auditfilter.c | 19 +++++++++++++------
kernel/auditsc.c | 2 +-
3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 4d100c8..860df86 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -274,6 +274,9 @@
#define AUDIT_FILTERKEY 210
+/* Flag to indicate legacy AUDIT_LOGINUID unset usage */
+#define AUDIT_LOGINUID_LEGACY 0x80000000
+
#define AUDIT_NEGATE 0x80000000
/* These are the supported operators.
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 40ed981..39ce3e6 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -438,9 +438,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
f->type = data->fields[i];
f->val = data->values[i];
+ err = audit_field_valid(entry, f);
+ if (err)
+ goto exit_free;
+
/* Support legacy tests for a valid loginuid */
if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
- f->type = AUDIT_LOGINUID_SET;
+ f->type = AUDIT_LOGINUID_SET | AUDIT_LOGINUID_LEGACY;
f->val = 0;
}
@@ -457,10 +461,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
rcu_read_unlock();
}
- err = audit_field_valid(entry, f);
- if (err)
- goto exit_free;
-
err = -EINVAL;
switch (f->type) {
case AUDIT_LOGINUID:
@@ -630,6 +630,13 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
data->buflen += data->values[i] =
audit_pack_string(&bufp, krule->filterkey);
break;
+ case AUDIT_LOGINUID_SET | AUDIT_LOGINUID_LEGACY:
+ if (!f->val) {
+ data->fields[i] = AUDIT_LOGINUID;
+ data->values[i] = AUDIT_UID_UNSET;
+ break;
+ }
+ /* fallthrough if set */
default:
data->values[i] = f->val;
}
@@ -1270,7 +1277,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,
int result = 0;
u32 sid;
- switch (f->type) {
+ switch (f->type & ~AUDIT_LOGINUID_LEGACY) {
case AUDIT_PID:
pid = task_pid_nr(current);
result = audit_comparator(pid, f->op, f->val);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8933572..ef25cbc 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -452,7 +452,7 @@ static int audit_filter_rules(struct task_struct *tsk,
int result = 0;
pid_t pid;
- switch (f->type) {
+ switch (f->type & ~AUDIT_LOGINUID_LEGACY) {
case AUDIT_PID:
pid = task_pid_nr(tsk);
result = audit_comparator(pid, f->op, f->val);
--
1.7.1
9 years, 10 months
[PATCH] audit: add ppc64 mach support
by Tony Jones
Add support for ppc64le.
$ uname -a
Linux cabernet 3.12.26-3-default #1 SMP Mon Aug 18 15:07:30 UTC 2014 (d318f3a) ppc64le ppc64le ppc64le GNU/Linux
Without this, perf trace and auditctl fail. There is no 32 bit (ppcle).
Signed-off-by: Tony Jones <tonyj(a)suse.de>
---
Index: trunk/lib/libaudit.c
===================================================================
--- trunk/lib/libaudit.c (revision 1011)
+++ trunk/lib/libaudit.c (working copy)
@@ -1195,6 +1195,11 @@
return -6;
break;
#endif
+ case MACH_PPC64LE:
+ if (bits != __AUDIT_ARCH_64BIT)
+ return -6;
+ break;
+
case MACH_86_64: /* fallthrough */
case MACH_PPC64: /* fallthrough */
case MACH_S390X: /* fallthrough */
Index: trunk/lib/libaudit.h
===================================================================
--- trunk/lib/libaudit.h (revision 1011)
+++ trunk/lib/libaudit.h (working copy)
@@ -356,6 +356,9 @@
#define AUDIT_ARCH_AARCH64 (EM_AARCH64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#endif
+#ifndef AUDIT_ARCH_PPC64LE
+#define AUDIT_ARCH_PPC64LE (EM_PPC64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#endif
//////////////////////////////////////////////////////
// This is an external ABI. Any changes in here will
@@ -438,7 +441,8 @@
MACH_S390,
MACH_ALPHA,
MACH_ARM,
- MACH_AARCH64
+ MACH_AARCH64,
+ MACH_PPC64LE
} machine_t;
/* These are the valid audit failure tunable enum values */
Index: trunk/lib/lookup_table.c
===================================================================
--- trunk/lib/lookup_table.c (revision 1011)
+++ trunk/lib/lookup_table.c (working copy)
@@ -70,6 +70,7 @@
{ MACH_86_64, AUDIT_ARCH_X86_64 },
{ MACH_IA64, AUDIT_ARCH_IA64 },
{ MACH_PPC64, AUDIT_ARCH_PPC64 },
+ { MACH_PPC64LE, AUDIT_ARCH_PPC64LE},
{ MACH_PPC, AUDIT_ARCH_PPC },
{ MACH_S390X, AUDIT_ARCH_S390X },
{ MACH_S390, AUDIT_ARCH_S390 },
@@ -123,6 +124,7 @@
found = ia64_syscall_s2i(sc, &res);
break;
case MACH_PPC64:
+ case MACH_PPC64LE:
case MACH_PPC:
found = ppc_syscall_s2i(sc, &res);
break;
@@ -169,6 +171,7 @@
case MACH_IA64:
return ia64_syscall_i2s(sc);
case MACH_PPC64:
+ case MACH_PPC64LE:
case MACH_PPC:
return ppc_syscall_i2s(sc);
case MACH_S390X:
Index: trunk/lib/machinetab.h
===================================================================
--- trunk/lib/machinetab.h (revision 1011)
+++ trunk/lib/machinetab.h (working copy)
@@ -27,6 +27,7 @@
_S(MACH_86_64, "x86_64" )
_S(MACH_IA64, "ia64" )
_S(MACH_PPC64, "ppc64" )
+_S(MACH_PPC64LE, "ppc64le")
_S(MACH_PPC, "ppc" )
_S(MACH_S390X, "s390x" )
_S(MACH_S390, "s390" )
9 years, 11 months
peculiar disappearance of most audit rules
by Peter Grandi
Hi, I have started using 'auditd', mostly to monitor various directories
where packages get installed to check for changes in their contents,
with rules like:
-w /bin -p wa -k pkg-s
-w /boot -p wa -k pkg-s
-w /etc -p wa -k pkg-s
-w /lib -p wa -k pkg-s
-w /lib32 -p wa -k pkg-s
-w /lib64 -p wa -k pkg-s
-w /opt -p wa -k pkg-s
-w /usr -p wa -k pkg-s
-w /fs/sozan/loc -p wa -k pkg-l
-w /fs/sozan/loc32-el5 -p wa -k pkg-l
-w /fs/sozan/loc64-u12 -p wa -k pkg-l
-w /fs/sozan/com -p wa -k pkg-l
-w /fs/sozan/com32-el5 -p wa -k pkg-l
-w /fs/sozan/com64-u12 -p wa -k pkg-l
After setting them, I can verify that for example creating, updating and
deleting a file in '/boot' or '/opt' gets reported.
Wheat then happens is that even if I set 'auditctl -e 2' some of the
rules disappear, usually at around the same time as 'cron.daily' scripts
run, and some more disappear later. This usually seems to relate to
times where there some significant IO activity ('mlocate' scan, backup),
but this is a guess.
For example:
time->Thu Apr 17 07:58:44 2014
type=CONFIG_CHANGE msg=audit(1397717924.255:37148): op="remove rule" dir="/boot" key="pkg-s" list=4 res=1
time->Thu Apr 17 07:59:04 2014
type=CONFIG_CHANGE msg=audit(1397717944.762:37151): op="remove rule" dir="/opt" key="pkg-s" list=4 res=1
time->Thu Apr 17 10:01:02 2014
type=CONFIG_CHANGE msg=audit(1397725262.301:37157): op="remove rule" dir="/fs/sozan/loc64-u12" key="pkg-l" list=4 res=1
time->Thu Apr 17 10:01:02 2014
type=CONFIG_CHANGE msg=audit(1397725262.301:37156): op="remove rule" dir="/fs/sozan/loc32-el5" key="pkg-l" list=4 res=1
There is no equivalent line in 'dmesg'.
I understand that the 'audit' kernel modules may remove rules if they
refer to invalid paths, but all the relevant directories do exist, as
for example '/boot' and '/opt' are the standard usual directories in the
"root" tree itself:
$ ls -ldn /boot /opt /fs/sozan/loc64-u12 /fs/sozan/loc32-el5
drwxr-xr-x 3 0 0 4096 Apr 21 07:22 /boot
drwxrwsr-x 7 1 1 61 Jul 30 2011 /fs/sozan/loc32-el5
drwxrwsr-x 5 1 1 39 Oct 4 2011 /fs/sozan/loc64-u12
drwxr-xr-x 7 0 0 4096 Apr 20 14:52 /opt
$ df /boot/. /opt/. /fs/sozan/loc64-u12/. /fs/sozan/loc32-el5/.
Filesystem 1M-blocks Used Available Use% Mounted on
/dev/sda3 24815 16853 4106 81% /
/dev/sda3 24815 16853 4106 81% /
/dev/sda6 90048 82355 7694 92% /fs/sozan
/dev/sda6 90048 82355 7694 92% /fs/sozan
This is happening on two similarly configured Ubuntu 12.04 systems with
both 3.2 and 3.11 Ubuntu "official" kernels. I also have an AppArmor
configuration which seem to trigger bugs in AppArmor, but all the
relative profiles are essentially unchanged.
Eventually around almost all of the rules I have set "disappear". For
example of all these rules:
LIST_RULES: exit,always dir=/fs/sozan/search (0x10) perm=r key=pkg-r
LIST_RULES: exit,always dir=/fs/sozan/mlocate (0x11) perm=r key=pkg-r
....
LIST_RULES: exit,always dir=/bin (0x4) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/boot (0x5) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/etc (0x4) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/lib (0x4) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/lib32 (0x6) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/lib64 (0x6) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/opt (0x4) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/usr (0x4) perm=wa key=pkg-s
LIST_RULES: exit,always dir=/fs/sozan/loc (0xd) perm=wa key=pkg-l
LIST_RULES: exit,always dir=/fs/sozan/loc32-el5 (0x13) perm=wa key=pkg-l
LIST_RULES: exit,always dir=/fs/sozan/loc64-u12 (0x13) perm=wa key=pkg-l
LIST_RULES: exit,always dir=/fs/sozan/com (0xd) perm=wa key=pkg-l
LIST_RULES: exit,always dir=/fs/sozan/com32-el5 (0x13) perm=wa key=pkg-l
LIST_RULES: exit,always dir=/fs/sozan/com64-u12 (0x13) perm=wa key=pkg-l
Only the first two have not "disappeared" on one of the systems.
This is rather peculiar, please let me know if it is a configuration
error, an issue, and any fixes or workaround if available (other than
running 'auditctl -R /etc/audit/audit.rules' every few minutes via CRON).
9 years, 12 months
[PATCH] lsm: get comm using lock to avoid race in string printing
by Richard Guy Briggs
When task->comm is passed directly to audit_log_untrustedstring() without
getting a copy or using the task_lock, there is a race that could happen that
would output a NULL (\0) in the output string that would effectively truncate
the rest of the report text after the comm= field in the audit, losing fields.
Use get_task_comm() to get a copy while acquiring the task_lock to prevent
this and to prevent the result from being a mixture of old and new values of
comm.
Tetsuo Handa <penguin-kernel(a)I-love.SAKURA.ne.jp>
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
I've manually checked for locking issues and found none. I've also enabled all the kernel lock debugging options and it came up clean.
security/lsm_audit.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 69fdf3b..4773b91 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -212,6 +212,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
struct common_audit_data *a)
{
struct task_struct *tsk = current;
+ char comm[sizeof(tsk->comm)];
/*
* To keep stack sizes in check force programers to notice if they
@@ -221,7 +222,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=", task_pid_nr(tsk));
- audit_log_untrustedstring(ab, tsk->comm);
+ audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
switch (a->type) {
case LSM_AUDIT_DATA_NONE:
@@ -282,7 +283,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
pid_t pid = task_pid_nr(tsk);
if (pid) {
audit_log_format(ab, " pid=%d comm=", pid);
- audit_log_untrustedstring(ab, tsk->comm);
+ audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
}
}
break;
--
1.7.1
10 years
Refactoring src/ausearch-report.c:output_interpreted_node()
by Burn Alting
Steve,
In lib/lookup_table.c:audit_name_to_msg_type(), the event type value is
parsed and converted to an integer as per,
Given
type=<type_value>
then
<type_value>
is parsed for
- a known string
- a long integer number, n, found in the specific string
"UNKNOWN[n]"
- a long integer number, n, found in the specific string
"n"
In src/ausearch-report.c:output_interpreted_node() it additionally
parses for a <type_value> of
- a long integer number, n, found in the string "[^\[]*[n].*"
i.e.
type=something[n]something_else
Is there any reason against adding this additional parsing into
lib/lookup_table.c:audit_name_to_msg_type()?
If we can, then output_interpreted_node() can be re-factored so we are
not parsing the same data twice for every event.
I am uncertain what effect of accepting this additional format would
have when adding rules to the running audit system - i.e.
audit_name_to_msg_type() is called by autrace/auditctl when parsing
rules (ie the msgtype field name).
Regards
Burn
10 years
[PATCH] netlink: have netlink per-protocol bind function return an error code.
by Richard Guy Briggs
Have the netlink per-protocol optional bind function return an int error code
rather than void to signal a failure.
This will enable netlink protocols to perform extra checks including
capabilities and permissions verifications when updating memberships in
multicast groups.
In netlink_bind() and netlink_setsockopt() the call to the per-protocol bind
function was moved above the multicast group update to prevent any access to
the multicast socket groups before checking with the per-protocol bind
function. This will enable the per-protocol bind function to be used to check
permissions which could be denied before making them available, and to avoid
the messy job of undoing the addition should the per-protocol bind function
fail.
The netfilter subsystem seems to be the only one currently using the
per-protocol bind function.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
In particular, the audit subsystem (NETLINK_AUDIT protocol) could benefit by
being able to check specific capabilities for each multicast group before
granting membership to the requesting socket. Currently, all NETLINK_AUDIT
sockets must have the capability CAP_NET_ADMIN. No other capabilities are
required to join a multicast group. This capability is too broad allowing
access to this socket by many applications that must not have access to this
information. It is proposed to add capability CAP_AUDIT_READ to allow this
access while dropping the exessively broad capability CAP_NET_ADMIN.
There has also been some interest expressed by IETF ForCES folk.
---
include/linux/netlink.h | 2 +-
net/netfilter/nfnetlink.c | 3 ++-
net/netlink/af_netlink.c | 30 +++++++++++++++++-------------
net/netlink/af_netlink.h | 4 ++--
4 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 7a6c396..4402653 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -45,7 +45,7 @@ struct netlink_kernel_cfg {
unsigned int flags;
void (*input)(struct sk_buff *skb);
struct mutex *cb_mutex;
- void (*bind)(int group);
+ int (*bind)(int group);
bool (*compare)(struct net *net, struct sock *sk);
};
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 75619f9..10a4cf5 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -392,7 +392,7 @@ static void nfnetlink_rcv(struct sk_buff *skb)
}
#ifdef CONFIG_MODULES
-static void nfnetlink_bind(int group)
+static int nfnetlink_bind(int group)
{
const struct nfnetlink_subsystem *ss;
int type = nfnl_group2type[group];
@@ -403,6 +403,7 @@ static void nfnetlink_bind(int group)
if (!ss) {
request_module("nfnetlink-subsys-%d", type);
}
+ return 0;
}
#endif
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index bca50b9..4224dc5 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1198,7 +1198,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
struct module *module = NULL;
struct mutex *cb_mutex;
struct netlink_sock *nlk;
- void (*bind)(int group);
+ int (*bind)(int group);
int err = 0;
sock->state = SS_UNCONNECTED;
@@ -1441,6 +1441,17 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
if (!nladdr->nl_groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
return 0;
+ if (nlk->netlink_bind && nladdr->nl_groups) {
+ int i;
+
+ for (i = 0; i < nlk->ngroups; i++)
+ if (test_bit(i, (long unsigned int *)&nladdr->nl_groups)) {
+ err = nlk->netlink_bind(i);
+ if (err)
+ return err;
+ }
+ }
+
netlink_table_grab();
netlink_update_subscriptions(sk, nlk->subscriptions +
hweight32(nladdr->nl_groups) -
@@ -1449,15 +1460,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
netlink_update_listeners(sk);
netlink_table_ungrab();
- if (nlk->netlink_bind && nlk->groups[0]) {
- int i;
-
- for (i=0; i<nlk->ngroups; i++) {
- if (test_bit(i, nlk->groups))
- nlk->netlink_bind(i);
- }
- }
-
return 0;
}
@@ -2095,14 +2097,16 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
return err;
if (!val || val - 1 >= nlk->ngroups)
return -EINVAL;
+ if (nlk->netlink_bind) {
+ err = nlk->netlink_bind(val);
+ if (err)
+ return err;
+ }
netlink_table_grab();
netlink_update_socket_mc(nlk, val,
optname == NETLINK_ADD_MEMBERSHIP);
netlink_table_ungrab();
- if (nlk->netlink_bind)
- nlk->netlink_bind(val);
-
err = 0;
break;
}
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index acbd774..0edb8d5 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -37,7 +37,7 @@ struct netlink_sock {
struct mutex *cb_mutex;
struct mutex cb_def_mutex;
void (*netlink_rcv)(struct sk_buff *skb);
- void (*netlink_bind)(int group);
+ int (*netlink_bind)(int group);
struct module *module;
#ifdef CONFIG_NETLINK_MMAP
struct mutex pg_vec_lock;
@@ -73,7 +73,7 @@ struct netlink_table {
unsigned int groups;
struct mutex *cb_mutex;
struct module *module;
- void (*bind)(int group);
+ int (*bind)(int group);
bool (*compare)(struct net *net, struct sock *sock);
int registered;
};
--
1.7.1
10 years