commit
4ba9f98f28
@ -0,0 +1,2 @@
|
||||
3887d3f97a4f506ad6bf7dcef36b01cc7897a692 SOURCES/fapolicyd-1.1.3.tar.gz
|
||||
bdbe20a4db2cd58073abf17a537e3a6766cdea21 SOURCES/fapolicyd-selinux-0.4.tar.gz
|
@ -0,0 +1,2 @@
|
||||
SOURCES/fapolicyd-1.1.3.tar.gz
|
||||
SOURCES/fapolicyd-selinux-0.4.tar.gz
|
@ -0,0 +1,13 @@
|
||||
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
|
@ -0,0 +1,110 @@
|
||||
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);
|
@ -0,0 +1,11 @@
|
||||
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";
|
@ -0,0 +1,35 @@
|
||||
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 @@
|
||||
class Fapolicyd(dnf.Plugin):
|
||||
|
||||
name = "fapolicyd"
|
||||
- pipe = "/var/run/fapolicyd/fapolicyd.fifo"
|
||||
- file = None
|
||||
|
||||
def __init__(self, base, cli):
|
||||
pass
|
||||
|
||||
def transaction(self):
|
||||
-
|
||||
- if not os.path.exists(self.pipe):
|
||||
- sys.stderr.write("Pipe does not exist (" + self.pipe + ")\n")
|
||||
- sys.stderr.write("Perhaps fapolicy-plugin does not have enough permissions\n")
|
||||
- sys.stderr.write("or fapolicyd is not running...\n")
|
||||
- return
|
||||
-
|
||||
- if not stat.S_ISFIFO(os.stat(self.pipe).st_mode):
|
||||
- sys.stderr.write(self.pipe + ": is not a pipe!\n")
|
||||
- return
|
||||
-
|
||||
- try:
|
||||
- self.file = open(self.pipe, "w")
|
||||
- except PermissionError:
|
||||
- sys.stderr.write("fapolicy-plugin does not have write permission: " + self.pipe + "\n")
|
||||
- return
|
||||
-
|
||||
- self.file.write("1")
|
||||
- self.file.close()
|
||||
+ pass
|
||||
Only in b/dnf: fapolicyd-dnf-plugin.py.plugin
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,74 @@
|
||||
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
|
@ -0,0 +1,215 @@
|
||||
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();
|
||||
|
@ -0,0 +1,195 @@
|
||||
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;
|
@ -0,0 +1,30 @@
|
||||
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
|
@ -0,0 +1,31 @@
|
||||
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)
|
||||
')
|
@ -0,0 +1,141 @@
|
||||
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;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
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
|
||||
|
@ -0,0 +1,445 @@
|
||||
%global selinuxtype targeted
|
||||
%global moduletype contrib
|
||||
%define semodule_version 0.4
|
||||
|
||||
Summary: Application Whitelisting Daemon
|
||||
Name: fapolicyd
|
||||
Version: 1.1.3
|
||||
Release: 12%{?dist}
|
||||
License: GPLv3+
|
||||
URL: http://people.redhat.com/sgrubb/fapolicyd
|
||||
Source0: https://people.redhat.com/sgrubb/fapolicyd/%{name}-%{version}.tar.gz
|
||||
Source1: https://github.com/linux-application-whitelisting/%{name}-selinux/releases/download/v%{semodule_version}/%{name}-selinux-%{semodule_version}.tar.gz
|
||||
BuildRequires: gcc
|
||||
BuildRequires: kernel-headers
|
||||
BuildRequires: autoconf automake make gcc libtool
|
||||
BuildRequires: systemd-devel openssl-devel rpm-devel file-devel file
|
||||
BuildRequires: libcap-ng-devel libseccomp-devel lmdb-devel
|
||||
BuildRequires: python3-devel
|
||||
BuildRequires: python2-devel
|
||||
BuildRequires: uthash-devel
|
||||
Requires: rpm-plugin-fapolicyd >= 4.14.3-12
|
||||
Recommends: %{name}-selinux
|
||||
Requires(pre): shadow-utils
|
||||
Requires(post): systemd-units
|
||||
Requires(preun): systemd-units
|
||||
Requires(postun): systemd-units
|
||||
|
||||
# we are making the dnf-plugin completelly dummy because of
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1929163
|
||||
# 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
|
||||
|
||||
%description
|
||||
Fapolicyd (File Access Policy Daemon) implements application whitelisting
|
||||
to decide file access rights. Applications that are known via a reputation
|
||||
source are allowed access while unknown applications are not. The daemon
|
||||
makes use of the kernel's fanotify interface to determine file access rights.
|
||||
|
||||
%package selinux
|
||||
Summary: Fapolicyd selinux
|
||||
Group: Applications/System
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
BuildRequires: selinux-policy
|
||||
BuildRequires: selinux-policy-devel
|
||||
BuildArch: noarch
|
||||
%{?selinux_requires}
|
||||
|
||||
%description selinux
|
||||
The %{name}-selinux package contains selinux policy for the %{name} daemon.
|
||||
|
||||
%prep
|
||||
|
||||
%setup -q
|
||||
|
||||
# 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
|
||||
|
||||
# generate rules for python
|
||||
sed -i "s|%python2_path%|`readlink -f %{__python2}`|g" rules.d/*.rules
|
||||
sed -i "s|%python3_path%|`readlink -f %{__python3}`|g" rules.d/*.rules
|
||||
|
||||
interpret=`readelf -e /usr/bin/bash \
|
||||
| grep Requesting \
|
||||
| sed 's/.$//' \
|
||||
| rev | cut -d" " -f1 \
|
||||
| rev`
|
||||
|
||||
sed -i "s|%ld_so_path%|`realpath $interpret`|g" rules.d/*.rules
|
||||
|
||||
%build
|
||||
./autogen.sh
|
||||
%configure \
|
||||
--with-audit \
|
||||
--with-rpm \
|
||||
--disable-shared
|
||||
|
||||
%make_build
|
||||
|
||||
# selinux
|
||||
pushd %{name}-selinux-%{semodule_version}
|
||||
make
|
||||
popd
|
||||
|
||||
%check
|
||||
make check
|
||||
|
||||
# Selinux
|
||||
%pre selinux
|
||||
%selinux_relabel_pre -s %{selinuxtype}
|
||||
|
||||
%install
|
||||
%make_install
|
||||
mkdir -p %{buildroot}/%{python3_sitelib}/dnf-plugins/
|
||||
install -p -m 644 dnf/%{name}-dnf-plugin.py %{buildroot}/%{python3_sitelib}/dnf-plugins/
|
||||
install -p -m 644 -D init/%{name}-tmpfiles.conf %{buildroot}/%{_tmpfilesdir}/%{name}.conf
|
||||
mkdir -p %{buildroot}/%{_localstatedir}/lib/%{name}
|
||||
mkdir -p %{buildroot}/run/%{name}
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/%{name}/trust.d
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/%{name}/rules.d
|
||||
# get list of file names between known-libs and restrictive from sample-rules/README-rules
|
||||
cat %{buildroot}/%{_datadir}/%{name}/sample-rules/README-rules \
|
||||
| grep -A 100 'known-libs' \
|
||||
| grep -B 100 'restrictive' \
|
||||
| grep '^[0-9]' > %{buildroot}/%{_datadir}/%{name}/default-ruleset.known-libs
|
||||
chmod 644 %{buildroot}/%{_datadir}/%{name}/default-ruleset.known-libs
|
||||
|
||||
# selinux
|
||||
install -d %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype}
|
||||
install -m 0644 %{name}-selinux-%{semodule_version}/%{name}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype}
|
||||
install -d -p %{buildroot}%{_datadir}/selinux/devel/include/%{moduletype}
|
||||
install -p -m 644 %{name}-selinux-%{semodule_version}/%{name}.if %{buildroot}%{_datadir}/selinux/devel/include/%{moduletype}/ipp-%{name}.if
|
||||
|
||||
#cleanup
|
||||
find %{buildroot} \( -name '*.la' -o -name '*.a' \) -delete
|
||||
|
||||
%define manage_default_rules default_changed=0 \
|
||||
# check changed fapolicyd.rules \
|
||||
if [ -e %{_sysconfdir}/%{name}/%{name}.rules ]; then \
|
||||
diff %{_sysconfdir}/%{name}/%{name}.rules %{_datadir}/%{name}/%{name}.rules.known-libs >/dev/null 2>&1 || { \
|
||||
default_changed=1; \
|
||||
#echo "change detected in fapolicyd.rules"; \
|
||||
} \
|
||||
fi \
|
||||
if [ -e %{_sysconfdir}/%{name}/rules.d ]; then \
|
||||
default_ruleset='' \
|
||||
# get listing of default rule files in known-libs \
|
||||
[ -e %{_datadir}/%{name}/default-ruleset.known-libs ] && default_ruleset=`cat %{_datadir}/%{name}/default-ruleset.known-libs` \
|
||||
# check for removed or added files \
|
||||
default_count=`echo "$default_ruleset" | wc -l` \
|
||||
current_count=`ls -1 %{_sysconfdir}/%{name}/rules.d/*.rules | wc -l` \
|
||||
[ $default_count -eq $current_count ] || { \
|
||||
default_changed=1; \
|
||||
#echo "change detected in number of rule files d:$default_count vs c:$current_count"; \
|
||||
} \
|
||||
for file in %{_sysconfdir}/%{name}/rules.d/*.rules; do \
|
||||
if echo "$default_ruleset" | grep -q "`basename $file`"; then \
|
||||
# compare content of the rule files \
|
||||
diff $file %{_datadir}/%{name}/sample-rules/`basename $file` >/dev/null 2>&1 || { \
|
||||
default_changed=1; \
|
||||
#echo "change detected in `basename $file`"; \
|
||||
} \
|
||||
else \
|
||||
# added file detected \
|
||||
default_changed=1 \
|
||||
#echo "change detected in added rules file `basename $file`"; \
|
||||
fi \
|
||||
done \
|
||||
fi \
|
||||
# remove files if no change against default rules detected \
|
||||
[ $default_changed -eq 0 ] && rm -rf %{_sysconfdir}/%{name}/%{name}.rules %{_sysconfdir}/%{name}/rules.d/* || : \
|
||||
|
||||
|
||||
%pre
|
||||
getent passwd %{name} >/dev/null || useradd -r -M -d %{_localstatedir}/lib/%{name} -s /sbin/nologin -c "Application Whitelisting Daemon" %{name}
|
||||
if [ $1 -eq 2 ]; then
|
||||
# detect changed default rules in case of upgrade
|
||||
%manage_default_rules
|
||||
fi
|
||||
|
||||
%post
|
||||
# if no pre-existing rule file
|
||||
if [ ! -e %{_sysconfdir}/%{name}/%{name}.rules ] ; then
|
||||
files=`ls %{_sysconfdir}/%{name}/rules.d/ 2>/dev/null | wc -w`
|
||||
# Only if no pre-existing component rules
|
||||
if [ "$files" -eq 0 ] ; then
|
||||
## Install the known libs policy
|
||||
for rulesfile in `cat %{_datadir}/%{name}/default-ruleset.known-libs`; do
|
||||
cp %{_datadir}/%{name}/sample-rules/$rulesfile %{_sysconfdir}/%{name}/rules.d/
|
||||
done
|
||||
chgrp %{name} %{_sysconfdir}/%{name}/rules.d/*
|
||||
if [ -x /usr/sbin/restorecon ] ; then
|
||||
# restore correct label
|
||||
/usr/sbin/restorecon -F %{_sysconfdir}/%{name}/rules.d/*
|
||||
fi
|
||||
fagenrules >/dev/null
|
||||
fi
|
||||
fi
|
||||
%systemd_post %{name}.service
|
||||
|
||||
%preun
|
||||
%systemd_preun %{name}.service
|
||||
if [ $1 -eq 0 ]; then
|
||||
# detect changed default rules in case of uninstall
|
||||
%manage_default_rules
|
||||
else
|
||||
[ -e %{_sysconfdir}/%{name}/%{name}.rules ] && rm -rf %{_sysconfdir}/%{name}/rules.d/* || :
|
||||
fi
|
||||
|
||||
%postun
|
||||
%systemd_postun_with_restart %{name}.service
|
||||
|
||||
%files
|
||||
%doc README.md
|
||||
%{!?_licensedir:%global license %%doc}
|
||||
%license COPYING
|
||||
%attr(755,root,%{name}) %dir %{_datadir}/%{name}
|
||||
%attr(755,root,%{name}) %dir %{_datadir}/%{name}/sample-rules
|
||||
%attr(644,root,%{name}) %{_datadir}/%{name}/default-ruleset.known-libs
|
||||
%attr(644,root,%{name}) %{_datadir}/%{name}/sample-rules/*
|
||||
%attr(644,root,%{name}) %{_datadir}/%{name}/fapolicyd-magic.mgc
|
||||
%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
|
||||
%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}.trust
|
||||
%attr(644,root,root) %{_unitdir}/%{name}.service
|
||||
%attr(644,root,root) %{_tmpfilesdir}/%{name}.conf
|
||||
%attr(755,root,root) %{_sbindir}/%{name}
|
||||
%attr(755,root,root) %{_sbindir}/%{name}-cli
|
||||
%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}
|
||||
%ghost %attr(660,root,%{name}) /run/%{name}/%{name}.fifo
|
||||
%ghost %attr(660,%{name},%{name}) %verify(not md5 size mtime) %{_localstatedir}/lib/%{name}/data.mdb
|
||||
%ghost %attr(660,%{name},%{name}) %verify(not md5 size mtime) %{_localstatedir}/lib/%{name}/lock.mdb
|
||||
%{python3_sitelib}/dnf-plugins/%{name}-dnf-plugin.py
|
||||
%{python3_sitelib}/dnf-plugins/__pycache__/%{name}-dnf-plugin.*.pyc
|
||||
|
||||
# selinux
|
||||
%files selinux
|
||||
%{_datadir}/selinux/packages/%{selinuxtype}/%{name}.pp.bz2
|
||||
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{name}
|
||||
%{_datadir}/selinux/devel/include/%{moduletype}/ipp-%{name}.if
|
||||
|
||||
%post selinux
|
||||
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{name}.pp.bz2
|
||||
%selinux_relabel_post -s %{selinuxtype}
|
||||
|
||||
%postun selinux
|
||||
if [ $1 -eq 0 ]; then
|
||||
%selinux_modules_uninstall -s %{selinuxtype} %{name}
|
||||
fi
|
||||
|
||||
%posttrans selinux
|
||||
%selinux_relabel_post -s %{selinuxtype}
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
Resolves: rhbz#2088349
|
||||
- Starting manually fapolicyd while the service is already running breaks the system
|
||||
Resolves: rhbz#2103352
|
||||
- Cannot execute /usr/libexec/grepconf.sh when falcon-sensor is enabled
|
||||
Resolves: rhbz#2087040
|
||||
- fapolicyd: Introduce filtering of rpmdb
|
||||
Resolves: rhbz#2165645
|
||||
|
||||
* Fri Aug 05 2022 Radovan Sroka <rsroka@redhat.com> - 1.1.3-8
|
||||
RHEL 8.7.0 ERRATUM
|
||||
- rebase fapolicyd to the latest stable vesion
|
||||
Resolves: rhbz#2100087
|
||||
- fapolicyd does not correctly handle SIGHUP
|
||||
Resolves: rhbz#2070639
|
||||
- fapolicyd often breaks package updates
|
||||
Resolves: rhbz#2111243
|
||||
- drop libgcrypt in favour of openssl
|
||||
Resolves: rhbz#2111935
|
||||
- fapolicyd.rules doesn't advertise that using a username/groupname instead of uid/gid also works
|
||||
Resolves: rhbz#2103914
|
||||
- fapolicyd gets way too easily killed by OOM killer
|
||||
Resolves: rhbz#2100089
|
||||
- compiled.rules file ownership and mode
|
||||
Resolves: rhbz#2066653
|
||||
- Faulty handling of static applications
|
||||
Resolves: rhbz#2084497
|
||||
- Introduce ppid rule attribute
|
||||
Resolves: rhbz#2102563
|
||||
- CVE-2022-1117 fapolicyd: fapolicyd wrongly prepares ld.so path [rhel-8.7.0]
|
||||
Resolves: rhbz#2069121
|
||||
- Fapolicyd denies access to /usr/lib64/ld-2.28.so [rhel-8.7.0]
|
||||
Resolves: rhbz#2068105
|
||||
|
||||
* Wed Feb 16 2022 Radovan Sroka <rsroka@redhat.com> - 1.1-1
|
||||
RHEL 8.6.0 ERRATUM
|
||||
- rebase to 1.1
|
||||
Resolves: rhbz#1939379
|
||||
- introduce rules.d feature
|
||||
Resolves: rhbz#2054741
|
||||
- remove pretrans scriptlet
|
||||
Resolves: rhbz#2051485
|
||||
|
||||
* Mon Dec 13 2021 Zoltan Fridrich <zfridric@redhat.com> - 1.0.4-2
|
||||
RHEL 8.6.0 ERRATUM
|
||||
- rebase to 1.0.4
|
||||
- added rpm_sha256_only option
|
||||
- added trust.d directory
|
||||
- allow file names with whitespace in trust files
|
||||
- use full paths in trust files
|
||||
Resolves: rhbz#1939379
|
||||
- fix libc.so getting identified as application/x-executable
|
||||
Resolves: rhbz#1989272
|
||||
- fix fapolicyd-dnf-plugin reporting as '<invalid>'
|
||||
Resolves: rhbz#1997414
|
||||
- fix selinux DSP module definition in spec file
|
||||
Resolves: rhbz#2014445
|
||||
|
||||
* Thu Aug 19 2021 Radovan Sroka <rsroka@redhat.com> - 1.0.2-7
|
||||
- fapolicyd abnormally exits by executing sosreport
|
||||
- fixed multiple problems with unlink()
|
||||
- fapolicyd breaks system upgrade, leaving system in dead state - complete fix
|
||||
Resolves: rhbz#1943251
|
||||
|
||||
* Tue Feb 16 2021 Radovan Sroka <rsroka@redhat.com> - 1.0.2-3
|
||||
RHEL 8.4.0 ERRATUM
|
||||
- rebase to 1.0.2
|
||||
- strong dependency on rpm/rpm-plugin-fapolicyd
|
||||
- installed dnf-plugin is dummy and we are not using it anymore
|
||||
- enabled integrity setting
|
||||
Resolves: rhbz#1887451
|
||||
- added make check
|
||||
- Adding DISA STIG during OS installation causes 'ipa-server-install' to fail
|
||||
- fixed java detection
|
||||
Resolves: rhbz#1895435
|
||||
- dnf update fails when fapolicyd is enabled
|
||||
Resolves: rhbz#1876975
|
||||
- fapolicyd breaks system upgrade, leaving system in dead state - complete fix
|
||||
Resolves: rhbz#1896875
|
||||
|
||||
* Tue Jun 30 2020 Radovan Sroka <rsroka@redhat.com> - 1.0-3
|
||||
RHEL 8.3 ERRATUM
|
||||
- fixed manpage fapolicyd-conf
|
||||
Resolves: rhbz#1817413
|
||||
|
||||
* Mon May 25 2020 Radovan Sroka <rsroka@redhat.com> - 1.0-2
|
||||
RHEL 8.3 ERRATUM
|
||||
- rebase to v1.0
|
||||
- installed multiple policies to /usr/share/fapolicyd
|
||||
- known-libs (default)
|
||||
- restrictive
|
||||
- installed fapolicyd.trust file
|
||||
- enhanced fapolicyd-cli
|
||||
Resolves: rhbz#1817413
|
||||
- introduced fapolicyd-selinux that provides SELinux policy module
|
||||
Resolves: rhbz#1714529
|
||||
|
||||
* Tue Mar 03 2020 Radovan Sroka <rsroka@redhat.com> - 0.9.1-4
|
||||
RHEL 8.2 ERRATUM
|
||||
- fixed possible heap buffer overflow in elf parser
|
||||
Resolves: rhbz#1807912
|
||||
|
||||
* Tue Feb 11 2020 Radovan Sroka <rsroka@redhat.com> - 0.9.1-3
|
||||
RHEL 8.2 ERRATUM
|
||||
- fixed build time python interpreter detection (spec)
|
||||
- added python2-devel as a BuildRequires (spec)
|
||||
- allow running bash scripts in home directories
|
||||
Resolves: rhbz#1801872
|
||||
|
||||
* Wed Nov 20 2019 Radovan Sroka <rsroka@redhat.com> - 0.9.1-2
|
||||
RHEL 8.2 ERRATUM
|
||||
- rebase to v0.9.1
|
||||
- updated default configuration with new syntax
|
||||
- removed daemon mounts configuration
|
||||
Resolves: rhbz#1759895
|
||||
- default fapolicyd policy prevents Ansible from running
|
||||
- added ansible rule to default ruleset
|
||||
Resolves: rhbz#1746464
|
||||
- suspicious logs on service start
|
||||
Resolves: rhbz#1747494
|
||||
- fapolicyd blocks dracut from generating initramfs
|
||||
- added dracut rule to default configuration
|
||||
Resolves: rhbz#1757736
|
||||
- fapolicyd fails to identify perl interpreter
|
||||
Resolves: rhbz#1765039
|
||||
|
||||
* Wed Jul 24 2019 Radovan Sroka <rsroka@redhat.com> - 0.8.10-3
|
||||
- added missing manpage for fapolicyd-cli
|
||||
Resolves: rhbz#1708015
|
||||
|
||||
* Mon Jul 22 2019 Radovan Sroka <rsroka@redhat.com> - 0.8.10-2
|
||||
- Convert hashes to lowercase like sha256sum outputs
|
||||
- Stop littering STDOUT output for dnf plugin in fapolicyd
|
||||
Resolves: rhbz#1721496
|
||||
|
||||
* Tue Jun 18 2019 Radovan Sroka <rsroka@redhat.com> - 0.8.10-1
|
||||
- new upstream release
|
||||
Resolves: rhbz#1673323
|
||||
|
||||
* Mon May 06 2019 Radovan Sroka <rsroka@redhat.com> - 0.8.9-1
|
||||
- New upstream release
|
||||
- imported from fedora30
|
||||
resolves: rhbz#1673323
|
||||
|
||||
* Wed Mar 13 2019 Radovan Sroka <rsroka@redhat.com> - 0.8.8-2
|
||||
- backport some patches to resolve dac_override for fapolicyd
|
||||
|
||||
* Mon Mar 11 2019 Radovan Sroka <rsroka@redhat.com> - 0.8.8-1
|
||||
- New upstream release
|
||||
- Added new DNF plugin that can update the trust database when rpms are installed
|
||||
- Added support for FAN_OPEN_EXEC_PERM
|
||||
|
||||
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.7-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
|
||||
* Wed Oct 03 2018 Steve Grubb <sgrubb@redhat.com> 0.8.7-1
|
||||
- New upstream bugfix release
|
||||
|
||||
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.6-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Thu Jun 07 2018 Steve Grubb <sgrubb@redhat.com> 0.8.6-1
|
||||
- New upstream feature release
|
||||
|
||||
* Fri May 18 2018 Steve Grubb <sgrubb@redhat.com> 0.8.5-2
|
||||
- Add dist tag (#1579362)
|
||||
|
||||
* Fri Feb 16 2018 Steve Grubb <sgrubb@redhat.com> 0.8.5-1
|
||||
- New release
|
Loading…
Reference in new issue