Compare commits

...

No commits in common. "imports/c8-beta/fapolicyd-1.1.3-12.el8" and "c8" have entirely different histories.

19 changed files with 252 additions and 1998 deletions

View File

@ -1,2 +0,0 @@
3887d3f97a4f506ad6bf7dcef36b01cc7897a692 SOURCES/fapolicyd-1.1.3.tar.gz
bdbe20a4db2cd58073abf17a537e3a6766cdea21 SOURCES/fapolicyd-selinux-0.4.tar.gz

4
.gitignore vendored
View File

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

View File

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

View File

@ -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);

View File

@ -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";

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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 <errno.h>
#include <unistd.h>
#include <fcntl.h>
+#include <ctype.h>
#include <gcrypt.h>
#include <signal.h>
#include <sys/stat.h>
@@ -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();

View File

@ -0,0 +1,78 @@
From 248219377a034d7da9238e7424c97558395700e3 Mon Sep 17 00:00:00 2001
From: Radovan Sroka <rsroka@redhat.com>
Date: Tue, 18 Jul 2023 17:05:11 +0200
Subject: [PATCH] Fix multiple leaks
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
---
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 <rsroka@redhat.com>
*/
+#include "attr-sets.h"
#include "config.h"
#include <stdbool.h>
#include <stdio.h>
@@ -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;
}

View File

@ -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 <rpm/rpmdb.h>
#include <rpm/rpmpgp.h>
#include <fnmatch.h>
+#include <glob.h>
+#include <pwd.h>
+#include <grp.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <uthash.h>
#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

View File

@ -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 <stdatomic.h>
#include <lmdb.h>
#include <limits.h>
-#include <gcrypt.h>
#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 <unistd.h>
#include <fcntl.h>
#include <ctype.h>
-#include <gcrypt.h>
+#include <openssl/sha.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -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 <sys/stat.h>
#include <string.h>
#include <stdlib.h>
-#include <gcrypt.h>
+#include <openssl/sha.h>
#include <magic.h>
#include <libudev.h>
#include <elf.h>
@@ -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;

View File

@ -1,30 +0,0 @@
From b4618d133f473b9bbc36f2a5e94b8b0f257ba3e0 Mon Sep 17 00:00:00 2001
From: Radovan Sroka <rsroka@redhat.com>
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 <rsroka@redhat.com>
---
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

View File

@ -0,0 +1,23 @@
From 05780f9accae504440ffed0548bd3e4144cfb70e Mon Sep 17 00:00:00 2001
From: Radovan Sroka <rsroka@redhat.com>
Date: Wed, 19 Jul 2023 16:00:13 +0200
Subject: [PATCH] Allow links
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
---
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)

View File

@ -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)
')

View File

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

View File

@ -1,47 +0,0 @@
From fb4c274f4857f2d652014b0189abafb1df4b001a Mon Sep 17 00:00:00 2001
From: Steve Grubb <sgrubb@redhat.com>
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

13
SOURCES/selinux.patch Normal file
View File

@ -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)
')

View File

@ -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 <rsroka@redhat.com> - 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 <rsroka@redhat.com> - 1.1.3-12
RHEL 8.8.0 ERRATUM
- statically linked app can execute untrusted app