[PATCH] audit=0 appears not to completely disable auditing
by Steve Grubb
Hi,
There was a bz, 231371, reporting that current upstream kernels do not completely
disable auditing when boot with audit=0 and the audit daemon not configured to
run. You can reproduce the problem by:
service auditd stop
auditctl -e 0
auditctl -w /etc/passwd
and you'd get an event in syslog:
Mar 9 15:43:04 localhost kernel: audit(1173472984.321:982): auid=4294967295
subj=user_u:system_r:auditctl_t:s0 op=add rule key=(null) list=4 res=1
The patch below solves this problem by checking audit_enabled before creating
an audit event.
Signed-off-by: Steve Grubb <sgrubb(a)redhat.com>
diff -urp linux-2.6.18.x86_64.orig/kernel/audit.c linux-2.6.18.x86_64/kernel/audit.c
--- linux-2.6.18.x86_64.orig/kernel/audit.c 2007-03-09 14:08:18.000000000 -0500
+++ linux-2.6.18.x86_64/kernel/audit.c 2007-03-09 14:06:59.000000000 -0500
@@ -238,46 +238,50 @@ void audit_log_lost(const char *message)
static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_rate_limit;
+ if (audit_enabled) {
+ int old = audit_rate_limit;
- if (sid) {
- char *ctx = NULL;
- u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_rate_limit=%d old=%d by auid=%u subj=%s",
- limit, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_rate_limit=%d old=%d by auid=%u",
- limit, old, loginuid);
+ limit, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u",
+ limit, old, loginuid);
+ }
audit_rate_limit = limit;
return 0;
}
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_backlog_limit;
+ if (audit_enabled) {
+ int old = audit_backlog_limit;
- if (sid) {
- char *ctx = NULL;
- u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_backlog_limit=%d old=%d by auid=%u subj=%s",
- limit, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_backlog_limit=%d old=%d by auid=%u",
- limit, old, loginuid);
+ limit, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u",
+ limit, old, loginuid);
+ }
audit_backlog_limit = limit;
return 0;
}
@@ -289,21 +293,23 @@ static int audit_set_enabled(int state,
if (state != 0 && state != 1)
return -EINVAL;
- if (sid) {
- char *ctx = NULL;
- u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ if (audit_enabled || state) {
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_enabled=%d old=%d by auid=%u subj=%s",
- state, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_enabled=%d old=%d by auid=%u",
- state, old, loginuid);
+ state, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u",
+ state, old, loginuid);
+ }
audit_enabled = state;
return 0;
}
@@ -317,21 +323,23 @@ static int audit_set_failure(int state,
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
- if (sid) {
- char *ctx = NULL;
- u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ if (audit_enabled) {
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_failure=%d old=%d by auid=%u subj=%s",
- state, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_failure=%d old=%d by auid=%u",
- state, old, loginuid);
+ state, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u",
+ state, old, loginuid);
+ }
audit_failure = state;
return 0;
}
@@ -536,22 +544,26 @@ static int audit_receive_msg(struct sk_b
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_PID) {
- int old = audit_pid;
- if (sid) {
- if ((err = selinux_ctxid_to_string(
- sid, &ctx, &len)))
- return err;
- else
+ if (audit_enabled) {
+ int old = audit_pid;
+ if (sid) {
+ if ((err = selinux_ctxid_to_string(
+ sid, &ctx, &len)))
+ return err;
+ else
+ audit_log(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE,
+ "audit_pid=%d old=%d by auid=%u subj=%s",
+ status_get->pid, old,
+ loginuid, ctx);
+ kfree(ctx);
+ } else
audit_log(NULL, GFP_KERNEL,
AUDIT_CONFIG_CHANGE,
- "audit_pid=%d old=%d by auid=%u subj=%s",
- status_get->pid, old,
- loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_pid=%d old=%d by auid=%u",
- status_get->pid, old, loginuid);
+ status_get->pid, old,
+ loginuid);
+ }
audit_pid = status_get->pid;
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
diff -urp linux-2.6.18.x86_64.orig/kernel/auditfilter.c linux-2.6.18.x86_64/kernel/auditfilter.c
--- linux-2.6.18.x86_64.orig/kernel/auditfilter.c 2007-03-09 14:08:18.000000000 -0500
+++ linux-2.6.18.x86_64/kernel/auditfilter.c 2007-03-09 14:05:54.000000000 -0500
@@ -95,6 +95,8 @@ extern struct inotify_handle *audit_ih;
/* Inotify events we care about. */
#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
+extern int audit_enabled;
+
void audit_free_parent(struct inotify_watch *i_watch)
{
struct audit_parent *parent;
@@ -897,7 +899,6 @@ static void audit_update_watch(struct au
struct audit_watch *owatch, *nwatch, *nextw;
struct audit_krule *r, *nextr;
struct audit_entry *oentry, *nentry;
- struct audit_buffer *ab;
mutex_lock(&audit_filter_mutex);
list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
@@ -937,13 +938,18 @@ static void audit_update_watch(struct au
call_rcu(&oentry->rcu, audit_free_rule_rcu);
}
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
- audit_log_format(ab, "op=updated rules specifying path=");
- audit_log_untrustedstring(ab, owatch->path);
- audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
- audit_log_format(ab, " list=%d res=1", r->listnr);
- audit_log_end(ab);
-
+ if (audit_enabled) {
+ struct audit_buffer *ab;
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ audit_log_format(ab,
+ "op=updated rules specifying path=");
+ audit_log_untrustedstring(ab, owatch->path);
+ audit_log_format(ab, " with dev=%u ino=%lu\n",
+ dev, ino);
+ audit_log_format(ab, " list=%d res=1", r->listnr);
+ audit_log_end(ab);
+ }
audit_remove_watch(owatch);
goto add_watch_to_parent; /* event applies to a single watch */
}
@@ -962,25 +968,28 @@ static void audit_remove_parent_watches(
struct audit_watch *w, *nextw;
struct audit_krule *r, *nextr;
struct audit_entry *e;
- struct audit_buffer *ab;
mutex_lock(&audit_filter_mutex);
parent->flags |= AUDIT_PARENT_INVALID;
list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
e = container_of(r, struct audit_entry, rule);
-
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
- audit_log_format(ab, "op=remove rule path=");
- audit_log_untrustedstring(ab, w->path);
- if (r->filterkey) {
- audit_log_format(ab, " key=");
- audit_log_untrustedstring(ab, r->filterkey);
- } else
- audit_log_format(ab, " key=(null)");
- audit_log_format(ab, " list=%d res=1", r->listnr);
- audit_log_end(ab);
-
+ if (audit_enabled) {
+ struct audit_buffer *ab;
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ audit_log_format(ab, "op=remove rule path=");
+ audit_log_untrustedstring(ab, w->path);
+ if (r->filterkey) {
+ audit_log_format(ab, " key=");
+ audit_log_untrustedstring(ab,
+ r->filterkey);
+ } else
+ audit_log_format(ab, " key=(null)");
+ audit_log_format(ab, " list=%d res=1",
+ r->listnr);
+ audit_log_end(ab);
+ }
list_del(&r->rlist);
list_del_rcu(&e->list);
call_rcu(&e->rcu, audit_free_rule_rcu);
@@ -1409,6 +1418,9 @@ static void audit_log_rule_change(uid_t
{
struct audit_buffer *ab;
+ if (!audit_enabled)
+ return;
+
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab)
return;
17 years, 3 months
RE: Recording user commands (from RE: Linux-audit Digest, Vol 31, Issue 12)
by Taylor_Tad@emc.com
-----Original Message-----
While a little more verbose than one might like, couldn't you audit
exec() system calls? That would certainly capture all the commands
issued from a shell. However, you might want to only audit successful
exec()s. As I recall from auditing *nix systems years ago, shells tend
to just start trying to execute a command name along your path and if it
fails, it tries again with the next path (for example, the command
doesn't exist in /usr/local/bin, let's try /usr/bin and then /usr/sbin,
etc.)
This would pick up other exec()s as well, but you should be able to
generate reports to find the ones that were issued by a shell. Just a
thought.
--Tad Taylor
Message: 3
Date: Thu, 26 Apr 2007 11:10:05 -0400
From: Steve Grubb <sgrubb(a)redhat.com>
Subject: Re: Recording user command ?
To: linux-audit(a)redhat.com
Message-ID: <200704261110.05440.sgrubb(a)redhat.com>
Content-Type: text/plain; charset="iso-8859-1"
On Thursday 26 April 2007 10:32, Gavin White wrote:
> In addition to recording system calls, file activity etc, I would
like
> to record issued commands, ie. anything typed into a shell by a
user.
>
> Is this a reasonable thing to do with auditd? Is it possible?
Well, there are 2 kinds of users, root and everyone else. What
everyone else
does cannot be logged by the session they are running in because it
does not
have enough privileges to log to the audit system.
For the root user, it has enough privileges to log. We are working on
a
solution for this problem. I think most security targets are only
interested
in actions performed by the root user since they can affect the
machine in
many ways.
So, as it stands today, it can't be done with the audit system. We
hope to
have something that starts to address the problem soon.
-Steve
------------------------------
--
Linux-audit mailing list
Linux-audit(a)redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit
End of Linux-audit Digest, Vol 31, Issue 12
*******************************************
17 years, 8 months
Recording user command ?
by Gavin White
Hello,
I've been using auditd with the the capp rules on RHEL4, and all is well.
In addition to recording system calls, file activity etc, I would like
to record issued commands, ie. anything typed into a shell by a user.
Is this a reasonable thing to do with auditd? Is it possible?
Thanks,
Gavin
17 years, 8 months
Status of /etc/audit/filter.conf
by Aaron Lippold
Hello All,
Silly question 1:
I have a security checking script that is complaining that my system
is not able to audit all discretionary access to control permission
modifications.
To verify this it is looking for /etc/audit/filter.conf
Is this still the correct place to look on RHEL4/5? I'd assume not
since I can't find a man page on audit-filter.conf anymore.
Silly Question 2:
If not, where and how would I add this feature to my audit configuration?
Thanks,
Aaron
17 years, 8 months
Audit recv on RHEL 4 x86_64
by Matthew Booth
How do I audit the recv system call on RHEL 4 x86_64? More generally,
how do I get a list of all system calls which can be audited on a
particular system?
Thanks,
Matt
--
Matthew Booth, RHCA, RHCSS
Red Hat, Global Professional Services
M: +44 (0)7977 267231
GPG ID: D33C3490
GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490
17 years, 8 months
CONFIG_AUDITFILESYSTEM RedHat only
by Machin, Glenn D
Can anyone tell me if the RedHat Kernel configuration that allows one to
watch filesystem objects made it back into the Linux Kernel Archives
(www.kernel.org)? Is this a RedHat only enhancement?
Thanks,
Glenn
17 years, 8 months
command missing
by xi-chen-0@northwestern.edu
Hi,
I've just started using auditing utilities to monitor filesystem events. I'm using audit-1.5.2
version. The problem is as follows:
If I do "auditctl -a entry,always -w /etc/passwd", then "grep man /etc/passwd", then "ausearch -f
passwd", the "grep" command is logged in the log file.
However, if I do "auditctl -a entry,always -w /etc", then "grep man /etc/passwd", then "ausearch -f
passwd", the "grep" command is not logged in the log file. However, the "vim" command is recorded
if I use vim to open that "/etc/passwd" file.
Is this the preassumed behavior for the auditing system or have I misconfigured something? Any
clues on that?
ps: Is there a better way to monitor the whole filesystem behaviors, such as open, create, delete
syscalls, instead of just monitoring a single directory?
Thanks for your help,
Xi
17 years, 8 months
(no subject)
by paul moore
My understanding is that the auid/loginid process property is to allow the
audit system to *really* know who did things In particular it seems to be
for tracking who did things when they run su or sudo
But it seems to be trivial to spoof it
login as: paul
paul(a)192.168.111.40's password:
Last login: Fri Apr 13 13:34:26 2007 from 192.168.111.101
[paul@rhes5-wa-1 ~]$ sudo bash
[root@rhes5-wa-1 ~]# cat /proc/self/loginuid
556[root@rhes5-wa-1 ~]# echo 600 > /proc/self/loginuid
[root@rhes5-wa-1 ~]# cat /proc/self/loginuid
600[root@rhes5-wa-1 ~]# exit
[paul@rhes5-wa-1 ~]$ cat /proc/self/loginuid
556[paul@rhes5-wa-1 ~]$
I was 556 at login, after sudo i am still 556 but then as root I can now
change it to 600 and the audit log for my actions has auid=600 in it
doesnt that undermine the whole point of the login id?
Surely once it has been set it should not be possible to change it again.
I see a debate in the thread "proc_loginuid_write() checks wrong capability"
about who should be able to do this but it misses the point. It should only
be writtable if its -1 at the moment.
Otherwise it must be unconditionally rejected.
The argument for it being like it is is that root is all powerfull so they
should be allowed to do anything. But the beauty of auid is that it lets me
see who the root sudoer really is.
(BTW - my 10$ says its should be a new capability since it doesn't match
either CONTROL or WRITE, But if that's not possible then it should be
CONTROL)
Any insights gratefully received
Paul Moore
17 years, 8 months
listening to /dev/audit in a pthread program
by paul moore
I have an test app that quite happily does an audit_set_pid and then sits
there reading /dev/audit.
It works fine if its in the lead thread. But when I run the same code in my
real app it runs in a different thread. No matter what PID I pass to the
audit subsystem it complains that nobody is listening
I did audit_set_pid(....getpid...) - no (passes the pid of the manager
thread)
I did audit_set_pid(....gettid...) - no (passes the pid of the LWP)
(I dont really mean I did gettid - I did syscall(_NR_gettid))
I can see in the complaint message that I have given it the pid I intended
to.
I can see in gdb that my LWP id is the same as the one I send to the audit
subsystem - ie gettid worked.
Is this a known issue?
Heres the code snippet
void listen()
{
// register for events
pid_t mytid = (pid_t)syscall(__NR_gettid);
int res = audit_set_pid(m_auditFD, mytid, WAIT_YES);
res = audit_set_enabled(m_auditFD, 1);
assert(res >= 0);
static audit_reply reply;
while (true)
{
res = audit_get_reply(m_auditFD, &reply, GET_REPLY_BLOCKING, 0);
if (res < 0)
{
printf("exit audit %d %d\n", res, errno);
break;
}
printf("got event %.*s\n", reply.msg.nlh.nlmsg_len, reply.msg.data);
}
}
The thread sits waiting on the audit_get_reply call, so the FD is open
17 years, 8 months
command missing
by xi-chen-0@northwestern.edu
Hi,
I've just started using auditing utilities to monitor filesystem events. I'm using audit-1.5.2
version. The problem is as follows:
If I do "auditctl -a entry,always -w /etc/passwd", then "grep man /etc/passwd", then "ausearch -f
passwd", the "grep" command is logged in the log file.
However, if I do "auditctl -a entry,always -w /etc", then "grep man /etc/passwd", then "ausearch -f
passwd", the "grep" command is not logged in the log file. However, the "vim" command is recorded
if I use vim to open that "/etc/passwd" file.
Is this the preassumed behavior for the auditing system or have I misconfigured something? Any
clues on that?
ps: Is there a better way to monitor the whole filesystem behaviors, such as open, create, delete
syscalls, instead of just monitoring a single directory?
Thanks for your help,
Xi
17 years, 8 months