diff options
Diffstat (limited to 'kernel/auditfilter.c')
| -rw-r--r-- | kernel/auditfilter.c | 137 |
1 files changed, 118 insertions, 19 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index a6c3f1abd206..c4bcdbaf4d4d 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -342,6 +342,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 342 | 342 | ||
| 343 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); | 343 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); |
| 344 | f->val = rule->values[i]; | 344 | f->val = rule->values[i]; |
| 345 | f->uid = INVALID_UID; | ||
| 346 | f->gid = INVALID_GID; | ||
| 345 | 347 | ||
| 346 | err = -EINVAL; | 348 | err = -EINVAL; |
| 347 | if (f->op == Audit_bad) | 349 | if (f->op == Audit_bad) |
| @@ -350,16 +352,32 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 350 | switch(f->type) { | 352 | switch(f->type) { |
| 351 | default: | 353 | default: |
| 352 | goto exit_free; | 354 | goto exit_free; |
| 353 | case AUDIT_PID: | ||
| 354 | case AUDIT_UID: | 355 | case AUDIT_UID: |
| 355 | case AUDIT_EUID: | 356 | case AUDIT_EUID: |
| 356 | case AUDIT_SUID: | 357 | case AUDIT_SUID: |
| 357 | case AUDIT_FSUID: | 358 | case AUDIT_FSUID: |
| 359 | case AUDIT_LOGINUID: | ||
| 360 | /* bit ops not implemented for uid comparisons */ | ||
| 361 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 362 | goto exit_free; | ||
| 363 | |||
| 364 | f->uid = make_kuid(current_user_ns(), f->val); | ||
| 365 | if (!uid_valid(f->uid)) | ||
| 366 | goto exit_free; | ||
| 367 | break; | ||
| 358 | case AUDIT_GID: | 368 | case AUDIT_GID: |
| 359 | case AUDIT_EGID: | 369 | case AUDIT_EGID: |
| 360 | case AUDIT_SGID: | 370 | case AUDIT_SGID: |
| 361 | case AUDIT_FSGID: | 371 | case AUDIT_FSGID: |
| 362 | case AUDIT_LOGINUID: | 372 | /* bit ops not implemented for gid comparisons */ |
| 373 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 374 | goto exit_free; | ||
| 375 | |||
| 376 | f->gid = make_kgid(current_user_ns(), f->val); | ||
| 377 | if (!gid_valid(f->gid)) | ||
| 378 | goto exit_free; | ||
| 379 | break; | ||
| 380 | case AUDIT_PID: | ||
| 363 | case AUDIT_PERS: | 381 | case AUDIT_PERS: |
| 364 | case AUDIT_MSGTYPE: | 382 | case AUDIT_MSGTYPE: |
| 365 | case AUDIT_PPID: | 383 | case AUDIT_PPID: |
| @@ -437,19 +455,39 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 437 | 455 | ||
| 438 | f->type = data->fields[i]; | 456 | f->type = data->fields[i]; |
| 439 | f->val = data->values[i]; | 457 | f->val = data->values[i]; |
| 458 | f->uid = INVALID_UID; | ||
| 459 | f->gid = INVALID_GID; | ||
| 440 | f->lsm_str = NULL; | 460 | f->lsm_str = NULL; |
| 441 | f->lsm_rule = NULL; | 461 | f->lsm_rule = NULL; |
| 442 | switch(f->type) { | 462 | switch(f->type) { |
| 443 | case AUDIT_PID: | ||
| 444 | case AUDIT_UID: | 463 | case AUDIT_UID: |
| 445 | case AUDIT_EUID: | 464 | case AUDIT_EUID: |
| 446 | case AUDIT_SUID: | 465 | case AUDIT_SUID: |
| 447 | case AUDIT_FSUID: | 466 | case AUDIT_FSUID: |
| 467 | case AUDIT_LOGINUID: | ||
| 468 | case AUDIT_OBJ_UID: | ||
| 469 | /* bit ops not implemented for uid comparisons */ | ||
| 470 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 471 | goto exit_free; | ||
| 472 | |||
| 473 | f->uid = make_kuid(current_user_ns(), f->val); | ||
| 474 | if (!uid_valid(f->uid)) | ||
| 475 | goto exit_free; | ||
| 476 | break; | ||
| 448 | case AUDIT_GID: | 477 | case AUDIT_GID: |
| 449 | case AUDIT_EGID: | 478 | case AUDIT_EGID: |
| 450 | case AUDIT_SGID: | 479 | case AUDIT_SGID: |
| 451 | case AUDIT_FSGID: | 480 | case AUDIT_FSGID: |
| 452 | case AUDIT_LOGINUID: | 481 | case AUDIT_OBJ_GID: |
| 482 | /* bit ops not implemented for gid comparisons */ | ||
| 483 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 484 | goto exit_free; | ||
| 485 | |||
| 486 | f->gid = make_kgid(current_user_ns(), f->val); | ||
| 487 | if (!gid_valid(f->gid)) | ||
| 488 | goto exit_free; | ||
| 489 | break; | ||
| 490 | case AUDIT_PID: | ||
| 453 | case AUDIT_PERS: | 491 | case AUDIT_PERS: |
| 454 | case AUDIT_MSGTYPE: | 492 | case AUDIT_MSGTYPE: |
| 455 | case AUDIT_PPID: | 493 | case AUDIT_PPID: |
| @@ -461,8 +499,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 461 | case AUDIT_ARG1: | 499 | case AUDIT_ARG1: |
| 462 | case AUDIT_ARG2: | 500 | case AUDIT_ARG2: |
| 463 | case AUDIT_ARG3: | 501 | case AUDIT_ARG3: |
| 464 | case AUDIT_OBJ_UID: | ||
| 465 | case AUDIT_OBJ_GID: | ||
| 466 | break; | 502 | break; |
| 467 | case AUDIT_ARCH: | 503 | case AUDIT_ARCH: |
| 468 | entry->rule.arch_f = f; | 504 | entry->rule.arch_f = f; |
| @@ -707,6 +743,23 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
| 707 | if (strcmp(a->filterkey, b->filterkey)) | 743 | if (strcmp(a->filterkey, b->filterkey)) |
| 708 | return 1; | 744 | return 1; |
| 709 | break; | 745 | break; |
| 746 | case AUDIT_UID: | ||
| 747 | case AUDIT_EUID: | ||
| 748 | case AUDIT_SUID: | ||
| 749 | case AUDIT_FSUID: | ||
| 750 | case AUDIT_LOGINUID: | ||
| 751 | case AUDIT_OBJ_UID: | ||
| 752 | if (!uid_eq(a->fields[i].uid, b->fields[i].uid)) | ||
| 753 | return 1; | ||
| 754 | break; | ||
| 755 | case AUDIT_GID: | ||
| 756 | case AUDIT_EGID: | ||
| 757 | case AUDIT_SGID: | ||
| 758 | case AUDIT_FSGID: | ||
| 759 | case AUDIT_OBJ_GID: | ||
| 760 | if (!gid_eq(a->fields[i].gid, b->fields[i].gid)) | ||
| 761 | return 1; | ||
| 762 | break; | ||
| 710 | default: | 763 | default: |
| 711 | if (a->fields[i].val != b->fields[i].val) | 764 | if (a->fields[i].val != b->fields[i].val) |
| 712 | return 1; | 765 | return 1; |
| @@ -1056,7 +1109,7 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | |||
| 1056 | } | 1109 | } |
| 1057 | 1110 | ||
| 1058 | /* Log rule additions and removals */ | 1111 | /* Log rule additions and removals */ |
| 1059 | static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, | 1112 | static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, |
| 1060 | char *action, struct audit_krule *rule, | 1113 | char *action, struct audit_krule *rule, |
| 1061 | int res) | 1114 | int res) |
| 1062 | { | 1115 | { |
| @@ -1068,7 +1121,8 @@ static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, | |||
| 1068 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1121 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 1069 | if (!ab) | 1122 | if (!ab) |
| 1070 | return; | 1123 | return; |
| 1071 | audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid); | 1124 | audit_log_format(ab, "auid=%u ses=%u", |
| 1125 | from_kuid(&init_user_ns, loginuid), sessionid); | ||
| 1072 | if (sid) { | 1126 | if (sid) { |
| 1073 | char *ctx = NULL; | 1127 | char *ctx = NULL; |
| 1074 | u32 len; | 1128 | u32 len; |
| @@ -1098,8 +1152,8 @@ static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, | |||
| 1098 | * @sessionid: sessionid for netlink audit message | 1152 | * @sessionid: sessionid for netlink audit message |
| 1099 | * @sid: SE Linux Security ID of sender | 1153 | * @sid: SE Linux Security ID of sender |
| 1100 | */ | 1154 | */ |
| 1101 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | 1155 | int audit_receive_filter(int type, int pid, int seq, void *data, |
| 1102 | size_t datasz, uid_t loginuid, u32 sessionid, u32 sid) | 1156 | size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid) |
| 1103 | { | 1157 | { |
| 1104 | struct task_struct *tsk; | 1158 | struct task_struct *tsk; |
| 1105 | struct audit_netlink_list *dest; | 1159 | struct audit_netlink_list *dest; |
| @@ -1198,6 +1252,52 @@ int audit_comparator(u32 left, u32 op, u32 right) | |||
| 1198 | } | 1252 | } |
| 1199 | } | 1253 | } |
| 1200 | 1254 | ||
| 1255 | int audit_uid_comparator(kuid_t left, u32 op, kuid_t right) | ||
| 1256 | { | ||
| 1257 | switch (op) { | ||
| 1258 | case Audit_equal: | ||
| 1259 | return uid_eq(left, right); | ||
| 1260 | case Audit_not_equal: | ||
| 1261 | return !uid_eq(left, right); | ||
| 1262 | case Audit_lt: | ||
| 1263 | return uid_lt(left, right); | ||
| 1264 | case Audit_le: | ||
| 1265 | return uid_lte(left, right); | ||
| 1266 | case Audit_gt: | ||
| 1267 | return uid_gt(left, right); | ||
| 1268 | case Audit_ge: | ||
| 1269 | return uid_gte(left, right); | ||
| 1270 | case Audit_bitmask: | ||
| 1271 | case Audit_bittest: | ||
| 1272 | default: | ||
| 1273 | BUG(); | ||
| 1274 | return 0; | ||
| 1275 | } | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | int audit_gid_comparator(kgid_t left, u32 op, kgid_t right) | ||
| 1279 | { | ||
| 1280 | switch (op) { | ||
| 1281 | case Audit_equal: | ||
| 1282 | return gid_eq(left, right); | ||
| 1283 | case Audit_not_equal: | ||
| 1284 | return !gid_eq(left, right); | ||
| 1285 | case Audit_lt: | ||
| 1286 | return gid_lt(left, right); | ||
| 1287 | case Audit_le: | ||
| 1288 | return gid_lte(left, right); | ||
| 1289 | case Audit_gt: | ||
| 1290 | return gid_gt(left, right); | ||
| 1291 | case Audit_ge: | ||
| 1292 | return gid_gte(left, right); | ||
| 1293 | case Audit_bitmask: | ||
| 1294 | case Audit_bittest: | ||
| 1295 | default: | ||
| 1296 | BUG(); | ||
| 1297 | return 0; | ||
| 1298 | } | ||
| 1299 | } | ||
| 1300 | |||
| 1201 | /* Compare given dentry name with last component in given path, | 1301 | /* Compare given dentry name with last component in given path, |
| 1202 | * return of 0 indicates a match. */ | 1302 | * return of 0 indicates a match. */ |
| 1203 | int audit_compare_dname_path(const char *dname, const char *path, | 1303 | int audit_compare_dname_path(const char *dname, const char *path, |
| @@ -1236,8 +1336,7 @@ int audit_compare_dname_path(const char *dname, const char *path, | |||
| 1236 | return strncmp(p, dname, dlen); | 1336 | return strncmp(p, dname, dlen); |
| 1237 | } | 1337 | } |
| 1238 | 1338 | ||
| 1239 | static int audit_filter_user_rules(struct netlink_skb_parms *cb, | 1339 | static int audit_filter_user_rules(struct audit_krule *rule, |
| 1240 | struct audit_krule *rule, | ||
| 1241 | enum audit_state *state) | 1340 | enum audit_state *state) |
| 1242 | { | 1341 | { |
| 1243 | int i; | 1342 | int i; |
| @@ -1249,17 +1348,17 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb, | |||
| 1249 | 1348 | ||
| 1250 | switch (f->type) { | 1349 | switch (f->type) { |
| 1251 | case AUDIT_PID: | 1350 | case AUDIT_PID: |
| 1252 | result = audit_comparator(cb->creds.pid, f->op, f->val); | 1351 | result = audit_comparator(task_pid_vnr(current), f->op, f->val); |
| 1253 | break; | 1352 | break; |
| 1254 | case AUDIT_UID: | 1353 | case AUDIT_UID: |
| 1255 | result = audit_comparator(cb->creds.uid, f->op, f->val); | 1354 | result = audit_uid_comparator(current_uid(), f->op, f->uid); |
| 1256 | break; | 1355 | break; |
| 1257 | case AUDIT_GID: | 1356 | case AUDIT_GID: |
| 1258 | result = audit_comparator(cb->creds.gid, f->op, f->val); | 1357 | result = audit_gid_comparator(current_gid(), f->op, f->gid); |
| 1259 | break; | 1358 | break; |
| 1260 | case AUDIT_LOGINUID: | 1359 | case AUDIT_LOGINUID: |
| 1261 | result = audit_comparator(audit_get_loginuid(current), | 1360 | result = audit_uid_comparator(audit_get_loginuid(current), |
| 1262 | f->op, f->val); | 1361 | f->op, f->uid); |
| 1263 | break; | 1362 | break; |
| 1264 | case AUDIT_SUBJ_USER: | 1363 | case AUDIT_SUBJ_USER: |
| 1265 | case AUDIT_SUBJ_ROLE: | 1364 | case AUDIT_SUBJ_ROLE: |
| @@ -1287,7 +1386,7 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb, | |||
| 1287 | return 1; | 1386 | return 1; |
| 1288 | } | 1387 | } |
| 1289 | 1388 | ||
| 1290 | int audit_filter_user(struct netlink_skb_parms *cb) | 1389 | int audit_filter_user(void) |
| 1291 | { | 1390 | { |
| 1292 | enum audit_state state = AUDIT_DISABLED; | 1391 | enum audit_state state = AUDIT_DISABLED; |
| 1293 | struct audit_entry *e; | 1392 | struct audit_entry *e; |
| @@ -1295,7 +1394,7 @@ int audit_filter_user(struct netlink_skb_parms *cb) | |||
| 1295 | 1394 | ||
| 1296 | rcu_read_lock(); | 1395 | rcu_read_lock(); |
| 1297 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | 1396 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { |
| 1298 | if (audit_filter_user_rules(cb, &e->rule, &state)) { | 1397 | if (audit_filter_user_rules(&e->rule, &state)) { |
| 1299 | if (state == AUDIT_DISABLED) | 1398 | if (state == AUDIT_DISABLED) |
| 1300 | ret = 0; | 1399 | ret = 0; |
| 1301 | break; | 1400 | break; |
