/
githubmirror
/
audit-userspace
Обзор
Документация
Войти
/
githubmirror
/
audit-userspace
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/ausearch-match.c
422 строки
10 KB
Mikhail Novosyolov
Fix DEREF_OF_NULL.RET.STAT in ausearch-match.c
01 мар 2026, 00:52
01 мар 2026, 00:52
d00aa1a
Код
Авторство
О чём код?
/* * ausearch-match.c - Extract interesting fields and check for match * Copyright (c) 2005-08, 2011 Red Hat Inc. * Copyright (c) 2011 IBM Corp. * All Rights Reserved. * * This software may be freely redistributed and/or modified under the * terms of the GNU General Public License as published by the Free * Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor * Boston, MA 02110-1335, USA. * * Authors: * Steve Grubb <sgrubb@redhat.com> * Marcelo Henrique Cerri <mhcerri@br.ibm.com> */ #include "config.h" #include <string.h> #include "libaudit.h" #include "ausearch-options.h" #include "ausearch-parse.h" extern void ausearch_load_interpretations(const lnode *n); /* local functions */ static int strmatch(const char *needle, const char *haystack); static int user_match(llist *l); static int group_match(llist *l); static int context_match(llist *l); static void load_interpretations(const llist *l) { // See if there is any reason to load interpretations if (event_tuid == NULL && event_teuid == NULL && event_tauid == NULL) return; // If there is only 1 record load it, or load just the syscall one if ((l->cnt == 1) || (l->head && l->head->type == AUDIT_SYSCALL)) ausearch_load_interpretations(l->head); } /* * This function performs that matching of search params with the record. * It returns 1 on a match, and 0 if no match. The way that this function * works is that it will try to determine if there is not a match and exit * as soon as possible. We can do this since all command line params form * an 'and' statement. If anything does not match, no need to evaluate the * rest of the params. */ #include <stdio.h> int match(llist *l) { // Are we within time range? if (start_time == 0 || l->e.sec >= start_time) { if (end_time == 0 || l->e.sec <= end_time) { if (event_id == -1 || event_id == l->e.serial) { // Load interpretations if needed load_interpretations(l); // OK - do the heavier checking if (extract_search_items(l)) { return 0; } // perform additional tests for the field if (event_node_list) { const snode *sn; int found=0; slist *sptr = event_node_list; if (l->e.node == NULL) return 0; slist_first(sptr); sn=slist_get_cur(sptr); while (sn && !found) { if (sn->str && (!strcmp(sn->str, l->e.node))) found++; else sn=slist_next(sptr); } if (!found) return 0; } if (user_match(l) == 0) return 0; if (group_match(l) == 0) return 0; if ((event_ppid != -1) && (event_ppid != l->s.ppid)) return 0; if ((event_pid != -1) && (event_pid != l->s.pid)) return 0; if (event_machine != -1 && (event_machine != audit_elf_to_machine(l->s.arch))) return 0; if ((event_syscall != -1) && (event_syscall != l->s.syscall)) return 0; if ((event_session_id != -2) && (event_session_id != l->s.session_id)) return 0; if (event_exit_is_set) { if (l->s.exit_is_set == 0) return 0; if (event_exit != l->s.exit) return 0; } if ((event_success != S_UNSET) && (event_success != l->s.success)) return 0; // event_type requires looking at each item if (event_type != NULL) { int found = 0; const lnode *n; list_first(l); n = list_get_cur(l); while (n) { int_node *in; ilist_first(event_type); in = ilist_get_cur(event_type); while (in) { if (in->num == n->type){ found = 1; break; } in = ilist_next(event_type); } if (found) break; n = list_next(l); } if (!found) return 0; } // Done all the easy compares, now do the // string searches. if (event_filename) { int found = 0; if (l->s.filename == NULL && l->s.cwd == NULL) return 0; if (l->s.filename) { const snode *sn; slist *sptr = l->s.filename; slist_first(sptr); sn=slist_get_cur(sptr); while (sn) { if (sn->str == NULL) return 0; if (strmatch( event_filename, sn->str)) { found = 1; break; } sn = slist_next(sptr); } if (!found && l->s.cwd == NULL) return 0; } if (l->s.cwd && !found) { /* Check cwd, too */ if (strmatch(event_filename, l->s.cwd) == 0) return 0; } } if (event_hostname) { if (l->s.hostname == NULL) return 0; if (strmatch(event_hostname, l->s.hostname) == 0) return 0; } if (event_terminal) { if (l->s.terminal == NULL) return 0; if (strmatch(event_terminal, l->s.terminal) == 0) return 0; } if (event_exe) { if (l->s.exe == NULL) return 0; if (strmatch(event_exe, l->s.exe) == 0) return 0; } if (event_comm) { if (l->s.comm == NULL) return 0; if (strmatch(event_comm, l->s.comm) == 0) return 0; } if (event_key) { if (l->s.key == NULL) return 0; else { int found = 0; const snode *sn; slist *sptr = l->s.key; slist_first(sptr); sn=slist_get_cur(sptr); while (sn) { if (sn->str == NULL) return 0; if (strmatch( event_key, sn->str)) { found = 1; break; } sn = slist_next(sptr); } if (!found) return 0; } } if (event_vmname) { if (l->s.vmname == NULL) return 0; if (strmatch(event_vmname, l->s.vmname) == 0) return 0; } if (event_uuid) { if (l->s.uuid == NULL) return 0; if (strmatch(event_uuid, l->s.uuid) == 0) return 0; } if (context_match(l) == 0) return 0; return 1; } } } return 0; } /* * This function compares strings. It returns a 0 if no match and a 1 if * there is a match */ static int strmatch(const char *needle, const char *haystack) { if (event_exact_match) { if (strcmp(haystack, needle) != 0) return 0; } else { if (strstr(haystack, needle) == NULL) return 0; } return 1; } /* * This function compares user id's. * It returns a 0 if no match and a 1 if there is a match */ static int user_match(llist *l) { // Match by string if set (assume all event vars are set) if (event_ua && event_tuid) { // This will "or" the user tests if (l->s.tuid && strcmp(event_tuid, l->s.tuid) == 0) return 1; if (l->s.teuid && strcmp(event_teuid, l->s.teuid) == 0) return 1; if (l->s.tauid && strcmp(event_tauid, l->s.tauid) == 0) return 1; return 0; // OK, try a pure numeric match } else if (event_ua) { // This will "or" the user tests if (event_uid == l->s.uid) return 1; if (event_euid == l->s.euid) return 1; if (event_loginuid == l->s.loginuid) return 1; return 0; } else { // This will "and" the user tests if (event_tuid || event_teuid || event_tauid) { if (event_tuid) { if (l->s.tuid == NULL) return 0; if (strcmp(event_tuid, l->s.tuid)) return 0; } if (event_teuid) { if (l->s.teuid == NULL) return 0; if (strcmp(event_teuid, l->s.teuid)) return 0; } if (event_tauid) { if (l->s.tauid == NULL) return 0; if (strcmp(event_tauid, l->s.tauid)) return 0; } } else { // Numeric only match if ((event_uid != -1) && (event_uid != l->s.uid)) return 0; if ((event_euid != -1) &&(event_euid != l->s.euid)) return 0; if ((event_loginuid != -2) && (event_loginuid != l->s.loginuid)) return 0; } } return 1; } /* * This function compares group id's. It returns a 0 if no match and a 1 if * there is a match */ static int group_match(llist *l) { if (event_ga) { // This will "or" the group tests if (event_gid == l->s.gid) return 1; if (event_egid == l->s.egid) return 1; return 0; } else { // This will "and" the group tests if ((event_gid != -1) && (event_gid != l->s.gid)) return 0; if ((event_egid != -1) &&(event_egid != l->s.egid)) return 0; } return 1; } /* * This function compares contexts. It returns a 0 if no match and a 1 if * there is a match */ static int context_match(llist *l) { if (event_se) { /* This does the "or" check if -se test */ if (event_subject) { if (l->s.avc && alist_find_subj(l->s.avc)) { do { if (strmatch(event_subject, l->s.avc->cur->scontext)) return 1; } while(alist_next_subj(l->s.avc)); } } if (event_object) { if (l->s.avc) { alist_first(l->s.avc); if (alist_find_obj(l->s.avc)) { do { if (strmatch(event_object, l->s.avc->cur->tcontext)) return 1; } while(alist_next_obj(l->s.avc)); } } } return 0; } else { /* This is an 'and' requiring both to match */ int found = 0; if (event_subject) { if (l->s.avc == NULL) return 0; if (alist_find_subj(l->s.avc)) { do { if (strmatch(event_subject, l->s.avc->cur->scontext)) found = 1; } while(alist_next_subj(l->s.avc)); } if (!found) return 0; } found = 0; if (event_object) { if (l->s.avc == NULL) return 0; if (alist_find_obj(l->s.avc)) { do { if (strmatch(event_object, l->s.avc->cur->tcontext)) found = 1; } while(alist_next_obj(l->s.avc)); } if (!found) return 0; } } return 1; }