Commit 86b2efbe authored by Richard Guy Briggs's avatar Richard Guy Briggs Committed by Paul Moore

audit: add fields to exclude filter by reusing user filter

RFE: add additional fields for use in audit filter exclude rules
https://github.com/linux-audit/audit-kernel/issues/5

Re-factor and combine audit_filter_type() with audit_filter_user() to
use audit_filter_user_rules() to enable the exclude filter to
additionally filter on PID, UID, GID, AUID, LOGINUID_SET, SUBJ_*.

The process of combining the similar audit_filter_user() and
audit_filter_type() functions, required inverting the meaning and
including the ALWAYS action of the latter.

Include audit_filter_user_rules() into audit_filter(), removing
unneeded logic in the process.

Keep the check to quit early if the list is empty.
Signed-off-by: default avatarRichard Guy Briggs <rgb@redhat.com>
[PM: checkpatch.pl fixes - whitespace damage, wrapped description]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent da7f750c
...@@ -163,8 +163,6 @@ extern void audit_log_task_info(struct audit_buffer *ab, ...@@ -163,8 +163,6 @@ extern void audit_log_task_info(struct audit_buffer *ab,
extern int audit_update_lsm_rules(void); extern int audit_update_lsm_rules(void);
/* Private API (for audit.c only) */ /* Private API (for audit.c only) */
extern int audit_filter_user(int type);
extern int audit_filter_type(int type);
extern int audit_rule_change(int type, __u32 portid, int seq, extern int audit_rule_change(int type, __u32 portid, int seq,
void *data, size_t datasz); void *data, size_t datasz);
extern int audit_list_rules_send(struct sk_buff *request_skb, int seq); extern int audit_list_rules_send(struct sk_buff *request_skb, int seq);
......
...@@ -934,7 +934,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -934,7 +934,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (!audit_enabled && msg_type != AUDIT_USER_AVC) if (!audit_enabled && msg_type != AUDIT_USER_AVC)
return 0; return 0;
err = audit_filter_user(msg_type); err = audit_filter(msg_type, AUDIT_FILTER_USER);
if (err == 1) { /* match or error */ if (err == 1) { /* match or error */
err = 0; err = 0;
if (msg_type == AUDIT_USER_TTY) { if (msg_type == AUDIT_USER_TTY) {
...@@ -1382,7 +1382,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, ...@@ -1382,7 +1382,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
if (audit_initialized != AUDIT_INITIALIZED) if (audit_initialized != AUDIT_INITIALIZED)
return NULL; return NULL;
if (unlikely(audit_filter_type(type))) if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE)))
return NULL; return NULL;
if (gfp_mask & __GFP_DIRECT_RECLAIM) { if (gfp_mask & __GFP_DIRECT_RECLAIM) {
......
...@@ -327,6 +327,8 @@ extern pid_t audit_sig_pid; ...@@ -327,6 +327,8 @@ extern pid_t audit_sig_pid;
extern kuid_t audit_sig_uid; extern kuid_t audit_sig_uid;
extern u32 audit_sig_sid; extern u32 audit_sig_sid;
extern int audit_filter(int msgtype, unsigned int listtype);
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
extern int __audit_signal_info(int sig, struct task_struct *t); extern int __audit_signal_info(int sig, struct task_struct *t);
static inline int audit_signal_info(int sig, struct task_struct *t) static inline int audit_signal_info(int sig, struct task_struct *t)
......
...@@ -1290,15 +1290,20 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) ...@@ -1290,15 +1290,20 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
return strncmp(p, dname, dlen); return strncmp(p, dname, dlen);
} }
static int audit_filter_user_rules(struct audit_krule *rule, int type, int audit_filter(int msgtype, unsigned int listtype)
enum audit_state *state)
{ {
int i; struct audit_entry *e;
int ret = 1; /* Audit by default */
rcu_read_lock();
if (list_empty(&audit_filter_list[listtype]))
goto unlock_and_return;
list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) {
int i, result = 0;
for (i = 0; i < rule->field_count; i++) { for (i = 0; i < e->rule.field_count; i++) {
struct audit_field *f = &rule->fields[i]; struct audit_field *f = &e->rule.fields[i];
pid_t pid; pid_t pid;
int result = 0;
u32 sid; u32 sid;
switch (f->type) { switch (f->type) {
...@@ -1321,7 +1326,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type, ...@@ -1321,7 +1326,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,
f->op, f->val); f->op, f->val);
break; break;
case AUDIT_MSGTYPE: case AUDIT_MSGTYPE:
result = audit_comparator(type, f->op, f->val); result = audit_comparator(msgtype, f->op, f->val);
break; break;
case AUDIT_SUBJ_USER: case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_ROLE:
...@@ -1331,76 +1336,26 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type, ...@@ -1331,76 +1336,26 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,
if (f->lsm_rule) { if (f->lsm_rule) {
security_task_getsecid(current, &sid); security_task_getsecid(current, &sid);
result = security_audit_rule_match(sid, result = security_audit_rule_match(sid,
f->type, f->type, f->op, f->lsm_rule, NULL);
f->op,
f->lsm_rule,
NULL);
}
break;
}
if (result <= 0)
return result;
} }
switch (rule->action) {
case AUDIT_NEVER:
*state = AUDIT_DISABLED;
break; break;
case AUDIT_ALWAYS: default:
*state = AUDIT_RECORD_CONTEXT; goto unlock_and_return;
break;
}
return 1;
}
int audit_filter_user(int type)
{
enum audit_state state = AUDIT_DISABLED;
struct audit_entry *e;
int rc, ret;
ret = 1; /* Audit by default */
rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
rc = audit_filter_user_rules(&e->rule, type, &state);
if (rc) {
if (rc > 0 && state == AUDIT_DISABLED)
ret = 0;
break;
}
} }
rcu_read_unlock(); if (result < 0) /* error */
return ret;
}
int audit_filter_type(int type)
{
struct audit_entry *e;
int result = 0;
rcu_read_lock();
if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
goto unlock_and_return; goto unlock_and_return;
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
list) {
int i;
for (i = 0; i < e->rule.field_count; i++) {
struct audit_field *f = &e->rule.fields[i];
if (f->type == AUDIT_MSGTYPE) {
result = audit_comparator(type, f->op, f->val);
if (!result) if (!result)
break; break;
} }
if (result > 0) {
if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_TYPE)
ret = 0;
break;
} }
if (result)
goto unlock_and_return;
} }
unlock_and_return: unlock_and_return:
rcu_read_unlock(); rcu_read_unlock();
return result; return ret;
} }
static int update_lsm_rule(struct audit_krule *r) static int update_lsm_rule(struct audit_krule *r)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment