[PATCH] Support for auditing on the actions of a not-yet-executed process.
by Peter Moody
eg:
-a exit,always -F arch=b64 -S socket -F 'a0!=1' -F exe=/bin/bash -F success=1
to see instances of /bin/bash opening a non-local socket. Or
-a exit,always -F arch=b64 -S socket -F 'a0!=1' -F exe_children=/bin/bash -F success=1
to instances of /bin/bash, and any descendant processes, opening a non local socket.
proposed https://www.redhat.com/archives/linux-audit/2012-June/msg00002.html
and it seemed like there was interest.
Signed-off-by: Peter Moody <pmoody(a)google.com>
---
trunk/lib/errormsg.h | 2 +-
trunk/lib/fieldtab.h | 2 ++
trunk/lib/libaudit.c | 11 +++++++++++
trunk/lib/libaudit.h | 7 ++++++-
4 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/trunk/lib/errormsg.h b/trunk/lib/errormsg.h
index 4d996d5..cd595ec 100644
--- a/trunk/lib/errormsg.h
+++ b/trunk/lib/errormsg.h
@@ -51,7 +51,7 @@ static const struct msg_tab err_msgtab[] = {
{ -15, 2, "-F unknown errno -"},
{ -16, 2, "-F unknown file type - " },
{ -17, 1, "can only be used with exit and entry filter list" },
- { -18, 1, "" }, // Unused
+ { -18, 1, "only takes = operator" },
{ -19, 0, "Key field needs a watch or syscall given prior to it" },
{ -20, 2, "-F missing value after operation for" },
{ -21, 2, "-F value should be number for" },
diff --git a/trunk/lib/fieldtab.h b/trunk/lib/fieldtab.h
index c0432cc..245b541 100644
--- a/trunk/lib/fieldtab.h
+++ b/trunk/lib/fieldtab.h
@@ -66,3 +66,5 @@ _S(AUDIT_ARG3, "a3" )
_S(AUDIT_FILTERKEY, "key" )
_S(AUDIT_FIELD_COMPARE, "field_compare" )
+_S(AUDIT_EXE, "exe" )
+_S(AUDIT_EXE_CHILDREN, "exe_children" )
diff --git a/trunk/lib/libaudit.c b/trunk/lib/libaudit.c
index 20eaf5f..06eed86 100644
--- a/trunk/lib/libaudit.c
+++ b/trunk/lib/libaudit.c
@@ -1400,6 +1400,17 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
else
return -21;
break;
+ case AUDIT_EXE_CHILDREN:
+ case AUDIT_EXE:
+ {
+ struct stat buf;
+ if ((stat(v, &buf)) < 0)
+ return -2;
+ if (op != AUDIT_EQUAL)
+ return -18;
+ rule->values[rule->field_count] = (unsigned long)buf.st_ino;
+ }
+ break;
case AUDIT_DEVMAJOR...AUDIT_INODE:
case AUDIT_SUCCESS:
if (flags != AUDIT_FILTER_EXIT)
diff --git a/trunk/lib/libaudit.h b/trunk/lib/libaudit.h
index 89dd588..2c8a802 100644
--- a/trunk/lib/libaudit.h
+++ b/trunk/lib/libaudit.h
@@ -243,6 +243,12 @@ extern "C" {
#ifndef AUDIT_FIELD_COMPARE
#define AUDIT_FIELD_COMPARE 111
#endif
+#ifndef AUDIT_EXE
+#define AUDIT_EXE 112
+#endif
+#ifndef AUDIT_EXE_CHILDREN
+#define AUDIT_EXE_CHILDREN 113
+#endif
#ifndef AUDIT_COMPARE_UID_TO_OBJ_UID
#define AUDIT_COMPARE_UID_TO_OBJ_UID 1
@@ -524,4 +530,3 @@ extern void audit_rule_free_data(struct audit_rule_data *rule);
#endif
#endif
-
--
1.7.7.3
10 years, 6 months
Re: [PATCH RFC 7/8] audit: report namespace information along with USER events
by Eric W. Biederman
Aristeu Rozanski <arozansk(a)redhat.com> writes:
> For userspace generated events, include a record with the namespace
> procfs inode numbers the process belongs to. This allows to track down
> and filter audit messages by userspace.
I am not comfortable with using the inode numbers this way. It does not
pass the test of can I migrate a container and still have this work
test. Any kind of kernel assigned name for namespaces fails that test.
I also don't like that you don't include the procfs device number. An
inode number means nothing without knowing which filesystem you are
referring to.
It may never happen but I reserve the right to have the inode numbers
for namespaces to show up differently in different instances of procfs.
Beyond that I think this usage is possibly buggy by using two audit
records for one event.
> Signed-off-by: Aristeu Rozanski <arozansk(a)redhat.com>
> ---
> include/uapi/linux/audit.h | 1 +
> kernel/audit.c | 51 +++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 51 insertions(+), 1 deletions(-)
>
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index 9f096f1..3ec3ccb 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -106,6 +106,7 @@
> #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */
> #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */
> #define AUDIT_SECCOMP 1326 /* Secure Computing event */
> +#define AUDIT_USER_NAMESPACE 1327 /* Information about process' namespaces */
>
> #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
> #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 58db117..b17f9c0 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -62,6 +62,11 @@
> #include <linux/freezer.h>
> #include <linux/tty.h>
> #include <linux/pid_namespace.h>
> +#include <linux/ipc_namespace.h>
> +#include <linux/mnt_namespace.h>
> +#include <linux/utsname.h>
> +#include <linux/user_namespace.h>
> +#include <net/net_namespace.h>
>
> #include "audit.h"
>
> @@ -641,6 +646,49 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
> return rc;
> }
>
> +#ifdef CONFIG_NAMESPACES
> +static int audit_log_namespaces(struct task_struct *tsk,
> + struct sk_buff *skb)
> +{
> + struct audit_context *ctx = tsk->audit_context;
> + struct audit_buffer *ab;
> +
> + if (!audit_enabled)
> + return 0;
> +
> + ab = audit_log_start(ctx, GFP_KERNEL, AUDIT_USER_NAMESPACE);
> + if (unlikely(!ab))
> + return -ENOMEM;
> +
> + audit_log_format(ab, "mnt=%u", mntns_get_inum(tsk));
> +#ifdef CONFIG_NET_NS
> + audit_log_format(ab, " net=%u", netns_get_inum(tsk));
> +#endif
> +#ifdef CONFIG_UTS_NS
> + audit_log_format(ab, " uts=%u", utsns_get_inum(tsk));
> +#endif
> +#ifdef CONFIG_IPC_NS
> + audit_log_format(ab, " ipc=%u", ipcns_get_inum(tsk));
> +#endif
> +#ifdef CONFIG_PID_NS
> + audit_log_format(ab, " pid=%u", pidns_get_inum(tsk));
> +#endif
> +#ifdef CONFIG_USER_NS
> + audit_log_format(ab, " user=%u", userns_get_inum(tsk));
> +#endif
> + audit_set_pid(ab, NETLINK_CB(skb).portid);
> + audit_log_end(ab);
> +
> + return 0;
> +}
> +#else
> +static inline int audit_log_namespaces(struct task_struct *tsk,
> + struct sk_buff *skb)
> +{
> + return 0;
> +}
> +#endif
> +
> static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
> {
> u32 seq, sid;
> @@ -741,7 +789,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
> }
> audit_log_common_recv_msg(&ab, msg_type,
> loginuid, sessionid, sid,
> - NULL);
> + current->audit_context);
>
> if (msg_type != AUDIT_USER_TTY)
> audit_log_format(ab, " msg='%.1024s'",
> @@ -758,6 +806,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
> }
> audit_set_pid(ab, NETLINK_CB(skb).portid);
> audit_log_end(ab);
> + audit_log_namespaces(current, skb);
> }
> break;
> case AUDIT_ADD:
10 years, 9 months
[PATCH] audit: audit on the future execution of a binary.
by Peter Moody
This adds the ability audit the actions of a not-yet-running process,
as well as the children of a not-yet-running process.
Signed-off-by: Peter Moody <pmoody(a)google.com>
---
include/linux/audit.h | 2 ++
kernel/auditfilter.c | 6 ++++++
kernel/auditsc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 22f292a..5506cb1 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -260,6 +260,8 @@
#define AUDIT_OBJ_UID 109
#define AUDIT_OBJ_GID 110
#define AUDIT_FIELD_COMPARE 111
+#define AUDIT_EXE 112
+#define AUDIT_EXE_CHILDREN 113
#define AUDIT_ARG0 200
#define AUDIT_ARG1 (AUDIT_ARG0+1)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a6c3f1a..1e6c571 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -546,6 +546,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
if (f->val > AUDIT_MAX_FIELD_COMPARE)
goto exit_free;
break;
+ case AUDIT_EXE:
+ case AUDIT_EXE_CHILDREN:
+ if (f->op != Audit_equal) {
+ goto exit_free;
+ }
+ break;
default:
goto exit_free;
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4b96415..9cebe95 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -46,6 +46,7 @@
#include <asm/types.h>
#include <linux/atomic.h>
#include <linux/fs.h>
+#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/mm.h>
#include <linux/export.h>
@@ -68,6 +69,7 @@
#include <linux/capability.h>
#include <linux/fs_struct.h>
#include <linux/compat.h>
+#include <linux/sched.h>
#include "audit.h"
@@ -592,6 +594,35 @@ static int audit_field_compare(struct task_struct *tsk,
return 0;
}
+int audit_match_exe(struct task_struct *tsk, struct audit_field *f)
+{
+ int result = 0;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+
+ if (!tsk)
+ goto out;
+
+ mm = tsk->mm;
+ if (!mm)
+ goto out;
+
+ down_read(&mm->mmap_sem);
+ vma = mm->mmap;
+ while (vma) {
+ if ((vma->vm_flags & VM_EXECUTABLE) &&
+ vma->vm_file) {
+ struct inode *ino = vma->vm_file->f_path.dentry->d_inode;
+ result = audit_comparator(ino->i_ino, f->op, f->val);
+ break;
+ }
+ vma = vma->vm_next;
+ }
+ up_read(&mm->mmap_sem);
+out:
+ return result;
+}
+
/* Determine if any context name data matches a rule's watch data */
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise.
@@ -629,6 +660,22 @@ static int audit_filter_rules(struct task_struct *tsk,
result = audit_comparator(ctx->ppid, f->op, f->val);
}
break;
+ case AUDIT_EXE:
+ result = audit_match_exe(tsk, f);
+ break;
+ case AUDIT_EXE_CHILDREN:
+ {
+ struct task_struct *ptsk;
+ for (ptsk = tsk;
+ ptsk->parent->pid > 0;
+ ptsk = find_task_by_vpid(ptsk->parent->pid)) {
+ if (audit_match_exe(ptsk, f)) {
+ ++result;
+ break;
+ }
+ }
+ }
+ break;
case AUDIT_UID:
result = audit_comparator(cred->uid, f->op, f->val);
break;
--
1.7.7.3
11 years, 1 month
user message limits
by LC Bruzenak
I know I can go look at the code, however I figured I'd ask here first
about the limits on the user message in both audit_log_user_message and
ausearch.
With audit_log_user_message the maximum length allowed appears to be
around MAX_AUDIT_MESSAGE_LENGTH-100. I think it may depend on the
executable name length (and other stuff auto-pushed into the string)
which is why I say "around".
Even when I get a successful return value (from audit_log_user_message),
I don't get my string back out in "ausearch" unless it is WAY smaller -
~1K or less I think.
Any ideas/thoughts?
This is the latest (1.7.11-2) audit package.
Thx,
LCB.
--
LC (Lenny) Bruzenak
lenny(a)magitekltd.com
11 years, 1 month
Proposed additions to ausearch
by Burn Alting
I want to add a number of features to ausearch and would like the list
to make comment on my proposals before implementing same.
#1
Have ausearch only output whole events (all supplemental records of an
event must be present in the audit.log files to be output) and maintain
state to know the last whole event displayed.
The use case is for when one periodically processes the audit log files
and the last log file opened does not necessarily hold whole events for
the last few events in the file.
One could possibly achieve this using the --start/--end arguments to
ausearch but it would be challenging to work out the appropriate
start/end times on a high log throughput system.
My plan is to maintain state recording the last whole event displayed
along with details of the file it resided in (eg inode, etc).
#2
Add a 'parser friendly' option to ausearch's -i output such that it is
more friendly for parsing. As we know, the -i argument causes output in
the form of
- a "header" comprising
- the node if present as a key value pair
- the event type as a key value pair
- the message date/time and serial
- a colon
- a series of key value pairs
The new option would have output that
- surrounds all values with double quotes
- escape embedded double quote and backslash characters in the value
with the backslash character '\'
- translate embedded newlines or carriage returns into '\n' and '\r'
respectively
- translate all non-printing characters into escaped octal values or
some other recommended text based format.
#3
Add an option to include the original value as well as the interpreted
value when interpretation (-i) is requested. This would be for specified
keys or, key types.
One use case would be for user or group names to include the original
uid/gids. This is to aid de-conflicting inadvertent user or group
attribution across an enterprise environment.
The option would have arguments that identify what key values will have
both original and interpreted values.
Regards
Burn Alting
11 years, 5 months
[PATCH] [BZ905179] audit: omit check for uid and gid validity in audit rules and data
by Richard Guy Briggs
audit rule additions containing "-F auid!=4294967295" were failing with EINVAL.
UID_INVALID (and GID_INVALID) is actually a valid uid (gid) for setting and
testing against audit rules. Remove the check for invalid uid and gid when
parsing rules and data for logging.
Revert part of ca57ec0f00c3f139c41bf6b0a5b9bcc95bbb2ad7 (2012-09-11) to fix
this.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/auditfilter.c | 12 ------------
1 files changed, 0 insertions(+), 12 deletions(-)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index f9fc54b..457ee39 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -360,10 +360,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
/* bit ops not implemented for uid comparisons */
if (f->op == Audit_bitmask || f->op == Audit_bittest)
goto exit_free;
-
f->uid = make_kuid(current_user_ns(), f->val);
- if (!uid_valid(f->uid))
- goto exit_free;
break;
case AUDIT_GID:
case AUDIT_EGID:
@@ -372,10 +369,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
/* bit ops not implemented for gid comparisons */
if (f->op == Audit_bitmask || f->op == Audit_bittest)
goto exit_free;
-
f->gid = make_kgid(current_user_ns(), f->val);
- if (!gid_valid(f->gid))
- goto exit_free;
break;
case AUDIT_PID:
case AUDIT_PERS:
@@ -469,10 +463,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
/* bit ops not implemented for uid comparisons */
if (f->op == Audit_bitmask || f->op == Audit_bittest)
goto exit_free;
-
f->uid = make_kuid(current_user_ns(), f->val);
- if (!uid_valid(f->uid))
- goto exit_free;
break;
case AUDIT_GID:
case AUDIT_EGID:
@@ -482,10 +473,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
/* bit ops not implemented for gid comparisons */
if (f->op == Audit_bitmask || f->op == Audit_bittest)
goto exit_free;
-
f->gid = make_kgid(current_user_ns(), f->val);
- if (!gid_valid(f->gid))
- goto exit_free;
break;
case AUDIT_PID:
case AUDIT_PERS:
--
1.7.1
11 years, 5 months
libaudit large stack requirement in audit_send()
by Luciano Chavez
Hello,
I am working with a development team developing a J2EE application. They
reported a problem with a crash in audit_send(). The crash occurred in a
ppc64 architecture environment early on in the invocation to audit send.
The crash occurs in this instruction which is establishing the size of
the local stack:
=> 0xfff73237994 <audit_send+52>: stdu r1,-27232(r1)
I found one large struct defined to a local variable
(gdb) print sizeof(struct audit_message)
$4 = 8988
but you will note that it asks for much more than that and after looking
at the audit_send() routine, it calls a function called check_ack()
which appears to be inlined and it contains two even larger definitions
on the stack for the following structure:
struct audit_reply
(gdb) print sizeof(struct audit_reply)
$3 = 9016
So, the combination of the three is what requires almost 26.5K of local
stack usage in this frame alone.
Is there a requirement for libaudit to have the structs on the stack
versus allocated from heap? Is so, is this requirement documented
somewhere?
To be fair, the Java application has some heavy stack usage as it is
since it is deployed in a web application server and there is a JNI
function that is somewhere in the call stack as well. However, the stack
usage in the audit_send() function seems ... excessive.
Originally the thread stacksize size was set to 256K and that did not
help but once we raised it to 1MB it did but I think that is probably
more than we really need.
I have looked at the source for the audit 2.2.3 release from March and
don't see a difference in how the structs are allocated. So once again,
if there is not a requirement that the structs be on the stack, should
they not be allocated off the heap?
regards,
--
Luciano Chavez <lnx1138(a)linux.vnet.ibm.com>
11 years, 6 months
pam_tty_audit icanon log switch
by Richard Guy Briggs
Hi folks,
There's been a couple of requests to add a switch to pam_tty_audit to
*not* log passwords when logging user commands.
Most commands are entered one line at a time and processed as complete
lines in non-canonical mode. Commands that interactively require a
password, enter canonical mode to do this. This feature (icanon) can be
used to avoid logging passwords by audit while still logging the rest of
the command.
Adding a member to the struct audit_tty_status passed in by
pam_tty_audit allows control of canonical mode per task.
Note: The original patch added a sysctl to control this system-wide,
which did work fine as expected, but it was recommended to keep the
switch with the module invocation, turning it into a per-task switch.
This method has also been tested.
Here are two patches, the first to pam to add the switch to
the pam_tty_audit module. The second is to the kernel to add the
necessary bits in audit and tty:
pam_tty_audit: add an option to control logging of passwords
tty: add an option to control logging of passwords with pam_tty_audit
Please have a quick look and with some initial feedback I'll post them
upstream. I'd normally use git send-email and in-line it, but since
they were patches for two different entities, thought it best to do it
this way instead.
- RGB
--
Richard Guy Briggs <rbriggs(a)redhat.com>
Senior Software Engineer
AMER ENG Base Operating Systems
Remote, Canada, Ottawa
Voice: 1.647.777.2635
Internal: (81) 32635
11 years, 6 months
Audit filter by TTY
by John Bambenek
I was playing around and wanted to know if there is plans to allow audit rule filters by TTY, or specifically filter when tty != (none) (i.e. interactive login events).
11 years, 6 months
Adding enterprise capability - an includeConfig directive for audit.rules?
by Burn Alting
All,
Has anyone considered allowing an includeConfig statement for
audit.rules (or auditd.conf if need be)?
The action would be to, at that point in the parse (or the end of the
file, if auditd.conf holds the directive), open the nominated directory
and any files within, and parse them.
The idea is to allow for localization of audit. At an enterprise level
one would deploy the common, corporate set of rules
in /etc/audit/audit.rules. Should a local system need additional rules
such as tailored file watches, workstation or capability specific
monitoring, these could appear in files in the includeConfig directory.
That way, distribution mechanisms such as puppet, rpm satellite server,
apt repositories, etc can maintain the corporate set of rules without
changing localized configurations on updates.
I'm happy to author this.
Regards
Burn Alting
11 years, 6 months