auditing kdbus service names
by Paul Moore
Hello all,
I'm currently working on a set of LSM hooks for the new kdbus IPC mechanism
and one of the things that I believe we will need to add is a new audit field
for the kdbus service name (very similar to the old fashioned dbus service
name). I was thinking "kdbus_svc" for the field name, any objections?
--
paul moore
security @ redhat
9 years, 1 month
[PATCH 1/2] audit: stop an old auditd being starved out by a new auditd
by Richard Guy Briggs
Nothing prevents a new auditd starting up and replacing a valid
audit_pid when an old auditd is still running, effectively starving out
the old auditd since audit_pid no longer points to the old valid auditd.
If no message to auditd has been attempted since auditd died unnaturally
or got killed, audit_pid will still indicate it is alive. There isn't
an easy way to detect if an old auditd is still running on the existing
audit_pid other than attempting to send a message to see if it fails.
An -ECONNREFUSED almost certainly means it disappeared and can be
replaced. Other errors are not so straightforward and may indicate
transient problems that will resolve themselves and the old auditd will
recover. Yet others will likely need manual intervention for which a
new auditd will not solve the problem.
Send a new message type (AUDIT_PING) to the old auditd containing a u32
with the PID of the new auditd. If the audit ping succeeds (or doesn't
fail with certainty), fail to register the new auditd and return an
error (-EEXIST).
This is expected to make the patch preventing an old auditd orphaning a
new auditd redundant.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 19 +++++++++++++++++--
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index d3475e1..4c97e30 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -70,6 +70,7 @@
#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_PING 1020 /* Ping auditd to see if it is alive */
#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */
diff --git a/kernel/audit.c b/kernel/audit.c
index 18cdfe2..3399ab2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -810,6 +810,15 @@ static int audit_set_feature(struct sk_buff *skb)
return 0;
}
+static int audit_ping(pid_t pid, u32 seq, u32 portid)
+{
+ struct sk_buff *skb = audit_make_reply(portid, seq, AUDIT_PING, 0, 0, &pid, sizeof(pid));
+
+ if (!skb)
+ return -ENOMEM;
+ return netlink_unicast(audit_sock, skb, audit_nlk_portid, 0);
+}
+
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
u32 seq;
@@ -871,13 +880,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
if (s.mask & AUDIT_STATUS_PID) {
int new_pid = s.pid;
+ pid_t requesting_pid = task_tgid_vnr(current);
+ u32 portid = NETLINK_CB(skb).portid;
- if ((!new_pid) && (task_tgid_vnr(current) != audit_pid))
+ if ((!new_pid) && (requesting_pid != audit_pid))
return -EACCES;
+ if (audit_pid && new_pid &&
+ audit_ping(requesting_pid, nlmsg_hdr(skb)->nlmsg_seq, portid) !=
+ -ECONNREFUSED)
+ return -EEXIST;
if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
audit_pid = new_pid;
- audit_nlk_portid = NETLINK_CB(skb).portid;
+ audit_nlk_portid = portid;
audit_sock = skb->sk;
}
if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
--
1.7.1
9 years, 1 month
[PATCH 1/3] kernel/audit: audit_dummy_context can be boolean
by Yaowei Bai
This patch makes audit_dummy_context return bool due to this
particular function only using either one or zero as its return
value.
No functional change.
Signed-off-by: Yaowei Bai <bywxiaobai(a)163.com>
---
include/linux/audit.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b2abc99..69844b6 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -143,7 +143,7 @@ extern void __audit_inode_child(const struct inode *parent,
extern void __audit_seccomp(unsigned long syscall, long signr, int code);
extern void __audit_ptrace(struct task_struct *t);
-static inline int audit_dummy_context(void)
+static inline bool audit_dummy_context(void)
{
void *p = current->audit_context;
return !p || *(int *)p;
@@ -345,9 +345,9 @@ static inline void audit_syscall_entry(int major, unsigned long a0,
{ }
static inline void audit_syscall_exit(void *pt_regs)
{ }
-static inline int audit_dummy_context(void)
+static inline bool audit_dummy_context(void)
{
- return 1;
+ return true;
}
static inline struct filename *audit_reusename(const __user char *name)
{
--
1.9.1
9 years, 1 month
[PATCH] fixup! audit: try harder to send to auditd upon netlink failure
by Richard Guy Briggs
A bug was introduced by "audit: try harder to send to auditd upon
netlink failure", caused by incomplete code and a function that expects
a string and does not accept a format plus arguments. Create a
temporary string variable to assemble the output text. It could be
merged as a fixup if it is not yet upstream.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/audit.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 18cdfe2..9d32218 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -420,7 +420,10 @@ restart:
if (audit_pid) {
if (err == -ECONNREFUSED || err == -EPERM
|| ++attempts >= AUDITD_RETRIES) {
- audit_log_lost("audit_pid=%d reset");
+ char s[32];
+
+ snprintf(s, sizeof(s), "audit_pid=%d reset", audit_pid);
+ audit_log_lost(s);
audit_pid = 0;
audit_sock = NULL;
} else {
--
1.7.1
9 years, 1 month
[PATCH] fixup! audit: try harder to send to auditd upon netlink failure
by Richard Guy Briggs
A bug was introduced by "audit: try harder to send to auditd upon
netlink failure", caused by incomplete code and a function that expects
a string and does not accept a format plus arguments. Create a
temporary string variable to assemble the output text. It could be
merged as a fixup if it is not yet upstream.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/audit.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 18cdfe2..60913e6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -420,7 +420,10 @@ restart:
if (audit_pid) {
if (err == -ECONNREFUSED || err == -EPERM
|| ++attempts >= AUDITD_RETRIES) {
- audit_log_lost("audit_pid=%d reset");
+ char s[32];
+
+ sprintf(s, "audit_pid=%d reset", audit_pid);
+ audit_log_lost(s);
audit_pid = 0;
audit_sock = NULL;
} else {
--
1.7.1
9 years, 1 month
auditd on nonexistent files
by Davíð Steinn Geirsson
Hi all,
What is the best practice for using auditd for file integrity monitoring?
From the documentation, I have this, which works fine:
-a always,exit -F dir=/bin -F perm=wa
However, it seems that if I have a rule on a nonexistent directory,
auditd will fail to add the rule (I assume because it's adding a watch
on an inode or something like that?), but it will also just stop reading
audit.rules and not add any subsequent rules.
This is bad in an environment where we have to have FIM for critical
application files, but where another team may be maintaining some of the
apps and therefore might remove some watched directories, especially as
their mishaps may impact auditing for other parts of the system.
Can something be done to get better behaviour here?
I see two ways it could be better
1) (the ideal case) auditd will add rules even for nonexistent
directories, and when they are created will add a watch for them. If a
directory is removed and another created with the same name, auditd will
add a watch on the new directory.
2) auditd still cannot add watches to nonexistent directories, but a
failed rule add from audit.rules will become a warning rather than an
error so subsequent watches still get added.
I suspect 1) is not possible, but can I get auditd to behave like in 2)?
Best regards,
Davíð
9 years, 1 month
[PATCH V1] audit: add warning that an old auditd may be starved out by a new auditd
by Richard Guy Briggs
Nothing prevents a new auditd starting up and replacing a valid
audit_pid when an old auditd is still running, effectively starving out
the old auditd since audit_pid no longer points to the old valid auditd.
There isn't an easy way to detect if an old auditd is still running on
the existing audit_pid other than attempting to send a message to see if
it fails. If no message to auditd has been attempted since auditd died
unnaturally or got killed, audit_pid will still indicate it is alive.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
Note: Would it be too bold to actually block the registration of a new
auditd if the netlink_getsockbyportid() call succeeded? Would other
checks be appropriate?
kernel/audit.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 18cdfe2..1fa1e0d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -872,6 +872,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (s.mask & AUDIT_STATUS_PID) {
int new_pid = s.pid;
+ if (audit_pid && new_pid &&
+ !IS_ERR(netlink_getsockbyportid(audit_sock, audit_nlk_portid)))
+ pr_warn("auditd replaced by new auditd before normal shutdown: "
+ "(old)audit_pid=%d (by)pid=%d new_pid=%d",
+ audit_pid, pid, new_pid);
if ((!new_pid) && (task_tgid_vnr(current) != audit_pid))
return -EACCES;
if (audit_enabled != AUDIT_OFF)
--
1.7.1
9 years, 1 month
Early processes (daemons) do not report audit events
by Kangkook Jee
Dear all,
We are developing custom user space audit agent to gather system wide system
call trace. While experimenting with various programs, we found out that
processes (daemons) that started early (along with the system bootstrapping) do
not report any audit events at all. These processes typically fall into PID
range of less than 2000. Here’s how I reproduced the symptom with sshd daemon.
1. Reboot the system
2. Add and enable audit events
# /sbin/auditctl -a exit,always -F arch=b64 -S clone -S close -S creat -S dup
-S dup2 -S dup3 -S execve -S exit -S exit_group -S fork -S open -S openat
-S unlink -S unlinkat -S vfork -S 288 -S accept -S bind -S connect
-S listen -S socket -S socketpair
# /sbin/auditctl -e1 -b 102400
3. Connect to the system via ssh
Audit messages generated only from child processes and none are seen from
the original daemon.
4. Restart sshd
# restart ssh
5. Connect again to the system via ssh
Now, we see audit messages from both parent and child processes.
I did the experiment from Ubuntu 14.04.2 LTS distribution (64-bit, kernel
version 3.13.0-58-generic).
I first wonder whether this is intended behavior of audit framework or
not. If it is intended, I also want to know how can we configure auditd
differently to capture system calls from all processes.
Thanks a lot for your help in advance!
Regards, Kangkook
9 years, 1 month
[PATCH V2] audit: try harder to send to auditd upon netlink failure
by Richard Guy Briggs
There are several reports of the kernel losing contact with auditd when
it is, in fact, still running. When this happens, kernel syslogs show:
"audit: *NO* daemon at audit_pid=<pid>"
although auditd is still running, and is apparently happy, listening on
the netlink socket. The pid in the "*NO* daemon" message matches the pid
of the running auditd process. Restarting auditd solves this.
The problem appears to happen randomly, and doesn't seem to be strongly
correlated to the rate of audit events being logged. The problem
happens fairly regularly (every few days), but not yet reproduced to
order.
On production kernels, BUG_ON() is a no-op, so any error will trigger
this.
Commit 34eab0a7cd45 ("audit: prevent an older auditd shutdown from
orphaning a newer auditd startup") eliminates one possible cause. This
isn't the case here, since the PID in the error message and the PID of
the running auditd match.
The primary expected cause of error here is -ECONNREFUSED when the audit
daemon goes away, when netlink_getsockbyportid() can't find the auditd
portid entry in the netlink audit table (or there is no receive
function). If -EPERM is returned, that situation isn't likely to be
resolved in a timely fashion without administrator intervention. In
both cases, reset the audit_pid. This does not rule out a race
condition. SELinux is expected to return zero since this isn't an INET
or INET6 socket. Other LSMs may have other return codes. Log the error
code for better diagnosis in the future.
In the case of -ENOMEM, the situation could be temporary, based on local
or general availability of buffers. -EAGAIN should never happen since
the netlink audit (kernel) socket is set to MAX_SCHEDULE_TIMEOUT.
-ERESTARTSYS and -EINTR are not expected since this kernel thread is not
expected to receive signals. In these cases (or any other unexpected
ones for now), report the error and re-schedule the thread, retrying up
to 5 times.
v2:
Removed BUG_ON().
Moved comma in pr_*() statements.
Removed audit_strerror() text.
Reported-by: Vipin Rathor <v.rathor(a)gmail.com>
Reported-by: <ctcard(a)hotmail.com>
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/audit.c | 24 +++++++++++++++++++-----
1 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 1c13e42..18cdfe2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -407,16 +407,30 @@ static void audit_printk_skb(struct sk_buff *skb)
static void kauditd_send_skb(struct sk_buff *skb)
{
int err;
+ int attempts = 0;
+#define AUDITD_RETRIES 5
+
+restart:
/* take a reference in case we can't send it and we want to hold it */
skb_get(skb);
err = netlink_unicast(audit_sock, skb, audit_nlk_portid, 0);
if (err < 0) {
- BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */
+ pr_err("netlink_unicast sending to audit_pid=%d returned error: %d\n",
+ audit_pid, err);
if (audit_pid) {
- pr_err("*NO* daemon at audit_pid=%d\n", audit_pid);
- audit_log_lost("auditd disappeared");
- audit_pid = 0;
- audit_sock = NULL;
+ if (err == -ECONNREFUSED || err == -EPERM
+ || ++attempts >= AUDITD_RETRIES) {
+ audit_log_lost("audit_pid=%d reset");
+ audit_pid = 0;
+ audit_sock = NULL;
+ } else {
+ pr_warn("re-scheduling(#%d) write to audit_pid=%d\n",
+ attempts, audit_pid);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ goto restart;
+ }
}
/* we might get lucky and get this in the next auditd */
audit_hold_skb(skb);
--
1.7.1
9 years, 1 month