Re: [PATCH] LSM hooks for audit
by Serge Hallyn
On Wed, 2004-09-15 at 10:02, Stephen Smalley wrote:
> On Wed, 2004-09-15 at 09:59, Serge Hallyn wrote:
> case AUDIT_SET:
> - if (!capable(CAP_SYS_ADMIN))
> - return -EPERM;
> + err = security_audit_set(status_get->mask);
> + if (err)
> + return err;
> status_get = (struct audit_status *)data;
>
> Hook is called _before_ setting of status_get?
Good point, we should send the status_get to the hook for finer-grained
controls.
> And what checks that the
> data length is at least sizeof(struct audit_status)? Looks like the
> existing code is assuming that the caller didn't send a short message.
True.
>
> @@ -364,8 +365,9 @@ static int audit_receive_msg(struct sk_b
> audit_log_end(ab);
> break;
> case AUDIT_LOGIN:
> - if (!capable(CAP_SYS_ADMIN))
> - return -EPERM;
> + err = security_audit_login();
> + if (err)
> + return err;
> login = (struct audit_login *)data;
> ab = audit_log_start(NULL);
> if (ab) {
>
> Why not call the hook after extracting the data (and again, checking the
> length) and pass the audit_login info to the hook.
>
> I would also suggest a hook on AUDIT_USER.
Thanks, I will send a new patch with each of these incorporated.
-serge
--
=======================================================
Serge Hallyn
Security Software Engineer, IBM Linux Technology Center
serue(a)us.ibm.com
20 years, 3 months
Re: Auditing - Snare, LAuS, SELinux
by Jonathan Abbey
On Wed, Aug 25, 2004 at 05:44:46PM +0200, Olaf Kirch wrote:
| Hi,
|
| On Wed, Aug 25, 2004 at 09:53:44AM -0500, Jonathan Abbey wrote:
| > | You may want to use auditing with subdomain, or you may even want to use
| > | it without any security modules at all (because frankly, SElinux sucks
| > | performance-wise, and it's not terribly stable yet either)
| >
| > Rik's audit work can be used without the bulk of SELinux, as I
| > understand the implementation?
|
| I seriously hope it can.
|
| > The audit daemon's efficiency has been increased by a factor of 10 or
| > so in the recent code, the username/groupname caching being part of
| > that. There's still more work to do, though, particularly at the
| > kernel/userland interface.
|
| I seriously believe that filtering in the user land is wrong. At most,
| the daemon should shovel fully cooked records from the kernel into
| the audit trail files and potentially other consumers (such as IDSs).
Snare does do preliminary filtering in the kernel, deciding which
syscall audit records should be passed to the userland based on what
objectives are specified to the daemon.. i.e., if you don't specify
any filters on open(), no open syscall audit record will be passed to
the daemon.
| For performance reasons, filtering should happen in the kernel module, so
| we avoid costly memory allocations and kernel-user land copying.
To be sure. The big win for Snare in doing userland filtering is the
ability to apply regular expressions, but as long as you have support
for prefix and suffix matching in the kernel, you might not gain all
that much for the extra cost, flexible though it is for the user.
| > The biggest dissatisfaction we have with the 2.6.6 audit framework is
| > that syscall arguments are not logged in the event of early abort of
| > syscall processing due to a lack of capabilities, etc. We read NISPOM
| > Ch. 8 as requiring detailed logging of failed attempts to access
| > "security-relevant objects". A non-root user attempting to do root
| > actions like 'chroot' is a pretty silly user, but NISPOM would like to
| > know that sort of thing.
|
| Same for CAPP. I'd have to go and see how hard it would be to adapt
| the laus module to this infrastructure.
|
| > Therefore, we would prefer to see a mechanism in which all auditable
| > parameters are copied to kernel space up front, and that the syscalls
| > would then be written to use the pre-copied parameters rather than
| > doing direct mapping from user space. There would obviously be
| > certain kinds of parameters that could not reasonably be audited in
| > such a framework, but that will be true in any prospective auditing
| > system.
|
| Not sure if I understand what you intend to do here. Some audit
| implementations I looked at created wrapper functions that copied
| arguments from user space and did a set_fs(KERNEL_DS). This is obviously
| a simple way of doing it but it creates security problems if you audit
| system calls that pass structs with pointers in them. That way, you could
| never audit ioctls (besides, there are many ioctls that don't follow the
| convention of including call direction and argument size in the ioctl
| number, so you wouldn't know the argument size beforehand).
Well, right.. I expect that there would have to be context sensitive
code to decide which arguments should be considered auditable. If we
can't get a clean snapshot of a syscall's arguments for such practical
reasons, then the auditing framework should be cognizant of that.
| > | Maybe there's even a way we can tap into copy_from_user pretty much
| > | the same way Rik taps into getname.
| >
| > Hmm.. we could perhaps add a identifying tag as an additional
| > parameter to copy_from_user, so as to allow tracking of multiple
| > parameters copied from user space, but that still wouldn't support
| > full auditing of preemptively rejected syscalls.
|
| Why not? The basic idea is simple.
|
| - intercept system call on entry, copy arguments from registers
| to some internal per-process structure.
| - in copy_from_user, check the source pointer against all
| arguments in above structure
| - if we have a match, kmalloc a suitable chunk of memory and
| copy the argument
| - on the way out, call the audit filter to find out if we need
| to audit the syscall. If yes, build the audit record.
| - When building the audit record, check if we have a copy of
| the argument. If not, we aborted early, so get the argument
| now.
Why kmalloc/copy in copy_from_user when we've already copied the
arguments from registers to a per-process structure?
| This is mostly generic; it doesn't even involve selinux.
| All you need is a table mapping system call numbers to argument types,
| the way we did in laus. This allows you to audit _any_ system call
| without having to touch each and every kernel function.
| (You need some special cases, because some arguments need to be copied on
| their way in, such as the argv array in execve - when we return, argv
| no longer points to anything useful)
Right.
| The down side is obviously that you have to put a branch into copy_from_user,
| which many people will not like for performance reasons. Obviously, some
| clever magic is needed here.
Only if you are running with audit enabled, yes? I don't know how
often copy_from_user is used outside of the syscall argument
processing case, but if there's a distinction to be drawn between
conceivably auditable use and never-auditable use, one could split
copy_from_user and provide an audit-enabled variant for syscalls.
| Another extension along the same line would be to add a hook to the namei
| functions so that we get the dentry and thereby the resolved path, rather
| than some more or less useless string.
Right.
Thanks,
Jon
| Olaf
| --
| Olaf Kirch | The Hardware Gods hate me.
| okir(a)suse.de |
| ---------------+
--
-------------------------------------------------------------------------------
Jonathan Abbey jonabbey(a)arlut.utexas.edu
Applied Research Laboratories The University of Texas at Austin
GPG Key: 71767586 at keyserver pgp.mit.edu, http://www.ganymeta.org/workkey.gpg
20 years, 3 months
(forw) Re: [PATCH] LSM hooks for audit
by Serge E. Hallyn
----- Forwarded message from Serge Hallyn <serue(a)us.ibm.com> -----
From: Serge Hallyn <serue(a)us.ibm.com>
To: Crispin Cowan <crispin(a)immunix.com>
Message-Id: <1095258766.5294.28.camel(a)serge.austin.ibm.com>
X-Mailer: Ximian Evolution 1.4.5
Date: Wed, 15 Sep 2004 09:32:46 -0500
Cc: LSM <linux-security-module(a)wirex.com>
Subject: Re: [PATCH] LSM hooks for audit
Sorry, on a second look I notice the descriptions in security.h are far
less helpful than I'd thought!
The new hooks allow an LSM to refuse a process the ability to:
view a list of audit rules
add to the list of audit rules
delete an audit rule
set audit parameters (ie enable/disable audit, rate limit, etc)
create a 'login' audit record.
The last one is the most dubious one in my mind, but we do want to
prevent a user from sending fake login audit messages, either to mislead
the auditor or to fill the log with garbage.
Note that the audit code (kernel/audit.c and kernel/auditsc.c) is in the
kernel now. This patch only allows LSMs to restrict processes'
interaction with the audit subsystem. At the moment, some of this
interaction depends upon CAP_SYS_ADMIN, and some (like listing the audit
rules) is always allowed.
-serge
On Wed, 2004-09-15 at 08:01, Crispin Cowan wrote:
> Serge Hallyn wrote:
>
> >Attached is a patch which provides LSM controls over actions related to
> >the new audit framework. As a specific example, we might like to have
> >an "audit role", enabled by selinux or some other LSM, which would be
> >the only role allowed to add or delete filter rules.
> >
> >What do people think about adding these hooks, both in general and these
> >hooks specifically?
> >
> >
> LSM is about enabling policy modules, not imposing policy. Glancing
> through the patch, it appears to put audit-specific stuff into LSM. I
> would rather see appropriate hook placement so that an audit module (or
> an audit-aware module) could be created, but without imposing
> audit-specific semantics on the hooks.
>
> But then again, I'm just guessing at what the patch does based on
> variable names :) Can you post a description of what the patch does?
>
> Crispin
--
=======================================================
Serge Hallyn
Security Software Engineer, IBM Linux Technology Center
serue(a)us.ibm.com
----- End forwarded message -----
20 years, 3 months
(forw) [PATCH] LSM hooks for audit
by Serge E. Hallyn
----- Forwarded message from Serge Hallyn <serue(a)us.ibm.com> -----
From: Serge Hallyn <serue(a)us.ibm.com>
To: LSM <linux-security-module(a)wirex.com>
Message-Id: <1095256778.5294.17.camel(a)serge.austin.ibm.com>
X-Mailer: Ximian Evolution 1.4.5
Date: Wed, 15 Sep 2004 08:59:38 -0500
Cc:
Subject: [PATCH] LSM hooks for audit
Hi,
Attached is a patch which provides LSM controls over actions related to
the new audit framework. As a specific example, we might like to have
an "audit role", enabled by selinux or some other LSM, which would be
the only role allowed to add or delete filter rules.
What do people think about adding these hooks, both in general and these
hooks specifically?
thanks,
-serge
--
=======================================================
Serge Hallyn
Security Software Engineer, IBM Linux Technology Center
serue(a)us.ibm.com
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/include/linux/security.h linux-2.6.8.1/include/linux/security.h
--- /home/hallyn/kernels/linux-2.6.8.1/include/linux/security.h 2004-08-14 05:55:48.000000000 -0500
+++ linux-2.6.8.1/include/linux/security.h 2004-09-09 11:27:25.661860264 -0500
@@ -1012,6 +1012,22 @@ struct swap_info_struct;
* remove a stacked module.
* @name contains the name of the security module being unstacked.
* @ops contains a pointer to the struct security_operations of the module to unstack.
+ * @audit_set:
+ * set login parameters
+ * @mask: list of what is being set, out of
+ * AUDIT_STATUS_ENABLED
+ * AUDIT_STATUS_FAILURE
+ * AUDIT_STATUS_PID
+ * AUDIT_STATUS_RATE_LIMIT
+ * AUDIT_STATUS_BACKLOG_LIMIT
+ * @audit_login:
+ * create a login audit record
+ * @audit_listfilter:
+ * list the syscall audit rules
+ * @audit_listadd:
+ * add a syscall audit rule
+ * @audit_listdel:
+ * delete a syscall audit rule
*
* This is the main security structure.
*/
@@ -1228,6 +1244,12 @@ struct security_operations {
int (*sk_alloc_security) (struct sock *sk, int family, int priority);
void (*sk_free_security) (struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */
+
+ int (*audit_set) (u32 mask);
+ int (*audit_login) (void);
+ int (*audit_listfilter) (void);
+ int (*audit_listadd) (void);
+ int (*audit_listdel) (void);
};
/* global variables */
@@ -1876,6 +1898,31 @@ static inline int security_setprocattr(s
return security_ops->setprocattr(p, name, value, size);
}
+static inline int security_audit_set (u32 mask)
+{
+ return security_ops->audit_set(mask);
+}
+
+static inline int security_audit_login (void)
+{
+ return security_ops->audit_login();
+}
+
+static inline int security_audit_listfilter (void)
+{
+ return security_ops->audit_listfilter();
+}
+
+static inline int security_audit_listadd (void)
+{
+ return security_ops->audit_listadd();
+}
+
+static inline int security_audit_listdel (void)
+{
+ return security_ops->audit_listdel();
+}
+
static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb)
{
return security_ops->netlink_send(sk, skb);
@@ -2499,6 +2546,31 @@ static inline int security_setprocattr(s
return -EINVAL;
}
+int security_audit_set (u32 mask)
+{
+ return 0;
+}
+
+int security_audit_login (void)
+{
+ return 0;
+}
+
+int security_audit_listfilter (void)
+{
+ return 0;
+}
+
+int security_audit_listadd (void)
+{
+ return 0;
+}
+
+int security_audit_listdel (void)
+{
+ return 0;
+}
+
/*
* The netlink capability defaults need to be used inline by default
* (rather than hooking into the capability module) to reduce overhead
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/kernel/audit.c linux-2.6.8.1/kernel/audit.c
--- /home/hallyn/kernels/linux-2.6.8.1/kernel/audit.c 2004-08-14 05:56:24.000000000 -0500
+++ linux-2.6.8.1/kernel/audit.c 2004-09-09 10:51:18.636298224 -0500
@@ -327,8 +327,9 @@ static int audit_receive_msg(struct sk_b
&status_set, sizeof(status_set));
break;
case AUDIT_SET:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ err = security_audit_set(status_get->mask);
+ if (err)
+ return err;
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
err = audit_set_enabled(status_get->enabled);
@@ -364,8 +365,9 @@ static int audit_receive_msg(struct sk_b
audit_log_end(ab);
break;
case AUDIT_LOGIN:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ err = security_audit_login();
+ if (err)
+ return err;
login = (struct audit_login *)data;
ab = audit_log_start(NULL);
if (ab) {
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/kernel/auditsc.c linux-2.6.8.1/kernel/auditsc.c
--- /home/hallyn/kernels/linux-2.6.8.1/kernel/auditsc.c 2004-08-14 05:55:48.000000000 -0500
+++ linux-2.6.8.1/kernel/auditsc.c 2004-09-09 11:37:43.176983696 -0500
@@ -34,6 +34,7 @@
#include <asm/types.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/security.h>
#include <linux/audit.h>
#include <linux/personality.h>
@@ -238,6 +239,9 @@ int audit_receive_filter(int type, int p
case AUDIT_LIST:
/* The *_rcu iterators not needed here because we are
always called with audit_netlink_sem held. */
+ err = security_audit_listfilter();
+ if (err)
+ return err;
list_for_each_entry(entry, &audit_tsklist, list)
audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
&entry->rule, sizeof(entry->rule));
@@ -250,8 +254,9 @@ int audit_receive_filter(int type, int p
audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
break;
case AUDIT_ADD:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ err = security_audit_listadd();
+ if (err)
+ return err;
if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
return -ENOMEM;
if (audit_copy_rule(&entry->rule, data)) {
@@ -267,6 +272,9 @@ int audit_receive_filter(int type, int p
err = audit_add_rule(entry, &audit_extlist);
break;
case AUDIT_DEL:
+ err = security_audit_listdel();
+ if (err)
+ return err;
flags =((struct audit_rule *)data)->flags;
if (!err && (flags & AUDIT_PER_TASK))
err = audit_del_rule(data, &audit_tsklist);
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/security/dummy.c linux-2.6.8.1/security/dummy.c
--- /home/hallyn/kernels/linux-2.6.8.1/security/dummy.c 2004-08-14 05:54:51.000000000 -0500
+++ linux-2.6.8.1/security/dummy.c 2004-09-09 11:00:40.591867992 -0500
@@ -873,6 +873,34 @@ static int dummy_setprocattr(struct task
return -EINVAL;
}
+static int dummy_audit_set(u32 mask)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
+
+static int dummy_audit_login(void)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
+
+static int dummy_audit_listfilter(void)
+{
+ return 0;
+}
+
+static int dummy_audit_listadd(void)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
+
+static int dummy_audit_listdel(void)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
struct security_operations dummy_security_ops;
@@ -1005,6 +1033,11 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, d_instantiate);
set_to_dummy_if_null(ops, getprocattr);
set_to_dummy_if_null(ops, setprocattr);
+ set_to_dummy_if_null(ops, audit_set);
+ set_to_dummy_if_null(ops, audit_login);
+ set_to_dummy_if_null(ops, audit_listfilter);
+ set_to_dummy_if_null(ops, audit_listadd);
+ set_to_dummy_if_null(ops, audit_listdel);
#ifdef CONFIG_SECURITY_NETWORK
set_to_dummy_if_null(ops, unix_stream_connect);
set_to_dummy_if_null(ops, unix_may_send);
----- End forwarded message -----
20 years, 3 months
Re: Auditing - Snare, LAuS, SELinux
by Thomas Biege
On Wed, 1 Sep 2004, Peter Martuccelli wrote:
> Hello,
Hello.
> We have some new people to the list, welcome. The latest post follows,
> I have added my comments to Leigh's summary at the end.
> > > I'm very much in favor of binary formats, actually. printf formatting
> > > wastes a lot of time and space on stuff that nobody's ever going to look
> > > at anyway, except using a toolset.
I prefer binary format too because the semantic of data can easily and
clearly be gained by using structures. This helps developing host-based
IDSs. The reason for the lack of HIDS on Linux is a missing syscall
auditing and audit trail mechanism.
But it is just a technical detail not worth discussing about. :) Just
add a switch (or a post-processing tool) and let the admin decide.
> > Binary records (ie: Stored as binary on disk, rather than as a
> > transition format between kernel and daemon) can be a real problem -
> > we've run into the following examples:
> >
> > * Trying to conduct forensics investigations on another machine is very
> > difficult:
> > - UID mappings are often different, so UID '123' on one machine,
> > translates to an entirely different user on another. Converting to text
> > format on the host machine at daemon write-time solves this problem.
> > This same problem exists on windows, with SID mappings.
> > - Even if analysed later on the same machine, user 123 may have been
> > deleted.
This happens even in text-format.. there will be always a race between
syscall generation and meaning of audit tokens like IDs, filenames,
sockets, whatever.
> > - Trying to view a Windows binary eventlog on a machine that it was not
> > generated on can cause massive problems - the "string conversion DLL's"
> > that exist on one machine (eg: exchange server) to translate event
> > strings to text format, may not be installed on another machine, so
> > windows reports garbage.
This is a technical problem of Windows. :)
> > * Disk forensics are more difficult
> > - There have been situations where a system (including audit log) has
> > been utterly trashed. dd if=/dev/hda | strings (or slightly more
> > targetted tools) can provide some potential audit strings of interest if
> > you can kill the system quickly enough before the attacker does too much
> > overwriting. Pulling out binary data is a little harder when you don't
> > have inodes to work with.
Such a setup is even prone to more errors resulting in problems while
doing post-mortem analysis.
If someone has root to trash the hdd he is even able to delete log entries
no matter of the format. (btw: text, binary, it's all data. so just
using the right tools to grep can help...)
In an ideal setup logs are signed, encrypted, and sent away over a
dedicated secure network to a secure log host on-the-fly.
Keeping the logs only on the disc of an exposed machine is... stupid. :)
> > Ok, In summary, it sounds like we:
> > * Want to make audit independent of SELinux - even the file-audit
> > settings
> This seems to be a popular request. Do people prefer we start with
> replicating the SELinux functionality and making a clean separation
> between the two, or using SELinux as a base and adding audit specfic
> extensions?
A clear separation avoids complexity. Adding SELinux to a customized
kernel seems not to be easily done. Bloating SELinux up more makes the
task even harder and may result in a bad acceptance of SELinux as well
as auditing in the community.
Additionally people will have the freedom of choice.
> > * Want to make it easy for the selinux guys (or any other module
> > provider) to inject audit log data 'through' the audit subsystem.
> > * Go with a binary format between kernel and daemon, but ensure that the
> > logs are written in text format.
> I suggest that we preserve the text interface for SELinux, making the
> binary format an option. LAuS stored the audit records in binary format
> which required audit specific tools, augrep, aucat, to analyze the data.
> Did 'aucat -F' ever get fixed? ccb? Thomas? :-)
Hey, "-F" is an undocumented option (not in aucat.1). ;-)
> I agree with writing the records in text format.
> > * Meet CAPP requirements where possible (eg: halt-on-audit-fail), but
> > provide a reasonable fallback position for real-world use.
> I am working through the CAPP requirements to see if we have any issues
> that need to be resolved with the current implementation. If anyone
> knows of any issues where audit does not meet CAPP requirements please
> post them to the list. I will follow up with my list when completed.
> > * Try and implement filtering in-kernel for items such as filename,
> > using wildcards where appropriate.
> Do we try to resue the LAuS filtering code? Olaf?
> > * Use Rik's code as a base, try and integrate Olaf's stuff (particularly
> > for certification reasons), and use a sprinkling of Snare concepts.
>
> Agreed.
Enhancing Rik's framework with LAuS code is really the best choice in my
opinion.
Bye,
Thomas
--
Thomas Biege <thomas(a)suse.de>, SUSE LINUX AG, Security Support & Auditing
--
Anyone who considers arithmetical methods of producing
random numbers is, of course, in a state of sin.
-- John von Neumann
20 years, 3 months