Using the kernel's audit.h
by Timothy R. Chavez
Hello,
Mounir brought to my attention that audit-0.6.5 now uses the kernel's
audit.h -- This is going to be a problem, currently and could be a
potential problem in the future. I thought using kernel space headers
in user space programs was generally discouraged.
Currently, the auditfs piece uses kernel-specific structures. If
using the kernel's audit.h is the way we're going to do it, though,
I'll attempt to hide my stuff with __KERNEL__, but I have a feeling
that using this macro is going to annoy people. Then again, the audit
subsystem requires user space tools for it to be useful and this may
be permissible and less annoying.
Later, someone could add functionality to the audit subsystem without
changing old functionality and break the user space tools. These
types of changes should not affect the user space tools, but if they
use kernel-specific structures without __KERNEL__, the audit tools
will not be compilable. Of course we're hoping for someone to review
the patch and know that user space tools do use the kernel header
file....
Anyway, just voicing this concern. I'd personally prefer just keeping
a copy of the header file in userspace for userspace.
--
- Timothy R. Chavez
19 years, 9 months
audit-0.6.5 tab confusion
by Timothy R. Chavez
So what's the deal with the spacing? Can we just indent -i8 -kr the
entire thing:)? It's the way Kerningham and Ritchie would want it ;-)
I see a mixture now between 8 space tabs, and 4 space tabs.
--
- Timothy R. Chavez
19 years, 9 months
audit-0.6.5 is released
by Steve Grubb
Hi,
The latest audit daemon is available at http://people.redhat.com/sgrubb/audit
The changes include:
- Lots of code cleanups
- Added write_pid function to auditd
- Added audit_log to libaudit
- Don't check file length in foreground mode of auditd
- Added *if_enabled functions to send messages only if audit system is enabled
- If syscall name is unknown when printing rules, use the syscall number
- Rework the build system to produce singly threaded public libraries
- Create a multithreaded version of libaudit for the audit daemon's use
Please check this version over and report any problems.
Thanks,
-Steve Grubb
19 years, 9 months
what is the correct use of linux kernel personality?
by Mounir Bsaibes
Can someone please explain the correct use of Linux kernel personality or
point me to some
documentation that explains it well. We are trying to see how to make use
of it with audit filters.
The man page for the system call "personality" states that if you give it
a 0Xffffffff
the system call returns the current personality.
So I wrote a little program to check this out. The program always
returned 0xff or 255.
on AMD iSeries and i386 platforms for 32 and 64 bit executables.
It turned out that the /usr/include/linux/personality.h has the following
line:
#define personality(pers) (pers & PER_MASK)
no wonder. PER_MASK is 0xff and the name of the syscall is also
personality.
Which means in my application, the system call was never called.
OK, so I commented this line out. Now I get 0 for the personality on the
all platforms mentioned above
with 32 & 64 bit executables.
Mounir Bsaibes
Linux Security
Tel: (512) 838-1301
Cell: (512) 762-9957
Fax: (512) 838-8858
e-mail: bsaibes(a)us.ibm.com
19 years, 9 months
syscalls not known by auditctl
by Debora Velarde
There are some syscall numbers that are not known by auditctl.
When running on IX86,
/usr/include/asm-i386/unistd.h contains:
#define __NR_setfsuid32 215
But I am unable to audit this syscall number. Because when I add the rule:
auditctl -a entry,always -S 215
auditctl returns:
AUDIT_LIST: entry always syscall=(null)
No rules
This is true for other syscalls found in /usr/include/asm-i386/unistd.h
that are not found in /usr/include/asm-x86_64/unistd.h
-debbie
19 years, 9 months
syscall filtering on personality
by Debora Velarde
I have a question about how to filter on personality.
>From /usr/include/linux/personality.h I see:
PER_LINUX = 0x0000,
PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
PER_LINUX32 = 0x0008,
PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
So if I want to audit a particular syscall, chmod for example, in a 32bit
executable, is this the correct usage?:
"auditctl -a exit,always -S chmod -F pers=0x0008"
I've created a simple test that executes the __NR_chmod syscall and
compiled it 32bit
(out put from "file":
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux
2.2.5, dynamically linked (uses shared libs), not stripped")
When I add the above rule, it is accepted by auditctl and is listed as:
"AUDIT_LIST: exit always pers=8 (0x8) syscall=chmod"
But I do not see any audit records generated.
Also, if I add the rule
"auditctl -a exit,always -S chmod -F pers=0x0000"
It is accepted by auditctl and is listed as:
"AUDIT_LIST: exit always pers=0 syscall=chmod"
And I do see audit records generated in /var/log/messages. Note: "pers" is
not displayed in the record.
I wasn't sure if 0x0008 was the correct value to capture syscalls compiled
in 32bit mode. So I tried this auditctl filter next:
"auditctl -a exit,always -S chmod -F pers!=0x0000"
It is accepted by auditctl and is listed as:
"AUDIT_LIST: exit always pers!=0 syscall=chmod"
Again, no audit records are generated.
In the same personality.h, I found:
ADDR_LIMIT_32BIT = 0x0800000,
So I also tried:
"auditctl -a exit,always -S chmod -F pers=0x0800000"
It is accepted by auditctl and is listed as:
AUDIT_LIST: exit always pers=8388608 (0x800000) syscall=chmod
But again, I don't see any audit records generated.
-debbie
19 years, 9 months
Netlink Socket Problem
by Steve Grubb
Hi,
I'm still working on some bugs that I found over the weekend for libaudit. I
modified pam and passwd to log events to the audit netlink connection. As a
result, I ran into a problem. The problem is probably best illustrated by
showing in auditctl.c how to reproduce it.
If you open auditctl.c, look for reset_vars(). In that function is
audit_open(). Add a second call to audit_open so that it looks like this:
static int reset_vars(void)
{
list_requested = 0;
syscalladded = 0;
add = 0;
del = 0;
action = 0;
memset(&rule, 0, sizeof(rule));
audit_open(); // this is added. we don't care what the return is.
if ((fd = audit_open()) < 0) {
fprintf(stderr, "Cannot open netlink audit socket\n");
return 1;
}
return 0;
}
What this does is makes the application open 2 netlink connections to the
audit system. Compile it and try ./auditctl -s Using strace this is what I
get (with my annotations):
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0 getrlimit(RLIMIT_STACK,
{rlim_cur=10240*1024, rlim_max=RLIM_INFINITY}) = 0
_sysctl({{CTL_KERN, KERN_VERSION}, 2, 0xbfec898c, 31, (nil), 0}) = 0
socket(PF_NETLINK, SOCK_RAW, 9) = 3
<- first open ->
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
socket(PF_NETLINK, SOCK_RAW, 9) = 4
<- second open ->
bind(4, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
fcntl64(4, F_SETFD, FD_CLOEXEC) = 0
sendto(4, "\20\0\0\0\350\3\1\0gE\213k\0\0\0\0", 16, 0, {sa_family=AF_NETLINK,
pid=0, groups=00000000}, 12) = 16
<- send request , now get answer ->
recvfrom(4, 0xbfec7ed0, 1216, 64, 0xbfec7e60, 0xbfec7e5c) = -1 EAGAIN
(Resource temporarily unavailable) write(2, "Error receiving netlink packet
("..., 65Error receiving netlink packet (Resource temporarily unavailable)) =
65 write(2, "\n", 1
) = 1
<- error? ->
nanosleep({0, 100000000}, NULL) = 0
recvfrom(4, 0xbfec7ed0, 1216, 64, 0xbfec7e60, 0xbfec7e5c) = -1 EAGAIN
(Resource temporarily unavailable)
write(2, "Error receiving netlink packet ("..., 65Error receiving netlink
packet (Resource temporarily unavailable)) = 65
write(2, "\n", 1
<- error? ->
As you can see it scrolls messages because you get EAGAIN returned. This is a
real problem right now and I'm not sure how best to solve it short of making
a request, closing the descriptor, and re-open it for each communication to
the kernel.
What happens in real life is that passwd is going to log some data to the
audit system and opens a socket, then it collects the passwords, if
everything is OK, it passes the passwords to pam for authentication token
update. Pam decides that it needs to do some logging of its own and opens
descriptors to the audit system. They fail like above, EAGAIN.
Does any of you kernel hackers know why apps are limited to 1 netlink socket
connection? Can someone else verify the problem?
I think I can fix the problem by constantly closing and opening connections,
but that is ugly and not efficient. This "bug/feature" is holding up the
release of the next version of audit and patched trusted programs.
Thanks,
-Steve Grubb
19 years, 9 months
[PATCH] send audit reply to correct socket
by Chris Wright
Send audit repsonse to socket which request came from, rather than pid
that request came from.
Signed-off-by: Chris Wright <chrisw(a)osdl.org>
===== kernel/audit.c 1.9 vs edited =====
--- 1.9/kernel/audit.c 2005-01-30 22:33:47 -08:00
+++ edited/kernel/audit.c 2005-02-28 18:34:47 -08:00
@@ -360,7 +360,7 @@ static int audit_receive_msg(struct sk_b
status_set.backlog_limit = audit_backlog_limit;
status_set.lost = atomic_read(&audit_lost);
status_set.backlog = atomic_read(&audit_backlog);
- audit_send_reply(pid, seq, AUDIT_GET, 0, 0,
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,
&status_set, sizeof(status_set));
break;
case AUDIT_SET:
@@ -407,8 +407,8 @@ static int audit_receive_msg(struct sk_b
/* fallthrough */
case AUDIT_LIST:
#ifdef CONFIG_AUDITSYSCALL
- err = audit_receive_filter(nlh->nlmsg_type, pid, uid, seq,
- data);
+ err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+ uid, seq, data);
#else
err = -EOPNOTSUPP;
#endif
19 years, 9 months
[PATCH] Audit permission changes on IPC objects.
by David Woodhouse
Capture the requested permissions on IPC_SET calls. We do this with a
hook in ipc/{sem,shm,msg}.c for two reasons. Firstly, it would require a
lot of arch-specific knowledge about syscall numbers and sys_ipc()
multiplexing to get at this information from syscall_trace_enter().
Secondly, if we did it there it could be changed by the time the IPC
code does copy_from_user() to fetch it again.
Signed-off-by: David Woodhouse <dwmw2(a)infradead.org>
===== include/linux/audit.h 1.2 vs edited =====
--- 1.2/include/linux/audit.h 2005-01-31 06:33:47 +00:00
+++ edited/include/linux/audit.h 2005-02-28 13:39:05 +00:00
@@ -150,6 +150,7 @@
struct timespec *t, int *serial);
extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
+extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -159,6 +160,7 @@
#define audit_putname(n) do { ; } while (0)
#define audit_inode(n,i,d) do { ; } while (0)
#define audit_get_loginuid(c) ({ -1; })
+#define audit_ipc_perms(q,u,g,m) ({ 0; })
#endif
#ifdef CONFIG_AUDIT
===== ipc/msg.c 1.24 vs edited =====
--- 1.24/ipc/msg.c 2004-10-28 08:39:57 +01:00
+++ edited/ipc/msg.c 2005-02-28 13:39:42 +00:00
@@ -25,6 +25,7 @@
#include <linux/security.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
+#include <linux/audit.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -425,6 +426,8 @@
return -EFAULT;
if (copy_msqid_from_user (&setbuf, buf, version))
return -EFAULT;
+ if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
break;
case IPC_RMID:
break;
===== ipc/sem.c 1.36 vs edited =====
--- 1.36/ipc/sem.c 2005-01-05 02:48:17 +00:00
+++ edited/ipc/sem.c 2005-02-28 13:39:48 +00:00
@@ -72,6 +72,7 @@
#include <linux/smp_lock.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -803,6 +804,8 @@
if(cmd == IPC_SET) {
if(copy_semid_from_user (&setbuf, arg.buf, version))
return -EFAULT;
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
}
sma = sem_lock(semid);
if(sma==NULL)
===== ipc/shm.c 1.43 vs edited =====
--- 1.43/ipc/shm.c 2004-12-13 10:47:27 +00:00
+++ edited/ipc/shm.c 2005-02-28 13:39:28 +00:00
@@ -27,6 +27,7 @@
#include <linux/shmem_fs.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -600,6 +601,8 @@
err = -EFAULT;
goto out;
}
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
down(&shm_ids.sem);
shp = shm_lock(shmid);
err=-EINVAL;
===== kernel/auditsc.c 1.6 vs edited =====
--- 1.6/kernel/auditsc.c 2005-01-31 06:33:47 +00:00
+++ edited/kernel/auditsc.c 2005-02-28 13:43:01 +00:00
@@ -92,6 +92,23 @@
dev_t rdev;
};
+struct audit_aux_data {
+ struct audit_aux_data *next;
+ int type;
+};
+
+#define AUDIT_AUX_IPCPERM 0
+
+struct audit_aux_data_ipcctl {
+ struct audit_aux_data d;
+ struct ipc_perm p;
+ unsigned long qbytes;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+};
+
+
/* The per-task audit context. */
struct audit_context {
int in_syscall; /* 1 if task is in a syscall */
@@ -107,6 +124,7 @@
int name_count;
struct audit_names names[AUDIT_NAMES];
struct audit_context *previous; /* For nested syscalls */
+ struct audit_aux_data *aux;
/* Save things to print about task_struct */
pid_t pid;
@@ -504,6 +522,16 @@
context->name_count = 0;
}
+static inline void audit_free_aux(struct audit_context *context)
+{
+ struct audit_aux_data *aux;
+
+ while ((aux = context->aux)) {
+ context->aux = aux->next;
+ kfree(aux);
+ }
+}
+
static inline void audit_zero_context(struct audit_context *context,
enum audit_state state)
{
@@ -570,6 +598,7 @@
context->name_count, count);
}
audit_free_names(context);
+ audit_free_aux(context);
kfree(context);
context = previous;
} while (context);
@@ -607,6 +636,29 @@
context->euid, context->suid, context->fsuid,
context->egid, context->sgid, context->fsgid);
audit_log_end(ab);
+ while (context->aux) {
+ struct audit_aux_data *aux;
+
+ ab = audit_log_start(context);
+ if (!ab)
+ continue; /* audit_panic has been called */
+
+ aux = context->aux;
+ context->aux = aux->next;
+
+ audit_log_format(ab, "auxitem=%d", aux->type);
+ switch (aux->type) {
+ case AUDIT_AUX_IPCPERM: {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+ audit_log_format(ab,
+ " qbytes=%lx uid=%d gid=%d mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ }
+ }
+ audit_log_end(ab);
+ kfree(aux);
+ }
+
for (i = 0; i < context->name_count; i++) {
ab = audit_log_start(context);
if (!ab)
@@ -789,6 +841,7 @@
tsk->audit_context = new_context;
} else {
audit_free_names(context);
+ audit_free_aux(context);
audit_zero_context(context, context->state);
tsk->audit_context = context;
}
@@ -926,4 +979,30 @@
uid_t audit_get_loginuid(struct audit_context *ctx)
{
return ctx ? ctx->loginuid : -1;
+}
+
+ return 0;
+ }
+
+int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+{
+ struct audit_aux_data_ipcctl *ax;
+ struct audit_context *context = current->audit_context;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->qbytes = qbytes;
+ ax->uid = uid;
+ ax->gid = gid;
+ ax->mode = mode;
+
+ ax->d.type = AUDIT_AUX_IPCPERM;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
}
A
6 (
x 9
z
z
z
raph
z
z
z
5
n
6
y c li
!
50,
6
9
6
0)
z
ph
0,
6
6
6!
,
6
z
ph
9
z
y
A
y
ph
y c li
y
50y
y c link
h
y c link
x
!
0,
6
y
y
ph
ph
y
y
aph
y c link
ph
h
h
'
aph
y c link
t
h
h
y c link
W ÿ
)Y ¡
x
x
h
Òn A
6
6
pc/msg.
x c link
8
x
s
ne !
6
0,
6
05
6
8
05
50,
6
--
dwmw2
19 years, 9 months
[RFC][PATCH] (#5) prelim auditfs
by Timothy R. Chavez
Hello,
Before we get started I just have to tell the world: It's a beautiful
day here in Austin, TX.
There were enough changes for this patch that I felt it'd be OK and
simpler if I just called it patch #5. In this patch I fix the logic
which was pretty broken last time (man was it broken). I also cleaned
up the code: reduced more code redundancy, tightened up helper
functions, fixed minor and major bugs, and attempted to make the code
more readable.
Two improvements:
1.
I did something which might be kind of ballsy, but it seems to work just fine.
In a very tired state I tried explaining this one over the phone. My
guess is that it made little to no sense -- sorry :( perhaps I'll be a
little more eloquent via e-mail.
A file/directory that is already being watched gives that watch
precedence on that inode. This means that if we move a watched file,
/tmp/foo, to /tmp/bar and then watch /tmp/bar, /tmp/bar will still
report watch information for /tmp/foo (Likewise, if we moved /tmp/foo
to /tmp/bar and a watch already exists on /tmp/bar, the watch for
/tmp/foo would remain). This is only semi-cool. To become fully-cool
we'd also like to be able to adopt (automatically) the watch on
/tmp/bar if and when the watch on /tmp/foo is ever removed. Hooking
d_lookup seemed like the best place to do this.
2.
There are three kinds of inodes that make use of the audit_data inode
struct: watched, watching, both. When we watch an inode that is also
watching, it'd be a mistake to overwrite it with the preallocated
memory associated with that watch entry. There goes the watchlist,
doh! So, in this case, we simply transfer into the preallocated
memory the inode's current audit_data. This has a nifty side-effect.
Iff the inode is stationary in the filesystem (movement destroys
watchlists), then if we were to delete and recreate the directory, its
watches would still be intact. If we remove the acutally watch, the
watchlist will automatically be drained. To remove individual
watches, the directory would have to first be resurrected.
What is left?
- Feature: List all watches currently in the filesystem
- Comments: Add [better | more] comments
- Test, test, test
Testing:
Starting tomorrow, Loulwa S. will officially be joining this project,
and will be helping me with the functional test case development
needed for the auditfs piece.
Chris, I wasn't really able to find much on the umount() problem the
Inotify guys were having. I found a conversation / beat down which
alluded to it, but that's it. Still, I hadn't actually tested the
behavior when I umount a device that has watches on it, so I figured
I'd at least do this test:
I added watches to a mount, removed the mount, and saw all the watches
putting back all their references and being freed / put back into
their respective caches. This is the correct behavior in my book.
Was it something more / different?
Still unable to provide userspace piece for testing. I am going to
port it to audit-0.6.4
Please, please, please... look this over and give comments, feedback,
and suggestions. Don't hold back, let me have it.
--
- Timothy R. Chavez
19 years, 10 months