SELinux for auditing
by Matthew Booth
I have a couple of requirements which on the face of it don't seem
simple to achieve with auditctl. These are:
* Audit changes to executables
* Audit changes to configuration files
I'll concentrate on the former as it's more obviously problematic. I
believe this would require putting a watch explicitly on every
executable in the system. If this isn't correct, please correct me and
this problem goes away. Assuming it is, though, I don't believe this is
a practical solution.
It occurs to me that this might be more easily achieved with SELinux. As
a test, I made the following small change to the unconfined domain of
the RHEL 4 targeted policy macros/global_macros.te:
define(`executable_files', `{ exec_type sbin_t bin_t lib_t shlib_t
ld_so_t }')
#allow $1 file_type:dir_file_class_set *;
allow $1 file_type:dir_file_class_set ~execute;
allow $1 executable_files:dir_file_class_set *;
auditallow $1 executable_files:dir_file_class_set { create write rename
setattr append relabelfrom };
This does 2 things. Firstly it enforces that the system won't execute
files which aren't labelled with an executable type. This is really just
to make sure everything is caught by the second rule, which is to audit
changes to executables. To make this thorough, you'd have to go through
everywhere else execute is granted in other domains.
However, I'm worried I might be stepping outside design intentions. Is
the above a good idea? Is using SELinux for writing auditing rules a
good idea in general? uIs there a better way to achieve this and similar
requirements which affect a potentially large class of file?
Thanks,
Matt
--
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, 10 months
Qusetion on logging file deletions with auditd
by Walt Powell
What would the appropriate syscall be in the audit.rules file to log file deletions with auditd? I'm thinking the syntax would be something akin to -w entry, always -S delete, but that doesn't seem to work...
Thanks to all...
17 years, 10 months
Re: missing avc message field names
by Eamon Walsh
Steve G wrote:
>> If you have to include code for parsing the current format, why the rush
>> to change the kernel output?
>>
>
> I was thinking that it should be done in near future so its not forgotten. But
> that is the only reason. It could be delayed for a while.
>
> But back to the original question, any preference for non-conflicting names? :)
>
>
>
CC'ing linux-audit.
Some comments regarding userspace object managers and the userspace AVC:
in general userspace object managers will introduce new fields to the
AVC messages. For example the AVC's generated by the X server have
fields such as window=, property=, and extension= for X-specific things
which do not appear in the kernel AVC's. So it should be relatively
easy to add new keywords to the dictionary, or even have the audit
system gracefully accept keywords that are not in its dictionary.
If all of these keywords in the data dictionary have to be unique, I'm
wondering if it might be useful to use a 3-tuple instead of a
(name,value) pair. The 3-tuple would consist of (namespace,name,value)
with namespace coming from a defined list of subsystems. So for example
there would be an "SELinux" namespace encompassing all of the selinux
keywords, so that the "result" and "perms" keywords from the previous
example would not conflict with the "other" ones which would presumably
be in a different namespace. Or just prefix the names with "selinux-",
"syscall-", etc.
Another request I have is that if this scheme moves forward, that we do
away with the audit_log_user_avc_message(3) family of functions and
instead introduce an interface that takes an array of name/value pairs
making up the audit message, or a single string which it could parse as
name/value pairs. This would be one-size-fits-all and would avoid the
10+ parameter situation with the current functions.
--
Eamon Walsh <ewalsh(a)tycho.nsa.gov>
National Security Agency
17 years, 10 months
trouble with a number of audit rules
by Bill Tangren
Hello all,
I am trying to add the following functionality to auditd (via audit.rules) using
the following rules, but the rules don't work on my RHEL ES 4 system (fully
patched). Could someone look at them and tell me what I am doing wrong, or where
I can read how to do it right?
1)
# Ensures that any reads of the audit log by the current user that's logged is
# audited. It might be beneficial to create a rule for each of the 5 logs
# that are generated.
RULE:
-w /var/log/audit/audit.log -p r -F auid=-1
ERROR:
List must be given before field
2)
# Ensures that any user who mounts or unmounts a device is audited
RULE:
-a exit,always -S mount -S umount
ERROR:
Syscall name unknown: umount
3)
# ensures auditing whenever the reboot command is sent to the kernel
RULE:
-a always,entry -S socketcall -F a0=13
ERROR:
Syscall name unknown: socketcall
4)
# Ensures auditing of any unauthorized access to roots home directory.
RULE:
-w /root -p rw -F uid!=0
ERROR:
List must be given before field
5)
#Ensure that failed use of the following system calls is audited
RULE:
-a exit,always -S quotactl -S mount -S stime -S kill -S chroot -F success=0 -F
auid=-1 -F auid=0
ERROR:
Syscall name unknown: stime
TIA,
Bill Tangren
17 years, 10 months
RE: close(2) not being audited? (Wieprecht, Karen M.)
by Randy Zagar
Actually, this statement was amended in a later Industrial Security
Letter...
The comments from the ISL have been incorporated into our NISPOM docs
and include the following:
8.602. Audit Capability
(c) Successful and unsuccessful accesses to security-relevant
objects and directories, including creation, open, close,
modification, and deletion.
55. Question: Paragraph 8-602a(1)(c) can generate upwards to 100
audit entries for each successful access to security-relevant
objects and/or directories. From a security standpoint, is this
information of enough importance to generate voluminous amounts of
auditing data?
Answer: No. Only unsuccessful accesses need to be audited.
Now I can easily imagine that Sarbanes-Oxley or HIPPA may require
auditing successful accesses to SROs, but the NISPOM no longer requires
it...
-Randy Zagar
linux-audit-request(a)redhat.com wrote:
> Date: Fri, 26 Jan 2007 15:14:10 -0500
>
>From: "Wieprecht, Karen M." <Karen.Wieprecht(a)jhuapl.edu>
>Subject: RE: close(2) not being audited?
>To: "Steve Grubb" <sgrubb(a)redhat.com>, <linux-audit(a)redhat.com>
>Cc: "Todd, Charles" <CTODD(a)ball.com>
>Message-ID:
> <FC11D747323EB24493CDC753367EEB92019FA4D3(a)aplesnation.dom1.jhuapl.edu>
>Content-Type: text/plain; charset="us-ascii"
>
>Actually, the exact wording says:
>
>"Successful and unsuccessful accesses to security-relevant objects and
>directories"
>
>It does not specify exactly how that should be collected, but the
>NISPOM does request that the audit record include who tried to access
>it, what they tried to access, the time and date of the access attempt,
>what command they were trying to run (rm, chmod, etc.), and if they
>were successful or not. What happens behind the scenes after the
>operating system takes over the request may not be of as much interest
>unless collecting that info helps to provide the above details to the
>audit record.
>
>-Karen Wieprecht
>
>
--
Randy Zagar Sr. Unix Systems Administrator
E-mail: zagar(a)arlut.utexas.edu Applied Research Laboratories
Phone: 512 835-3131 Univ. of Texas at Austin
17 years, 10 months
Log file security
by Matthew Booth
I have what I suspect is a fairly common requirement for immediate log
file security for auditing. At the same time, I have the same
requirement for logging several arbitrary applications. After
considering various options, I'm currently looking at writing logs to
NetApp SnapLock: http://www.netapp.com/products/software/snaplock.html.
Does anybody have any specific experience with this kind of setup? I'm
particularly interested in the practicalities of archiving.
Thanks,
Matt
--
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, 10 months
Volume of audit messages
by Matthew Booth
I'm considering turning on some fairly severe auditing. In addition to
the usual suspects, the following are under consideration:
1. All opens for write
2. All execs
3. All incoming and outgoing network connections
Has anybody tried the above on:
* An idle system
* A system running a moderately busy Oracle RAC node
* A system running WebLogic
If so, I'd be interested in what sort of volume of data we're talking
about. I'd also be interested in any potted recipes for achieving (3)
above that anybody might have ;)
Thanks,
Matt
--
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, 10 months
[PATCH] audit config lockdown
by Steve Grubb
Hi,
The following patch adds a new mode to the audit system. It uses the
audit_enabled config option to introduce the idea of audit enabled, but
configuration is immutable. Any attempt to change the configuration
while in this mode is audited. To change the audit rules, you'd need to
reboot the machine.
To use this option, you'd need a modified version of auditctl and use "-e 2".
This is intended to go at the end of the audit.rules file for people that
want an immutable configuration.
This patch also adds "res=" to a number of configuration commands that did not
have it before.
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-01-19 13:17:56.000000000 -0500
+++ linux-2.6.18.x86_64/kernel/audit.c 2007-01-19 13:18:50.000000000 -0500
@@ -2,7 +2,7 @@
* Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
* System-call specific features have moved to auditsc.c
*
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -64,7 +64,9 @@
* (Initialization happens after skb_init is called.) */
static int audit_initialized;
-/* No syscall auditing will take place unless audit_enabled != 0. */
+/* 0 - no auditing
+ * 1 - auditing enabled
+ * 2 - auditing enabled and configuration is locked/unchangeable. */
int audit_enabled;
/* Default state when kernel boots without any parameters. */
@@ -238,102 +240,150 @@ 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;
+ int res, rc = 0, old = audit_rate_limit;
+
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
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);
- audit_rate_limit = limit;
- return 0;
+ "audit_rate_limit=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ limit, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u res=%d",
+ limit, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_rate_limit = limit;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_backlog_limit;
+ int res, rc = 0, old = audit_backlog_limit;
+
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
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);
- audit_backlog_limit = limit;
- return 0;
+ "audit_backlog_limit=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ limit, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u res=%d",
+ limit, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_backlog_limit = limit;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
{
- int old = audit_enabled;
+ int res, rc = 0, old = audit_enabled;
- if (state != 0 && state != 1)
+ if (state < 0 || state > 2)
return -EINVAL;
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
+
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
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);
- audit_enabled = state;
- return 0;
+ "audit_enabled=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ state, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u res=%d",
+ state, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_enabled = state;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{
- int old = audit_failure;
+ int res, rc = 0, old = audit_failure;
if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
+
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
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);
- audit_failure = state;
- return 0;
+ "audit_failure=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ state, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u res=%d",
+ state, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_failure = state;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int kauditd_thread(void *dummy)
@@ -597,6 +647,30 @@ static int audit_receive_msg(struct sk_b
case AUDIT_DEL:
if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
+ if (audit_enabled == 2) {
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (ab) {
+ audit_log_format(ab,
+ "pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ if (selinux_ctxid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+ audit_log_end(ab);
+ }
+ return -EPERM;
+ }
/* fallthrough */
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -607,6 +681,30 @@ static int audit_receive_msg(struct sk_b
case AUDIT_DEL_RULE:
if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
return -EINVAL;
+ if (audit_enabled == 2) {
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (ab) {
+ audit_log_format(ab,
+ "pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ if (selinux_ctxid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+ audit_log_end(ab);
+ }
+ return -EPERM;
+ }
/* fallthrough */
case AUDIT_LIST_RULES:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
17 years, 10 months
close(2) not being audited?
by Todd, Charles
All,
I'm on an RHEL4u3 with Steve's preliminary 1.0.15 package (I built the
RPM) under x86_64 2.6.9-34-ELsmp. I'm using the CAPP.rules sample
fileset to great success. NISPOM 8-602 requires that CLOSE operations
on security-relevant objects be logged. Well, I've got logging for OPEN
on security-relevant objects (with the watches) working VERY well
(yeah!!!). The default CAPP.rules file had nothing about close(2), so
just to test it, I ran:
auditctl -a entry,possible -S close
and then as a normal user typed: cat /etc/group (which is a
security-relevant object that I have permission to open, and thus
eventually close)
However, when I review the audit files, nothing is logged. If I change
the "entry,possible" to "entry,always" then lots of stuff gets logged,
but not my actual opening of the /etc/group file.
There is only one other thing that could be a configuration issue:
"auditctl -l |grep /etc/group" reveals an additional "perm=wa" field
that is set by the -p option in CAPP.rules, but even if root writes to
one of the watched files, close(2) is still not logged.
Do I have a configuration problem or is something deeper going on?
Thanks,
Charlie Todd
Ball Aerospace & Technologies Corp.
ctodd- at -ball.com
17 years, 10 months
[PATCH] log mq object label for mq_timedreceive/mq_timedsend
by Amy Griffis
Log the message queue's object label for mq_timedreceive() and
mq_timedsend() syscalls.
Untested patch against lspp.63 kernel.
Signed-off-by: Amy Griffis <amy.griffis(a)hp.com>
---
diff -Nrup linux-2.6.18.x86_64/ipc/mqueue.c linux-2.6.18.x86_64-amg/ipc/mqueue.c
--- linux-2.6.18.x86_64/ipc/mqueue.c 2007-01-23 18:25:25.000000000 -0500
+++ linux-2.6.18.x86_64-amg/ipc/mqueue.c 2007-01-23 18:31:23.000000000 -0500
@@ -839,6 +839,7 @@ asmlinkage long sys_mq_timedsend(mqd_t m
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
+ audit_inode(NULL, inode);
if (unlikely(!(filp->f_mode & FMODE_WRITE)))
goto out_fput;
@@ -922,6 +923,7 @@ asmlinkage ssize_t sys_mq_timedreceive(m
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
+ audit_inode(NULL, inode);
if (unlikely(!(filp->f_mode & FMODE_READ)))
goto out_fput;
17 years, 10 months