| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* auditfilter.c -- filtering of audit events |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright 2003-2004 Red Hat, Inc. |
|---|
| 4 | 5 | * Copyright 2005 Hewlett-Packard Development Company, L.P. |
|---|
| 5 | 6 | * Copyright 2005 IBM Corporation |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | | - * |
|---|
| 17 | | - * You should have received a copy of the GNU General Public License |
|---|
| 18 | | - * along with this program; if not, write to the Free Software |
|---|
| 19 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 20 | 7 | */ |
|---|
| 21 | 8 | |
|---|
| 22 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 335 | 322 | /* check if an audit field is valid */ |
|---|
| 336 | 323 | static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) |
|---|
| 337 | 324 | { |
|---|
| 338 | | - switch(f->type) { |
|---|
| 325 | + switch (f->type) { |
|---|
| 339 | 326 | case AUDIT_MSGTYPE: |
|---|
| 340 | 327 | if (entry->rule.listnr != AUDIT_FILTER_EXCLUDE && |
|---|
| 341 | 328 | entry->rule.listnr != AUDIT_FILTER_USER) |
|---|
| .. | .. |
|---|
| 347 | 334 | break; |
|---|
| 348 | 335 | } |
|---|
| 349 | 336 | |
|---|
| 350 | | - switch(entry->rule.listnr) { |
|---|
| 337 | + switch (entry->rule.listnr) { |
|---|
| 351 | 338 | case AUDIT_FILTER_FS: |
|---|
| 352 | 339 | switch(f->type) { |
|---|
| 353 | 340 | case AUDIT_FSTYPE: |
|---|
| .. | .. |
|---|
| 358 | 345 | } |
|---|
| 359 | 346 | } |
|---|
| 360 | 347 | |
|---|
| 361 | | - switch(f->type) { |
|---|
| 362 | | - default: |
|---|
| 363 | | - return -EINVAL; |
|---|
| 348 | + /* Check for valid field type and op */ |
|---|
| 349 | + switch (f->type) { |
|---|
| 350 | + case AUDIT_ARG0: |
|---|
| 351 | + case AUDIT_ARG1: |
|---|
| 352 | + case AUDIT_ARG2: |
|---|
| 353 | + case AUDIT_ARG3: |
|---|
| 354 | + case AUDIT_PERS: /* <uapi/linux/personality.h> */ |
|---|
| 355 | + case AUDIT_DEVMINOR: |
|---|
| 356 | + /* all ops are valid */ |
|---|
| 357 | + break; |
|---|
| 364 | 358 | case AUDIT_UID: |
|---|
| 365 | 359 | case AUDIT_EUID: |
|---|
| 366 | 360 | case AUDIT_SUID: |
|---|
| .. | .. |
|---|
| 373 | 367 | case AUDIT_FSGID: |
|---|
| 374 | 368 | case AUDIT_OBJ_GID: |
|---|
| 375 | 369 | case AUDIT_PID: |
|---|
| 376 | | - case AUDIT_PERS: |
|---|
| 377 | 370 | case AUDIT_MSGTYPE: |
|---|
| 378 | 371 | case AUDIT_PPID: |
|---|
| 379 | 372 | case AUDIT_DEVMAJOR: |
|---|
| 380 | | - case AUDIT_DEVMINOR: |
|---|
| 381 | 373 | case AUDIT_EXIT: |
|---|
| 382 | 374 | case AUDIT_SUCCESS: |
|---|
| 383 | 375 | case AUDIT_INODE: |
|---|
| 384 | 376 | case AUDIT_SESSIONID: |
|---|
| 377 | + case AUDIT_SUBJ_SEN: |
|---|
| 378 | + case AUDIT_SUBJ_CLR: |
|---|
| 379 | + case AUDIT_OBJ_LEV_LOW: |
|---|
| 380 | + case AUDIT_OBJ_LEV_HIGH: |
|---|
| 381 | + case AUDIT_SADDR_FAM: |
|---|
| 385 | 382 | /* bit ops are only useful on syscall args */ |
|---|
| 386 | 383 | if (f->op == Audit_bitmask || f->op == Audit_bittest) |
|---|
| 387 | 384 | return -EINVAL; |
|---|
| 388 | 385 | break; |
|---|
| 389 | | - case AUDIT_ARG0: |
|---|
| 390 | | - case AUDIT_ARG1: |
|---|
| 391 | | - case AUDIT_ARG2: |
|---|
| 392 | | - case AUDIT_ARG3: |
|---|
| 393 | 386 | case AUDIT_SUBJ_USER: |
|---|
| 394 | 387 | case AUDIT_SUBJ_ROLE: |
|---|
| 395 | 388 | case AUDIT_SUBJ_TYPE: |
|---|
| 396 | | - case AUDIT_SUBJ_SEN: |
|---|
| 397 | | - case AUDIT_SUBJ_CLR: |
|---|
| 398 | 389 | case AUDIT_OBJ_USER: |
|---|
| 399 | 390 | case AUDIT_OBJ_ROLE: |
|---|
| 400 | 391 | case AUDIT_OBJ_TYPE: |
|---|
| 401 | | - case AUDIT_OBJ_LEV_LOW: |
|---|
| 402 | | - case AUDIT_OBJ_LEV_HIGH: |
|---|
| 403 | 392 | case AUDIT_WATCH: |
|---|
| 404 | 393 | case AUDIT_DIR: |
|---|
| 405 | 394 | case AUDIT_FILTERKEY: |
|---|
| 406 | | - break; |
|---|
| 407 | 395 | case AUDIT_LOGINUID_SET: |
|---|
| 408 | | - if ((f->val != 0) && (f->val != 1)) |
|---|
| 409 | | - return -EINVAL; |
|---|
| 410 | | - /* FALL THROUGH */ |
|---|
| 411 | 396 | case AUDIT_ARCH: |
|---|
| 412 | 397 | case AUDIT_FSTYPE: |
|---|
| 398 | + case AUDIT_PERM: |
|---|
| 399 | + case AUDIT_FILETYPE: |
|---|
| 400 | + case AUDIT_FIELD_COMPARE: |
|---|
| 401 | + case AUDIT_EXE: |
|---|
| 402 | + /* only equal and not equal valid ops */ |
|---|
| 413 | 403 | if (f->op != Audit_not_equal && f->op != Audit_equal) |
|---|
| 404 | + return -EINVAL; |
|---|
| 405 | + break; |
|---|
| 406 | + default: |
|---|
| 407 | + /* field not recognized */ |
|---|
| 408 | + return -EINVAL; |
|---|
| 409 | + } |
|---|
| 410 | + |
|---|
| 411 | + /* Check for select valid field values */ |
|---|
| 412 | + switch (f->type) { |
|---|
| 413 | + case AUDIT_LOGINUID_SET: |
|---|
| 414 | + if ((f->val != 0) && (f->val != 1)) |
|---|
| 414 | 415 | return -EINVAL; |
|---|
| 415 | 416 | break; |
|---|
| 416 | 417 | case AUDIT_PERM: |
|---|
| .. | .. |
|---|
| 425 | 426 | if (f->val > AUDIT_MAX_FIELD_COMPARE) |
|---|
| 426 | 427 | return -EINVAL; |
|---|
| 427 | 428 | break; |
|---|
| 428 | | - case AUDIT_EXE: |
|---|
| 429 | | - if (f->op != Audit_not_equal && f->op != Audit_equal) |
|---|
| 429 | + case AUDIT_SADDR_FAM: |
|---|
| 430 | + if (f->val >= AF_MAX) |
|---|
| 430 | 431 | return -EINVAL; |
|---|
| 431 | 432 | break; |
|---|
| 433 | + default: |
|---|
| 434 | + break; |
|---|
| 432 | 435 | } |
|---|
| 436 | + |
|---|
| 433 | 437 | return 0; |
|---|
| 434 | 438 | } |
|---|
| 435 | 439 | |
|---|
| .. | .. |
|---|
| 677 | 681 | data->values[i] = AUDIT_UID_UNSET; |
|---|
| 678 | 682 | break; |
|---|
| 679 | 683 | } |
|---|
| 680 | | - /* fallthrough if set */ |
|---|
| 684 | + fallthrough; /* if set */ |
|---|
| 681 | 685 | default: |
|---|
| 682 | 686 | data->values[i] = f->val; |
|---|
| 683 | 687 | } |
|---|
| .. | .. |
|---|
| 1098 | 1102 | if (!audit_enabled) |
|---|
| 1099 | 1103 | return; |
|---|
| 1100 | 1104 | |
|---|
| 1101 | | - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
|---|
| 1105 | + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
|---|
| 1102 | 1106 | if (!ab) |
|---|
| 1103 | 1107 | return; |
|---|
| 1104 | 1108 | audit_log_session_info(ab); |
|---|
| .. | .. |
|---|
| 1208 | 1212 | case Audit_bittest: |
|---|
| 1209 | 1213 | return ((left & right) == right); |
|---|
| 1210 | 1214 | default: |
|---|
| 1211 | | - BUG(); |
|---|
| 1212 | 1215 | return 0; |
|---|
| 1213 | 1216 | } |
|---|
| 1214 | 1217 | } |
|---|
| .. | .. |
|---|
| 1231 | 1234 | case Audit_bitmask: |
|---|
| 1232 | 1235 | case Audit_bittest: |
|---|
| 1233 | 1236 | default: |
|---|
| 1234 | | - BUG(); |
|---|
| 1235 | 1237 | return 0; |
|---|
| 1236 | 1238 | } |
|---|
| 1237 | 1239 | } |
|---|
| .. | .. |
|---|
| 1254 | 1256 | case Audit_bitmask: |
|---|
| 1255 | 1257 | case Audit_bittest: |
|---|
| 1256 | 1258 | default: |
|---|
| 1257 | | - BUG(); |
|---|
| 1258 | 1259 | return 0; |
|---|
| 1259 | 1260 | } |
|---|
| 1260 | 1261 | } |
|---|
| .. | .. |
|---|
| 1297 | 1298 | * @parentlen: length of the parent if known. Passing in AUDIT_NAME_FULL |
|---|
| 1298 | 1299 | * here indicates that we must compute this value. |
|---|
| 1299 | 1300 | */ |
|---|
| 1300 | | -int audit_compare_dname_path(const char *dname, const char *path, int parentlen) |
|---|
| 1301 | +int audit_compare_dname_path(const struct qstr *dname, const char *path, int parentlen) |
|---|
| 1301 | 1302 | { |
|---|
| 1302 | 1303 | int dlen, pathlen; |
|---|
| 1303 | 1304 | const char *p; |
|---|
| 1304 | 1305 | |
|---|
| 1305 | | - dlen = strlen(dname); |
|---|
| 1306 | + dlen = dname->len; |
|---|
| 1306 | 1307 | pathlen = strlen(path); |
|---|
| 1307 | 1308 | if (pathlen < dlen) |
|---|
| 1308 | 1309 | return 1; |
|---|
| .. | .. |
|---|
| 1313 | 1314 | |
|---|
| 1314 | 1315 | p = path + parentlen; |
|---|
| 1315 | 1316 | |
|---|
| 1316 | | - return strncmp(p, dname, dlen); |
|---|
| 1317 | + return strncmp(p, dname->name, dlen); |
|---|
| 1317 | 1318 | } |
|---|
| 1318 | 1319 | |
|---|
| 1319 | 1320 | int audit_filter(int msgtype, unsigned int listtype) |
|---|
| .. | .. |
|---|
| 1322 | 1323 | int ret = 1; /* Audit by default */ |
|---|
| 1323 | 1324 | |
|---|
| 1324 | 1325 | rcu_read_lock(); |
|---|
| 1325 | | - if (list_empty(&audit_filter_list[listtype])) |
|---|
| 1326 | | - goto unlock_and_return; |
|---|
| 1327 | 1326 | list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) { |
|---|
| 1328 | 1327 | int i, result = 0; |
|---|
| 1329 | 1328 | |
|---|
| .. | .. |
|---|
| 1362 | 1361 | if (f->lsm_rule) { |
|---|
| 1363 | 1362 | security_task_getsecid(current, &sid); |
|---|
| 1364 | 1363 | result = security_audit_rule_match(sid, |
|---|
| 1365 | | - f->type, f->op, f->lsm_rule, NULL); |
|---|
| 1364 | + f->type, f->op, f->lsm_rule); |
|---|
| 1366 | 1365 | } |
|---|
| 1367 | 1366 | break; |
|---|
| 1368 | 1367 | case AUDIT_EXE: |
|---|