RE: Kernel audit_context and name_count problem
by Andy Fanton
Hi -
I'm working on an LKM for a security software product that does real-time
file system change monitoring. The product has been in the field for a
number of years and in use by many customers with great success.
Recently we ran into an installation that is making use of Audit in addition
to some Symantec products along with our product. This "stack" of security
and detection software all running simultaneously is causing an issue that
they're blaming on our driver.
After lots of digging, the real issue is that the audit_context->name_count
is growing during certain syscall paths (sys_rename in particular), and at
some point a getname() (which ends up in audit_getname() ) is called that
hits the following line in auditsc.c:
BUG_ON(context->name_count >= AUDIT_NAMES);
This is on RHEL 5.8 with a 2.6.18-330el5 kernel, but looking at kernel
sources shows this same code exists in most of the 2.6 kernel lines.
The question is this: Is there any sane way for my code to check that
name_count value in current->audit_context BEFORE calling getname() so I can
avoid the BUG_ON and subsequent mayhem that ensues? I'd rather fail
gracefully than crash their system every time too many people call
getname().
Unfortunately the structure definition for audit_context is inside the C
file, which makes it opaque to my LKM code. That structure changes enough
between kernel versions that it would be difficult (and stupid anyway) to
put a manual "copy" of the structure definition in my own code so that I
could access that value.
My own code only uses a maximum of 4 of the available AUDIT_NAMES (20) slots
in the audit_context structure. It's the presence of other 3rd party LKMs
and their use of Audit that is causing this condition, and the reason it is
somewhat beyond my control.
Any suggestions or hints would be greatly appreciated! Thanks to all!
- Andy
11 years
SYSCALL and you...err...and me...
by leam hall
I'm making a little progress in identifying the unknown syscalls. It often
helps if you are not so cold and remember to look for a log...
The failed call below is root doing a grep. I do not know why it failed.
The PPID is a bash shell. Any good docs available to explain the codes?
Thanks!
Leam
###
grep SYSCALL audit.log | grep "success=no" | tail -1
type=SYSCALL msg=audit(1382703881.711:2677787): arch=c000003e syscall=2
success=no exit=-2 a0=7914b20 a1=0 a2=0 a3=3a89724793 items=1 ppid=25339
pid=26563 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=pts1 ses=4445 comm="grep" exe="/bin/grep"
subj=root:system_r:unconfined_t:s0-s0:c0.c1023 key=(null)
--
Mind on a Mission <http://leamhall.blogspot.com/>
11 years
[PATCH] audit: change pid to portid for audit_reply
by Gao feng
The "pid" is not a suitable name for netlink port,
change it to "portid".
more information, please see commit
15e473046cb6e5d18a4d0057e61d76315230382b
Signed-off-by: Gao feng <gaofeng(a)cn.fujitsu.com>
---
kernel/audit.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 7b0e23a..50fdcba 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -165,7 +165,7 @@ struct audit_buffer {
};
struct audit_reply {
- int pid;
+ int portid;
struct sk_buff *skb;
};
@@ -487,7 +487,7 @@ int audit_send_list(void *_dest)
return 0;
}
-struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
+struct sk_buff *audit_make_reply(int portid, int seq, int type, int done,
int multi, const void *payload, int size)
{
struct sk_buff *skb;
@@ -500,7 +500,7 @@ struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
if (!skb)
return NULL;
- nlh = nlmsg_put(skb, pid, seq, t, size, flags);
+ nlh = nlmsg_put(skb, portid, seq, t, size, flags);
if (!nlh)
goto out_kfree_skb;
data = nlmsg_data(nlh);
@@ -521,13 +521,13 @@ static int audit_send_reply_thread(void *arg)
/* Ignore failure. It'll only happen if the sender goes away,
because our timeout is set to infinite. */
- netlink_unicast(audit_sock, reply->skb, reply->pid, 0);
+ netlink_unicast(audit_sock, reply->skb, reply->portid, 0);
kfree(reply);
return 0;
}
/**
* audit_send_reply - send an audit reply message via netlink
- * @pid: process id to send reply to
+ * @portid: the portid of netlink socket
* @seq: sequence number
* @type: audit message type
* @done: done (last) flag
@@ -538,7 +538,7 @@ static int audit_send_reply_thread(void *arg)
* Allocates an skb, builds the netlink message, and sends it to the pid.
* No failure notifications.
*/
-static void audit_send_reply(int pid, int seq, int type, int done, int multi,
+static void audit_send_reply(int portid, int seq, int type, int done, int multi,
const void *payload, int size)
{
struct sk_buff *skb;
@@ -549,11 +549,11 @@ static void audit_send_reply(int pid, int seq, int type, int done, int multi,
if (!reply)
return;
- skb = audit_make_reply(pid, seq, type, done, multi, payload, size);
+ skb = audit_make_reply(portid, seq, type, done, multi, payload, size);
if (!skb)
goto out;
- reply->pid = pid;
+ reply->portid = portid;
reply->skb = skb;
tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
--
1.8.3.1
11 years
[PATCH] audit: don't create audit log when audit_backlog_limit is zero
by Gao feng
As the man page of auditctl said:
"
-b backlog
Set max number of outstanding audit buffers allowed (Kernel Default=64)
If all buffers are full, the failure flag is consulted by the kernel
for action.
"
So if audit_backlog_limit is zero, it means no audit buffer
should be allocated.
Signed-off-by: Gao feng <gaofeng(a)cn.fujitsu.com>
---
kernel/audit.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 7b0e23a..bbb4000 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1104,14 +1104,16 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
if (unlikely(audit_filter_type(type)))
return NULL;
+ if (!audit_backlog_limit)
+ return NULL;
+
if (gfp_mask & __GFP_WAIT)
reserve = 0;
else
reserve = 5; /* Allow atomic callers to go up to five
entries over the normal backlog limit */
- while (audit_backlog_limit
- && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
+ while (skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) {
unsigned long sleep_time;
--
1.8.3.1
11 years
audit_ftype_to_name?
by Stephen Quinney
I am wanting to use the audit_ftype_to_name function which is provided
in the audit python module. It seems that this always returns None
which is not particularly useful. I can see that the function is
implemented in lib/lookup_table.c and it only does something when the
NO_TABLES cpp macro is not defined. In src/mt/Makefile.am that is
defined (with -DNO_TABLES in AM_CFLAGS), I assume that is deliberate?
I can't see any definition of the ftype_i2s function which is called
by audit_ftype_to_name so maybe this hasn't been implemented yet?
Thanks,
Stephen
--
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
11 years
[BUG][PATCH][RFC] audit: hang up in audit_log_start executed on auditd
by Toshiyuki Okajima
Hi.
The following reproducer causes auditd daemon hang up.
(But the hang up is released after the audit_backlog_wait_time passes.)
# auditctl -a exit,always -S all
# reboot
I reproduced the hangup on KVM, and then got a crash dump.
After I analyzed the dump, I found auditd daemon hung up in audit_log_start.
(I have confirmed it on linux-3.12-rc4.)
Like this:
crash> bt 1426
PID: 1426 TASK: ffff88007b63e040 CPU: 1 COMMAND: "auditd"
#0 [ffff88007cb93918] __schedule at ffffffff8155d980
#1 [ffff88007cb939b0] schedule at ffffffff8155de99
#2 [ffff88007cb939c0] schedule_timeout at ffffffff8155b840
#3 [ffff88007cb93a60] audit_log_start at ffffffff810d3ce5
#4 [ffff88007cb93b20] audit_log_config_change at ffffffff810d3ece
#5 [ffff88007cb93b60] audit_receive_msg at ffffffff810d4fd6
#6 [ffff88007cb93c00] audit_receive at ffffffff810d5173
#7 [ffff88007cb93c30] netlink_unicast at ffffffff814c5269
#8 [ffff88007cb93c90] netlink_sendmsg at ffffffff814c6386
#9 [ffff88007cb93d20] sock_sendmsg at ffffffff814813c0
#10 [ffff88007cb93e30] SYSC_sendto at ffffffff81481524
#11 [ffff88007cb93f70] sys_sendto at ffffffff8148157e
#12 [ffff88007cb93f80] system_call_fastpath at ffffffff81568052
RIP: 00007f5c47f7fba3 RSP: 00007fffcf21a118 RFLAGS: 00010202
RAX: 000000000000002c RBX: ffffffff81568052 RCX: 0000000000000000
RDX: 0000000000000030 RSI: 00007fffcf21e7d0 RDI: 0000000000000003
RBP: 00007fffcf21e7d0 R8: 00007fffcf21a130 R9: 000000000000000c
R10: 0000000000000000 R11: 0000000000000293 R12: ffffffff8148157e
R13: ffff88007cb93f78 R14: 0000000000000020 R15: 0000000000000030
ORIG_RAX: 000000000000002c CS: 0033 SS: 002b
The reason is that auditd daemon itself cannot consume its backlog
while audit_log_start is calling schedule_timeout on auditd daemon.
So, that is a deadlock!
Therefore, I think audit_log_start shouldn't handle auditd's backlog
when auditd daemon executes audit_log_start.
For example, I made the following fix patch.
--------------------------------------------------------------
auditd daemon can execute the audit_log_start, and then it can cause
a hang up because only auditd daemon can consume the backlog.
So, audit_log_start executed by auditd daemon should not handle the backlog
in case auditd daemon hangs up (while wait_for_auditd is calling).
Signed-off-by: Toshiyuki Okajima <toshi.okajima(a)jp.fujitsu.com>
---
kernel/audit.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 7b0e23a..86c389e 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1098,6 +1098,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
int reserve;
unsigned long timeout_start = jiffies;
+ if (audit_pid && (audit_pid == current->pid))
+ return NULL;
+
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
--
1.5.5.6
11 years
Auditing only when auid and uid differ
by Maupertuis Philippe
I want to track what people are doing when then change their userid.
Basically I would like to write :
-a exit,never -F arch=b32 -S all -F auid=4294967295
-a exit,never -F arch=b64 -S all -F auid=4294967295
-a exit,always -F arch=b32 -S all -F auid>1000 -F uid!=auid -k userchange
-a exit,always -F arch=b64 -S all -F auid>1000 -F uid!=auid -k userchange
However it seems that it's not a valid syntax.
Is there a way to achieve that.
Philippe
________________________________
Ce message et les pi?ces jointes sont confidentiels et r?serv?s ? l'usage exclusif de ses destinataires. Il peut ?galement ?tre prot?g? par le secret professionnel. Si vous recevez ce message par erreur, merci d'en avertir imm?diatement l'exp?diteur et de le d?truire. L'int?grit? du message ne pouvant ?tre assur?e sur Internet, la responsabilit? de Worldline ne pourra ?tre recherch?e quant au contenu de ce message. Bien que les meilleurs efforts soient faits pour maintenir cette transmission exempte de tout virus, l'exp?diteur ne donne aucune garantie ? cet ?gard et sa responsabilit? ne saurait ?tre recherch?e pour tout dommage r?sultant d'un virus transmis.
This e-mail and the documents attached are confidential and intended solely for the addressee; it may also be privileged. If you receive this e-mail in error, please notify the sender immediately and destroy it. As its integrity cannot be secured on the Internet, the Worldline liability cannot be triggered for the message content. Although the sender endeavours to maintain a computer virus-free network, the sender does not warrant that this transmission is virus-free and will not be liable for any damages resulting from any virus transmitted.
11 years
[PATCH] audit: update AUDIT_INODE filter rule to comparator function
by Richard Guy Briggs
It appears this one comparison function got missed in f368c07d (and 9c937dcc).
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/auditsc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 63223d6..065c7a1 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -566,7 +566,7 @@ static int audit_filter_rules(struct task_struct *tsk,
break;
case AUDIT_INODE:
if (name)
- result = (name->ino == f->val);
+ result = audit_comparator(name->ino, f->op, f->val);
else if (ctx) {
list_for_each_entry(n, &ctx->names_list, list) {
if (audit_comparator(n->ino, f->op, f->val)) {
--
1.7.1
11 years