[RFC][PATCH v2 3/3] audit: Audit proc cmdline value
by William Roberts
During an audit event, cache and print the value of the process's
cmdline value (proc/<pid>/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 cmdline is tied to the life-cycle of the audit_context
structure and is built on demand.
Example denial prior to patch (Ubuntu):
CALL msg=audit(1387828084.070:361): arch=c000003e syscall=82 success=yes exit=0 a0=4184bf a1=418547 a2=0 a3=0 items=0 ppid=1 pid=1329 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 ses=4294967295 tty=(none) comm="console-kit-dae" exe="/usr/sbin/console-kit-daemon" subj=system_u:system_r:consolekit_t:s0-s0:c0.c255 key=(null)
After Patches (Ubuntu):
type=SYSCALL msg=audit(1387828084.070:361): arch=c000003e syscall=82 success=yes exit=0 a0=4184bf a1=418547 a2=0 a3=0 items=0 ppid=1 pid=1329 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 ses=4294967295 tty=(none) comm="console-kit-dae" exe="/usr/sbin/console-kit-daemon" subj=system_u:system_r:consolekit_t:s0-s0:c0.c255 cmdline="/usr/lib/dbus-1.0/dbus-daemon-launch-helper" key=(null)
Example denial prior to patch (Android):
type=1300 msg=audit(248323.940:247): arch=40000028 syscall=54 per=840000 success=yes exit=0 a0=39 a1=540b a2=2 a3=750eecec items=0 ppid=224 pid=1858 auid=4294967295 uid=1002 gid=1002 euid=1002 suid=1002 fsuid=1002 egid=1002 sgid=1002 fsgid=1002 tty=(none) ses=4294967295 comm="bt_hc_worker" exe="/system/bin/app_process" subj=u:r:bluetooth:s0 key=(null)
After Patches (Android):
type=1300 msg=audit(248323.940:247): arch=40000028 syscall=54 per=840000 success=yes exit=0 a0=39 a1=540b a2=2 a3=750eecec items=0 ppid=224 pid=1858 auid=4294967295 uid=1002 gid=1002 euid=1002 suid=1002 fsuid=1002 egid=1002 sgid=1002 fsgid=1002 tty=(none) ses=4294967295 comm="bt_hc_worker" exe="/system/bin/app_process" cmdline="com.android.bluetooth" subj=u:r:bluetooth:s0 key=(null)
Signed-off-by: William Roberts <wroberts(a)tresys.com>
---
kernel/audit.h | 1 +
kernel/auditsc.c | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/kernel/audit.h b/kernel/audit.h
index b779642..bd6211f 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -202,6 +202,7 @@ struct audit_context {
} execve;
};
int fds[2];
+ char *cmdline;
#if AUDIT_DEBUG
int put_count;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 90594c9..08bdbec 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -842,6 +842,12 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
return context;
}
+static inline void audit_cmdline_free(struct audit_context *context)
+{
+ kfree(context->cmdline);
+ context->cmdline = NULL;
+}
+
static inline void audit_free_names(struct audit_context *context)
{
struct audit_names *n, *next;
@@ -955,6 +961,7 @@ static inline void audit_free_context(struct audit_context *context)
audit_free_aux(context);
kfree(context->filterkey);
kfree(context->sockaddr);
+ audit_cmdline_free(context);
kfree(context);
}
@@ -1271,6 +1278,41 @@ static void show_special(struct audit_context *context, int *call_panic)
audit_log_end(ab);
}
+static void audit_log_cmdline(struct audit_buffer *ab, struct task_struct *tsk,
+ struct audit_context *context)
+{
+ int res;
+ char *buf;
+ char *msg = "(null)";
+ audit_log_format(ab, " cmdline=");
+
+ /* Not cached */
+ if (!context->cmdline) {
+ buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!buf)
+ goto out;
+ res = get_cmdline(tsk, buf, PATH_MAX);
+ if (res == 0) {
+ kfree(buf);
+ goto out;
+ }
+ /*
+ * Ensure NULL terminated but don't clobber the end
+ * unless the buffer is full. Worst case you end up
+ * with 2 null bytes ending it. By doing it this way
+ * one avoids additional branching. One checking if the
+ * end is null and another to check if their should be
+ * an increment before setting the null byte.
+ */
+ res -= res == PATH_MAX;
+ buf[res] = '\0';
+ context->cmdline = buf;
+ }
+ msg = context->cmdline;
+out:
+ audit_log_untrustedstring(ab, msg);
+}
+
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
int i, call_panic = 0;
@@ -1303,6 +1345,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_task_info(ab, tsk);
audit_log_key(ab, context->filterkey);
+ audit_log_cmdline(ab, tsk, context);
audit_log_end(ab);
for (aux = context->aux; aux; aux = aux->next) {
--
1.7.9.5
10 years, 11 months
Auditd bug in 2.6.9 kernel
by Aaron Lewis
Hi,
I'm running auditd 1.0.16 (compiled manually) with 2.6.9 kernel (RHEL4)
When I added a watch rule, e.g auditctl -w /usr/bin, all 32bit
programs get stuck:
$ strace /path/to/32bit_program
execve("XX", ["XX"], [/* 21 vars */]) = 0
[ Process PID=2901 runs in 32 bit mode. ]
uname(0xffffd880) = -1 EINTR (Interrupted system call)
open("/proc/sys/kernel/osrelease", O_RDONLY) = -1 EINTR (Interrupted
system call)
writev(2, [{"", 0}], 1) = -1 EINTR (Interrupted system call)
_exit(1)
Any ideas? Looks like a kernel-side bug.
--
Best Regards,
Aaron Lewis - PGP: 0x13714D33 - http://pgp.mit.edu/
Finger Print: 9F67 391B B770 8FF6 99DC D92D 87F6 2602 1371 4D33
10 years, 11 months
[RFC][PATCH] - auditing cmdline
by William Roberts
Just some updates from the review that I have gathered.
1. Possibility of accessing invalid memory on res being 0.
2. Do not switch ordering of fields.
Does anyone hate using the boolean expression to get my
increment value? Removes some branches. Based on my
loose understanding that boolean operators are guarenteed
to be 0 or 1. Although I am never a big fan of stuff like
this in general. Should I just do the branches?
http://c-faq.com/bool/bool2.html
[PATCH] squash: review-updates
10 years, 11 months
[PATCH] audit: correct a type mismatch in audit_syscall_exit()
by AKASHI Takahiro
audit_syscall_exit() saves a result of regs_return_value() in intermediate
"int" variable and passes it to __audit_syscall_exit(), which expects its
second argument as a "long" value.
This will result in truncating the value returned by a system call and
making a wrong audit record.
I don't know why gcc compiler doesn't complain about this, but anyway it
causes a problem at runtime on arm64 (and probably most 64-bit archs).
Signed-off-by: AKASHI Takahiro <takahiro.akashi(a)linaro.org>
---
include/linux/audit.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index c49a312..3dcb3f0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -144,7 +144,7 @@ static inline void audit_syscall_exit(void *pt_regs)
{
if (unlikely(current->audit_context)) {
int success = is_syscall_success(pt_regs);
- int return_code = regs_return_value(pt_regs);
+ long return_code = regs_return_value(pt_regs);
__audit_syscall_exit(success, return_code);
}
--
1.7.9.5
10 years, 11 months
[PATCH 1/2] audit: print error message when fail to create audit socket
by Gao feng
print the error message and then return -ENOMEM.
Signed-off-by: Gao feng <gaofeng(a)cn.fujitsu.com>
---
kernel/audit.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 2a0ed0b..041b951 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1083,12 +1083,11 @@ static int __net_init audit_net_init(struct net *net)
pr_info("audit: initializing netlink socket in namespace\n");
aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
- if (aunet->nlsk == NULL)
- return -ENOMEM;
- if (!aunet->nlsk)
+ if (aunet->nlsk == NULL) {
audit_panic("cannot initialize netlink socket in namespace");
- else
- aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+ return -ENOMEM;
+ }
+ aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
return 0;
}
--
1.8.3.1
10 years, 11 months
ausearch-test
by Steve Grubb
Hi,
This is to announce the release of a test suite that exercises the ausearch
program. I thought it might be good to release it now so that people can see
if they have fields not being found during development of new events. I added a
link to it on the main audit page. But you can find it here for convenience:
http://people.redhat.com/sgrubb/audit/ausearch-test-0.4.tar.gz
-Steve
10 years, 11 months
[RFC] Comments on audit command line failure
by William Roberts
I've been doing some testing of the recent audit cmdline patches,
notably as many as the error paths as I can.
On a failure, the field is populated with null, like when key is null.
However, it has quotes, should I drop the quotes...
Example:
Now:
cmdline="(null)" key=(null)
Proposed:
cmdline=(null) key=(null)
I noticed that tty if its null also does not have quotes.
--
Respectfully,
William C Roberts
10 years, 11 months
TTY logging using auditd feedback requested
by Edward Bailey
Greetings
I am looking into using auditd to capture tty logging for all users
and I am having some trouble. Capturing keystrokes is a requirement
from our security team that I am not wild about, but for various
reasons it is what is. We already push all the log data into Splunk so
I am not that concerned with managing the data flow.
We are using snoopy and it works ok, but increasingly we are seeing
issues with how it loads its kernel module on bootup so I am looking
for something better. Auditd would be a good option since we use it
already and could expand its usage and eliminate a tool.
I added the suggested line to capture tty logs to system-auth in pam.d
"session required pam_tty_audit.so enable=*"
restarted auditd
I can see the tty logs from the root user fine, but any other users
are not working as expected. When I do see commands from non root
users the log message is a dump of all the commands run during the
session instead of cleanly separated events for each command. Is that
expected?
I also added syscall rules for execve which work ok but not as good as
the keystroke logging for the root user.
Any idea what is wrong? Is this expected behavior? Any suggestions for
a better method to achieve the requirement?
Thanks
Ed
10 years, 11 months
Log rotation issue
by David Flatley
Run audit on dozens of systems but this one system (Red Hat 6.4 64 bit
server Audit 2..2.2 ) does a strange thing. We use "/sbin/service auditd
rotate" as part of a script that runs in /etc/cron.daily to do the audit
extractions. When the /etc/audit/audit.log is rotated, all the entries in
the log after rotation have their date as 12/31/1969 19:00. And on top of
this there is a bunch of audit entries. Reviewing the log and the entries
go along normally but when it does this date thing the log blows up in
size. This is the same audit config I run on all the other RHEL 6 systems.
My understanding is that when auditd rotates the logs that there should not
be any further entries in the rotated log. Thoughts?
David Flatley
"To err is human. To really screw up requires the root password." -UNKNOWN
10 years, 11 months