[RFC][PATCH] add security label to user messages
by Timothy R. Chavez
Hello,
This is a quicky patch to add security label info to user messages,
please take a look over it and let me know if there are objections.
Thanks.
-tim
diff --git a/kernel/audit.c b/kernel/audit.c
index d95efd6..576078b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -54,6 +54,7 @@
#include <net/sock.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
+#include <linux/sched.h>
/* No auditing will take place until audit_initialized != 0.
* (Initialization happens after skb_init is called.) */
@@ -136,6 +137,8 @@ struct audit_buffer {
gfp_t gfp_mask;
};
+extern void audit_log_task_context(struct task_struct *tsk, struct audit_buffer *ab);
+
static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
{
struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
@@ -391,6 +394,7 @@ static int audit_receive_msg(struct sk_b
u16 msg_type = nlh->nlmsg_type;
uid_t loginuid; /* loginuid of sender */
struct audit_sig_info sig_data;
+ struct task_struct *tsk;
err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
if (err)
@@ -464,6 +468,13 @@ static int audit_receive_msg(struct sk_b
"user pid=%d uid=%u auid=%u msg='%.1024s'",
pid, uid, loginuid, (char *)data);
audit_set_pid(ab, pid);
+ read_lock(&tasklist_lock);
+ tsk = find_task_by_pid(pid);
+ if (tsk)
+ get_task_struct(tsk);
+ read_unlock(&tasklist_lock);
+ audit_log_task_context(tsk, ab);
+ put_task_struct(tsk);
audit_log_end(ab);
}
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8f0a61c..689bac3 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -503,12 +503,12 @@ static inline void audit_free_context(st
printk(KERN_ERR "audit: freed %d contexts\n", count);
}
-static void audit_log_task_context(struct audit_buffer *ab)
+void audit_log_task_context(struct task_struct *tsk, struct audit_buffer *ab)
{
char *ctx = NULL;
ssize_t len = 0;
- len = security_getprocattr(current, "current", NULL, 0);
+ len = security_getprocattr(tsk, "current", NULL, 0);
if (len < 0) {
if (len != -EINVAL)
goto error_path;
@@ -519,7 +519,7 @@ static void audit_log_task_context(struc
if (!ctx)
goto error_path;
- len = security_getprocattr(current, "current", ctx, len);
+ len = security_getprocattr(tsk, "current", ctx, len);
if (len < 0 )
goto error_path;
@@ -559,7 +559,7 @@ static void audit_log_task_info(struct a
vma = vma->vm_next;
}
up_read(&mm->mmap_sem);
- audit_log_task_context(ab);
+ audit_log_task_context(current, ab);
}
static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
18 years, 11 months
Updated kernel package available
by David Woodhouse
I've just placed a new kernel based on the Fedora Core 5 Test 2 release
kernel in the yum repository at http://david.woodhou.se/lspp/kernel/
This is kernel-2.6.15-1.1826.2.10.2.2_FC5.lspp.6
It contains the contents of the audit git tree, Janak's unshare patch
sequence, some patches from Steve and Amy's "string fields interface"
patches.
Note that the system call numbers used for the unshare system call are
going to change -- this is _not_ an official system call allocation.
I've done what Andrew does in the -mm tree and just used the next
available number on each architecture, but I can guarantee that some
other new syscall will actually get merged to Linus before unshare does,
so it will change. Do bear this in mind if you're trying to do anything
with it from userspace.
I'm departing tomorrow for Australia, where I'll spend a few days before
going on to linux.conf.au (which is actually in New Zealand). I'll be
back home on February 3rd, but I'll be reading email in the meantime
anyway -- just not quite as frequently.
--
dwmw2
18 years, 11 months
Updated Rawhide+LSPP kernel available.
by David Woodhouse
I'm currently uploading a 2.6.15-1.1826.2.8.2.1_FC5.lspp.5 kernel
package, based on the kernel branch for Fedora Core 5 Test 2, to
http://david.woodhou.se/lspp/kernel/
This contains only the patches which are currently in my git tree at
http://git.kernel.org/git/?p=linux/kernel/git/dwmw2/audit-2.6.git -- I'd
like to send the contents of that tree to Linus now that 2.6.15 is
released. OK?
This is the changelog:
commit efe4c9decd99b905e599fde2a00b73e70176d63a
tree d8402fcd24a44573f6073dc51f79905aa62cc1ee
parent 73bb3c2ee49e216264db6edd441754598978f43d
author David Woodhouse <dwmw2(a)infradead.org> Fri, 18 Nov 2005 14:43:54 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Fri, 18 Nov 2005 14:43:54 +0000
[AUDIT] Fix IA64 success/failure indication in syscall auditing.
Original 2.6.9 patch and explanation from somewhere within HP via
bugzilla...
ia64 stores a success/failure code in r10, and the return value (normal
return, or *positive* errno) in r8. The patch also sets the exit code to
negative errno if it's a failure result for consistency with other
architectures.
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 287b3527d50bcc5fa26acdb4d25b76b9cb503610
tree 7760273dbe190a1d6702fafa81ca56f34d9be8b5
parent cf85b1baa8ad2adfe0cf86b05b7913b5f655fa98
author Dustin Kirkland <dustin.kirkland(a)us.ibm.com> Wed, 16 Nov 2005 15:53:13 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Wed, 16 Nov 2005 15:53:13 +0000
[AUDIT] Miscellaneous bug and warning fixes
This patch fixes a couple of bugs revealed in new features recently
added to -mm1:
* fixes warnings due to inconsistent use of const struct inode *inode
* fixes bug that prevent a kernel from booting with audit on, and SELinux off
due to a missing function in security/dummy.c
* fixes a bug that throws spurious audit_panic() messages due to a missing
return just before an error_path label
* some reasonable house cleaning in audit_ipc_context(),
audit_inode_context(), and audit_log_task_context()
Signed-off-by: Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit cf85b1baa8ad2adfe0cf86b05b7913b5f655fa98
tree 8795faf34565dc6643bf4e908d9b01dcbe1d8f10
parent 251dd82c7124db3fa7b88c4847e6eb25d59621cc
author Andrew Morton <akpm(a)osdl.org> Mon, 07 Nov 2005 10:32:39 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Mon, 07 Nov 2005 10:32:39 +0000
[AUDIT] Fix !CONFIG_AUDIT definition of audit_ipc_perms()
It gained an extra argument.
Signed-off-by: Andrew Morton <akpm(a)osdl.org>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 251dd82c7124db3fa7b88c4847e6eb25d59621cc
tree fc27f08edcfe1ebf8872ebc31e0fcf2ec8e88bd1
parent 184d50aa366f710442fe639b058c0d4a593c21fe
author Andrew Morton <akpm(a)osdl.org> Mon, 07 Nov 2005 10:31:12 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Mon, 07 Nov 2005 10:31:12 +0000
[AUDIT] Remove superfluous check for kfree(NULL)
Signed-off-by: Andrew Morton <akpm(a)osdl.org>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 40bfd914033fbb9d8d9dfb34910a0506b5077e8c
tree 5fd7ca4eb5856064509a63cedb938c97d5d53b66
parent d0cf88729b22b89af17a747cb30b78c7a914a316
author Dustin Kirkland <dustin.kirkland(a)us.ibm.com> Fri, 04 Nov 2005 08:03:53 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Fri, 04 Nov 2005 08:03:53 +0000
[AUDIT] Fix logic error in audit_filter_exclude()
There's supposed to be an implicit AND between all subsequent rules in a
given filter list. There's supposed to be an implicit OR between all
subsequent filters of a given type. The way the audit_filter_exclude()
code currently operates, it forces an implicit AND between all rules in
all exclude filters. This trivial patch fixes that problem with correct
logic. If any one of the rules fails in a given list, break out of
examining that list and move on to the next list. If all rules succeed
in a given list, return 1.
Signed-off-by: Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit d0cf88729b22b89af17a747cb30b78c7a914a316
tree dc882d918c525cf5993d052135f6fd62a84f5616
parent f39d1c7bcc4e32c10d0815f2dbb7ec0890acd21c
author Dustin Kirkland <dustin.kirkland(a)us.ibm.com> Thu, 03 Nov 2005 17:15:16 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Thu, 03 Nov 2005 17:15:16 +0000
[AUDIT] Capture selinux subject/object context information.
This patch extends existing audit records with subject/object context
information. Audit records associated with filesystem inodes, ipc, and
tasks now contain SELinux label information in the field "subj" if the
item is performing the action, or in "obj" if the item is the receiver
of an action.
These labels are collected via hooks in SELinux and appended to the
appropriate record in the audit code.
This additional information is required for Common Criteria Labeled
Security Protection Profile (LSPP).
Signed-off-by: Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit f39d1c7bcc4e32c10d0815f2dbb7ec0890acd21c
tree f3e07c498121a63e90a3fbfe5401def695cb800c
parent eaa82a665dfab434b194ad8018fbebbc084e87c0
author Dustin Kirkland <dustin.kirkland(a)us.ibm.com> Thu, 03 Nov 2005 16:12:36 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Thu, 03 Nov 2005 16:12:36 +0000
[AUDIT] Exclude messages by message type
- Add a new, 5th filter called "exclude".
- And add a new field AUDIT_MSGTYPE.
- Define a new function audit_filter_exclude() that takes a message type
as input and examines all rules in the filter. It returns '1' if the
message is to be excluded, and '0' otherwise.
- Call the audit_filter_exclude() function near the top of
audit_log_start() just after asserting audit_initialized. If the
message type is not to be audited, return NULL very early, before
doing a lot of work.
Signed-off-by: Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit eaa82a665dfab434b194ad8018fbebbc084e87c0
tree a972b384869466f7350e50eeb92ff1eb8ceb5313
parent 4b1191d552f513aa3b275c821932471ef2152d3d
author Amy Griffis <amy.griffis(a)hp.com> Thu, 03 Nov 2005 16:00:25 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Thu, 03 Nov 2005 16:00:25 +0000
[AUDIT] Collect more inode information during syscall processing.
This patch augments the collection of inode info during syscall
processing. It represents part of the functionality that was provided
by the auditfs patch included in RHEL4.
Specifically, it:
- Collects information for target inodes created or removed during
syscalls. Previous code only collects information for the target
inode's parent.
- Adds the audit_inode() hook to syscalls that operate on a file
descriptor (e.g. fchown), enabling audit to do inode filtering for
these calls.
- Modifies filtering code to check audit context for either an inode #
or a parent inode # matching a given rule.
- Modifies logging to provide inode # for both parent and child.
- Protect debug info from NULL audit_names.name.
Signed-off-by: Amy Griffis <amy.griffis(a)hp.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 4b1191d552f513aa3b275c821932471ef2152d3d
tree 2b9bb7397f448f1642a8f27df328d58a89cb7701
parent 5c9dcc2d902dc946cdce8913ad3d7e0e1cdb8cc4
author Amy Griffis <amy.griffis(a)hp.com> Thu, 03 Nov 2005 15:57:06 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Thu, 03 Nov 2005 15:57:06 +0000
Pass dentry, not just name, in fsnotify creation hooks.
The audit hooks (to be added shortly) will want to see dentry->d_inode
too, not just the name.
Signed-off-by: Amy Griffis <amy.griffis(a)hp.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 5c9dcc2d902dc946cdce8913ad3d7e0e1cdb8cc4
tree 384e054fab107ad40a02c64296895f7697a047be
parent 8e2705a286ebfbe1ad5f098becab5fd257f7ec81
author Steve Grubb <sgrubb(a)redhat.com> Thu, 03 Nov 2005 15:48:08 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Thu, 03 Nov 2005 15:48:08 +0000
[AUDIT] Define new range of userspace messages.
The attached patch updates various items for the new user space
messages. Please apply.
Signed-off-by: Steve Grubb <sgrubb(a)redhat.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 8e2705a286ebfbe1ad5f098becab5fd257f7ec81
tree 171c0c268933c7c2f643d68c625c169392eeb7b8
parent de8c398a7b5f4ce4766f45ae9542bf32d63595be
author Dustin Kirkland <dustin.kirkland(a)us.ibm.com> Thu, 03 Nov 2005 15:41:46 +0000
committer David Woodhouse <dwmw2(a)infradead.org> Thu, 03 Nov 2005 15:41:46 +0000
[AUDIT] Filter rule comparators
Currently, audit only supports the "=" and "!=" operators in the -F
filter rules.
This patch reworks the support for "=" and "!=", and adds support
for ">", ">=", "<", and "<=".
This turned out to be a pretty clean, and simply process. I ended up
using the high order bits of the "field", as suggested by Steve and Amy.
This allowed for no changes whatsoever to the netlink communications.
See the documentation within the patch in the include/linux/audit.h
area, where there is a table that explains the reasoning of the bitmask
assignments clearly.
The patch adds a new function, audit_comparator(left, op, right).
This function will perform the specified comparison (op, which defaults
to "==" for backward compatibility) between two values (left and right).
If the negate bit is on, it will negate whatever that result was. This
value is returned.
Signed-off-by: Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
commit 1cce80e3d890237fc39f244c48d22fe6ed0ea522
tree 7e26791e7661494fb34076fa1e0c1e6bdc6aa010
parent c77054e518d9163578cfcad09826d7b959f95ece
author Randy Dunlap <rdunlap(a)xenotime.net> Tue, 13 Sep 2005 12:47:11 -0700
committer David Woodhouse <dwmw2(a)baythorne.infradead.org> Mon, 03 Oct 2005 15:50:31 +0100
AUDIT: kerneldoc for kernel/audit*.c
- add kerneldoc for non-static functions;
- don't init static data to 0;
- limit lines to < 80 columns;
- fix long-format style;
- delete whitespace at end of some lines;
(chrisw: resend and update to current audit-2.6 tree)
Signed-off-by: Randy Dunlap <rdunlap(a)xenotime.net>
Signed-off-by: Chris Wright <chrisw(a)osdl.org>
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
--
dwmw2
18 years, 11 months
[PATCH] add/remove rule update
by Steve Grubb
Hi,
The following patch adds a little more information to the add/remove rule message emitted
by the kernel.
Signed-off-by: Steve Grubb <sgrubb(a)redhat.com>
diff -urp linux-2.6.14.orig/include/linux/audit.h linux-2.6.14/include/linux/audit.h
--- linux-2.6.14.orig/include/linux/audit.h 2006-01-05 10:13:30.000000000 -0500
+++ linux-2.6.14/include/linux/audit.h 2006-01-05 10:12:09.000000000 -0500
@@ -238,7 +238,7 @@ struct audit_rule { /* for AUDIT_LIST,
__u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
__u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
__u32 field_count;
- __u32 mask[AUDIT_BITMASK_SIZE];
+ __u32 mask[AUDIT_BITMASK_SIZE]; /* syscall(s) affected */
__u32 fields[AUDIT_MAX_FIELDS];
__u32 values[AUDIT_MAX_FIELDS];
};
diff -urp linux-2.6.14.orig/kernel/auditfilter.c linux-2.6.14/kernel/auditfilter.c
--- linux-2.6.14.orig/kernel/auditfilter.c 2006-01-05 10:13:40.000000000 -0500
+++ linux-2.6.14/kernel/auditfilter.c 2006-01-05 10:11:29.000000000 -0500
@@ -243,9 +243,9 @@ int audit_receive_filter(int type, int p
;
}
err = audit_add_rule(data, &audit_filter_list[listnr]);
- if (!err)
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u added an audit rule\n", loginuid);
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u added rule to list=%d res=%d\n",
+ loginuid, listnr, !err);
break;
case AUDIT_DEL:
listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
@@ -253,9 +253,9 @@ int audit_receive_filter(int type, int p
return -EINVAL;
err = audit_del_rule(data, &audit_filter_list[listnr]);
- if (!err)
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u removed an audit rule\n", loginuid);
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u removed rule from list=%d res=%d\n",
+ loginuid, listnr, !err);
break;
default:
return -EINVAL;
18 years, 11 months
Re: Re. 2.6.15-mm1
by David Woodhouse
On Fri, 2006-01-06 at 00:31 +0100, Etienne Lorrain wrote:
> Jan 5 22:41:37 localhost kernel: Unable to handle kernel NULL pointer dereference at virtual address 00000010
> Jan 5 22:41:37 localhost kernel: printing eip:
> Jan 5 22:41:37 localhost kernel: c013da3a
> Jan 5 22:41:37 localhost kernel: *pde = 1d165067
> Jan 5 22:41:37 localhost kernel: *pte = 00000000
> Jan 5 22:41:37 localhost kernel: Oops: 0000 [#1]
> Jan 5 22:41:37 localhost kernel: last sysfs file: /class/vc/vcs7/dev
> Jan 5 22:41:37 localhost kernel: Modules linked in: autofs4 pcmcia ipt_REJECT ipt_state ip_conntrack iptable_filter ip_tables vfat fat yenta_socket rsrc_nonstatic pcmcia_core uhci_hcd ehci_hcd i2c_viapro i2c_core snd_via82xx snd_ac97_codec snd_ac97_bus snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_mpu401_uart snd_rawmidi snd_seq_device snd soundcore ext3 jbd
> Jan 5 22:41:37 localhost kernel: CPU: 0
> Jan 5 22:41:37 localhost kernel: EIP: 0060:[<c013da3a>] Not tainted VLI
> Jan 5 22:41:37 localhost kernel: EFLAGS: 00013256 (2.6.15-mm1)
> Jan 5 22:41:37 localhost kernel: EIP is at __audit_inode+0xba/0x190
> Jan 5 22:41:37 localhost kernel: eax: 00000008 ebx: 00000000 ecx: dcbf02c0 edx: d9343268
> Jan 5 22:41:37 localhost kernel: esi: d922ef44 edi: d9fd3000 ebp: dcbf02c0 esp: d922ee88
> Jan 5 22:41:37 localhost kernel: ds: 007b es: 007b ss: 0068
> Jan 5 22:41:37 localhost kernel: Process X (pid: 2192, threadinfo=d922e000 task=d8abcff0)
> Jan 5 22:41:37 localhost kernel: Stack: <0>00000003 00000000 dcbf02c0 fffffffe d922ef44 d9fd3000 00000003 c017002c
> Jan 5 22:41:37 localhost kernel: <0>d9fd3000 d9343268 00000101 00000101 00000101 d922ef44 ffffffe9 00000003
> Jan 5 22:41:37 localhost kernel: <0>c0170096 d922e000 00000002 d922ef44 00000006 c017011f d9fd3000 00000001
> Jan 5 22:41:38 localhost gdm[2183]: gdm_slave_xioerror_handler: Fatal X error - Restarting :0
> Jan 5 22:41:38 localhost kernel: Call Trace:
> Jan 5 22:41:39 localhost kernel: [<c017002c>] path_lookup+0x1ac/0x1d0
> Jan 5 22:41:40 localhost kernel: [<c0170096>] __path_lookup_intent_open+0x46/0xa0
> Jan 5 22:41:41 localhost kernel: [<c017011f>] path_lookup_open+0x2f/0x40
> Jan 5 22:41:41 localhost kernel: [<c0170b33>] open_namei+0x73/0x530
> Jan 5 22:41:42 localhost kernel: [<c0144cdd>] __alloc_pages+0x5d/0x390
> Jan 5 22:41:42 localhost kernel: [<c015e8b8>] filp_open+0x38/0x60
> Jan 5 22:41:42 localhost kernel: [<c015eaf0>] get_unused_fd+0xb0/0xe0
> Jan 5 22:41:42 localhost kernel: [<c015ec45>] do_sys_open+0x55/0x100
> Jan 5 22:41:42 localhost kernel: [<c01031a5>] syscall_call+0x7/0xb
> Jan 5 22:41:43 localhost kernel: Code: 42 38 89 d8 c1 e0 05 8d 04 98 c7 44 10 3c 00 00 00 00 89 d8 8b 54 24 24 8b 4c 24 08 c1 e0 05 8d 04 98 8d 2c 08 8b 82 c4 00 00 00 <8b> 40 08 89 45 48 0f b7 42 28 66 89 45 4c 8b 42 30 89 45 50 8b
Your oops was word-wrapped. I've fixed it up for you, but please make
the effort to ensure that your mail isn't corrupted. If you think your
mail client might be misbehaving, try sending the mail to yourself
first, to make sure it arrives OK.
Please could you tell me the line of code which corresponds to
'__audit_inode+0xba/0x190'? Assuming your kernel was compiled with
debugging information, you can do this by loading your vmlinux into gdb
and issuing the command 'list *__audit_inode+0xba'.
What audit rules had you entered? You shouldn't be seeing this code path
unless you've actually enabled auditing for yourself.
--
dwmw2
18 years, 11 months
[PATCH] kaudit_thread return val
by Stephen Hemminger
Fix warning because kaudit_thread() is not returning a value.
This is in current linux-2.6.git.
Signed-off-by: Stephen Hemminger <shemminger(a)osdl.org>
--- skge-2.6.orig/kernel/audit.c
+++ skge-2.6/kernel/audit.c
@@ -300,6 +300,8 @@ static int kauditd_thread(void *dummy)
remove_wait_queue(&kauditd_wait, &wait);
}
}
+
+ return 0;
}
void audit_send_reply(int pid, int seq, int type, int done, int multi,
18 years, 11 months
Problem with start of auditd on 2.6.13-2smp machine
by Lisa Giacchetti
I have a redhat enterprise linux 4 update 1 based system running
2.6.13-2smp kernel with audit-1.0.3-6.EL4 and audit-libs-1.0.3-6.EL4
installed.
The problem is that when I start auditd I get this error:
[root@cmsstor02 etc]# /etc/init.d/auditd start
Starting auditd: [ OK ]
Error receiving watch list (Invalid argument)
There was an error in line 5 of /etc/audit.rules
auditd actually starts but I am concerned that the -D
option (which is what is on line 5 of /etc/audit.rules)
is not being recognized or honored.
I see that newer versions of the audit rpm may have fixed this
"* Thu May 26 2005 Steve Grubb <sgrubb(a)redhat.com> 0.9-1
- Translate numeric info to human readable for ausearch output
- add '-if' option to ausearch to select input file
- add '-c' option to ausearch to allow searching by comm field
- init script now deletes all rules when daemon stops
- Make auditctl display perms correctly in watch listings
*** - Make auditctl -D remove all watches"
but I do not have the glibc-kernheaders needed. Mine
are glibc-kernheaders-2.4-9.1.87 and audit-1.0.1201 needs
glibc-kernheaders>=2.4-9.1.95.
First - is this error I see really a problem?
Second: Is the fix above really a fix for the problem I am seeing?
If so is there any other way to get it fixed.
If not what is the fix?
Thanks in advance for any help that is provided.
lisa
--
Lisa Giacchetti
Fermilab Computing Division
USCMS Tier1 Facility Support
lisa at fnal dot gov | 1-630-840-8023
18 years, 11 months
Problem with start of auditd on 2.6.13-2smp machine
by Lisa Giacchetti
I have a redhat enterprise linux 4 update 1 based system running
2.6.13-2smp kernel with audit-1.0.3-6.EL4 and audit-libs-1.0.3-6.EL4
installed.
The problem is that when I start auditd I get this error:
[root@cmsstor02 etc]# /etc/init.d/auditd start
Starting auditd: [ OK ]
Error receiving watch list (Invalid argument)
There was an error in line 5 of /etc/audit.rules
auditd actually starts but I am concerned that the -D
option (which is what is on line 5 of /etc/audit.rules)
is not being recognized or honored.
I see that newer versions of the audit rpm may have fixed this
"* Thu May 26 2005 Steve Grubb <sgrubb(a)redhat.com> 0.9-1
- Translate numeric info to human readable for ausearch output
- add '-if' option to ausearch to select input file
- add '-c' option to ausearch to allow searching by comm field
- init script now deletes all rules when daemon stops
- Make auditctl display perms correctly in watch listings
*** - Make auditctl -D remove all watches"
but I do not have the glibc-kernheaders needed. Mine
are glibc-kernheaders-2.4-9.1.87 and audit-1.0.1201 needs
glibc-kernheaders>=2.4-9.1.95.
First - is this error I see really a problem?
Second: Is the fix above really a fix for the problem I am seeing?
If so is there any other way to get it fixed.
If not what is the fix?
Thanks in advance for any help that is provided.
lisa
--
Lisa Giacchetti
Fermilab Computing Division
USCMS Tier1 Facility Support
lisa at fnal dot gov | 1-630-840-8023
18 years, 11 months
[PATCH] new audit rule interface
by Amy Griffis
Hello,
Follwing is an updated patch which provides an interface for specifing
audit rules with string fields. The code related to filesystem paths
has been removed, and the interface has been generalized to support
string fields for more than one field type.
To summarize the interface, a new struct audit_rule_xprt and
corresponding netlink message types have been added. The new struct
allows userspace to supply one or more string fields packed in a
variable length buffer. The kernel expects the buffer to be neither
null-delimited nor null-terminated.
The length of string data for a given field is provided as its value
element in the array. The kernel provides the buflen element for
convenience on rule listing, to allow userspace to allocate memory for
the buffer without walking the array to tabulate lengths. Buflen is
ignored coming from userspace. Instead, the kernel ensures that the
total of the lengths specified in the value elements do not exceed the
length of the message payload minus sizeof(struct audit_rule_xprt).
Several routines have been added to auditfilter.c to translate between
the kernel's rule representation and the two userspace rule
representations.
This patch resolves the following issues present in the previous
patch:
- splits string fields interface patch from filesystem audit patch.
- struct audit_krule uses a separate field for operator bits
- struct audit_krule tracks which type of operator bits were used,
and sends rule back to userspace as it was supplied
- contents of struct audit_rule_xprt reviewed and solidified
Several of us talked on IRC and decided to split the field flags
away from the field type in the new structure. We also decided
against adding empty fields and versioning the structure.
- documentation related to modified routines has been updated
Signed-off-by: Amy Griffis <amy.griffis(a)hp.com>
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 79d8271..b5da475 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -50,15 +50,18 @@
*/
#define AUDIT_GET 1000 /* Get status */
#define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */
-#define AUDIT_LIST 1002 /* List syscall filtering rules */
-#define AUDIT_ADD 1003 /* Add syscall filtering rule */
-#define AUDIT_DEL 1004 /* Delete syscall filtering rule */
+#define AUDIT_LIST 1002 /* List syscall rules -- deprecated */
+#define AUDIT_ADD 1003 /* Add syscall rule -- deprecated */
+#define AUDIT_DEL 1004 /* Delete syscall rule -- deprecated */
#define AUDIT_USER 1005 /* Message from userspace -- deprecated */
#define AUDIT_LOGIN 1006 /* Define the login id and information */
#define AUDIT_WATCH_INS 1007 /* Insert file/dir watch entry */
#define AUDIT_WATCH_REM 1008 /* Remove file/dir watch entry */
#define AUDIT_WATCH_LIST 1009 /* List all file/dir watches */
#define AUDIT_SIGNAL_INFO 1010 /* Get info about sender of signal to auditd */
+#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */
+#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */
+#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */
#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */
@@ -226,6 +229,26 @@ struct audit_status {
__u32 backlog; /* messages waiting in queue */
};
+/* audit_rule_xprt supports filter rules with both integer and string
+ * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
+ * AUDIT_LIST_RULES requests.
+ */
+struct audit_rule_xprt {
+ __u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
+ __u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
+ __u32 field_count;
+ __u32 mask[AUDIT_BITMASK_SIZE];
+ __u32 fields[AUDIT_MAX_FIELDS];
+ __u32 values[AUDIT_MAX_FIELDS];
+ __u32 fieldflags[AUDIT_MAX_FIELDS];
+ __u32 buflen; /* total length of string fields */
+ char buf[0]; /* string fields buffer */
+};
+
+/* audit_rule is supported to maintain backward compatibility with
+ * userspace. It supports integer fields only and corresponds to
+ * AUDIT_ADD, AUDIT_DEL and AUDIT_LIST requests.
+ */
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
__u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
__u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
@@ -337,7 +360,7 @@ extern void audit_log_d_path(struct
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int uid, int seq,
- void *data, uid_t loginuid);
+ void *data, int dlen, uid_t loginuid);
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
#define audit_log_start(c,g,t) ({ NULL; })
diff --git a/kernel/audit.c b/kernel/audit.c
index d95efd6..d55e8c5 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -52,6 +52,7 @@
#include <linux/audit.h>
#include <net/sock.h>
+#include <net/netlink.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
@@ -361,9 +362,12 @@ static int audit_netlink_ok(kernel_cap_t
switch (msg_type) {
case AUDIT_GET:
case AUDIT_LIST:
+ case AUDIT_LIST_RULES:
case AUDIT_SET:
case AUDIT_ADD:
+ case AUDIT_ADD_RULE:
case AUDIT_DEL:
+ case AUDIT_DEL_RULE:
case AUDIT_SIGNAL_INFO:
if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
err = -EPERM;
@@ -470,12 +474,23 @@ static int audit_receive_msg(struct sk_b
break;
case AUDIT_ADD:
case AUDIT_DEL:
- if (nlh->nlmsg_len < sizeof(struct audit_rule))
+ if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
/* fallthrough */
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
- uid, seq, data, loginuid);
+ uid, seq, data, nlmsg_len(nlh),
+ loginuid);
+ break;
+ case AUDIT_ADD_RULE:
+ case AUDIT_DEL_RULE:
+ if (nlmsg_len(nlh) < sizeof(struct audit_rule_xprt))
+ return -EINVAL;
+ /* fallthrough */
+ case AUDIT_LIST_RULES:
+ err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+ uid, seq, data, nlmsg_len(nlh),
+ loginuid);
break;
case AUDIT_SIGNAL_INFO:
sig_data.uid = audit_sig_uid;
diff --git a/kernel/audit.h b/kernel/audit.h
index 7643e46..3e69ab3 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -52,12 +52,28 @@ enum audit_state {
};
/* Rule lists */
-struct audit_entry {
- struct list_head list;
- struct rcu_head rcu;
- struct audit_rule rule;
+struct audit_field {
+ u32 type;
+ u32 val;
+ u32 op;
+};
+
+struct audit_krule {
+ int vers_ops;
+ u32 flags;
+ u32 listnr;
+ u32 action;
+ u32 mask[AUDIT_BITMASK_SIZE];
+ u32 buflen; /* for data alloc on list rules */
+ u32 field_count;
+ struct audit_field fields[AUDIT_MAX_FIELDS];
};
+struct audit_entry {
+ struct list_head list;
+ struct rcu_head rcu;
+ struct audit_krule rule;
+};
extern int audit_pid;
extern int audit_comparator(const u32 left, const u32 op, const u32 right);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a3a3275..1fd4b2a 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -40,52 +40,253 @@ struct list_head audit_filter_list[AUDIT
#endif
};
-/* Copy rule from user-space to kernel-space. Called from
- * audit_add_rule during AUDIT_ADD. */
-static inline int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
+/* Unpack a filter field's string representation from user-space
+ * buffer. */
+static inline char *audit_unpack_string(void **bufp, int *remaining, int len)
{
+ char *str;
+
+ if (!*bufp || (len > *remaining))
+ return ERR_PTR(-EINVAL);
+
+ str = kmalloc(len + 1, GFP_KERNEL);
+ if (!str)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(str, *bufp, len);
+ str[len] = 0;
+ *bufp += len;
+ *remaining -= len;
+
+ return str;
+}
+
+/* Common user-space to kernel rule translation. */
+static struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
+{
+ unsigned listnr;
+ struct audit_entry *entry;
+ int i, err;
+
+ err = -EINVAL;
+ listnr = rule->flags & ~AUDIT_FILTER_PREPEND;
+ switch(listnr) {
+ default:
+ goto exit_err;
+ case AUDIT_FILTER_USER:
+ case AUDIT_FILTER_TYPE:
+#ifdef CONFIG_AUDITSYSCALL
+ case AUDIT_FILTER_ENTRY:
+ case AUDIT_FILTER_EXIT:
+ case AUDIT_FILTER_TASK:
+#endif
+ ;
+ }
+ if (rule->action != AUDIT_NEVER && rule->action != AUDIT_POSSIBLE &&
+ rule->action != AUDIT_ALWAYS)
+ goto exit_err;
+ if (rule->field_count < 0 || rule->field_count > AUDIT_MAX_FIELDS)
+ goto exit_err;
+
+ err = -ENOMEM;
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ goto exit_err;
+ memset(&entry->rule, 0, sizeof(struct audit_krule));
+
+ entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
+ entry->rule.listnr = listnr;
+ entry->rule.action = rule->action;
+ entry->rule.field_count = rule->field_count;
+
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+ entry->rule.mask[i] = rule->mask[i];
+
+ return entry;
+
+exit_err:
+ return ERR_PTR(err);
+}
+
+/* Translate struct audit_rule to kernel's rule respresentation.
+ * Exists for backward compatibility with userspace. */
+static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+{
+ struct audit_entry *entry;
+ int err = 0;
int i;
- if (s->action != AUDIT_NEVER
- && s->action != AUDIT_POSSIBLE
- && s->action != AUDIT_ALWAYS)
- return -1;
- if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
- return -1;
- if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
- return -1;
-
- d->flags = s->flags;
- d->action = s->action;
- d->field_count = s->field_count;
- for (i = 0; i < d->field_count; i++) {
- d->fields[i] = s->fields[i];
- d->values[i] = s->values[i];
+ entry = audit_to_entry_common(rule);
+ if (IS_ERR(entry))
+ goto exit_nofree;
+
+ for (i = 0; i < rule->field_count; i++) {
+ struct audit_field *f = &entry->rule.fields[i];
+
+ if (rule->fields[i] & AUDIT_UNUSED_BITS) {
+ err = -EINVAL;
+ goto exit_free;
+ }
+
+ f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
+ f->type = rule->fields[i] & (~AUDIT_NEGATE|AUDIT_OPERATORS);
+ f->val = rule->values[i];
+
+ entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
+ if (f->op & AUDIT_NEGATE)
+ f->op |= AUDIT_NOT_EQUAL;
+ else if (!(f->op & AUDIT_OPERATORS))
+ f->op |= AUDIT_EQUAL;
+ f->op &= ~AUDIT_NEGATE;
}
- for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
- return 0;
+
+exit_nofree:
+ return entry;
+
+exit_free:
+ kfree(entry);
+ return ERR_PTR(err);
}
-/* Check to see if two rules are identical. It is called from
- * audit_add_rule during AUDIT_ADD and
- * audit_del_rule during AUDIT_DEL. */
-static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
+/* Translate struct audit_rule_xprt to kernel's rule respresentation. */
+static struct audit_entry *audit_xprt_to_entry(struct audit_rule_xprt *xprt,
+ int dlen)
{
+ int err = 0;
+ struct audit_entry *entry;
+ void *bufp;
+ /* int remaining = dlen - sizeof(struct audit_rule_xprt); */
int i;
- if (a->flags != b->flags)
- return 1;
+ entry = audit_to_entry_common((struct audit_rule *)xprt);
+ if (IS_ERR(entry))
+ goto exit_nofree;
+
+ bufp = xprt->buf;
+ entry->rule.vers_ops = 2;
+ for (i = 0; i < xprt->field_count; i++) {
+ struct audit_field *f = &entry->rule.fields[i];
+
+ if (!(xprt->fieldflags[i] & AUDIT_OPERATORS) ||
+ xprt->fieldflags[i] & ~AUDIT_OPERATORS) {
+ err = -EINVAL;
+ goto exit_free;
+ }
- if (a->action != b->action)
- return 1;
+ f->op = xprt->fieldflags[i] & AUDIT_OPERATORS;
+ f->type = xprt->fields[i];
+ switch(f->type) {
+ /* call type-specific conversion routines here */
+ default:
+ f->val = xprt->values[i];
+ }
+ }
+
+exit_nofree:
+ return entry;
+
+exit_free:
+ kfree(entry);
+ return ERR_PTR(err);
+}
+
+/* Pack a filter field's string representation into data block. */
+static inline int audit_pack_string(void **bufp, char *str)
+{
+ int len = strlen(str);
+
+ memcpy(*bufp, str, len);
+ *bufp += len;
+
+ return len;
+}
+
+/* Translate kernel rule respresentation to struct audit_rule.
+ * Exists for backward compatibility with userspace. */
+static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
+{
+ struct audit_rule *rule;
+ int i;
+
+ rule = kmalloc(sizeof(*rule), GFP_KERNEL);
+ if (!rule)
+ return ERR_PTR(-ENOMEM);
+ memset(rule, 0, sizeof(*rule));
+
+ rule->flags = krule->flags | krule->listnr;
+ rule->action = krule->action;
+ rule->field_count = krule->field_count;
+ for (i = 0; i < rule->field_count; i++) {
+ rule->values[i] = krule->fields[i].val;
+ rule->fields[i] = krule->fields[i].type;
+
+ if (krule->vers_ops == 1) {
+ if (krule->fields[i].op & AUDIT_NOT_EQUAL)
+ rule->fields[i] |= AUDIT_NEGATE;
+ } else {
+ rule->fields[i] |= krule->fields[i].op;
+ }
+ }
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
+
+ return rule;
+}
+
+/* Translate kernel rule respresentation to struct audit_rule_xprt. */
+static struct audit_rule_xprt *audit_krule_to_xprt(struct audit_krule *krule)
+{
+ struct audit_rule_xprt *xprt;
+ void *bufp;
+ int i;
+
+ xprt = kmalloc(sizeof(*xprt) + krule->buflen, GFP_KERNEL);
+ if (!xprt)
+ return ERR_PTR(-ENOMEM);
+ memset(xprt, 0, sizeof(*xprt));
+
+ xprt->flags = krule->flags | krule->listnr;
+ xprt->action = krule->action;
+ xprt->field_count = krule->field_count;
+ bufp = xprt->buf;
+ for (i = 0; i < xprt->field_count; i++) {
+ struct audit_field *f = &krule->fields[i];
+
+ xprt->fields[i] = f->type;
+ xprt->fieldflags[i] = f->op;
+ switch(f->type) {
+ /* call type-specific conversion routines here */
+ default:
+ xprt->values[i] = f->val;
+ }
+ }
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++) xprt->mask[i] = krule->mask[i];
+
+ return xprt;
+}
- if (a->field_count != b->field_count)
+/* Compare two rules in kernel format. Considered success if rules
+ * don't match. */
+static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
+{
+ int i;
+
+ if (a->flags != b->flags ||
+ a->listnr != b->listnr ||
+ a->action != b->action ||
+ a->field_count != b->field_count)
return 1;
for (i = 0; i < a->field_count; i++) {
- if (a->fields[i] != b->fields[i]
- || a->values[i] != b->values[i])
+ if (a->fields[i].type != b->fields[i].type ||
+ a->fields[i].op != b->fields[i].op)
return 1;
+
+ switch(a->fields[i].type) {
+ /* call type-specific comparison routines here */
+ default:
+ if (a->fields[i].val != b->fields[i].val)
+ return 1;
+ }
}
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
@@ -95,41 +296,21 @@ static int audit_compare_rule(struct aud
return 0;
}
-/* Note that audit_add_rule and audit_del_rule are called via
- * audit_receive() in audit.c, and are protected by
+/* Add rule to given filterlist if not a duplicate. Protected by
* audit_netlink_sem. */
-static inline int audit_add_rule(struct audit_rule *rule,
- struct list_head *list)
+static inline int audit_add_rule(struct audit_entry *entry,
+ struct list_head *list)
{
- struct audit_entry *entry;
- int i;
+ struct audit_entry *e;
/* Do not use the _rcu iterator here, since this is the only
* addition routine. */
- list_for_each_entry(entry, list, list) {
- if (!audit_compare_rule(rule, &entry->rule))
+ list_for_each_entry(e, list, list) {
+ if (!audit_compare_rule(&entry->rule, &e->rule))
return -EEXIST;
}
- for (i = 0; i < rule->field_count; i++) {
- if (rule->fields[i] & AUDIT_UNUSED_BITS)
- return -EINVAL;
- if ( rule->fields[i] & AUDIT_NEGATE)
- rule->fields[i] |= AUDIT_NOT_EQUAL;
- else if ( (rule->fields[i] & AUDIT_OPERATORS) == 0 )
- rule->fields[i] |= AUDIT_EQUAL;
- rule->fields[i] &= ~AUDIT_NEGATE;
- }
-
- if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
- return -ENOMEM;
- if (audit_copy_rule(&entry->rule, rule)) {
- kfree(entry);
- return -EINVAL;
- }
-
if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
- entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
list_add_rcu(&entry->list, list);
} else {
list_add_tail_rcu(&entry->list, list);
@@ -144,10 +325,9 @@ static inline void audit_free_rule(struc
kfree(e);
}
-/* Note that audit_add_rule and audit_del_rule are called via
- * audit_receive() in audit.c, and are protected by
+/* Remove an existing rule from filterlist. Protected by
* audit_netlink_sem. */
-static inline int audit_del_rule(struct audit_rule *rule,
+static inline int audit_del_rule(struct audit_entry *entry,
struct list_head *list)
{
struct audit_entry *e;
@@ -155,7 +335,7 @@ static inline int audit_del_rule(struct
/* Do not use the _rcu iterator here, since this is the only
* deletion routine. */
list_for_each_entry(e, list, list) {
- if (!audit_compare_rule(rule, &e->rule)) {
+ if (!audit_compare_rule(&entry->rule, &e->rule)) {
list_del_rcu(&e->list);
call_rcu(&e->rcu, audit_free_rule);
return 0;
@@ -164,7 +344,9 @@ static inline int audit_del_rule(struct
return -ENOENT; /* No matching rule */
}
-static int audit_list_rules(void *_dest)
+/* List rules using struct audit_rule. Exists for backward
+ * compatibility with userspace. */
+static int audit_list(void *_dest)
{
int pid, seq;
int *dest = _dest;
@@ -180,9 +362,16 @@ static int audit_list_rules(void *_dest)
/* The *_rcu iterators not needed here because we are
always called with audit_netlink_sem held. */
for (i=0; i<AUDIT_NR_FILTERS; i++) {
- list_for_each_entry(entry, &audit_filter_list[i], list)
+ list_for_each_entry(entry, &audit_filter_list[i], list) {
+ struct audit_rule *rule;
+
+ rule = audit_krule_to_rule(&entry->rule);
+ if (!rule)
+ break;
audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
- &entry->rule, sizeof(entry->rule));
+ rule, sizeof(*rule));
+ kfree(rule);
+ }
}
audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
@@ -190,6 +379,40 @@ static int audit_list_rules(void *_dest)
return 0;
}
+/* List rules using struct audit_rule_xprt. */
+static int audit_list_rules(void *_dest)
+{
+ int pid, seq;
+ int *dest = _dest;
+ struct audit_entry *e;
+ int i;
+
+ pid = dest[0];
+ seq = dest[1];
+ kfree(dest);
+
+ down(&audit_netlink_sem);
+
+ /* The *_rcu iterators not needed here because we are
+ always called with audit_netlink_sem held. */
+ for (i=0; i<AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry(e, &audit_filter_list[i], list) {
+ struct audit_rule_xprt *xprt;
+
+ xprt = audit_krule_to_xprt(&e->rule);
+ if (!xprt)
+ break;
+ audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+ xprt, sizeof(*xprt));
+ kfree(xprt);
+ }
+ }
+ audit_send_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+
+ up(&audit_netlink_sem);
+ return 0;
+}
+
/**
* audit_receive_filter - apply all rules to the specified message type
* @type: audit message type
@@ -197,18 +420,20 @@ static int audit_list_rules(void *_dest)
* @uid: target uid for netlink audit messages
* @seq: netlink audit message sequence (serial) number
* @data: payload data
+ * @dlen: length of payload data
* @loginuid: loginuid of sender
*/
int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
- uid_t loginuid)
+ int dlen, uid_t loginuid)
{
struct task_struct *tsk;
int *dest;
- int err = 0;
- unsigned listnr;
+ int err = 0;
+ struct audit_entry *entry;
switch (type) {
case AUDIT_LIST:
+ case AUDIT_LIST_RULES:
/* We can't just spew out the rules here because we might fill
* the available socket buffer space and deadlock waiting for
* auditctl to read from it... which isn't ever going to
@@ -221,41 +446,48 @@ int audit_receive_filter(int type, int p
dest[0] = pid;
dest[1] = seq;
- tsk = kthread_run(audit_list_rules, dest, "audit_list_rules");
+ if (type == AUDIT_LIST)
+ tsk = kthread_run(audit_list, dest, "audit_list");
+ else
+ tsk = kthread_run(audit_list_rules, dest,
+ "audit_list_rules");
if (IS_ERR(tsk)) {
kfree(dest);
err = PTR_ERR(tsk);
}
break;
case AUDIT_ADD:
- listnr = ((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
- switch(listnr) {
- default:
- return -EINVAL;
+ case AUDIT_ADD_RULE:
+ if (type == AUDIT_ADD)
+ entry = audit_rule_to_entry(data);
+ else
+ entry = audit_xprt_to_entry(data, dlen);
+ if (IS_ERR(entry))
+ return PTR_ERR(entry);
- case AUDIT_FILTER_USER:
- case AUDIT_FILTER_TYPE:
-#ifdef CONFIG_AUDITSYSCALL
- case AUDIT_FILTER_ENTRY:
- case AUDIT_FILTER_EXIT:
- case AUDIT_FILTER_TASK:
-#endif
- ;
- }
- err = audit_add_rule(data, &audit_filter_list[listnr]);
+ err = audit_add_rule(entry,
+ &audit_filter_list[entry->rule.listnr]);
if (!err)
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"auid=%u added an audit rule\n", loginuid);
+ else
+ kfree(entry);
break;
case AUDIT_DEL:
- listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
- if (listnr >= AUDIT_NR_FILTERS)
- return -EINVAL;
+ case AUDIT_DEL_RULE:
+ if (type == AUDIT_DEL)
+ entry = audit_rule_to_entry(data);
+ else
+ entry = audit_xprt_to_entry(data, dlen);
+ if (IS_ERR(entry))
+ return PTR_ERR(entry);
- err = audit_del_rule(data, &audit_filter_list[listnr]);
+ err = audit_del_rule(entry,
+ &audit_filter_list[entry->rule.listnr]);
if (!err)
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"auid=%u removed an audit rule\n", loginuid);
+ kfree(entry);
break;
default:
return -EINVAL;
@@ -287,29 +519,27 @@ int audit_comparator(const u32 left, con
static int audit_filter_user_rules(struct netlink_skb_parms *cb,
- struct audit_rule *rule,
+ struct audit_krule *rule,
enum audit_state *state)
{
int i;
for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
- u32 op = rule->fields[i] & AUDIT_OPERATORS;
- u32 value = rule->values[i];
+ struct audit_field *f = &rule->fields[i];
int result = 0;
- switch (field) {
+ switch (f->type) {
case AUDIT_PID:
- result = audit_comparator(cb->creds.pid, op, value);
+ result = audit_comparator(cb->creds.pid, f->op, f->val);
break;
case AUDIT_UID:
- result = audit_comparator(cb->creds.uid, op, value);
+ result = audit_comparator(cb->creds.uid, f->op, f->val);
break;
case AUDIT_GID:
- result = audit_comparator(cb->creds.gid, op, value);
+ result = audit_comparator(cb->creds.gid, f->op, f->val);
break;
case AUDIT_LOGINUID:
- result = audit_comparator(cb->loginuid, op, value);
+ result = audit_comparator(cb->loginuid, f->op, f->val);
break;
}
@@ -354,14 +584,11 @@ int audit_filter_type(int type)
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
list) {
- struct audit_rule *rule = &e->rule;
int i;
- for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
- u32 op = rule->fields[i] & AUDIT_OPERATORS;
- u32 value = rule->values[i];
- if ( field == AUDIT_MSGTYPE ) {
- result = audit_comparator(type, op, value);
+ for (i = 0; i < e->rule.field_count; i++) {
+ struct audit_field *f = &e->rule.fields[i];
+ if (f->type == AUDIT_MSGTYPE) {
+ result = audit_comparator(type, f->op, f->val);
if (!result)
break;
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8f0a61c..e4f7096 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -161,70 +161,68 @@ struct audit_context {
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise. */
static int audit_filter_rules(struct task_struct *tsk,
- struct audit_rule *rule,
+ struct audit_krule *rule,
struct audit_context *ctx,
enum audit_state *state)
{
int i, j;
for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
- u32 op = rule->fields[i] & AUDIT_OPERATORS;
- u32 value = rule->values[i];
+ struct audit_field *f = &rule->fields[i];
int result = 0;
- switch (field) {
+ switch (f->type) {
case AUDIT_PID:
- result = audit_comparator(tsk->pid, op, value);
+ result = audit_comparator(tsk->pid, f->op, f->val);
break;
case AUDIT_UID:
- result = audit_comparator(tsk->uid, op, value);
+ result = audit_comparator(tsk->uid, f->op, f->val);
break;
case AUDIT_EUID:
- result = audit_comparator(tsk->euid, op, value);
+ result = audit_comparator(tsk->euid, f->op, f->val);
break;
case AUDIT_SUID:
- result = audit_comparator(tsk->suid, op, value);
+ result = audit_comparator(tsk->suid, f->op, f->val);
break;
case AUDIT_FSUID:
- result = audit_comparator(tsk->fsuid, op, value);
+ result = audit_comparator(tsk->fsuid, f->op, f->val);
break;
case AUDIT_GID:
- result = audit_comparator(tsk->gid, op, value);
+ result = audit_comparator(tsk->gid, f->op, f->val);
break;
case AUDIT_EGID:
- result = audit_comparator(tsk->egid, op, value);
+ result = audit_comparator(tsk->egid, f->op, f->val);
break;
case AUDIT_SGID:
- result = audit_comparator(tsk->sgid, op, value);
+ result = audit_comparator(tsk->sgid, f->op, f->val);
break;
case AUDIT_FSGID:
- result = audit_comparator(tsk->fsgid, op, value);
+ result = audit_comparator(tsk->fsgid, f->op, f->val);
break;
case AUDIT_PERS:
- result = audit_comparator(tsk->personality, op, value);
+ result = audit_comparator(tsk->personality, f->op, f->val);
break;
case AUDIT_ARCH:
if (ctx)
- result = audit_comparator(ctx->arch, op, value);
+ result = audit_comparator(ctx->arch, f->op, f->val);
break;
case AUDIT_EXIT:
if (ctx && ctx->return_valid)
- result = audit_comparator(ctx->return_code, op, value);
+ result = audit_comparator(ctx->return_code, f->op, f->val);
break;
case AUDIT_SUCCESS:
if (ctx && ctx->return_valid) {
- if (value)
- result = audit_comparator(ctx->return_valid, op, AUDITSC_SUCCESS);
+ if (f->val)
+ result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
else
- result = audit_comparator(ctx->return_valid, op, AUDITSC_FAILURE);
+ result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
}
break;
case AUDIT_DEVMAJOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (audit_comparator(MAJOR(ctx->names[j].dev), op, value)) {
+ if (audit_comparator(MAJOR(ctx->names[j].dev), f->op, f->val)) {
++result;
break;
}
@@ -234,7 +232,7 @@ static int audit_filter_rules(struct tas
case AUDIT_DEVMINOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (audit_comparator(MINOR(ctx->names[j].dev), op, value)) {
+ if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
++result;
break;
}
@@ -244,8 +242,8 @@ static int audit_filter_rules(struct tas
case AUDIT_INODE:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (audit_comparator(ctx->names[j].ino, op, value) ||
- audit_comparator(ctx->names[j].pino, op, value)) {
+ if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
+ audit_comparator(ctx->names[j].pino, f->op, f->val)) {
++result;
break;
}
@@ -255,14 +253,14 @@ static int audit_filter_rules(struct tas
case AUDIT_LOGINUID:
result = 0;
if (ctx)
- result = audit_comparator(ctx->loginuid, op, value);
+ result = audit_comparator(ctx->loginuid, f->op, f->val);
break;
case AUDIT_ARG0:
case AUDIT_ARG1:
case AUDIT_ARG2:
case AUDIT_ARG3:
if (ctx)
- result = audit_comparator(ctx->argv[field-AUDIT_ARG0], op, value);
+ result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
break;
}
18 years, 12 months
audit 1.1.3 released
by Steve Grubb
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit It will also be in rawhide
tomorrow. The Changelog is:
- Add timestamp to daemon_config messages (#174865)
- Add error checking of year for aureport & ausearch
- Treat af_unix sockets as files for searching and reporting
- Update capp & lspp rules to combine syscalls for higher performance
- Adjusted the chkconfig line for auditd to start a little earlier
- Added skeleton program to docs for people to write their own dispatcher with
- Apply patch from Ulrich Drepper that optimizes resource utilization
- Change ausearch and aureport to unlocked IO
This is mostly a clean up release. Please let me know if there are any
problems.
-Steve
18 years, 12 months