When userspace sends messages to the audit system it includes a type.
We want to be able to filter messages based on that type without have to
do the all or nothing option currently available on the
AUDIT_FILTER_TYPE filter list. Instead we should be able to use the
AUDIT_FILTER_USER filter list and just use the message type as one part
of the matching decision.
Signed-off-by: Eric Paris <eparis@redhat.com>
extern int audit_update_lsm_rules(void);
/* Private API (for audit.c only) */
extern int audit_update_lsm_rules(void);
/* Private API (for audit.c only) */
-extern int audit_filter_user(void);
+extern int audit_filter_user(int type);
extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int seq,
void *data, size_t datasz, kuid_t loginuid,
extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int seq,
void *data, size_t datasz, kuid_t loginuid,
if (!audit_enabled && msg_type != AUDIT_USER_AVC)
return 0;
if (!audit_enabled && msg_type != AUDIT_USER_AVC)
return 0;
- err = audit_filter_user();
+ err = audit_filter_user(msg_type);
if (err == 1) {
err = 0;
if (msg_type == AUDIT_USER_TTY) {
if (err == 1) {
err = 0;
if (msg_type == AUDIT_USER_TTY) {
+/* check if a field is valid for a given list */
+static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
+{
+ switch(f->type) {
+ case AUDIT_MSGTYPE:
+ if (entry->rule.listnr != AUDIT_FILTER_TYPE &&
+ entry->rule.listnr != AUDIT_FILTER_USER)
+ return -EINVAL;
+ break;
+ };
+ return 0;
+}
/* Translate struct audit_rule to kernel's rule respresentation.
* Exists for backward compatibility with userspace. */
/* Translate struct audit_rule to kernel's rule respresentation.
* Exists for backward compatibility with userspace. */
f->gid = INVALID_GID;
f->lsm_str = NULL;
f->lsm_rule = NULL;
f->gid = INVALID_GID;
f->lsm_str = NULL;
f->lsm_rule = NULL;
+
+ err = audit_field_valid(entry, f);
+ if (err)
+ goto exit_free;
+
+ err = -EINVAL;
+
switch(f->type) {
case AUDIT_UID:
case AUDIT_EUID:
switch(f->type) {
case AUDIT_UID:
case AUDIT_EUID:
return strncmp(p, dname, dlen);
}
return strncmp(p, dname, dlen);
}
-static int audit_filter_user_rules(struct audit_krule *rule,
+static int audit_filter_user_rules(struct audit_krule *rule, int type,
enum audit_state *state)
{
int i;
enum audit_state *state)
{
int i;
result = audit_uid_comparator(audit_get_loginuid(current),
f->op, f->uid);
break;
result = audit_uid_comparator(audit_get_loginuid(current),
f->op, f->uid);
break;
+ case AUDIT_MSGTYPE:
+ result = audit_comparator(type, f->op, f->val);
+ break;
case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE:
case AUDIT_SUBJ_TYPE:
case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE:
case AUDIT_SUBJ_TYPE:
-int audit_filter_user(void)
+int audit_filter_user(int type)
{
enum audit_state state = AUDIT_DISABLED;
struct audit_entry *e;
{
enum audit_state state = AUDIT_DISABLED;
struct audit_entry *e;
rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
- if (audit_filter_user_rules(&e->rule, &state)) {
+ if (audit_filter_user_rules(&e->rule, type, &state)) {
if (state == AUDIT_DISABLED)
ret = 0;
break;
if (state == AUDIT_DISABLED)
ret = 0;
break;