diff options
author | Richard Guy Briggs <rgb@redhat.com> | 2016-06-24 16:35:46 -0400 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2016-06-27 11:01:00 -0400 |
commit | 86b2efbe3a390e07dbba725ef700b0d143e9a385 (patch) | |
tree | 6f29eca2803a82292ca3fd0f282b37764445d547 /kernel | |
parent | da7f750c1ef570c0a22e5a3fc1fdfd8d308d9a1a (diff) |
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: Richard Guy Briggs <rgb@redhat.com>
[PM: checkpatch.pl fixes - whitespace damage, wrapped description]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 4 | ||||
-rw-r--r-- | kernel/audit.h | 2 | ||||
-rw-r--r-- | kernel/auditfilter.c | 151 |
3 files changed, 57 insertions, 100 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 678c3f000191..994588ef9489 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -934,7 +934,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
934 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 934 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
935 | return 0; | 935 | return 0; |
936 | 936 | ||
937 | err = audit_filter_user(msg_type); | 937 | err = audit_filter(msg_type, AUDIT_FILTER_USER); |
938 | if (err == 1) { /* match or error */ | 938 | if (err == 1) { /* match or error */ |
939 | err = 0; | 939 | err = 0; |
940 | if (msg_type == AUDIT_USER_TTY) { | 940 | 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 | if (audit_initialized != AUDIT_INITIALIZED) | 1382 | if (audit_initialized != AUDIT_INITIALIZED) |
1383 | return NULL; | 1383 | return NULL; |
1384 | 1384 | ||
1385 | if (unlikely(audit_filter_type(type))) | 1385 | if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE))) |
1386 | return NULL; | 1386 | return NULL; |
1387 | 1387 | ||
1388 | if (gfp_mask & __GFP_DIRECT_RECLAIM) { | 1388 | if (gfp_mask & __GFP_DIRECT_RECLAIM) { |
diff --git a/kernel/audit.h b/kernel/audit.h index cbbe6bb6496e..1879f02cb2c3 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -327,6 +327,8 @@ extern pid_t audit_sig_pid; | |||
327 | extern kuid_t audit_sig_uid; | 327 | extern kuid_t audit_sig_uid; |
328 | extern u32 audit_sig_sid; | 328 | extern u32 audit_sig_sid; |
329 | 329 | ||
330 | extern int audit_filter(int msgtype, unsigned int listtype); | ||
331 | |||
330 | #ifdef CONFIG_AUDITSYSCALL | 332 | #ifdef CONFIG_AUDITSYSCALL |
331 | extern int __audit_signal_info(int sig, struct task_struct *t); | 333 | extern int __audit_signal_info(int sig, struct task_struct *t); |
332 | static inline int audit_signal_info(int sig, struct task_struct *t) | 334 | static inline int audit_signal_info(int sig, struct task_struct *t) |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index ff59a5eed691..85d9cac497e4 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -1290,117 +1290,72 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) | |||
1290 | return strncmp(p, dname, dlen); | 1290 | return strncmp(p, dname, dlen); |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | static int audit_filter_user_rules(struct audit_krule *rule, int type, | 1293 | int audit_filter(int msgtype, unsigned int listtype) |
1294 | enum audit_state *state) | ||
1295 | { | ||
1296 | int i; | ||
1297 | |||
1298 | for (i = 0; i < rule->field_count; i++) { | ||
1299 | struct audit_field *f = &rule->fields[i]; | ||
1300 | pid_t pid; | ||
1301 | int result = 0; | ||
1302 | u32 sid; | ||
1303 | |||
1304 | switch (f->type) { | ||
1305 | case AUDIT_PID: | ||
1306 | pid = task_pid_nr(current); | ||
1307 | result = audit_comparator(pid, f->op, f->val); | ||
1308 | break; | ||
1309 | case AUDIT_UID: | ||
1310 | result = audit_uid_comparator(current_uid(), f->op, f->uid); | ||
1311 | break; | ||
1312 | case AUDIT_GID: | ||
1313 | result = audit_gid_comparator(current_gid(), f->op, f->gid); | ||
1314 | break; | ||
1315 | case AUDIT_LOGINUID: | ||
1316 | result = audit_uid_comparator(audit_get_loginuid(current), | ||
1317 | f->op, f->uid); | ||
1318 | break; | ||
1319 | case AUDIT_LOGINUID_SET: | ||
1320 | result = audit_comparator(audit_loginuid_set(current), | ||
1321 | f->op, f->val); | ||
1322 | break; | ||
1323 | case AUDIT_MSGTYPE: | ||
1324 | result = audit_comparator(type, f->op, f->val); | ||
1325 | break; | ||
1326 | case AUDIT_SUBJ_USER: | ||
1327 | case AUDIT_SUBJ_ROLE: | ||
1328 | case AUDIT_SUBJ_TYPE: | ||
1329 | case AUDIT_SUBJ_SEN: | ||
1330 | case AUDIT_SUBJ_CLR: | ||
1331 | if (f->lsm_rule) { | ||
1332 | security_task_getsecid(current, &sid); | ||
1333 | result = security_audit_rule_match(sid, | ||
1334 | f->type, | ||
1335 | f->op, | ||
1336 | f->lsm_rule, | ||
1337 | NULL); | ||
1338 | } | ||
1339 | break; | ||
1340 | } | ||
1341 | |||
1342 | if (result <= 0) | ||
1343 | return result; | ||
1344 | } | ||
1345 | switch (rule->action) { | ||
1346 | case AUDIT_NEVER: | ||
1347 | *state = AUDIT_DISABLED; | ||
1348 | break; | ||
1349 | case AUDIT_ALWAYS: | ||
1350 | *state = AUDIT_RECORD_CONTEXT; | ||
1351 | break; | ||
1352 | } | ||
1353 | return 1; | ||
1354 | } | ||
1355 | |||
1356 | int audit_filter_user(int type) | ||
1357 | { | ||
1358 | enum audit_state state = AUDIT_DISABLED; | ||
1359 | struct audit_entry *e; | ||
1360 | int rc, ret; | ||
1361 | |||
1362 | ret = 1; /* Audit by default */ | ||
1363 | |||
1364 | rcu_read_lock(); | ||
1365 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | ||
1366 | rc = audit_filter_user_rules(&e->rule, type, &state); | ||
1367 | if (rc) { | ||
1368 | if (rc > 0 && state == AUDIT_DISABLED) | ||
1369 | ret = 0; | ||
1370 | break; | ||
1371 | } | ||
1372 | } | ||
1373 | rcu_read_unlock(); | ||
1374 | |||
1375 | return ret; | ||
1376 | } | ||
1377 | |||
1378 | int audit_filter_type(int type) | ||
1379 | { | 1294 | { |
1380 | struct audit_entry *e; | 1295 | struct audit_entry *e; |
1381 | int result = 0; | 1296 | int ret = 1; /* Audit by default */ |
1382 | 1297 | ||
1383 | rcu_read_lock(); | 1298 | rcu_read_lock(); |
1384 | if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE])) | 1299 | if (list_empty(&audit_filter_list[listtype])) |
1385 | goto unlock_and_return; | 1300 | goto unlock_and_return; |
1301 | list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) { | ||
1302 | int i, result = 0; | ||
1386 | 1303 | ||
1387 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE], | ||
1388 | list) { | ||
1389 | int i; | ||
1390 | for (i = 0; i < e->rule.field_count; i++) { | 1304 | for (i = 0; i < e->rule.field_count; i++) { |
1391 | struct audit_field *f = &e->rule.fields[i]; | 1305 | struct audit_field *f = &e->rule.fields[i]; |
1392 | if (f->type == AUDIT_MSGTYPE) { | 1306 | pid_t pid; |
1393 | result = audit_comparator(type, f->op, f->val); | 1307 | u32 sid; |
1394 | if (!result) | 1308 | |
1395 | break; | 1309 | switch (f->type) { |
1310 | case AUDIT_PID: | ||
1311 | pid = task_pid_nr(current); | ||
1312 | result = audit_comparator(pid, f->op, f->val); | ||
1313 | break; | ||
1314 | case AUDIT_UID: | ||
1315 | result = audit_uid_comparator(current_uid(), f->op, f->uid); | ||
1316 | break; | ||
1317 | case AUDIT_GID: | ||
1318 | result = audit_gid_comparator(current_gid(), f->op, f->gid); | ||
1319 | break; | ||
1320 | case AUDIT_LOGINUID: | ||
1321 | result = audit_uid_comparator(audit_get_loginuid(current), | ||
1322 | f->op, f->uid); | ||
1323 | break; | ||
1324 | case AUDIT_LOGINUID_SET: | ||
1325 | result = audit_comparator(audit_loginuid_set(current), | ||
1326 | f->op, f->val); | ||
1327 | break; | ||
1328 | case AUDIT_MSGTYPE: | ||
1329 | result = audit_comparator(msgtype, f->op, f->val); | ||
1330 | break; | ||
1331 | case AUDIT_SUBJ_USER: | ||
1332 | case AUDIT_SUBJ_ROLE: | ||
1333 | case AUDIT_SUBJ_TYPE: | ||
1334 | case AUDIT_SUBJ_SEN: | ||
1335 | case AUDIT_SUBJ_CLR: | ||
1336 | if (f->lsm_rule) { | ||
1337 | security_task_getsecid(current, &sid); | ||
1338 | result = security_audit_rule_match(sid, | ||
1339 | f->type, f->op, f->lsm_rule, NULL); | ||
1340 | } | ||
1341 | break; | ||
1342 | default: | ||
1343 | goto unlock_and_return; | ||
1396 | } | 1344 | } |
1345 | if (result < 0) /* error */ | ||
1346 | goto unlock_and_return; | ||
1347 | if (!result) | ||
1348 | break; | ||
1349 | } | ||
1350 | if (result > 0) { | ||
1351 | if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_TYPE) | ||
1352 | ret = 0; | ||
1353 | break; | ||
1397 | } | 1354 | } |
1398 | if (result) | ||
1399 | goto unlock_and_return; | ||
1400 | } | 1355 | } |
1401 | unlock_and_return: | 1356 | unlock_and_return: |
1402 | rcu_read_unlock(); | 1357 | rcu_read_unlock(); |
1403 | return result; | 1358 | return ret; |
1404 | } | 1359 | } |
1405 | 1360 | ||
1406 | static int update_lsm_rule(struct audit_krule *r) | 1361 | static int update_lsm_rule(struct audit_krule *r) |