SHA256
3
0
forked from pool/audit
audit/audit-ausearch-filter-apparmor-events.patch
Tony Jones 42d7928102 Accepting request 283367 from home:fdmanana:branches:security
- Teach ausearch to filter AppArmor events (Fate#317726).
  Added patch file audit-ausearch-filter-apparmor-events.patch

OBS-URL: https://build.opensuse.org/request/show/283367
OBS-URL: https://build.opensuse.org/package/show/security/audit?expand=0&rev=76
2015-01-29 19:21:15 +00:00

1491 lines
43 KiB
Diff

From: Filipe Manana <fdmanana@suse.com>
Date: Wed, 28 Jan 2015 16:08:01 +0000
References: Fate#317726
Upstream: never
Subject: [PATCH] Teach ausearch to filter AppArmor events
This changes makes ausearch able to filter AppArmor events according
to its specific fields. Several new command line parameters allow to
filter events by specific values, whose key matches the command line
parameters' names. These new parameters are:
--apparmor
--operation
--profile
--parent
--requested_mask
--denied_mask
--fsuid
--ouid
--target
--info
--capname
--error
--namespace
--rlimit
--laddr
--faddr
--lport
--fport
--family
--sock_type
--protocol
Usage examples:
$ ausearch -if log.txt --apparmor DENIED
----
time->Mon Jan 19 20:08:24 2015
type=1400 audit(1421698104.388:45): apparmor="DENIED" operation="open" parent=2442 profile="/usr/bin/xchat" name="/dev/shm/pulse-shm-1760669882" pid=2934 comm="xchat"
requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
----
time->Mon Jan 19 20:08:24 2015
type=1400 audit(1421698104.388:47): apparmor="DENIED" operation="mknod" parent=2442 profile="/usr/bin/xchat" name="/dev/shm/pulse-shm-1001794793" pid=2934 comm="xchat"
requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
$ ausearch -if log.txt --apparmor DENIED --operation mknod
----
time->Mon Jan 19 20:08:24 2015
type=1400 audit(1421698104.388:47): apparmor="DENIED" operation="mknod" parent=2442 profile="/usr/bin/xchat" name="/dev/shm/pulse-shm-1001794793" pid=2934 comm="xchat"
requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
$ ausearch -if log.txt --comm xchat --fport 6697
----
time->Sun Jan 18 18:37:45 2015
type=1400 audit(1421606265.719:2082): apparmor="ALLOWED" operation="recvmsg" parent=2391 profile="/usr/bin/xchat" pid=4107 comm="xchat" laddr=10.163.0.243 lport=55184
faddr=149.44.176.29 fport=6697 family="inet" sock_type="stream" protocol=6
----
time->Sun Jan 18 18:37:46 2015
type=1400 audit(1421606266.203:2098): apparmor="ALLOWED" operation="sendmsg" parent=2391 profile="/usr/bin/xchat" pid=4107 comm="xchat" laddr=10.163.0.243 lport=55184
faddr=149.44.176.29 fport=6697 family="inet" sock_type="stream" protocol=6
----
time->Sun Jan 18 18:37:46 2015
type=1400 audit(1421606266.259:2101): apparmor="ALLOWED" operation="recvmsg" parent=2391 profile="/usr/bin/xchat" pid=4107 comm="xchat" laddr=10.163.0.243 lport=55184
faddr=149.44.176.29 fport=6697 family="inet" sock_type="stream" protocol=6
----
time->Sun Jan 18 18:37:48 2015
type=1400 audit(1421606268.207:2104): apparmor="ALLOWED" operation="sendmsg" parent=2391 profile="/usr/bin/xchat" pid=4107 comm="xchat" laddr=10.163.0.243 lport=55184
faddr=149.44.176.29 fport=6697 family="inet" sock_type="stream" protocol=6
$ ausearch -if log.txt --comm xchat --fport 6697 --operation sendmsg
time->Sun Jan 18 18:37:46 2015
type=1400 audit(1421606266.203:2098): apparmor="ALLOWED" operation="sendmsg" parent=2391 profile="/usr/bin/xchat" pid=4107 comm="xchat" laddr=10.163.0.243 lport=55184
faddr=149.44.176.29 fport=6697 family="inet" sock_type="stream" protocol=6
----
time->Sun Jan 18 18:37:48 2015
type=1400 audit(1421606268.207:2104): apparmor="ALLOWED" operation="sendmsg" parent=2391 profile="/usr/bin/xchat" pid=4107 comm="xchat" laddr=10.163.0.243 lport=55184
faddr=149.44.176.29 fport=6697 family="inet" sock_type="stream" protocol=6
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
docs/ausearch.8 | 63 +++++++
src/aureport-options.c | 23 +++
src/ausearch-common.h | 23 +++
src/ausearch-llist.c | 56 ++++++
src/ausearch-llist.h | 22 +++
src/ausearch-lol.c | 2 +-
src/ausearch-match.c | 119 +++++++++++++
src/ausearch-options.c | 404 ++++++++++++++++++++++++++++++++++++++++++-
src/ausearch-parse.c | 459 +++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 1168 insertions(+), 3 deletions(-)
diff --git a/docs/ausearch.8 b/docs/ausearch.8
index 54018ae..c441f7c 100644
--- a/docs/ausearch.8
+++ b/docs/ausearch.8
@@ -18,15 +18,39 @@ Also be aware that not all record types have the requested information. For exam
.BR \-a ,\ \-\-event \ \fIaudit-event-id\fP
Search for an event based on the given \fIevent ID\fP. Messages always start with something like msg=audit(1116360555.329:2401771). The event ID is the number after the ':'. All audit events that are recorded from one application's syscall have the same audit event ID. A second syscall made by the same application will have a different event ID. This way they are unique.
.TP
+.BR \-\-apparmor \ \fItype\fP
+Search for an event matching the given AppArmor \fItype\fP value. This filters events from AppArmor wich have an attribute like apparmor="ALLOWED" for example.
+.TP
+.BR \-\-capname \ \fIcapname\fP
+Search for an event based on the given capability name \fIcapname\fP (AppArmor events).
+.TP
.BR \-c ,\ \-\-comm \ \fIcomm-name\fP
Search for an event based on the given \fIcomm name\fP. The comm name is the executable's name from the task structure.
.TP
+.BR \-\-denied_mask \ \fImask\fP
+Search for an event matching the given denied \fImask\fP (AppArmor events).
+.TP
+.BR \-\-error \ \fIerror\fP
+Search for an event based on the given \fIerror\fP (AppArmor events).
+.TP
.BR \-e,\ \-\-exit \ \fIexit-code-or-errno\fP
Search for an event based on the given syscall \fIexit code or errno\fP.
.TP
+.BR \-\-faddr \ \fIaddress\fP
+Search for an event based on the given foreign \fIaddress\fP (AppArmor events).
+.TP
+.BR \-\-family \ \fIfamily\fP
+Search for an event based on the given network \fIfamily\fP (AppArmor events).
+.TP
.BR \-f ,\ \-\-file \ \fIfile-name\fP
Search for an event based on the given \fIfilename\fP.
.TP
+.BR \-\-fport \ \fIport\fP
+Search for an event based on the given foreign \fport\fP (AppArmor events).
+.TP
+.BR \-\-fsuid \ \fIfsuid\fP
+Search for an event based on the given \fIfsuid\fP (AppArmor events).
+.TP
.BR \-ga ,\ \-\-gid-all \ \fIall-group-id\fP
Search for an event with either effective group ID or group ID matching the given \fIgroup ID\fP.
.TP
@@ -45,6 +69,9 @@ Search for an event with the given \fIhost name\fP. The hostname can be either a
.BR \-i ,\ \-\-interpret
Interpret numeric entities into text. For example, uid is converted to account name. The conversion is done using the current resources of the machine where the search is being run. If you have renamed the accounts, or don't have the same accounts on your machine, you could get misleading results.
.TP
+.BR \-\-info \ \fIinfo\fP
+Search for an event matching the given \fIinfo\fP value (AppArmor events).
+.TP
.BR \-if ,\ \-\-input \ \fIfile-name\fP
Use the given \fIfile\fP instead of the logs. This is to aid analysis where the logs have been moved to another machine or only part of a log was saved.
.TP
@@ -57,27 +84,57 @@ Stop after emitting the first event that matches the search criteria.
.BR \-k ,\ \-\-key \ \fIkey-string\fP
Search for an event based on the given \fIkey string\fP.
.TP
+.BR \-\-laddr \ \fIaddress\fP
+Search for an event based on the given local \fIaddress\fP (AppArmor events).
+.TP
.BR \-l ,\ \-\-line-buffered
Flush output on every line. Most useful when stdout is connected to a pipe and the default block buffering strategy is undesirable. May impose a performance penalty.
.TP
+.BR \-\-lport \ \fIport\fP
+Search for an event based on the given local \fport\fP (AppArmor events).
+.TP
.BR \-m ,\ \-\-message \ \fImessage-type\fP\ |\ \fIcomma-sep-message-type-list\fP
Search for an event matching the given \fImessage type\fP. You may also enter a \fIcomma separated list of message types\fP. There is an \fBALL\fP message type that doesn't exist in the actual logs. It allows you to get all messages in the system. The list of valid messages types is long. The program will display the list whenever no message type is passed with this parameter. The message type can be either text or numeric. If you enter a list, there can be only commas and no spaces separating the list.
.TP
+.BR \-\-namespace \ \fInamespace\fP
+Search for an event matching the given \fInamespace\fP (AppArmor events).
+.TP
.BR \-n ,\ \-\-node \ \fInode-name\fP
Search for events originating from \fInode name\fP string. Multiple nodes are allowed, and if any nodes match, the event is matched.
.TP
.BR \-o ,\ \-\-object \ \fISE-Linux-context-string\fP
Search for event with \fItcontext\fP (object) matching the string.
.TP
+.BR \-\-operation \ \fIoperation\fP
+Search for an event matching the given \fIoperation\fP (AppArmor events).
+.TP
+.BR \-\-ouid \ \fIouid\fP
+Search for an event based on the given \fIouid\fP (AppArmor events).
+.TP
.BR \-p ,\ \-\-pid \ \fIprocess-id\fP
Search for an event matching the given \fIprocess ID\fP.
.TP
.BR \-pp ,\ \-\-ppid \ \fIparent-process-id\fP
Search for an event matching the given \fIparent process ID\fP.
.TP
+.BR \-\-parent \ \fIparent\fP
+Search for an event matching the given \fIparent\fP (AppArmor events).
+.TP
+.BR \-\-profile \ \fIprofile\fP
+Search for an event matching the given \fIprofile\fP (AppArmor events).
+.TP
+.BR \-\-protocol \ \fIprotocol\fP
+Search for an event matching the given \fIprotocol\fP (AppArmor events).
+.TP
.BR \-r ,\ \-\-raw
Output is completely unformatted. This is useful for extracting records that can still be interpreted by audit tools.
.TP
+.BR \-\-requested_mask \ \fImask\fP
+Search for an event matching the given requested \fImask\fP (AppArmor events).
+.TP
+.BR \-\-rlimit \ \fIrlimit\fP
+Search for an event matching the given \fIrlimit\fP (AppArmor events).
+.TP
.BR \-sc ,\ \-\-syscall \ \fIsyscall-name-or-value\fP
Search for an event matching the given \fIsyscall\fP. You may either give the numeric syscall value or the syscall name. If you give the syscall name, it will use the syscall table for the machine that you are using.
.TP
@@ -87,6 +144,9 @@ Search for event with either \fIscontext\fP/subject or \fItcontext\fP/object mat
.BR \-\-session \ \fILogin-Session-ID\fP
Search for events matching the given Login Session ID. This process attribute is set when a user logs in and can tie any process to a particular user login.
.TP
+.BR \-\-sock_type \ \fIsocket-type\fP
+Search for an event based on the given \fIsocket-type\fP (AppArmor events).
+.TP
.BR \-su ,\ \-\-subject \ \fISE-Linux-context-string\fP
Search for event with \fIscontext\fP (subject) matching the string.
.TP
@@ -96,6 +156,9 @@ Search for an event matching the given \fIsuccess value\fP. Legal values are
and
.BR no .
.TP
+.BR \-\-target \ \fItarget\fP
+Search for events matching the given \fItarget\fP (AppArmor events).
+.TP
.BR \-te ,\ \-\-end \ [\fIend-date\fP]\ [\fIend-time\fP]
Search for events with time stamps equal to or before the given end time. The format of end time depends on your locale. If the date is omitted,
.B today
diff --git a/src/aureport-options.c b/src/aureport-options.c
index f1ab50a..f5a9ac1 100644
--- a/src/aureport-options.c
+++ b/src/aureport-options.c
@@ -51,6 +51,29 @@ const char *event_subject = NULL;
const char *event_object = NULL;
int event_exit = 0, event_exit_is_set = 0;
int event_ppid = -1, event_session_id = -2;
+/* AppArmor specific search fields */
+const char *event_aa_apparmor = NULL;
+const char *event_aa_operation = NULL;
+const char *event_aa_profile = NULL;
+pid_t event_aa_parent = -1;
+const char *event_aa_requested_mask = NULL;
+const char *event_aa_denied_mask = NULL;
+uid_t event_aa_fsuid = -1;
+uid_t event_aa_ouid = -1;
+const char *event_aa_target = NULL;
+const char *event_aa_info = NULL;
+const char *event_aa_capname = NULL;
+long event_aa_error = 0;
+const char *event_aa_namespace = NULL;
+const char *event_aa_rlimit = NULL;
+const char *event_aa_laddr = NULL;
+const char *event_aa_faddr = NULL;
+int event_aa_lport = -1;
+int event_aa_fport = -1;
+const char *event_aa_family = NULL;
+const char *event_aa_sock_type = NULL;
+int event_aa_protocol = -1;
+
/* These are used by aureport */
const char *dummy = "dummy";
diff --git a/src/ausearch-common.h b/src/ausearch-common.h
index 08b0cba..6509e0a 100644
--- a/src/ausearch-common.h
+++ b/src/ausearch-common.h
@@ -42,6 +42,29 @@ extern int event_syscall;
extern const char *event_exe;
extern int event_ua, event_ga;
extern int event_exit, event_exit_is_set;
+/* AppArmor search fields. */
+extern const char *event_aa_apparmor;
+extern const char *event_aa_operation;
+extern const char *event_aa_profile;
+extern pid_t event_aa_parent;
+extern const char *event_aa_requested_mask;
+extern const char *event_aa_denied_mask;
+extern uid_t event_aa_fsuid;
+extern uid_t event_aa_ouid;
+extern const char *event_aa_target;
+extern const char *event_aa_info;
+extern const char *event_aa_capname;
+extern long event_aa_error;
+extern const char *event_aa_namespace;
+extern const char *event_aa_rlimit;
+extern const char *event_aa_laddr;
+extern const char *event_aa_faddr;
+extern int event_aa_lport;
+extern int event_aa_fport;
+extern const char *event_aa_family;
+extern const char *event_aa_sock_type;
+extern int event_aa_protocol;
+
typedef enum { F_BOTH, F_FAILED, F_SUCCESS } failed_t;
typedef enum { C_NEITHER, C_ADD, C_DEL } conf_act_t;
diff --git a/src/ausearch-llist.c b/src/ausearch-llist.c
index 32cda7e..9077291 100644
--- a/src/ausearch-llist.c
+++ b/src/ausearch-llist.c
@@ -57,6 +57,27 @@ void list_create(llist *l)
l->s.session_id = -2;
l->s.exit = 0;
l->s.exit_is_set = 0;
+ l->s.aa_apparmor = NULL;
+ l->s.aa_operation = NULL;
+ l->s.aa_profile = NULL;
+ l->s.aa_parent = -1;
+ l->s.aa_requested_mask = NULL;
+ l->s.aa_denied_mask = NULL;
+ l->s.aa_fsuid = -1;
+ l->s.aa_ouid = -1;
+ l->s.aa_target = NULL;
+ l->s.aa_info = NULL;
+ l->s.aa_capname = NULL;
+ l->s.aa_error = 0;
+ l->s.aa_namespace = NULL;
+ l->s.aa_rlimit = NULL;
+ l->s.aa_laddr = NULL;
+ l->s.aa_faddr = NULL;
+ l->s.aa_lport = -1;
+ l->s.aa_fport = -1;
+ l->s.aa_family = NULL;
+ l->s.aa_sock_type = NULL;
+ l->s.aa_protocol = -1;
}
void list_last(llist *l)
@@ -199,6 +220,41 @@ void list_clear(llist* l)
l->s.session_id = -2;
l->s.exit = 0;
l->s.exit_is_set = 0;
+ free(l->s.aa_apparmor);
+ l->s.aa_apparmor = NULL;
+ free(l->s.aa_operation);
+ l->s.aa_operation = NULL;
+ free(l->s.aa_profile);
+ l->s.aa_profile = NULL;
+ l->s.aa_parent = -1;
+ free(l->s.aa_requested_mask);
+ l->s.aa_requested_mask = NULL;
+ free(l->s.aa_denied_mask);
+ l->s.aa_denied_mask = NULL;
+ l->s.aa_fsuid = -1;
+ l->s.aa_ouid = -1;
+ free(l->s.aa_target);
+ l->s.aa_target = NULL;
+ free(l->s.aa_info);
+ l->s.aa_info = NULL;
+ free(l->s.aa_capname);
+ l->s.aa_capname = NULL;
+ l->s.aa_error = 0;
+ free(l->s.aa_namespace);
+ l->s.aa_namespace = NULL;
+ free(l->s.aa_rlimit);
+ l->s.aa_rlimit = NULL;
+ free(l->s.aa_laddr);
+ l->s.aa_laddr = NULL;
+ free(l->s.aa_faddr);
+ l->s.aa_faddr = NULL;
+ l->s.aa_lport = -1;
+ l->s.aa_fport = -1;
+ free(l->s.aa_family);
+ l->s.aa_family = NULL;
+ free(l->s.aa_sock_type);
+ l->s.aa_sock_type = NULL;
+ l->s.aa_protocol = -1;
}
int list_get_event(llist* l, event *e)
diff --git a/src/ausearch-llist.h b/src/ausearch-llist.h
index a77d800..09c7ac6 100644
--- a/src/ausearch-llist.h
+++ b/src/ausearch-llist.h
@@ -64,6 +64,28 @@ typedef struct
char *comm; // comm name
alist *avc; // avcs for the event
char *acct; // account used when uid is invalid
+ // AppArmor specific fields
+ char *aa_apparmor; // ield apparmor=...
+ char *aa_operation; // field operation=...
+ char *aa_profile; // field profile=...
+ pid_t aa_parent; // field parent=...
+ char *aa_requested_mask; // field requested_mask=...
+ char *aa_denied_mask; // field denied_mask=...
+ uid_t aa_fsuid; // field fsuid=...
+ uid_t aa_ouid; // field ouid=...
+ char *aa_target; // field target=...
+ char *aa_info; // field info=...
+ char *aa_capname; // field capname=...
+ long aa_error; // field error=...
+ char *aa_namespace; // field namespace=...
+ char *aa_rlimit; // field rlimit=...
+ char *aa_laddr; // field laddr=...
+ char *aa_faddr; // field faddr=...
+ int aa_lport; // field lport=...
+ int aa_fport; // field fport=...
+ char *aa_family; // field family=...
+ char *aa_sock_type; // field sock_type=...
+ int aa_protocol; // field protocol=...
} search_items;
/* This is the node of the linked list. Any data elements that are per
diff --git a/src/ausearch-lol.c b/src/ausearch-lol.c
index c291f5f..12b4a95 100644
--- a/src/ausearch-lol.c
+++ b/src/ausearch-lol.c
@@ -28,7 +28,7 @@
#include <stdio.h>
#include "ausearch-common.h"
-#define ARRAY_LIMIT 80
+#define ARRAY_LIMIT 8192
static int ready = 0;
void lol_create(lol *lo)
diff --git a/src/ausearch-match.c b/src/ausearch-match.c
index 24b9320..f78e705 100644
--- a/src/ausearch-match.c
+++ b/src/ausearch-match.c
@@ -201,6 +201,125 @@ int match(llist *l)
return 0;
}
}
+ if (event_aa_apparmor) {
+ if (l->s.aa_apparmor == NULL)
+ return 0;
+ if (strmatch(event_aa_apparmor,
+ l->s.aa_apparmor) == 0)
+ return 0;
+ }
+ if (event_aa_operation) {
+ if (l->s.aa_operation == NULL)
+ return 0;
+ if (strmatch(event_aa_operation,
+ l->s.aa_operation) == 0)
+ return 0;
+ }
+ if (event_aa_profile) {
+ if (l->s.aa_profile == NULL)
+ return 0;
+ if (strmatch(event_aa_profile,
+ l->s.aa_profile) == 0)
+ return 0;
+ }
+ if ((event_aa_parent != -1) &&
+ (event_aa_parent != l->s.aa_parent))
+ return 0;
+ if (event_aa_requested_mask) {
+ if (l->s.aa_requested_mask == NULL)
+ return 0;
+ if (strmatch(event_aa_requested_mask,
+ l->s.aa_requested_mask) == 0)
+ return 0;
+ }
+ if (event_aa_denied_mask) {
+ if (l->s.aa_denied_mask == NULL)
+ return 0;
+ if (strmatch(event_aa_denied_mask,
+ l->s.aa_denied_mask) == 0)
+ return 0;
+ }
+ if ((event_aa_fsuid != -1) &&
+ (event_aa_fsuid != l->s.aa_fsuid))
+ return 0;
+ if ((event_aa_ouid != -1) &&
+ (event_aa_ouid != l->s.aa_ouid))
+ return 0;
+ if (event_aa_target) {
+ if (l->s.aa_target == NULL)
+ return 0;
+ if (strmatch(event_aa_target,
+ l->s.aa_target) == 0)
+ return 0;
+ }
+ if (event_aa_info) {
+ if (l->s.aa_info == NULL)
+ return 0;
+ if (strmatch(event_aa_info,
+ l->s.aa_info) == 0)
+ return 0;
+ }
+ if (event_aa_capname) {
+ if (l->s.aa_capname == NULL)
+ return 0;
+ if (strmatch(event_aa_capname,
+ l->s.aa_capname) == 0)
+ return 0;
+ }
+ if ((event_aa_error != 0) &&
+ (event_aa_error != l->s.aa_error))
+ return 0;
+ if (event_aa_namespace) {
+ if (l->s.aa_namespace == NULL)
+ return 0;
+ if (strmatch(event_aa_namespace,
+ l->s.aa_namespace) == 0)
+ return 0;
+ }
+ if (event_aa_rlimit) {
+ if (l->s.aa_rlimit == NULL)
+ return 0;
+ if (strmatch(event_aa_rlimit,
+ l->s.aa_rlimit) == 0)
+ return 0;
+ }
+ if (event_aa_laddr) {
+ if (l->s.aa_laddr == NULL)
+ return 0;
+ if (strmatch(event_aa_laddr,
+ l->s.aa_laddr) == 0)
+ return 0;
+ }
+ if (event_aa_faddr) {
+ if (l->s.aa_faddr == NULL)
+ return 0;
+ if (strmatch(event_aa_faddr,
+ l->s.aa_faddr) == 0)
+ return 0;
+ }
+ if ((event_aa_lport != -1) &&
+ (event_aa_lport != l->s.aa_lport))
+ return 0;
+ if ((event_aa_fport != -1) &&
+ (event_aa_fport != l->s.aa_fport))
+ return 0;
+ if (event_aa_family) {
+ if (l->s.aa_family == NULL)
+ return 0;
+ if (strmatch(event_aa_family,
+ l->s.aa_family) == 0)
+ return 0;
+ }
+ if (event_aa_sock_type) {
+ if (l->s.aa_sock_type == NULL)
+ return 0;
+ if (strmatch(event_aa_sock_type,
+ l->s.aa_sock_type) == 0)
+ return 0;
+ }
+ if ((event_aa_protocol != -1) &&
+ (event_aa_protocol != l->s.aa_protocol))
+ return 0;
if (context_match(l) == 0)
return 0;
return 1;
diff --git a/src/ausearch-options.c b/src/ausearch-options.c
index 8f4b64e..4e66771 100644
--- a/src/ausearch-options.c
+++ b/src/ausearch-options.c
@@ -63,6 +63,28 @@ const char *event_subject = NULL;
const char *event_object = NULL;
report_t report_format = RPT_DEFAULT;
ilist *event_type;
+/* AppArmor specific search fields */
+const char *event_aa_apparmor = NULL;
+const char *event_aa_operation = NULL;
+const char *event_aa_profile = NULL;
+pid_t event_aa_parent = -1;
+const char *event_aa_requested_mask = NULL;
+const char *event_aa_denied_mask = NULL;
+uid_t event_aa_fsuid = -1;
+uid_t event_aa_ouid = -1;
+const char *event_aa_target = NULL;
+const char *event_aa_info = NULL;
+const char *event_aa_capname = NULL;
+long event_aa_error = 0;
+const char *event_aa_namespace = NULL;
+const char *event_aa_rlimit = NULL;
+const char *event_aa_laddr = NULL;
+const char *event_aa_faddr = NULL;
+int event_aa_lport = -1;
+int event_aa_fport = -1;
+const char *event_aa_family = NULL;
+const char *event_aa_sock_type = NULL;
+int event_aa_protocol = -1;
const slist *event_node_list = NULL;
@@ -77,7 +99,13 @@ S_HOSTNAME, S_INTERP, S_INFILE, S_MESSAGE_TYPE, S_PID, S_SYSCALL, S_OSUCCESS,
S_TIME_END, S_TIME_START, S_TERMINAL, S_ALL_UID, S_EFF_UID, S_UID, S_LOGINID,
S_VERSION, S_EXACT_MATCH, S_EXECUTABLE, S_CONTEXT, S_SUBJECT, S_OBJECT,
S_PPID, S_KEY, S_RAW, S_NODE, S_IN_LOGS, S_JUST_ONE, S_SESSION, S_EXIT,
-S_LINEBUFFERED };
+S_LINEBUFFERED,
+/* AppArmor specific search options. */
+S_AA_APPARMOR, S_AA_OPERATION, S_AA_PROFILE, S_AA_PARENT,
+S_AA_REQUESTED_MASK, S_AA_DENIED_MASK, S_AA_FSUID, S_AA_OUID,
+S_AA_TARGET, S_AA_INFO, S_AA_CAPNAME, S_AA_ERROR, S_AA_NAMESPACE,
+S_AA_RLIMIT, S_AA_LADDR, S_AA_FADDR, S_AA_LPORT, S_AA_FPORT,
+S_AA_FAMILY, S_AA_SOCK_TYPE, S_AA_PROTOCOL };
static struct nv_pair optiontab[] = {
{ S_EVENT, "-a" },
@@ -148,7 +176,29 @@ static struct nv_pair optiontab[] = {
{ S_EXACT_MATCH, "-w" },
{ S_EXACT_MATCH, "--word" },
{ S_EXECUTABLE, "-x" },
- { S_EXECUTABLE, "--executable" }
+ { S_EXECUTABLE, "--executable" },
+ /* AppArmor specific search fields. */
+ { S_AA_APPARMOR, "--apparmor" },
+ { S_AA_OPERATION, "--operation" },
+ { S_AA_PROFILE, "--profile" },
+ { S_AA_PARENT, "--parent" },
+ { S_AA_REQUESTED_MASK, "--requested_mask" },
+ { S_AA_DENIED_MASK, "--denied_mask" },
+ { S_AA_FSUID, "--fsuid" },
+ { S_AA_OUID, "--ouid" },
+ { S_AA_TARGET, "--target" },
+ { S_AA_INFO, "--info" },
+ { S_AA_CAPNAME, "--capname" },
+ { S_AA_ERROR, "--error" },
+ { S_AA_NAMESPACE, "--namespace" },
+ { S_AA_RLIMIT, "--rlimit" },
+ { S_AA_LADDR, "--laddr" },
+ { S_AA_FADDR, "--faddr" },
+ { S_AA_LPORT, "--lport" },
+ { S_AA_FPORT, "--fport" },
+ { S_AA_FAMILY, "--family" },
+ { S_AA_SOCK_TYPE, "--sock_type" },
+ { S_AA_PROTOCOL, "--protocol" },
};
#define OPTION_NAMES (sizeof(optiontab)/sizeof(optiontab[0]))
@@ -167,9 +217,17 @@ static void usage(void)
{
printf("usage: ausearch [options]\n"
"\t-a,--event <Audit event id>\tsearch based on audit event id\n"
+ "\t--apparmor <Type>\tsearch based on AppArmor type\n"
+ "\t--capname <Capname>\tsearch based on capability name (AppArmor events)\n"
"\t-c,--comm <Comm name>\t\tsearch based on command line name\n"
+ "\t--denied_mask <Mask>\t\tsearch based on denied mask (AppArmor events)\n"
+ "\t--error <Error>\tsearch based on error value (AppArmor events)\n"
"\t-e,--exit <Exit code or errno>\tsearch based on syscall exit code\n"
+ "\t--faddr <Address>\tsearch based on foreign address (AppArmor events)\n"
+ "\t--family <Family>\tsearch based on network family (AppArmor events)\n"
"\t-f,--file <File name>\t\tsearch based on file name\n"
+ "\t--fport <Port>\tsearch based on foreign port (AppArmor events)\n"
+ "\t--fsuid <uid>\t\tsearch based on fsuid (AppArmor events)\n"
"\t-ga,--gid-all <all Group id>\tsearch based on All group ids\n"
"\t-ge,--gid-effective <effective Group id> search based on Effective\n\t\t\t\t\tgroup id\n"
"\t-gi,--gid <Group Id>\t\tsearch based on group id\n"
@@ -177,21 +235,34 @@ static void usage(void)
"\t-hn,--host <Host Name>\t\tsearch based on remote host name\n"
"\t-i,--interpret\t\t\tInterpret results to be human readable\n"
"\t-if,--input <Input File name>\tuse this file instead of current logs\n"
+ "\t--info <Info>\tsearch based on requested info (AppArmor events)\n"
"\t--input-logs\t\t\tUse the logs even if stdin is a pipe\n"
"\t--just-one\t\t\tEmit just one event\n"
"\t-k,--key <key string>\t\tsearch based on key field\n"
+ "\t--laddr <Address>\tsearch based on local address (AppArmor events)\n"
"\t-l, --line-buffered\t\tFlush output on every line\n"
+ "\t--lport <Port>\tsearch based on local port (AppArmor events)\n"
"\t-m,--message <Message type>\tsearch based on message type\n"
+ "\t--namespace <name>\tsearch based on namespace (AppArmor events)\n"
"\t-n,--node <Node name>\t\tsearch based on machine's name\n"
"\t-o,--object <SE Linux Object context> search based on context of object\n"
+ "\t--operation <Operation> search based on operation (AppArmor events)\n"
+ "\t--ouid <ouid> search based on ouid (AppArmor events)\n"
"\t-p,--pid <Process id>\t\tsearch based on process id\n"
"\t-pp,--ppid <Parent Process id>\tsearch based on parent process id\n"
+ "\t--parent <Parent>\tsearch based on parent (AppArmor events)\n"
+ "\t--profile <Profile>\tsearch based on profile (AppArmor events)\n"
+ "\t--protocol <Protocol>\tsearch based on protocol (AppArmor events)\n"
"\t-r,--raw\t\t\toutput is completely unformatted\n"
+ "\t--requested_mask <Mask>\tsearch based on requested mask (AppArmor events)\n"
+ "\t--rlimit <Rlimit>\tsearch based on rlimit (AppArmor events)\n"
"\t-sc,--syscall <SysCall name>\tsearch based on syscall name or number\n"
"\t-se,--context <SE Linux context> search based on either subject or\n\t\t\t\t\t object\n"
"\t--session <login session id>\tsearch based on login session id\n"
+ "\t--sock_type <Socket type> search based on socket type (AppArmor events)\n"
"\t-su,--subject <SE Linux context> search based on context of the Subject\n"
"\t-sv,--success <Success Value>\tsearch based on syscall or event\n\t\t\t\t\tsuccess value\n"
+ "\t--target <Target> search based on target (AppArmor events)\n"
"\t-te,--end [end date] [end time]\tending date & time for search\n"
"\t-ts,--start [start date] [start time]\tstarting data & time for search\n"
"\t-tm,--terminal <TerMinal>\tsearch based on terminal\n"
@@ -1026,6 +1097,335 @@ int check_params(int count, char *vars[])
case S_LINEBUFFERED:
line_buffered = 1;
break;
+ case S_AA_APPARMOR:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_apparmor = strdup(optarg);
+ if (event_aa_apparmor == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_OPERATION:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_operation = strdup(optarg);
+ if (event_aa_operation == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_PROFILE:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_profile = strdup(optarg);
+ if (event_aa_profile == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_PARENT:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_parent = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "Parent must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
+ case S_AA_REQUESTED_MASK:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_requested_mask = strdup(optarg);
+ if (event_aa_requested_mask == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_DENIED_MASK:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_denied_mask = strdup(optarg);
+ if (event_aa_denied_mask == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_FSUID:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_fsuid = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "fsuid must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
+ case S_AA_OUID:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_ouid = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "ouid must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
+ case S_AA_TARGET:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_target = strdup(optarg);
+ if (event_aa_target == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_INFO:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_info = strdup(optarg);
+ if (event_aa_info == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_CAPNAME:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_capname = strdup(optarg);
+ if (event_aa_capname == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_ERROR:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_error = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "error must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
+ case S_AA_NAMESPACE:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_namespace = strdup(optarg);
+ if (event_aa_namespace == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_RLIMIT:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_rlimit = strdup(optarg);
+ if (event_aa_rlimit == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_LADDR:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_laddr = strdup(optarg);
+ if (event_aa_laddr == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_FADDR:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_faddr = strdup(optarg);
+ if (event_aa_faddr == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_LPORT:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_lport = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "lport must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
+ case S_AA_FPORT:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_fport = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "fport must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
+ case S_AA_FAMILY:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_family = strdup(optarg);
+ if (event_aa_family == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_SOCK_TYPE:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ } else {
+ event_aa_sock_type = strdup(optarg);
+ if (event_aa_sock_type == NULL)
+ retval = -1;
+ c++;
+ }
+ break;
+ case S_AA_PROTOCOL:
+ if (!optarg) {
+ fprintf(stderr,
+ "Argument is required for %s\n",
+ vars[c]);
+ retval = -1;
+ break;
+ }
+ if (isdigit(optarg[0])) {
+ errno = 0;
+ event_aa_protocol = strtol(optarg, NULL, 10);
+ if (errno)
+ retval = -1;
+ c++;
+ } else {
+ fprintf(stderr,
+ "protocol must be a numeric value, was %s\n",
+ optarg);
+ retval = -1;
+ }
+ break;
default:
fprintf(stderr, "%s is an unsupported option\n",
vars[c]);
diff --git a/src/ausearch-parse.c b/src/ausearch-parse.c
index 08fa2be..55175b6 100644
--- a/src/ausearch-parse.c
+++ b/src/ausearch-parse.c
@@ -1366,6 +1366,461 @@ static int parse_integrity(const lnode *n, search_items *s)
return 0;
}
+/*
+ * Parse AppArmor specific fields.
+ * Note that this must be done before parsing all SELinux and common fields
+ * in parse_avc(), because parse_avc() relies on specific ordering of the
+ * fields and once it parses one, it doesn't look behind for other fields.
+ * This makes it complex to parse AppArmor fields, since many appear in
+ * the middle of common fields. So to make this AppArmor support simpler
+ * to maintain, move the parsing to a dedicate function that doesn't move
+ * the current "cursor" in the log line and doesn't depend on specific
+ * orderings.
+ */
+static int parse_avc_apparmor_fields(char *term, search_items *s)
+{
+ char *str;
+ char *tmp = term;
+
+ if (event_aa_apparmor) {
+ str = strstr(term, "apparmor=");
+ if (str) {
+ str += 9;
+ if (*str != '"')
+ return 100;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 100;
+ *term = 0;
+ s->aa_apparmor = strdup(str);
+ *term = '"';
+ if (s->aa_apparmor == NULL)
+ return 100;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_operation) {
+ str = strstr(term, "operation=");
+ if (str) {
+ str += 10;
+ if (*str != '"')
+ return 101;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 101;
+ *term = 0;
+ s->aa_operation = strdup(str);
+ *term = '"';
+ if (s->aa_operation == NULL)
+ return 101;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_profile) {
+ str = strstr(term, "profile=");
+ if (str) {
+ str += 8;
+ if (*str != '"')
+ return 102;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 102;
+ *term = 0;
+ s->aa_profile = strdup(str);
+ *term = '"';
+ if (s->aa_profile == NULL)
+ return 102;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_parent != -1) {
+ str = strstr(term, "parent=");
+ if (str) {
+ str += 7;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_parent = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_parent = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 103;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_requested_mask) {
+ str = strstr(term, "requested_mask=");
+ if (str) {
+ str += 15;
+ if (*str != '"')
+ return 104;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 104;
+ *term = 0;
+ s->aa_requested_mask = strdup(str);
+ *term = '"';
+ if (s->aa_requested_mask == NULL)
+ return 104;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_denied_mask) {
+ str = strstr(term, "denied_mask=");
+ if (str) {
+ str += 12;
+ if (*str != '"')
+ return 105;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 105;
+ *term = 0;
+ s->aa_denied_mask = strdup(str);
+ *term = '"';
+ if (s->aa_denied_mask == NULL)
+ return 105;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_fsuid != -1) {
+ str = strstr(term, "fsuid=");
+ if (str) {
+ str += 6;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_fsuid = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_fsuid = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 106;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_ouid != -1) {
+ str = strstr(term, "ouid=");
+ if (str) {
+ str += 5;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_ouid = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_ouid = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 107;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_target) {
+ str = strstr(term, "target=");
+ if (str) {
+ str += 7;
+ if (*str != '"')
+ return 108;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 108;
+ *term = 0;
+ s->aa_target = strdup(str);
+ *term = '"';
+ if (s->aa_target == NULL)
+ return 108;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_info) {
+ str = strstr(term, "info=");
+ if (str) {
+ str += 5;
+ if (*str != '"')
+ return 109;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 109;
+ *term = 0;
+ s->aa_info = strdup(str);
+ *term = '"';
+ if (s->aa_info == NULL)
+ return 109;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_capname) {
+ str = strstr(term, "capname=");
+ if (str) {
+ str += 8;
+ if (*str != '"')
+ return 110;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 110;
+ *term = 0;
+ s->aa_capname = strdup(str);
+ *term = '"';
+ if (s->aa_capname == NULL)
+ return 110;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_error != -1) {
+ str = strstr(term, "error=");
+ if (str) {
+ str += 6;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_error = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_error = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 111;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_namespace) {
+ str = strstr(term, "namespace=");
+ if (str) {
+ str += 10;
+ if (*str != '"')
+ return 112;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 112;
+ *term = 0;
+ s->aa_namespace = strdup(str);
+ *term = '"';
+ if (s->aa_namespace == NULL)
+ return 112;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_rlimit) {
+ str = strstr(term, "rlimit=");
+ if (str) {
+ str += 7;
+ term = strchr(str, ' ');
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_rlimit = strdup(str);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_rlimit = strdup(str);
+ }
+ if (s->aa_rlimit == NULL)
+ return 113;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_laddr) {
+ str = strstr(term, "laddr=");
+ if (str) {
+ str += 6;
+ if (*str == '"') {
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 114;
+ *term = 0;
+ s->aa_laddr = strdup(str);
+ *term = '"';
+ } else {
+ term = strchr(str, ' ');
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_laddr = strdup(str);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_laddr = strdup(str);
+ }
+ }
+ if (s->aa_laddr == NULL)
+ return 114;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_faddr) {
+ str = strstr(term, "faddr=");
+ if (str) {
+ str += 6;
+ if (*str == '"') {
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 115;
+ *term = 0;
+ s->aa_faddr = strdup(str);
+ *term = '"';
+ } else {
+ term = strchr(str, ' ');
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_faddr = strdup(str);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_faddr = strdup(str);
+ }
+ }
+ if (s->aa_faddr == NULL)
+ return 115;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_lport != -1) {
+ str = strstr(term, "lport=");
+ if (str) {
+ str += 6;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_lport = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_lport = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 116;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_fport != -1) {
+ str = strstr(term, "fport=");
+ if (str) {
+ str += 6;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_fport = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_fport = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 117;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_family) {
+ str = strstr(term, "family=");
+ if (str) {
+ str += 7;
+ if (*str != '"')
+ return 118;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 118;
+ *term = 0;
+ s->aa_family = strdup(str);
+ *term = '"';
+ if (s->aa_family == NULL)
+ return 118;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_sock_type) {
+ str = strstr(term, "sock_type=");
+ if (str) {
+ str += 10;
+ if (*str != '"')
+ return 119;
+ str++;
+ term = strchr(str, '"');
+ if (term == NULL)
+ return 119;
+ *term = 0;
+ s->aa_sock_type = strdup(str);
+ *term = '"';
+ if (s->aa_sock_type == NULL)
+ return 119;
+ term = tmp;
+ }
+ }
+
+ if (event_aa_protocol != -1) {
+ str = strstr(term, "protocol=");
+ if (str) {
+ str += 9;
+ term = strchr(str, ' ');
+ errno = 0;
+ if (term) {
+ /* We aren't the last field in the line. */
+ *term = 0;
+ s->aa_protocol = strtoul(str, NULL, 10);
+ *term = ' ';
+ } else {
+ /* We are the last field in the line. */
+ s->aa_protocol = strtoul(str, NULL, 10);
+ }
+ if (errno)
+ return 120;
+ term = tmp;
+ }
+ }
+
+ return 0;
+}
+
/* FIXME: If they are in permissive mode or hit an auditallow, there can
* be more that 1 avc in the same syscall. For now, we pickup just the first.
@@ -1379,6 +1834,10 @@ static int parse_avc(const lnode *n, search_items *s)
term = n->message;
anode_init(&an);
+ rc = parse_avc_apparmor_fields(term, s);
+ if (rc)
+ goto err;
+
// get the avc message info.
str = strstr(term, "avc: ");
if (str) {
--
1.8.4.5