diff --git a/.fapolicyd.metadata b/.fapolicyd.metadata deleted file mode 100644 index 871a2d0..0000000 --- a/.fapolicyd.metadata +++ /dev/null @@ -1,2 +0,0 @@ -3887d3f97a4f506ad6bf7dcef36b01cc7897a692 SOURCES/fapolicyd-1.1.3.tar.gz -bdbe20a4db2cd58073abf17a537e3a6766cdea21 SOURCES/fapolicyd-selinux-0.4.tar.gz diff --git a/.gitignore b/.gitignore index b3fd084..9234fd0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/fapolicyd-1.1.3.tar.gz -SOURCES/fapolicyd-selinux-0.4.tar.gz +SOURCES/fapolicyd-1.3.2.tar.gz +SOURCES/fapolicyd-selinux-0.6.tar.gz diff --git a/SOURCES/fagenrules-group.patch b/SOURCES/fagenrules-group.patch deleted file mode 100644 index 744bb64..0000000 --- a/SOURCES/fagenrules-group.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up ./init/fagenrules.fix ./init/fagenrules ---- ./init/fagenrules.fix 2022-04-01 16:12:50.512164904 +0200 -+++ ./init/fagenrules 2022-04-01 16:21:07.924712100 +0200 -@@ -117,7 +117,8 @@ fi - - # We copy the file so that it gets the right selinux label - cp ${TmpRules} ${DestinationFile} --chmod 0640 ${DestinationFile} -+chmod 0644 ${DestinationFile} -+chgrp fapolicyd ${DestinationFile} - - # Restore context on MLS system. - # /tmp is SystemLow & fapolicyd.rules is SystemHigh diff --git a/SOURCES/fapolicyd-already-started.patch b/SOURCES/fapolicyd-already-started.patch deleted file mode 100644 index 6a68b62..0000000 --- a/SOURCES/fapolicyd-already-started.patch +++ /dev/null @@ -1,110 +0,0 @@ -diff -up ./src/daemon/fapolicyd.c.already-started ./src/daemon/fapolicyd.c ---- ./src/daemon/fapolicyd.c.already-started 2023-01-12 17:40:45.366909652 +0100 -+++ ./src/daemon/fapolicyd.c 2023-01-12 17:46:22.458139519 +0100 -@@ -378,6 +378,58 @@ static void usage(void) - } - - -+int already_running(void) -+{ -+ int pidfd = open(pidfile, O_RDONLY); -+ if (pidfd >= 0) { -+ char pid_buf[16]; -+ -+ if (fd_fgets(pid_buf, sizeof(pid_buf), pidfd)) { -+ int pid; -+ char exe_buf[80], my_path[80]; -+ -+ // Get our path -+ if (get_program_from_pid(getpid(), -+ sizeof(exe_buf), my_path) == NULL) -+ goto err_out; // shouldn't happen, but be safe -+ -+ // convert pidfile to integer -+ errno = 0; -+ pid = strtoul(pid_buf, NULL, 10); -+ if (errno) -+ goto err_out; // shouldn't happen, but be safe -+ -+ // verify it really is fapolicyd -+ if (get_program_from_pid(pid, -+ sizeof(exe_buf), exe_buf) == NULL) -+ goto good; //if pid doesn't exist, we're OK -+ -+ // If the path doesn't have fapolicyd in it, we're OK -+ if (strstr(exe_buf, "fapolicyd") == NULL) -+ goto good; -+ -+ if (strcmp(exe_buf, my_path) == 0) -+ goto err_out; // if the same, we need to exit -+ -+ // one last sanity check in case path is unexpected -+ // for example: /sbin/fapolicyd & /home/test/fapolicyd -+ if (pid != getpid()) -+ goto err_out; -+good: -+ close(pidfd); -+ unlink(pidfile); -+ return 0; -+ } else -+ msg(LOG_ERR, "fapolicyd pid file found but unreadable"); -+err_out: // At this point, we have a pid file, let's just assume it's alive -+ // because if 2 are running, it deadlocks the machine -+ close(pidfd); -+ return 1; -+ } -+ return 0; // pid file doesn't exist, we're good to go -+} -+ -+ - int main(int argc, const char *argv[]) - { - struct pollfd pfd[2]; -@@ -428,6 +480,11 @@ int main(int argc, const char *argv[]) - } - } - -+ if (already_running()) { -+ msg(LOG_ERR, "fapolicyd is already running"); -+ exit(1); -+ } -+ - // Set a couple signal handlers - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); -@@ -446,9 +503,6 @@ int main(int argc, const char *argv[]) - setrlimit(RLIMIT_FSIZE, &limit); - setrlimit(RLIMIT_NOFILE, &limit); - -- // Set strict umask -- (void) umask( 0117 ); -- - // get more time slices because everything is waiting on us - rc = nice(-config.nice_val); - if (rc == -1) -@@ -473,17 +527,20 @@ int main(int argc, const char *argv[]) - exit(1); - } - -- if (preconstruct_fifo(&config)) { -- msg(LOG_ERR, "Cannot contruct a pipe"); -- exit(1); -- } -- - // Setup filesystem to watch list - init_fs_list(config.watch_fs); - - // Write the pid file for the init system - write_pid_file(); - -+ // Set strict umask -+ (void) umask( 0117 ); -+ -+ if (preconstruct_fifo(&config)) { -+ msg(LOG_ERR, "Cannot contruct a pipe"); -+ exit(1); -+ } -+ - // If we are not going to be root, then setup necessary capabilities - if (config.uid != 0) { - capng_clear(CAPNG_SELECT_BOTH); diff --git a/SOURCES/fapolicyd-cli-segfault.patch b/SOURCES/fapolicyd-cli-segfault.patch deleted file mode 100644 index 45c4699..0000000 --- a/SOURCES/fapolicyd-cli-segfault.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -up ./src/cli/fapolicyd-cli.c.segfault ./src/cli/fapolicyd-cli.c ---- ./src/cli/fapolicyd-cli.c.segfault 2022-08-03 17:51:54.903081124 +0200 -+++ ./src/cli/fapolicyd-cli.c 2022-08-03 17:55:18.256458750 +0200 -@@ -77,6 +77,7 @@ static struct option long_opts[] = - {"ftype", 1, NULL, 't'}, - {"list", 0, NULL, 'l'}, - {"update", 0, NULL, 'u'}, -+ {NULL, 0, NULL, 0 } - }; - - static const char *_pipe = "/run/fapolicyd/fapolicyd.fifo"; diff --git a/SOURCES/fapolicyd-dnf-plugin.patch b/SOURCES/fapolicyd-dnf-plugin.patch index e0cfce3..a16310f 100644 --- a/SOURCES/fapolicyd-dnf-plugin.patch +++ b/SOURCES/fapolicyd-dnf-plugin.patch @@ -1,12 +1,12 @@ -diff --color -ru a/dnf/fapolicyd-dnf-plugin.py b/dnf/fapolicyd-dnf-plugin.py ---- a/dnf/fapolicyd-dnf-plugin.py 2021-11-12 20:21:54.000000000 +0100 -+++ b/dnf/fapolicyd-dnf-plugin.py 2021-11-18 16:29:03.919237116 +0100 -@@ -8,29 +8,9 @@ +diff -up ./dnf/fapolicyd-dnf-plugin.py.fix ./dnf/fapolicyd-dnf-plugin.py +--- ./dnf/fapolicyd-dnf-plugin.py.fix 2023-06-20 13:21:21.098192421 +0200 ++++ ./dnf/fapolicyd-dnf-plugin.py 2023-06-20 13:21:46.287412300 +0200 +@@ -8,29 +8,10 @@ import sys class Fapolicyd(dnf.Plugin): name = "fapolicyd" -- pipe = "/var/run/fapolicyd/fapolicyd.fifo" -- file = None +- pipe = "/run/fapolicyd/fapolicyd.fifo" + file = None def __init__(self, base, cli): pass @@ -29,7 +29,6 @@ diff --color -ru a/dnf/fapolicyd-dnf-plugin.py b/dnf/fapolicyd-dnf-plugin.py - sys.stderr.write("fapolicy-plugin does not have write permission: " + self.pipe + "\n") - return - -- self.file.write("1") +- self.file.write("1\n") - self.file.close() + pass -Only in b/dnf: fapolicyd-dnf-plugin.py.plugin diff --git a/SOURCES/fapolicyd-exclude-list.patch b/SOURCES/fapolicyd-exclude-list.patch deleted file mode 100644 index 87d00e8..0000000 --- a/SOURCES/fapolicyd-exclude-list.patch +++ /dev/null @@ -1,1088 +0,0 @@ -From 4066d92395c18ad435ee6ff8e1da2745a68bacc1 Mon Sep 17 00:00:00 2001 -From: Radovan Sroka -Date: Fri, 24 Jun 2022 15:03:28 +0200 -Subject: [PATCH] Introduce filtering of rpmdb - -- this feature introduces very flexible filter syntax -- original filter was compiled in so this is very useful -- filter needs to keep a minimal set of files that will be excuted - on the system eventually -- all the configuration can be done in /etc/fapolicyd/rpm-filter.conf - -Signed-off-by: Radovan Sroka ---- - doc/Makefile.am | 3 +- - doc/rpm-filter.conf.5 | 63 +++++ - fapolicyd.spec | 1 + - init/Makefile.am | 2 + - init/rpm-filter.conf | 42 ++++ - src/Makefile.am | 8 +- - src/library/llist.c | 23 +- - src/library/llist.h | 1 + - src/library/rpm-backend.c | 79 ++----- - src/library/rpm-filter.c | 487 ++++++++++++++++++++++++++++++++++++++ - src/library/rpm-filter.h | 67 ++++++ - src/library/stack.c | 89 +++++++ - src/library/stack.h | 41 ++++ - 13 files changed, 837 insertions(+), 69 deletions(-) - create mode 100644 doc/rpm-filter.conf.5 - create mode 100644 init/rpm-filter.conf - create mode 100644 src/library/rpm-filter.c - create mode 100644 src/library/rpm-filter.h - create mode 100644 src/library/stack.c - create mode 100644 src/library/stack.h - -diff --git a/doc/Makefile.am b/doc/Makefile.am -index f0b79080..726218ed 100644 ---- a/doc/Makefile.am -+++ b/doc/Makefile.am -@@ -28,4 +28,5 @@ man_MANS = \ - fapolicyd-cli.1 \ - fapolicyd.rules.5 \ - fapolicyd.trust.5 \ -- fapolicyd.conf.5 -+ fapolicyd.conf.5 \ -+ rpm-filter.conf.5 -diff --git a/doc/rpm-filter.conf.5 b/doc/rpm-filter.conf.5 -new file mode 100644 -index 00000000..d415bd80 ---- /dev/null -+++ b/doc/rpm-filter.conf.5 -@@ -0,0 +1,63 @@ -+.TH RPM_FILTER.CONF: "5" "January 2023" "Red Hat" "System Administration Utilities" -+.SH NAME -+rpm-filter.conf \- fapolicyd filter configuration file -+.SH DESCRIPTION -+The file -+.I /etc/fapolicyd/rpm-filter.conf -+contains configuration of the filter for the application allowlisting daemon. This filter specifies an allow or exclude list of files from rpm. Valid line starts with character '+', '-' or '#' for comments. The rest of the line contains a path specification. Space can be used as indentation to add more specific filters to the previous one. Note, that only one space is required for one level of an indent. If there are multiple specifications on the same indentation level they extend the previous line with lower indentation, usually a directory. The path may be specified using the glob pattern. A directory specification has to end with a slash ‘/’. -+ -+The filters are processed as follows: Starting from the up the to bottom while in case of a match the result (+/-) is set unless there is an indented block which describes more detailed specification of the parent level match. The same processing logic is applied to the inner filters definitions. If there is no match, the parent’s result is set. If there is no match at all, the default result is minus (-). -+ -+If the result was a plus (+), the respective file from the rpmdb is imported to the TrustDB. Vice versa, if the result was a minus (-), the respective file is not imported. -+ -+From a performance point of view it is better to design an indented filter because in the ideal situation each component of the path is compared only once. In contrast to it, a filter without any indentation has to contain a full path which makes the pattern more complicated and thus slower to process. The motivation behind this is to have a flexible configuration and keep the TrustDB as small as possible to make the look-ups faster. -+ -+ -+ -+.nf -+.B # this is simple allow list -+.B - /usr/bin/some_binary1 -+.B - /usr/bin/some_binary2 -+.B + / -+.fi -+ -+.nf -+.B # this is the same -+.B + / -+.B \ + usr/bin/ -+.B \ \ - some_binary1 -+.B \ \ - some_binary2 -+.fi -+ -+.nf -+.B # this is similar allow list with a wildcard -+.B - /usr/bin/some_binary? -+.B + / -+.fi -+ -+.nf -+.B # this is similar with another wildcard -+.B + / -+.B \ - usr/bin/some_binary* -+.fi -+ -+.nf -+.B # keeps everything except usr/share except python and perl files -+.B # /usr/bin/ls - result is '+' -+.B # /usr/share/something - result is '-' -+.B # /usr/share/abcd.py - result is '+' -+.B + / -+.B \ - usr/share/ -+.B \ \ + *.py -+.B \ \ + *.pl -+.fi -+ -+.SH "SEE ALSO" -+.BR fapolicyd (8), -+.BR fapolicyd-cli (1) -+.BR fapolicy.rules (5) -+and -+.BR glob (7) -+ -+.SH AUTHOR -+Radovan Sroka -diff --git a/init/Makefile.am b/init/Makefile.am -index da948e4e..1f23dffe 100644 ---- a/init/Makefile.am -+++ b/init/Makefile.am -@@ -1,6 +1,7 @@ - EXTRA_DIST = \ - fapolicyd.service \ - fapolicyd.conf \ -+ rpm-filter.conf \ - fapolicyd.trust \ - fapolicyd-tmpfiles.conf \ - fapolicyd-magic \ -@@ -11,6 +12,7 @@ fapolicyddir = $(sysconfdir)/fapolicyd - - dist_fapolicyd_DATA = \ - fapolicyd.conf \ -+ rpm-filter.conf \ - fapolicyd.trust - - systemdservicedir = $(systemdsystemunitdir) -diff --git a/init/rpm-filter.conf b/init/rpm-filter.conf -new file mode 100644 -index 00000000..0c8fca40 ---- /dev/null -+++ b/init/rpm-filter.conf -@@ -0,0 +1,42 @@ -+# default filter file for fedora -+ -++ / -+ - usr/include/ -+ - usr/share/ -+ # Python byte code -+ + *.py? -+ # Python text files -+ + *.py -+ # Some apps have a private libexec -+ + */libexec/* -+ # Ruby -+ + *.rb -+ # Perl -+ + *.pl -+ # System tap -+ + *.stp -+ # Javascript -+ + *.js -+ # Java archive -+ + *.jar -+ # M4 -+ + *.m4 -+ # PHP -+ + *.php -+ # Perl Modules -+ + *.pm -+ # Lua -+ + *.lua -+ # Java -+ + *.class -+ # Typescript -+ + *.ts -+ # Typescript JSX -+ + *.tsx -+ # Lisp -+ + *.el -+ # Compiled Lisp -+ + *.elc -+ - usr/src/kernel*/ -+ + */scripts/* -+ + */tools/objtool/* -diff --git a/src/Makefile.am b/src/Makefile.am -index 547ea486..fd08eb06 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -62,13 +62,19 @@ libfapolicyd_la_SOURCES = \ - library/subject-attr.h \ - library/subject.c \ - library/subject.h \ -+ library/stack.c \ -+ library/stack.h \ - library/string-util.c \ - library/string-util.h \ - library/trust-file.c \ - library/trust-file.h - - if WITH_RPM --libfapolicyd_la_SOURCES += library/rpm-backend.c -+libfapolicyd_la_SOURCES += \ -+ library/rpm-backend.c \ -+ library/rpm-filter.c \ -+ library/rpm-filter.h -+ - endif - - libfapolicyd_la_CFLAGS = $(fapolicyd_CFLAGS) -diff --git a/src/library/llist.c b/src/library/llist.c -index 6132805a..44cfb4a3 100644 ---- a/src/library/llist.c -+++ b/src/library/llist.c -@@ -45,19 +45,36 @@ list_item_t *list_get_first(const list_t *list) - return list->first; - } - -- --int list_append(list_t *list, const char *index, const char *data) -+static list_item_t * create_item(const char *index, const char *data) - { - list_item_t *item = malloc(sizeof(list_item_t)); - if (!item) { - msg(LOG_ERR, "Malloc failed"); -- return 1; -+ return item; - } - - item->index = index; - item->data = data; - item->next = NULL; - -+ return item; -+} -+ -+int list_prepend(list_t *list, const char *index, const char *data) -+{ -+ list_item_t *item = create_item(index, data); -+ -+ item->next = list->first; -+ list->first = item; -+ -+ ++list->count; -+ return 0; -+} -+ -+int list_append(list_t *list, const char *index, const char *data) -+{ -+ list_item_t *item = create_item(index, data); -+ - if (list->first) { - list->last->next = item; - list->last = item; -diff --git a/src/library/llist.h b/src/library/llist.h -index 0c1d85a7..59eccf17 100644 ---- a/src/library/llist.h -+++ b/src/library/llist.h -@@ -40,6 +40,7 @@ typedef struct list_header { - - void list_init(list_t *list); - list_item_t *list_get_first(const list_t *list); -+int list_prepend(list_t *list, const char *index, const char *data); - int list_append(list_t *list, const char *index, const char *data); - void list_destroy_item(list_item_t **item); - void list_empty(list_t *list); -diff --git a/src/library/rpm-backend.c b/src/library/rpm-backend.c -index 7f1af438..0887d36a 100644 ---- a/src/library/rpm-backend.c -+++ b/src/library/rpm-backend.c -@@ -40,6 +40,8 @@ - #include "fapolicyd-backend.h" - #include "llist.h" - -+#include "rpm-filter.h" -+ - static int rpm_init_backend(void); - static int rpm_load_list(const conf_t *); - static int rpm_destroy_backend(void); -@@ -176,69 +178,6 @@ static void close_rpm(void) - rpmlogClose(); - } - --// This function will check a passed file name to see if the path should --// be kept or dropped. 1 means discard it, and 0 means keep it. --static int drop_path(const char *file_name) --{ -- const char *p = file_name; -- if (!strncmp(p, "/usr", 4)) { -- p += 4; -- -- // Drop anything in /usr/include -- if (!strncmp(p, "/include", 8)) -- return 1; -- -- // Only keep languages from /usr/share -- if (!strncmp(p, "/share", 6)) { -- p += 6; -- -- // These are roughly ordered by quantity -- static const char *arr_share[] = { -- "*.py?", // Python byte code -- "*.py", // Python text files -- "*/libexec/*", // Some apps have a private libexec -- "*.rb", // Ruby -- "*.pl", // Perl -- "*.stp", // System tap -- "*.js", // Javascript -- "*.jar", // Java archive -- "*.m4", // M4 -- "*.php", // PHP -- "*.pm", // Perl Modules -- "*.lua", // Lua -- "*.class", // Java -- "*.ts", // Typescript -- "*.tsx", // Typescript JSX -- "*.el", // Lisp -- "*.elc", // Compiled Lisp -- NULL -- }; -- -- for (int i = 0; arr_share[i]; ++i) -- if (!fnmatch(arr_share[i], p, 0)) -- return 0; -- return 1; -- } -- -- // Akmod needs scripts in /usr/src/kernel -- if (!strncmp(p, "/src/kernel", 11)) { -- p += 11; -- -- static const char *arr_src_kernel[] = { -- "*/scripts/*", -- "*/tools/objtool/*", -- NULL -- }; -- -- for (int i = 0; arr_src_kernel[i]; ++i) -- if (!fnmatch(arr_src_kernel[i], p, 0)) -- return 0; -- return 1; -- } -- } -- return 0; --} -- - struct _hash_record { - const char * key; - UT_hash_handle hh; -@@ -290,7 +229,8 @@ static int rpm_load_list(const conf_t *conf) - if (file_name == NULL) - continue; - -- if (drop_path(file_name)) { -+ // should we drop a path? -+ if (!filter_check(file_name)) { - free((void *)file_name); - free((void *)sha); - continue; -@@ -358,12 +298,23 @@ static int rpm_load_list(const conf_t *conf) - - static int rpm_init_backend(void) - { -+ if (filter_init()) -+ return 1; -+ -+ if (filter_load_file()) { -+ filter_destroy(); -+ return 1; -+ } -+ -+ - list_init(&rpm_backend.list); -+ - return 0; - } - - static int rpm_destroy_backend(void) - { -+ filter_destroy(); - list_empty(&rpm_backend.list); - return 0; - } -diff --git a/src/library/rpm-filter.c b/src/library/rpm-filter.c -new file mode 100644 -index 00000000..e3e3eb38 ---- /dev/null -+++ b/src/library/rpm-filter.c -@@ -0,0 +1,487 @@ -+/* -+* rpm-filter.c - filter for rpm trust source -+* Copyright (c) 2023 Red Hat Inc., Durham, North Carolina. -+* 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: -+* Radovan Sroka -+*/ -+ -+#include "rpm-filter.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "llist.h" -+#include "stack.h" -+#include "message.h" -+#include "string-util.h" -+ -+ -+#define RPM_FILTER_FILE "/etc/fapolicyd/rpm-filter.conf" -+ -+rpm_filter_t *global_filter = NULL; -+ -+static rpm_filter_t *filter_create_obj(void); -+static void filter_destroy_obj(rpm_filter_t *_filter); -+ -+// init fuction of this module -+int filter_init(void) -+{ -+ global_filter = filter_create_obj(); -+ if (global_filter == NULL) -+ return 1; -+ -+ return 0; -+} -+ -+// destroy funtion of this module -+void filter_destroy(void) -+{ -+ filter_destroy_obj(global_filter); -+ global_filter = NULL; -+} -+ -+// alocate new filter object and fill with the defaults -+static rpm_filter_t *filter_create_obj(void) -+{ -+ rpm_filter_t *filter = malloc(sizeof(rpm_filter_t)); -+ if (filter) { -+ filter->type = NONE; -+ filter->path = NULL; -+ filter->len = 0; -+ filter->matched = 0; -+ filter->processed = 0; -+ list_init(&filter->list); -+ } -+ return filter; -+} -+ -+// free all nested filters -+static void filter_destroy_obj(rpm_filter_t *_filter) -+{ -+ if (_filter == NULL) -+ return; -+ -+ rpm_filter_t *filter = _filter; -+ stack_t stack; -+ stack_init(&stack); -+ -+ stack_push(&stack, filter); -+ -+ while (!stack_is_empty(&stack)) { -+ filter = (rpm_filter_t*)stack_top(&stack); -+ if (filter->processed) { -+ (void)free(filter->path); -+ // asume that item->data is NULL -+ list_empty(&filter->list); -+ (void)free(filter); -+ stack_pop(&stack); -+ continue; -+ } -+ -+ list_item_t *item = list_get_first(&filter->list); -+ for (; item != NULL ; item = item->next) { -+ rpm_filter_t *next_filter = (rpm_filter_t*)item->data; -+ // we can use list_empty() later -+ // we dont want to free filter right now -+ // it will freed after popping -+ item->data = NULL; -+ stack_push(&stack, next_filter); -+ } -+ filter->processed = 1; -+ } -+ stack_destroy(&stack); -+} -+ -+// create struct and push it to the top of stack -+static void stack_push_vars(stack_t *_stack, int _level, int _offset, rpm_filter_t *_filter) -+{ -+ if (_stack == NULL) -+ return; -+ -+ stack_item_t *item = malloc(sizeof(stack_item_t)); -+ if (item == NULL) -+ return; -+ -+ item->level = _level; -+ item->offset = _offset; -+ item->filter = _filter; -+ -+ stack_push(_stack, item); -+} -+ -+// pop stack_item_t and free it -+static void stack_pop_vars(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ stack_item_t * item = (stack_item_t*)stack_top(_stack); -+ free(item); -+ stack_pop(_stack); -+} -+ -+// pop all the stack_item_t and free them -+static void stack_pop_all_vars(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ while (!stack_is_empty(_stack)) -+ stack_pop_vars(_stack); -+} -+ -+// reset filter to default, pop top and free -+static void stack_pop_reset(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ stack_item_t *stack_item = (stack_item_t*)stack_top(_stack); -+ if (stack_item) { -+ stack_item->filter->matched = 0; -+ stack_item->filter->processed = 0; -+ } -+ free(stack_item); -+ stack_pop(_stack); -+} -+ -+// reset and pop all the stack_item_t -+static void stack_pop_all_reset(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ while (!stack_is_empty(_stack)) -+ stack_pop_reset(_stack); -+} -+ -+// this funtion gets full path and checks it against filter -+// returns 1 for keeping the file and 0 for dropping it -+int filter_check(const char *_path) -+{ -+ if (_path == NULL) { -+ msg(LOG_ERR, "filter_check: path is NULL, something is wrong!"); -+ return 0; -+ } -+ -+ rpm_filter_t *filter = global_filter; -+ char *path = strdup(_path); -+ size_t path_len = strlen(_path); -+ size_t offset = 0; -+ // Create a stack to store the filters that need to be checked -+ stack_t stack; -+ stack_init(&stack); -+ -+ int res = 0; -+ int level = 0; -+ -+ stack_push_vars(&stack, level, offset, filter); -+ -+ while(!stack_is_empty(&stack)) { -+ int matched = 0; -+ filter->processed = 1; -+ -+ // this is starting branch of the algo -+ // assuming that in root filter filter->path is NULL -+ if (filter->path == NULL) { -+ list_item_t *item = list_get_first(&filter->list); -+ // push all the descendants to the stack -+ for (; item != NULL ; item = item->next) { -+ rpm_filter_t *next_filter = (rpm_filter_t*)item->data; -+ stack_push_vars(&stack, level+1, offset, next_filter); -+ } -+ -+ // usual branch, start with processing -+ } else { -+ // wildcard contition -+ char *is_wildcard = strpbrk(filter->path, "?*["); -+ if (is_wildcard) { -+ int count = 0; -+ char *filter_lim, *filter_old_lim; -+ filter_lim = filter_old_lim = filter->path; -+ -+ char *path_lim, *path_old_lim; -+ path_lim = path_old_lim = path+offset; -+ -+ // there can be wildcard in the dir name as well -+ // we need to count how many chars can be eaten by wildcard -+ while(1) { -+ filter_lim = strchr(filter_lim, '/'); -+ path_lim = strchr(path_lim, '/'); -+ -+ if (filter_lim) { -+ count++; -+ filter_old_lim = filter_lim; -+ filter_lim++; -+ } else -+ break; -+ -+ if (path_lim) { -+ path_old_lim = path_lim; -+ path_lim++; -+ } else -+ break; -+ -+ } -+ // put 0 after the last / -+ char tmp = '\0'; -+ if (count && *(filter_old_lim+1) == '\0') { -+ tmp = *(path_old_lim+1); -+ *(path_old_lim+1) = '\0'; -+ } -+ -+ // check fnmatch -+ matched = !fnmatch(filter->path, path+offset, 0); -+ -+ // and set back -+ if (count && *(filter_old_lim+1) == '\0') -+ *(path_old_lim+1) = tmp; -+ -+ if (matched) { -+ offset = path_old_lim - path+offset; -+ } -+ } else { -+ // match normal path or just specific part of it -+ matched = !strncmp(path+offset, filter->path, filter->len); -+ if (matched) -+ offset += filter->len; -+ } -+ -+ if (matched) { -+ level++; -+ filter->matched = 1; -+ -+ // if matched we need ot push descendants to the stack -+ list_item_t *item = list_get_first(&filter->list); -+ -+ // if there are no descendants and it is a wildcard then it's a match -+ if (item == NULL && is_wildcard) { -+ // if '+' ret 1 and if '-' ret 0 -+ res = filter->type == ADD ? 1 : 0; -+ goto end; -+ } -+ -+ // no descendants, and already compared whole path string so its a match -+ if (item == NULL && path_len == offset) { -+ // if '+' ret 1 and if '-' ret 0 -+ res = filter->type == ADD ? 1 : 0; -+ goto end; -+ } -+ -+ // push descendants to the stack -+ for (; item != NULL ; item = item->next) { -+ rpm_filter_t *next_filter = (rpm_filter_t*)item->data; -+ stack_push_vars(&stack, level, offset, next_filter); -+ } -+ -+ } -+ -+ } -+ -+ stack_item_t * stack_item = NULL; -+ // popping processed filters from the top of the stack -+ do { -+ if (stack_item) { -+ filter = stack_item->filter; -+ offset = stack_item->offset; -+ level = stack_item->level; -+ -+ // assuimg that nothing has matched on the upper level so it's a directory match -+ if (filter->matched && filter->path[filter->len-1] == '/') { -+ res = filter->type == ADD ? 1 : 0; -+ goto end; -+ } -+ -+ // reset processed flag -+ stack_pop_reset(&stack); -+ } -+ -+ stack_item = (stack_item_t*)stack_top(&stack); -+ } while(stack_item && stack_item->filter->processed); -+ -+ if (!stack_item) -+ break; -+ -+ filter = stack_item->filter; -+ offset = stack_item->offset; -+ level = stack_item->level; -+ } -+ -+end: -+ // Clean up the stack -+ stack_pop_all_reset(&stack); -+ stack_destroy(&stack); -+ free(path); -+ return res; -+} -+ -+// load rpm filter configuration file and fill the filter structure -+int filter_load_file(void) -+{ -+ int res = 0; -+ FILE *stream = fopen(RPM_FILTER_FILE, "r"); -+ -+ if (stream == NULL) { -+ msg(LOG_ERR, "Cannot open filter file %s", RPM_FILTER_FILE); -+ return 1; -+ } -+ -+ ssize_t nread; -+ size_t len = 0; -+ char * line = NULL; -+ long line_number = 0; -+ int last_level = 0; -+ -+ stack_t stack; -+ stack_init(&stack); -+ stack_push_vars(&stack, last_level, 0, global_filter); -+ -+ while ((nread = getline(&line, &len, stream)) != -1) { -+ line_number++; -+ -+ if (line[0] == '\0' || line[0] == '\n') { -+ free(line); -+ line = NULL; -+ continue; -+ } -+ -+ // get rid of the new line char -+ char * new_line = strchr(line, '\n'); -+ if (new_line) { -+ *new_line = '\0'; -+ len--; -+ } -+ -+ int level = 1; -+ char * rest = line; -+ rpm_filter_type_t type = NONE; -+ -+ for (size_t i = 0 ; i < len ; i++) { -+ switch (line[i]) { -+ case ' ': -+ level++; -+ continue; -+ case '+': -+ type = ADD; -+ break; -+ case '-': -+ type = SUB; -+ break; -+ case '#': -+ type = COMMENT; -+ break; -+ default: -+ type = BAD; -+ break; -+ } -+ -+ // continue with next char -+ // skip + and space -+ rest = fapolicyd_strtrim(&(line[i+2])); -+ break; -+ } -+ -+ // ignore comment -+ if (type == COMMENT) { -+ free(line); -+ line = NULL; -+ continue; -+ } -+ -+ // if something bad return error -+ if (type == BAD) { -+ msg(LOG_ERR, "filter_load_file: cannot parse line number %ld, \"%s\"", line_number, line); -+ free(line); -+ line = NULL; -+ goto bad; -+ } -+ -+ rpm_filter_t * filter = filter_create_obj(); -+ -+ if (filter) { -+ filter->path = strdup(rest); -+ filter->len = strlen(filter->path); -+ filter->type = type; -+ } -+ -+ // comparing level of indetantion between the last line and the current one -+ last_level = ((stack_item_t*)stack_top(&stack))->level; -+ if (level == last_level) { -+ -+ // since we are at the same level as filter before -+ // we need to pop the previous filter from the top -+ stack_pop_vars(&stack); -+ -+ // pushing filter to the list of top's children list -+ list_prepend(&((stack_item_t*)stack_top(&stack))->filter->list, NULL, (void*)filter); -+ -+ // pushing filter to the top of the stack -+ stack_push_vars(&stack, level, 0, filter); -+ -+ } else if (level == last_level + 1) { -+ // this filter has higher level tha privious one -+ // we wont do pop just push -+ -+ // pushing filter to the list of top's children list -+ list_prepend(&((stack_item_t*)stack_top(&stack))->filter->list, NULL, (void*)filter); -+ -+ // pushing filter to the top of the stack -+ stack_push_vars(&stack, level, 0, filter); -+ -+ } else if (level < last_level){ -+ // level of indentation dropped -+ // we need to pop -+ // +1 is meant for getting rid of the current level so we can again push -+ for (int i = 0 ; i < last_level - level + 1; i++) { -+ stack_pop_vars(&stack); -+ } -+ -+ // pushing filter to the list of top's children list -+ list_prepend(&((stack_item_t*)stack_top(&stack))->filter->list, NULL, (void*)filter); -+ -+ // pushing filter to the top of the stack -+ stack_push_vars(&stack, level, 0, filter); -+ -+ } else { -+ msg(LOG_ERR, "filter_load_file: paring error line: %ld, \"%s\"", line_number, line); -+ filter_destroy_obj(filter); -+ free(line); -+ goto bad; -+ } -+ -+ free(line); -+ line = NULL; -+ } -+ -+ goto good; -+bad: -+ res = 1; -+ -+good: -+ fclose(stream); -+ stack_pop_all_vars(&stack); -+ stack_destroy(&stack); -+ if (global_filter->list.count == 0) { -+ msg(LOG_ERR, "filter_load_file: no valid filter provided in %s", RPM_FILTER_FILE); -+ } -+ return res; -+} -diff --git a/src/library/rpm-filter.h b/src/library/rpm-filter.h -new file mode 100644 -index 00000000..2c49d338 ---- /dev/null -+++ b/src/library/rpm-filter.h -@@ -0,0 +1,67 @@ -+/* -+* rpm-filter.h - Header for rpm filter implementation -+* Copyright (c) 2023 Red Hat Inc., Durham, North Carolina. -+* 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: -+* Radovan Sroka -+*/ -+ -+#ifndef FILTER_H_ -+#define FILTER_H_ -+ -+#include -+#include -+ -+#include "llist.h" -+ -+typedef enum rpm_filter_type -+{ -+ NONE, -+ ADD, -+ SUB, -+ COMMENT, -+ BAD, -+} rpm_filter_type_t; -+ -+typedef struct _rpm_filter -+{ -+ rpm_filter_type_t type; -+ char * path; -+ size_t len; -+ int processed; -+ int matched; -+ list_t list; -+} rpm_filter_t; -+ -+ -+typedef struct _stack_item -+{ -+ int level; -+ int offset; -+ rpm_filter_t *filter; -+} stack_item_t; -+ -+ -+int filter_init(void); -+void filter_destroy(void); -+int filter_check(const char *_path); -+int filter_load_file(void); -+ -+ -+#endif // FILTER_H_ -diff --git a/src/library/stack.c b/src/library/stack.c -new file mode 100644 -index 00000000..93141b2c ---- /dev/null -+++ b/src/library/stack.c -@@ -0,0 +1,89 @@ -+/* -+* stack.c - generic stack impementation -+* Copyright (c) 2023 Red Hat Inc., Durham, North Carolina. -+* 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: -+* Radovan Sroka -+*/ -+ -+#include "stack.h" -+#include -+ -+// init of the stack struct -+void stack_init(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ list_init(_stack); -+} -+ -+// free all the resources from the stack -+void stack_destroy(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ list_empty(_stack); -+} -+ -+// push to the top of the stack -+void stack_push(stack_t *_stack, void *_data) -+{ -+ if (_stack == NULL) -+ return; -+ -+ list_prepend(_stack, NULL, (void *)_data); -+} -+ -+// pop the the top without returning what was on the top -+void stack_pop(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return; -+ -+ list_item_t *first = _stack->first; -+ _stack->first = first->next; -+ first->data = NULL; -+ list_destroy_item(&first); -+ _stack->count--; -+ -+ return; -+} -+ -+// function returns 1 if stack is emtpy 0 if it's not -+int stack_is_empty(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return -1; -+ -+ if (_stack->count == 0) -+ return 1; -+ -+ return 0; -+} -+ -+// return top of the stack without popping -+const void *stack_top(stack_t *_stack) -+{ -+ if (_stack == NULL) -+ return NULL; -+ -+ return _stack->first ? _stack->first->data : NULL; -+} -diff --git a/src/library/stack.h b/src/library/stack.h -new file mode 100644 -index 00000000..042476e3 ---- /dev/null -+++ b/src/library/stack.h -@@ -0,0 +1,41 @@ -+/* -+* stack.h - header for generic stack implementation -+* Copyright (c) 2023 Red Hat Inc., Durham, North Carolina. -+* 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: -+* Radovan Sroka -+*/ -+ -+ -+#ifndef STACK_H_ -+#define STACK_H_ -+ -+#include "llist.h" -+ -+typedef list_t stack_t; -+ -+void stack_init(stack_t *_stack); -+void stack_destroy(stack_t *_stack); -+void stack_push(stack_t *_stack, void *_data); -+void stack_pop(stack_t *_stack); -+int stack_is_empty(stack_t *_stack); -+const void *stack_top(stack_t *_stack); -+ -+ -+#endif // STACK_H_ diff --git a/SOURCES/fapolicyd-falcon-sensor.patch b/SOURCES/fapolicyd-falcon-sensor.patch deleted file mode 100644 index ed7ff43..0000000 --- a/SOURCES/fapolicyd-falcon-sensor.patch +++ /dev/null @@ -1,74 +0,0 @@ -diff -up ./src/library/event.c.event ./src/library/event.c ---- ./src/library/event.c.event 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/library/event.c 2022-12-22 13:12:58.226816235 +0100 -@@ -132,7 +132,15 @@ int new_event(const struct fanotify_even - if ((s->info->state == STATE_COLLECTING) && - (e->type & FAN_OPEN_PERM) && !rc) { - skip_path = 1; -+ - s->info->state = STATE_REOPEN; -+ -+ // special branch after ld_so exec -+ // next opens will go fall trough -+ if (s->info->path1 && -+ (strcmp(s->info->path1, SYSTEM_LD_SO) == 0)) -+ s->info->state = STATE_DEFAULT_REOPEN; -+ - } - - // If not same proc or we detect execution, evict -@@ -149,7 +157,6 @@ int new_event(const struct fanotify_even - skip_path = 1; - } - evict = 0; -- skip_path = 1; - subject_reset(s, EXE); - subject_reset(s, COMM); - subject_reset(s, EXE_TYPE); -@@ -165,6 +172,7 @@ int new_event(const struct fanotify_even - skip_path = 1; - } - -+ - // If we've seen the reopen and its an execute and process - // has an interpreter and we're the same process, don't evict - // and don't collect the path since reopen interp will. The -@@ -173,14 +181,25 @@ int new_event(const struct fanotify_even - if ((s->info->state == STATE_REOPEN) && !skip_path && - (e->type & FAN_OPEN_EXEC_PERM) && - (s->info->elf_info & HAS_INTERP) && !rc) { -+ s->info->state = STATE_DEFAULT_REOPEN; - evict = 0; - skip_path = 1; - } - -+ -+ // this is what differs between STATE_REOPEN and -+ // STATE_DEFAULT_REOPEN -+ // in STATE_REOPEN path is always skipped -+ if ((s->info->state == STATE_REOPEN) && !skip_path && -+ (e->type & FAN_OPEN_PERM) && !rc) { -+ skip_path = 1; -+ } -+ - if (evict) { - lru_evict(subj_cache, key); - q_node = check_lru_cache(subj_cache, key); - s = (s_array *)q_node->item; -+ - } else if (s->cnt == 0) - msg(LOG_DEBUG, "cached subject has cnt of 0"); - } -diff -up ./src/library/process.h.event ./src/library/process.h ---- ./src/library/process.h.event 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/library/process.h 2022-12-22 13:10:23.260996771 +0100 -@@ -31,7 +31,8 @@ - #include "gcc-attributes.h" - - typedef enum { STATE_COLLECTING=0, // initial state - execute -- STATE_REOPEN, // anticipating open perm next -+ STATE_REOPEN, // anticipating open perm next, always skips the path -+ STATE_DEFAULT_REOPEN, // reopen after dyn. linker exec, never skips the path - STATE_STATIC_REOPEN, // static app aniticipating - STATE_PARTIAL, // second path collected - STATE_STATIC_PARTIAL, // second path collected diff --git a/SOURCES/fapolicyd-fgets-update-thread.patch b/SOURCES/fapolicyd-fgets-update-thread.patch deleted file mode 100644 index bd8d8ec..0000000 --- a/SOURCES/fapolicyd-fgets-update-thread.patch +++ /dev/null @@ -1,215 +0,0 @@ -diff -up ./src/cli/fapolicyd-cli.c.upgrade-thread ./src/cli/fapolicyd-cli.c ---- ./src/cli/fapolicyd-cli.c.upgrade-thread 2022-08-03 18:00:02.374999369 +0200 -+++ ./src/cli/fapolicyd-cli.c 2022-08-03 18:00:09.802830497 +0200 -@@ -482,7 +482,7 @@ static int do_update(void) - } - } - -- ssize_t ret = write(fd, "1", 2); -+ ssize_t ret = write(fd, "1\n", 3); - - if (ret == -1) { - fprintf(stderr, "Write: %s -> %s\n", _pipe, strerror(errno)); -diff -up ./src/library/database.c.upgrade-thread ./src/library/database.c ---- ./src/library/database.c.upgrade-thread 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/library/database.c 2022-08-03 17:58:04.034689808 +0200 -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -43,6 +44,7 @@ - #include "message.h" - #include "llist.h" - #include "file.h" -+#include "fd-fgets.h" - - #include "fapolicyd-backend.h" - #include "backend-manager.h" -@@ -1181,6 +1183,7 @@ static void *update_thread_main(void *ar - return NULL; - } - -+ fcntl(ffd[0].fd, F_SETFL, O_NONBLOCK); - ffd[0].events = POLLIN; - - while (!stop) { -@@ -1200,97 +1203,102 @@ static void *update_thread_main(void *ar - } else { - msg(LOG_ERR, "Update poll error (%s)", - strerror_r(errno, err_buff, BUFFER_SIZE)); -- goto err_out; -+ goto finalize; - } - } else if (rc == 0) { - #ifdef DEBUG - msg(LOG_DEBUG, "Update poll timeout expired"); - #endif -- if (db_operation != DB_NO_OP) -- goto handle_db_ops; - continue; - } else { - if (ffd[0].revents & POLLIN) { -- ssize_t count = read(ffd[0].fd, buff, -- BUFFER_SIZE-1); - -- if (count == -1) { -- msg(LOG_ERR, -- "Failed to read from a pipe %s (%s)", -- fifo_path, -- strerror_r(errno, err_buff, -- BUFFER_SIZE)); -- goto err_out; -- } -+ do { -+ fd_fgets_rewind(); -+ int res = fd_fgets(buff, sizeof(buff), ffd[0].fd); - -- if (count == 0) { --#ifdef DEBUG -- msg(LOG_DEBUG, -- "Buffer contains zero bytes!"); --#endif -- continue; -- } else // Manually terminate buff -- buff[count] = 0; --#ifdef DEBUG -- msg(LOG_DEBUG, "Buffer contains: \"%s\"", buff); --#endif -- for (int i = 0 ; i < count ; i++) { -- // assume file name -- // operation = 0 -- if (buff[i] == '/') { -- db_operation = ONE_FILE; -+ // nothing to read -+ if (res == -1) - break; -- } -+ else if (res > 0) { -+ char* end = strchr(buff, '\n'); - -- if (buff[i] == '1') { -- db_operation = RELOAD_DB; -- break; -+ if (end == NULL) { -+ msg(LOG_ERR, "Too long line?"); -+ continue; -+ } -+ -+ int count = end - buff; -+ -+ *end = '\0'; -+ -+ for (int i = 0 ; i < count ; i++) { -+ // assume file name -+ // operation = 0 -+ if (buff[i] == '/') { -+ db_operation = ONE_FILE; -+ break; -+ } -+ -+ if (buff[i] == '1') { -+ db_operation = RELOAD_DB; -+ break; -+ } -+ -+ if (buff[i] == '2') { -+ db_operation = FLUSH_CACHE; -+ break; -+ } -+ -+ if (isspace(buff[i])) -+ continue; -+ -+ msg(LOG_ERR, "Cannot handle data \"%s\" from pipe", buff); -+ break; -+ } -+ -+ *end = '\n'; -+ -+ // got "1" -> reload db -+ if (db_operation == RELOAD_DB) { -+ db_operation = DB_NO_OP; -+ msg(LOG_INFO, -+ "It looks like there was an update of the system... Syncing DB."); -+ -+ backend_close(); -+ backend_init(config); -+ backend_load(config); -+ -+ if ((rc = update_database(config))) { -+ msg(LOG_ERR, -+ "Cannot update trust database!"); -+ close(ffd[0].fd); -+ backend_close(); -+ unlink_fifo(); -+ exit(rc); -+ } -+ -+ msg(LOG_INFO, "Updated"); -+ -+ // Conserve memory -+ backend_close(); -+ // got "2" -> flush cache -+ } else if (db_operation == FLUSH_CACHE) { -+ db_operation = DB_NO_OP; -+ needs_flush = true; -+ } else if (db_operation == ONE_FILE) { -+ db_operation = DB_NO_OP; -+ if (handle_record(buff)) -+ continue; -+ } - } - -- if (buff[i] == '2') { -- db_operation = FLUSH_CACHE; -- break; -- } -- } -- --handle_db_ops: -- // got "1" -> reload db -- if (db_operation == RELOAD_DB) { -- db_operation = DB_NO_OP; -- msg(LOG_INFO, -- "It looks like there was an update of the system... Syncing DB."); -- -- backend_close(); -- backend_init(config); -- backend_load(config); -- -- if ((rc = update_database(config))) { -- msg(LOG_ERR, -- "Cannot update trust database!"); -- close(ffd[0].fd); -- backend_close(); -- unlink_fifo(); -- exit(rc); -- } else -- msg(LOG_INFO, "Updated"); -- -- // Conserve memory -- backend_close(); -- // got "2" -> flush cache -- } else if (db_operation == FLUSH_CACHE) { -- db_operation = DB_NO_OP; -- needs_flush = true; -- } else if (db_operation == ONE_FILE) { -- db_operation = DB_NO_OP; -- if (handle_record(buff)) -- continue; -- } -+ } while(!fd_fgets_eof()); - } - } -- - } - --err_out: -+finalize: - close(ffd[0].fd); - unlink_fifo(); - diff --git a/SOURCES/fapolicyd-leaks.patch b/SOURCES/fapolicyd-leaks.patch new file mode 100644 index 0000000..dc6f8e2 --- /dev/null +++ b/SOURCES/fapolicyd-leaks.patch @@ -0,0 +1,78 @@ +From 248219377a034d7da9238e7424c97558395700e3 Mon Sep 17 00:00:00 2001 +From: Radovan Sroka +Date: Tue, 18 Jul 2023 17:05:11 +0200 +Subject: [PATCH] Fix multiple leaks + +Signed-off-by: Radovan Sroka +--- + src/library/filter.c | 3 +++ + src/library/policy.c | 13 +++++++++++-- + src/library/rules.c | 3 --- + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/src/library/filter.c b/src/library/filter.c +index d5d8cca..eb378ca 100644 +--- a/src/library/filter.c ++++ b/src/library/filter.c +@@ -472,9 +472,12 @@ int filter_load_file(void) + msg(LOG_ERR, "filter_load_file: paring error line: %ld, \"%s\"", line_number, line); + filter_destroy_obj(filter); + free(line); ++ line = NULL; + goto bad; + } ++ } + ++ if (line) { + free(line); + line = NULL; + } +diff --git a/src/library/policy.c b/src/library/policy.c +index 7fe1210..31ff6e2 100644 +--- a/src/library/policy.c ++++ b/src/library/policy.c +@@ -23,6 +23,7 @@ + * Radovan Sroka + */ + ++#include "attr-sets.h" + #include "config.h" + #include + #include +@@ -273,12 +274,20 @@ int load_rules(const conf_t *_config) + return 1; + + FILE * f = open_file(); +- if (f == NULL) ++ if (f == NULL) { ++ destroy_attr_sets(); + return 1; ++ } + + int res = _load_rules(_config, f); + fclose(f); +- return res; ++ ++ if (res) { ++ destroy_attr_sets(); ++ return 1; ++ } ++ ++ return 0; + } + + void destroy_rules(void) +diff --git a/src/library/rules.c b/src/library/rules.c +index 5ffa40e..4a8b098 100644 +--- a/src/library/rules.c ++++ b/src/library/rules.c +@@ -65,9 +65,6 @@ int rules_create(llist *l) + l->cur = NULL; + l->cnt = 0; + +- if (init_attr_sets()) +- return 1; +- + return 0; + } + diff --git a/SOURCES/fapolicyd-librpm-workaround.patch b/SOURCES/fapolicyd-librpm-workaround.patch new file mode 100644 index 0000000..ab00e7e --- /dev/null +++ b/SOURCES/fapolicyd-librpm-workaround.patch @@ -0,0 +1,93 @@ +diff -up ./src/daemon/fapolicyd.c.librpm-workaround ./src/daemon/fapolicyd.c +--- ./src/daemon/fapolicyd.c.librpm-workaround 2023-07-10 11:19:19.507044648 +0200 ++++ ./src/daemon/fapolicyd.c 2023-07-10 11:19:19.509044621 +0200 +@@ -572,7 +572,7 @@ int main(int argc, const char *argv[]) + capng_clear(CAPNG_SELECT_BOTH); + capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_DAC_OVERRIDE, CAP_SYS_ADMIN, CAP_SYS_PTRACE, +- CAP_SYS_NICE, CAP_SYS_RESOURCE, CAP_AUDIT_WRITE, -1); ++ CAP_SYS_NICE, CAP_SYS_RESOURCE, CAP_AUDIT_WRITE, CAP_CHOWN, -1); + if (capng_change_id(config.uid, config.gid, + CAPNG_DROP_SUPP_GRP)) { + msg(LOG_ERR, "Cannot change to uid %d", config.uid); +diff -up ./src/library/rpm-backend.c.librpm-workaround ./src/library/rpm-backend.c +--- ./src/library/rpm-backend.c.librpm-workaround 2023-06-15 16:45:14.000000000 +0200 ++++ ./src/library/rpm-backend.c 2023-07-10 11:22:07.066794595 +0200 +@@ -32,7 +32,12 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + ++#include + #include + + #include "message.h" +@@ -59,6 +64,50 @@ backend rpm_backend = + static rpmts ts = NULL; + static rpmdbMatchIterator mi = NULL; + ++static void fix_files(void) ++{ ++ glob_t glob_result; ++ const char *pattern = "/var/lib/rpm/__*"; ++ ++ struct passwd * usr = getpwnam("fapolicyd"); ++ if (usr == NULL) { ++ return; ++ } ++ ++ struct group * grp = getgrnam("fapolicyd"); ++ if (grp == NULL) { ++ return; ++ } ++ ++ int return_value = glob(pattern, 0, NULL, &glob_result); ++ if (return_value != 0) { ++ return; ++ } ++ ++ for (int i = 0; i < glob_result.gl_pathc; ++i) { ++ ++ int fd = open(glob_result.gl_pathv[i], O_NOFOLLOW); ++ ++ if (fd == -1) ++ continue; ++ ++ struct stat file_stat; ++ if (fstat(fd, &file_stat) != 0) { ++ continue; ++ } ++ ++ if (file_stat.st_uid == usr->pw_uid && ++ file_stat.st_gid == grp->gr_gid) { ++ ++ fchown(fd, 0, 0); ++ } ++ ++ close(fd); ++ } ++ ++ globfree(&glob_result); ++} ++ + static int init_rpm(void) + { + return rpmReadConfigFiles ((const char *)NULL, (const char *)NULL); +@@ -201,8 +250,13 @@ static int rpm_load_list(const conf_t *c + return rc; + } + ++ int fixed = 0; + // Loop across the rpm database + while (get_next_package_rpm()) { ++ if (!fixed) { ++ fixed = 1; ++ fix_files(); ++ } + // Loop across the packages + while (get_next_file_rpm()) { + // We do not want directories or symlinks in the diff --git a/SOURCES/fapolicyd-openssl.patch b/SOURCES/fapolicyd-openssl.patch deleted file mode 100644 index 9ef8ea2..0000000 --- a/SOURCES/fapolicyd-openssl.patch +++ /dev/null @@ -1,195 +0,0 @@ -diff -up ./BUILD.md.openssl ./BUILD.md ---- ./BUILD.md.openssl 2022-06-21 16:55:47.000000000 +0200 -+++ ./BUILD.md 2022-08-02 14:10:48.092466542 +0200 -@@ -16,7 +16,8 @@ BUILD-TIME DEPENDENCIES (fedora and RHEL - * libudev-devel - * kernel-headers - * systemd-devel --* libgcrypt-devel -+* libgcrypt-devel ( <= fapolicyd-1.1.3) -+* openssl ( >= fapolicyd-1.1.4) - * rpm-devel (optional) - * file - * file-devel -diff -U0 ./ChangeLog.openssl ./ChangeLog -diff -up ./configure.ac.openssl ./configure.ac ---- ./configure.ac.openssl 2022-06-21 16:55:47.000000000 +0200 -+++ ./configure.ac 2022-08-02 14:10:48.092466542 +0200 -@@ -87,7 +87,7 @@ AC_CHECK_HEADER(uthash.h, , [AC_MSG_ERRO - echo . - echo Checking for required libraries - AC_CHECK_LIB(udev, udev_device_get_devnode, , [AC_MSG_ERROR([libudev not found])], -ludev) --AC_CHECK_LIB(gcrypt, gcry_md_open, , [AC_MSG_ERROR([libgcrypt not found])], -lgcrypt) -+AC_CHECK_LIB(crypto, SHA256, , [AC_MSG_ERROR([openssl libcrypto not found])], -lcrypto) - AC_CHECK_LIB(magic, magic_descriptor, , [AC_MSG_ERROR([libmagic not found])], -lmagic) - AC_CHECK_LIB(cap-ng, capng_change_id, , [AC_MSG_ERROR([libcap-ng not found])], -lcap-ng) - AC_CHECK_LIB(seccomp, seccomp_rule_add, , [AC_MSG_ERROR([libseccomp not found])], -lseccomp) -diff -up ./fapolicyd.spec.openssl ./fapolicyd.spec ---- ./fapolicyd.spec.openssl 2022-06-21 16:55:47.000000000 +0200 -+++ ./fapolicyd.spec 2022-08-02 14:10:48.092466542 +0200 -@@ -8,7 +8,7 @@ Source0: https://people.redhat.com/sgrub - BuildRequires: gcc - BuildRequires: kernel-headers - BuildRequires: autoconf automake make gcc libtool --BuildRequires: systemd-devel libgcrypt-devel rpm-devel file-devel file -+BuildRequires: systemd-devel openssl-devel rpm-devel file-devel file - BuildRequires: libcap-ng-devel libseccomp-devel lmdb-devel - BuildRequires: python3-devel - BuildRequires: uthash-devel -diff -up ./src/cli/fapolicyd-cli.c.openssl ./src/cli/fapolicyd-cli.c ---- ./src/cli/fapolicyd-cli.c.openssl 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/cli/fapolicyd-cli.c 2022-08-02 14:10:48.093466520 +0200 -@@ -39,7 +39,6 @@ - #include - #include - #include --#include - #include "policy.h" - #include "database.h" - #include "file-cli.h" -@@ -670,11 +669,6 @@ static int check_trustdb(void) - if (rc) - return 1; - -- // Initialize libgcrypt -- gcry_check_version(NULL); -- gcry_control(GCRYCTL_DISABLE_SECMEM, 0); -- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); -- - do { - unsigned int tsource; // unused - off_t size; -diff -up ./src/library/database.c.openssl ./src/library/database.c ---- ./src/library/database.c.openssl 2022-08-02 14:10:48.090466587 +0200 -+++ ./src/library/database.c 2022-08-02 14:13:11.995236110 +0200 -@@ -35,7 +35,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -244,26 +244,18 @@ static void abort_transaction(MDB_txn *t - static char *path_to_hash(const char *path, const size_t path_len) MALLOCLIKE; - static char *path_to_hash(const char *path, const size_t path_len) - { -- gcry_md_hd_t h; -- unsigned int len; -- unsigned char *hptr; -+ unsigned char hptr[80]; - char *digest; - -- if (gcry_md_open(&h, GCRY_MD_SHA512, GCRY_MD_FLAG_SECURE)) -+ if (path_len == 0) - return NULL; - -- gcry_md_write(h, path, path_len); -- hptr = gcry_md_read(h, GCRY_MD_SHA512); -- -- len = gcry_md_get_algo_dlen(GCRY_MD_SHA512) * sizeof(char); -- digest = malloc((2 * len) + 1); -- if (digest == NULL) { -- gcry_md_close(h); -+ SHA512((unsigned char *)path, path_len, (unsigned char *)&hptr); -+ digest = malloc((SHA512_LEN * 2) + 1); -+ if (digest == NULL) - return digest; -- } - -- bytes2hex(digest, hptr, len); -- gcry_md_close(h); -+ bytes2hex(digest, hptr, SHA512_LEN); - - return digest; - } -@@ -296,7 +288,7 @@ static int write_db(const char *idx, con - if (hash == NULL) - return 5; - key.mv_data = (void *)hash; -- key.mv_size = gcry_md_get_algo_dlen(GCRY_MD_SHA512) * 2 + 1; -+ key.mv_size = (SHA512_LEN * 2) + 1; - } else { - key.mv_data = (void *)idx; - key.mv_size = len; -@@ -416,7 +408,7 @@ static char *lt_read_db(const char *inde - if (hash == NULL) - return NULL; - key.mv_data = (void *)hash; -- key.mv_size = gcry_md_get_algo_dlen(GCRY_MD_SHA512) * 2 + 1; -+ key.mv_size = (SHA512_LEN * 2) + 1; - } else { - key.mv_data = (void *)index; - key.mv_size = len; -diff -up ./src/library/file.c.openssl ./src/library/file.c ---- ./src/library/file.c.openssl 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/library/file.c 2022-08-02 14:10:48.094466497 +0200 -@@ -31,7 +31,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -51,7 +51,6 @@ static struct udev *udev; - magic_t magic_cookie; - struct cache { dev_t device; const char *devname; }; - static struct cache c = { 0, NULL }; --static size_t hash_size = 32; // init so cli doesn't need to call file_init - - // readelf -l path-to-app | grep 'Requesting' | cut -d':' -f2 | tr -d ' ]'; - static const char *interpreters[] = { -@@ -96,12 +95,6 @@ void file_init(void) - msg(LOG_ERR, "Unable to load magic database"); - exit(1); - } -- -- // Initialize libgcrypt -- gcry_check_version(NULL); -- gcry_control(GCRYCTL_DISABLE_SECMEM, 0); -- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); -- hash_size = gcry_md_get_algo_dlen(GCRY_MD_SHA256) * sizeof(char); - } - - -@@ -445,12 +438,12 @@ char *get_hash_from_fd2(int fd, size_t s - if (mapped != MAP_FAILED) { - unsigned char hptr[40]; - -- gcry_md_hash_buffer(GCRY_MD_SHA256, &hptr, mapped, size); -+ SHA256(mapped, size, (unsigned char *)&hptr); - munmap(mapped, size); -- digest = malloc(65); -+ digest = malloc((SHA256_LEN * 2) + 1); - - // Convert to ASCII string -- bytes2hex(digest, hptr, hash_size); -+ bytes2hex(digest, hptr, SHA256_LEN); - } - return digest; - } -@@ -476,7 +469,7 @@ int get_ima_hash(int fd, char *sha) - } - - // Looks like it what we want... -- bytes2hex(sha, &tmp[2], 32); -+ bytes2hex(sha, &tmp[2], SHA256_LEN); - return 1; - } - -diff -up ./src/library/file.h.openssl ./src/library/file.h ---- ./src/library/file.h.openssl 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/library/file.h 2022-08-02 14:10:48.094466497 +0200 -@@ -40,6 +40,9 @@ struct file_info - struct timespec time; - }; - -+#define SHA256_LEN 32 -+#define SHA512_LEN 64 -+ - void file_init(void); - void file_close(void); - struct file_info *stat_file_entry(int fd) MALLOCLIKE; diff --git a/SOURCES/fapolicyd-readme.patch b/SOURCES/fapolicyd-readme.patch deleted file mode 100644 index 5d93547..0000000 --- a/SOURCES/fapolicyd-readme.patch +++ /dev/null @@ -1,30 +0,0 @@ -From b4618d133f473b9bbc36f2a5e94b8b0f257ba3e0 Mon Sep 17 00:00:00 2001 -From: Radovan Sroka -Date: Fri, 5 Aug 2022 14:49:30 +0200 -Subject: [PATCH] Add mention that using of names requires name resolution - -- using of user and group names as uid and gid attributes - requires correct name resolution - -Signed-off-by: Radovan Sroka ---- - README.md | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/README.md b/README.md -index d932e00..abc5eee 100644 ---- a/README.md -+++ b/README.md -@@ -131,6 +131,12 @@ You can similarly do this for trusted users that have to execute things in - the home dir. You can create a trusted_user group, add them the group, - and then write a rule allowing them to execute from their home dir. - -+When you want to use user or group name (as a string). You have to guarantee -+that these names were correctly resolved. In case of systemd, you need to add -+a new after target 'After=nss-user-lookup.target'. -+To achieve that you can use `systemctl edit --full fapolicyd`, -+uncomment the respective line and save the change. -+ - ``` - allow perm=any gid=trusted_user : ftype=%languages dir=/home - deny_audit perm=any all : ftype=%languages dir=/home diff --git a/SOURCES/fapolicyd-selinux-links.patch b/SOURCES/fapolicyd-selinux-links.patch new file mode 100644 index 0000000..b0496c1 --- /dev/null +++ b/SOURCES/fapolicyd-selinux-links.patch @@ -0,0 +1,23 @@ +From 05780f9accae504440ffed0548bd3e4144cfb70e Mon Sep 17 00:00:00 2001 +From: Radovan Sroka +Date: Wed, 19 Jul 2023 16:00:13 +0200 +Subject: [PATCH] Allow links + +Signed-off-by: Radovan Sroka +--- + fapolicyd.te | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fapolicyd-selinux-0.6/fapolicyd.te b/fapolicyd-selinux-0.6/fapolicyd.te +index daf31bd..5d6f9aa 100644 +--- a/fapolicyd-selinux-0.6/fapolicyd.te ++++ b/fapolicyd-selinux-0.6/fapolicyd.te +@@ -53,6 +53,8 @@ ifdef(`fs_watch_all_fs',` + files_watch_sb_all_mountpoints(fapolicyd_t) + ') + ++allow fapolicyd_t file_type : lnk_file { getattr read }; ++ + manage_files_pattern(fapolicyd_t, fapolicyd_log_t, fapolicyd_log_t) + logging_log_filetrans(fapolicyd_t, fapolicyd_log_t, file) + diff --git a/SOURCES/fapolicyd-selinux.patch b/SOURCES/fapolicyd-selinux.patch deleted file mode 100644 index 2ece2d2..0000000 --- a/SOURCES/fapolicyd-selinux.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff -up ./fapolicyd-selinux-0.4/fapolicyd.te.selinux ./fapolicyd-selinux-0.4/fapolicyd.te ---- ./fapolicyd-selinux-0.4/fapolicyd.te.selinux 2021-03-23 10:21:31.000000000 +0100 -+++ ./fapolicyd-selinux-0.4/fapolicyd.te 2022-06-29 12:06:57.958124735 +0200 -@@ -61,25 +61,15 @@ corecmd_exec_bin(fapolicyd_t) - - domain_read_all_domains_state(fapolicyd_t) - --files_mmap_usr_files(fapolicyd_t) -+files_mmap_all_files(fapolicyd_t) - files_read_all_files(fapolicyd_t) --files_watch_mount_generic_tmp_dirs(fapolicyd_t) --files_watch_with_perm_generic_tmp_dirs(fapolicyd_t) --files_watch_mount_root_dirs(fapolicyd_t) --files_watch_with_perm_root_dirs(fapolicyd_t) - - fs_getattr_xattr_fs(fapolicyd_t) --fs_watch_mount_tmpfs_dirs(fapolicyd_t) --fs_watch_with_perm_tmpfs_dirs(fapolicyd_t) - - logging_send_syslog_msg(fapolicyd_t) - dbus_system_bus_client(fapolicyd_t) - --userdom_watch_mount_tmp_dirs(fapolicyd_t) --userdom_watch_with_perm_tmp_dirs(fapolicyd_t) -- - optional_policy(` - rpm_read_db(fapolicyd_t) -- allow fapolicyd_t rpm_var_lib_t:file { create }; -- allow fapolicyd_t rpm_var_lib_t:dir { add_name write }; -+ rpm_manage_db(fapolicyd_t) - ') diff --git a/SOURCES/fapolicyd-sighup.patch b/SOURCES/fapolicyd-sighup.patch deleted file mode 100644 index 47ee190..0000000 --- a/SOURCES/fapolicyd-sighup.patch +++ /dev/null @@ -1,141 +0,0 @@ -diff -up ./src/daemon/fapolicyd.c.sighup ./src/daemon/fapolicyd.c ---- ./src/daemon/fapolicyd.c.sighup 2022-06-21 16:55:47.000000000 +0200 -+++ ./src/daemon/fapolicyd.c 2022-08-04 11:07:10.245069443 +0200 -@@ -527,6 +527,7 @@ int main(int argc, const char *argv[]) - while (!stop) { - if (hup) { - hup = 0; -+ msg(LOG_INFO, "Got SIGHUP"); - reconfigure(); - } - rc = poll(pfd, 2, -1); -diff -up ./src/library/database.c.sighup ./src/library/database.c ---- ./src/library/database.c.sighup 2022-08-04 11:07:10.237069609 +0200 -+++ ./src/library/database.c 2022-08-04 11:08:44.852057119 +0200 -@@ -68,7 +68,7 @@ static int lib_symlink=0, lib64_symlink= - static struct pollfd ffd[1] = { {0, 0, 0} }; - static const char *fifo_path = "/run/fapolicyd/fapolicyd.fifo"; - static integrity_t integrity; --static atomic_int db_operation; -+static atomic_int reload_db = 0; - - static pthread_t update_thread; - static pthread_mutex_t update_lock; -@@ -1147,7 +1147,31 @@ static int handle_record(const char * bu - - void update_trust_database(void) - { -- db_operation = RELOAD_DB; -+ reload_db = 1; -+} -+ -+static void do_reload_db(conf_t* config) -+{ -+ msg(LOG_INFO,"It looks like there was an update of the system... Syncing DB."); -+ -+ int rc; -+ backend_close(); -+ backend_init(config); -+ backend_load(config); -+ -+ if ((rc = update_database(config))) { -+ msg(LOG_ERR, -+ "Cannot update trust database!"); -+ close(ffd[0].fd); -+ backend_close(); -+ unlink_fifo(); -+ exit(rc); -+ } -+ -+ msg(LOG_INFO, "Updated"); -+ -+ // Conserve memory -+ backend_close(); - } - - static void *update_thread_main(void *arg) -@@ -1158,6 +1182,8 @@ static void *update_thread_main(void *ar - char err_buff[BUFFER_SIZE]; - conf_t *config = (conf_t *)arg; - -+ int do_operation = DB_NO_OP;; -+ - #ifdef DEBUG - msg(LOG_DEBUG, "Update thread main started"); - #endif -@@ -1182,6 +1208,12 @@ static void *update_thread_main(void *ar - - rc = poll(ffd, 1, 1000); - -+ // got SIGHUP -+ if (reload_db) { -+ reload_db = 0; -+ do_reload_db(config); -+ } -+ - #ifdef DEBUG - msg(LOG_DEBUG, "Update poll interrupted"); - #endif -@@ -1228,17 +1260,17 @@ static void *update_thread_main(void *ar - // assume file name - // operation = 0 - if (buff[i] == '/') { -- db_operation = ONE_FILE; -+ do_operation = ONE_FILE; - break; - } - - if (buff[i] == '1') { -- db_operation = RELOAD_DB; -+ do_operation = RELOAD_DB; - break; - } - - if (buff[i] == '2') { -- db_operation = FLUSH_CACHE; -+ do_operation = FLUSH_CACHE; - break; - } - -@@ -1252,34 +1284,16 @@ static void *update_thread_main(void *ar - *end = '\n'; - - // got "1" -> reload db -- if (db_operation == RELOAD_DB) { -- db_operation = DB_NO_OP; -- msg(LOG_INFO, -- "It looks like there was an update of the system... Syncing DB."); -- -- backend_close(); -- backend_init(config); -- backend_load(config); -- -- if ((rc = update_database(config))) { -- msg(LOG_ERR, -- "Cannot update trust database!"); -- close(ffd[0].fd); -- backend_close(); -- unlink_fifo(); -- exit(rc); -- } -- -- msg(LOG_INFO, "Updated"); -+ if (do_operation == RELOAD_DB) { -+ do_operation = DB_NO_OP; -+ do_reload_db(config); - -- // Conserve memory -- backend_close(); - // got "2" -> flush cache -- } else if (db_operation == FLUSH_CACHE) { -- db_operation = DB_NO_OP; -+ } else if (do_operation == FLUSH_CACHE) { -+ do_operation = DB_NO_OP; - needs_flush = true; -- } else if (db_operation == ONE_FILE) { -- db_operation = DB_NO_OP; -+ } else if (do_operation == ONE_FILE) { -+ do_operation = DB_NO_OP; - if (handle_record(buff)) - continue; - } diff --git a/SOURCES/fapolicyd-user-group-doc.patch b/SOURCES/fapolicyd-user-group-doc.patch deleted file mode 100644 index c8cdd75..0000000 --- a/SOURCES/fapolicyd-user-group-doc.patch +++ /dev/null @@ -1,47 +0,0 @@ -From fb4c274f4857f2d652014b0189abafb1df4b001a Mon Sep 17 00:00:00 2001 -From: Steve Grubb -Date: Tue, 19 Jul 2022 12:18:18 -0400 -Subject: [PATCH] Add documentation describing support for user/group names - ---- - doc/fapolicyd.rules.5 | 6 +++--- - init/fapolicyd.service | 2 ++ - 2 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/doc/fapolicyd.rules.5 b/doc/fapolicyd.rules.5 -index aa77177..3b8ec09 100644 ---- a/doc/fapolicyd.rules.5 -+++ b/doc/fapolicyd.rules.5 -@@ -35,13 +35,13 @@ The subject is the process that is performing actions on system resources. The f - This matches against any subject. When used, this must be the only subject in the rule. - .TP - .B auid --This is the login uid that the audit system assigns users when they log in to the system. Daemons have a value of -1. -+This is the login uid that the audit system assigns users when they log in to the system. Daemons have a value of -1. The given value may be numeric or the account name. - .TP - .B uid --This is the user id that the program is running under. -+This is the user id that the program is running under. The given value may be numeric or the account name. - .TP - .B gid --This is the group id that the program is running under. -+This is the group id that the program is running under. The given value may be numeric or the group name. - .TP - .B sessionid - This is the numeric session id that the audit system assigns to users when they log in. Daemons have a value of -1. -diff --git a/init/fapolicyd.service b/init/fapolicyd.service -index 715de98..a5a6a3f 100644 ---- a/init/fapolicyd.service -+++ b/init/fapolicyd.service -@@ -11,6 +11,8 @@ PIDFile=/run/fapolicyd.pid - ExecStartPre=/usr/sbin/fagenrules - ExecStart=/usr/sbin/fapolicyd - Restart=on-abnormal -+# Uncomment the following line if rules need user/group name lookup -+#After=nss-user-lookup.target - - [Install] - WantedBy=multi-user.target --- -2.37.1 - diff --git a/SOURCES/selinux.patch b/SOURCES/selinux.patch new file mode 100644 index 0000000..2ea84c6 --- /dev/null +++ b/SOURCES/selinux.patch @@ -0,0 +1,13 @@ +diff -up ./fapolicyd-selinux-0.6/fapolicyd.te.fix ./fapolicyd-selinux-0.6/fapolicyd.te +--- ./fapolicyd-selinux-0.6/fapolicyd.te.fix 2023-06-15 17:11:47.964646794 +0200 ++++ ./fapolicyd-selinux-0.6/fapolicyd.te 2023-06-15 17:13:10.426477653 +0200 +@@ -50,6 +50,9 @@ ifdef(`watch_mount_dirs_pattern',` + + ifdef(`fs_watch_all_fs',` + fs_watch_all_fs(fapolicyd_t) ++') ++ ++ifdef(`files_watch_sb_all_mountpoints',` + files_watch_sb_all_mountpoints(fapolicyd_t) + ') + diff --git a/SPECS/fapolicyd.spec b/SPECS/fapolicyd.spec index 534666e..ec638e9 100644 --- a/SPECS/fapolicyd.spec +++ b/SPECS/fapolicyd.spec @@ -1,11 +1,11 @@ %global selinuxtype targeted %global moduletype contrib -%define semodule_version 0.4 +%define semodule_version 0.6 Summary: Application Whitelisting Daemon Name: fapolicyd -Version: 1.1.3 -Release: 12%{?dist} +Version: 1.3.2 +Release: 1%{?dist} License: GPLv3+ URL: http://people.redhat.com/sgrubb/fapolicyd Source0: https://people.redhat.com/sgrubb/fapolicyd/%{name}-%{version}.tar.gz @@ -30,19 +30,10 @@ Requires(postun): systemd-units # we require the rpm-plugin from now on and the dnf-plugin still needs to be part of # the fapolicyd package because it provides safe upgrade path Patch1: fapolicyd-dnf-plugin.patch -Patch2: fapolicyd-selinux.patch -Patch3: fagenrules-group.patch - -Patch4: fapolicyd-fgets-update-thread.patch -Patch5: fapolicyd-openssl.patch -Patch6: fapolicyd-user-group-doc.patch -Patch7: fapolicyd-cli-segfault.patch -Patch8: fapolicyd-sighup.patch -Patch9: fapolicyd-readme.patch - -Patch10: fapolicyd-falcon-sensor.patch -Patch11: fapolicyd-exclude-list.patch -Patch12: fapolicyd-already-started.patch +Patch2: selinux.patch +Patch3: fapolicyd-selinux-links.patch +Patch4: fapolicyd-leaks.patch +Patch5: fapolicyd-librpm-workaround.patch %description Fapolicyd (File Access Policy Daemon) implements application whitelisting @@ -69,19 +60,11 @@ The %{name}-selinux package contains selinux policy for the %{name} daemon. # selinux %setup -q -D -T -a 1 -%patch1 -p1 -b .plugin -%patch2 -p1 -b .selinux -%patch3 -p1 -b .group -%patch4 -p1 -b .update-thread -%patch5 -p1 -b .openssl -%patch6 -p1 -b .user-group -%patch7 -p1 -b .segfault -%patch8 -p1 -b .sighup -%patch9 -p1 -b .readme - -%patch10 -p1 -b .event -%patch11 -p1 -b .exclude -%patch12 -p1 -b .already-started +%patch -P 1 -p1 -b .dnf-plugin +%patch -P 2 -p1 -b .selinux +%patch -P 3 -p1 -b .selinux-links +%patch -P 4 -p1 -b .leaks +%patch -P 5 -p1 -b .librpm-workaround # generate rules for python sed -i "s|%python2_path%|`readlink -f %{__python2}`|g" rules.d/*.rules @@ -96,6 +79,7 @@ interpret=`readelf -e /usr/bin/bash \ sed -i "s|%ld_so_path%|`realpath $interpret`|g" rules.d/*.rules %build +cp INSTALL INSTALL.tmp ./autogen.sh %configure \ --with-audit \ @@ -229,11 +213,12 @@ fi %attr(750,root,%{name}) %dir %{_sysconfdir}/%{name} %attr(750,root,%{name}) %dir %{_sysconfdir}/%{name}/trust.d %attr(750,root,%{name}) %dir %{_sysconfdir}/%{name}/rules.d +%attr(644,root,root) %{_sysconfdir}/bash_completion.d/* %ghost %verify(not md5 size mtime) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/rules.d/* %ghost %verify(not md5 size mtime) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}.rules %ghost %verify(not md5 size mtime) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/compiled.rules %config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}.conf -%config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/rpm-filter.conf +%config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}-filter.conf %config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}.trust %attr(644,root,root) %{_unitdir}/%{name}.service %attr(644,root,root) %{_tmpfilesdir}/%{name}.conf @@ -242,7 +227,6 @@ fi %attr(755,root,root) %{_sbindir}/fagenrules %attr(644,root,root) %{_mandir}/man8/* %attr(644,root,root) %{_mandir}/man5/* -%attr(644,root,root) %{_mandir}/man1/* %ghost %attr(440,%{name},%{name}) %verify(not md5 size mtime) %{_localstatedir}/log/%{name}-access.log %attr(770,root,%{name}) %dir %{_localstatedir}/lib/%{name} %attr(770,root,%{name}) %dir /run/%{name} @@ -271,6 +255,27 @@ fi %selinux_relabel_post -s %{selinuxtype} %changelog +* Wed Jul 19 2023 Radovan Sroka - 1.3.2-1 +RHEL 8.9.0 ERRATUM +- Rebase fapolicyd to the latest stable version +Resolves: RHEL-519 +- RFE: send rule number to fanotify so it gets audited +Resolves: RHEL-628 +- Default q_size doesn't match manpage's one +Resolves: RHEL-629 +- fapolicyd can leak FDs and never answer request, causing target process to hang forever +Resolves: RHEL-632 +- fapolicyd needs to make sure the FD limit is never reached +Resolves: RHEL-631 +- fapolicyd still allows execution of a program after "untrusting" it +Resolves: RHEL-630 +- Fix broken backwards compatibility backend numbers +Resolves: RHEL-731 +- fapolicyd can create RPM DB files /var/lib/rpm/__db.xxx with bad ownership causing AVCs to occur +Resolves: RHEL-829 +- SELinux prevents the fapolicyd from reading symlink (cert_t) +Resolves: RHEL-820 + * Mon Jan 30 2023 Radovan Sroka - 1.1.3-12 RHEL 8.8.0 ERRATUM - statically linked app can execute untrusted app