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 | } | ||
