diff --git a/.fapolicyd.metadata b/.fapolicyd.metadata index 2895d71..b086157 100644 --- a/.fapolicyd.metadata +++ b/.fapolicyd.metadata @@ -1,3 +1,3 @@ -ff34a919c42f1256d0f6507cce70773d9e663447 SOURCES/fapolicyd-1.0.3.tar.gz +d0dd45121bf4a9ffa9f4d3e5c5bcdf89f5efa87a SOURCES/fapolicyd-1.0.4.tar.gz bdbe20a4db2cd58073abf17a537e3a6766cdea21 SOURCES/fapolicyd-selinux-0.4.tar.gz fbafa356359ace80787ce6634d84425b40d90907 SOURCES/uthash-2.3.0.tar.gz diff --git a/.gitignore b/.gitignore index 840245f..028dc2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -SOURCES/fapolicyd-1.0.3.tar.gz +SOURCES/fapolicyd-1.0.4.tar.gz SOURCES/fapolicyd-selinux-0.4.tar.gz SOURCES/uthash-2.3.0.tar.gz diff --git a/SOURCES/fapolicyd-detect-sharedlib.patch b/SOURCES/fapolicyd-detect-sharedlib.patch new file mode 100644 index 0000000..9ac38a8 --- /dev/null +++ b/SOURCES/fapolicyd-detect-sharedlib.patch @@ -0,0 +1,11 @@ +diff --color -ru a/src/library/file.c b/src/library/file.c +--- a/src/library/file.c 2021-11-12 20:21:54.000000000 +0100 ++++ b/src/library/file.c 2021-12-15 12:40:05.088564218 +0100 +@@ -295,6 +295,7 @@ + if (!strncmp(p, "64", 2)) + p += 2; + if (!strncmp(p, "/libc-2", 7) || ++ !strncmp(p, "/libc.so", 8) || + !strncmp(p, "/libpthread-2", 13)) + ptr = "application/x-sharedlib"; + } diff --git a/SOURCES/fapolicyd-do-manage-files.patch b/SOURCES/fapolicyd-do-manage-files.patch new file mode 100644 index 0000000..ce98850 --- /dev/null +++ b/SOURCES/fapolicyd-do-manage-files.patch @@ -0,0 +1,190 @@ +From 95ec2f9577abe98a73d8dcb9112043aa743fa7ad Mon Sep 17 00:00:00 2001 +From: Zoltan Fridrich +Date: Fri, 19 Nov 2021 18:15:33 +0100 +Subject: [PATCH] cli do_manage_file function refactoring and fix + +--- + src/cli/fapolicyd-cli.c | 159 ++++++++++++++++++++++------------------ + 1 file changed, 89 insertions(+), 70 deletions(-) + +diff --git a/src/cli/fapolicyd-cli.c b/src/cli/fapolicyd-cli.c +index ee5d5bd..30b92be 100644 +--- a/src/cli/fapolicyd-cli.c ++++ b/src/cli/fapolicyd-cli.c +@@ -207,87 +207,106 @@ static int do_dump_db(void) + return rc; + } + +- +-/* +- * This function always requires at least one option, the command. We can +- * guarantee that argv[2] is the command because getopt_long would have +- * printed an error otherwise. argv[3] would be an optional parameter based +- * on which command is being run. If argv[4] == "--trust-file" then argv[5] +- * specifies a trust file to operate on. +- * +- * The function returns 0 on success and 1 on failure +- */ +-static int do_manage_files(int argc, char * const argv[]) ++static int do_file_add(int argc, char * const argv[]) + { +- int rc = 0; ++ char full_path[PATH_MAX] = { 0 }; + +- if (argc > 0) { +- if ( (strcmp("add", argv[0]) != 0) +- && (strcmp("delete", argv[0]) != 0) +- && (strcmp("update", argv[0]) != 0) ) { +- fprintf(stderr, "%s is not valid option, choose from add|delete|update\n", argv[0]); +- goto args_err; +- } ++ if (argc == 1) { ++ if (!realpath(argv[0], full_path)) ++ return 3; ++ return file_append(full_path, NULL); + } ++ if (argc == 3) { ++ if (!realpath(argv[0], full_path)) ++ return 3; ++ if (strcmp("--trust-file", argv[1])) ++ return 2; ++ return file_append(full_path, argv[2]); ++ } ++ return 2; ++} + +- if (argc < 2) +- goto args_err; +- +- char full_path[PATH_MAX] = {0}; ++static int do_file_delete(int argc, char * const argv[]) ++{ ++ char full_path[PATH_MAX] = { 0 }; + +- if (realpath(argv[1], full_path) == NULL) { +- fprintf(stderr, "Cannot get realpath from: %s\n", argv[1]); +- perror("realpath"); +- goto args_err; ++ if (argc == 1) { ++ if (!realpath(argv[0], full_path)) ++ return 3; ++ return file_delete(full_path, NULL); + } ++ if (argc == 3) { ++ if (!realpath(argv[0], full_path)) ++ return 3; ++ if (strcmp("--trust-file", argv[1])) ++ return 2; ++ return file_delete(full_path, argv[2]); ++ } ++ return 2; ++} + +- if (strcmp("add", argv[0]) == 0) { +- switch (argc) { +- case 2: +- rc = file_append(full_path, NULL); +- break; +- case 4: +- if (strcmp("--trust-file", argv[2])) +- goto args_err; +- rc = file_append(full_path, argv[3]); +- break; +- default: +- goto args_err; +- } +- } else if (strcmp("delete", argv[0]) == 0) { +- switch (argc) { +- case 2: +- rc = file_delete(full_path, NULL); +- break; +- case 4: +- if (strcmp("--trust-file", argv[2])) +- goto args_err; +- rc = file_delete(full_path, argv[3]); +- break; +- default: +- goto args_err; +- } +- } else if (strcmp("update", argv[0]) == 0) { +- switch (argc) { +- case 2: +- rc = file_update(full_path, NULL); +- break; +- case 4: +- if (strcmp("--trust-file", argv[2])) +- goto args_err; +- rc = file_update(full_path, argv[3]); +- break; +- default: +- goto args_err; +- } ++static int do_file_update(int argc, char * const argv[]) ++{ ++ char full_path[PATH_MAX] = { 0 }; ++ ++ if (argc == 0) ++ return file_update("/", NULL); ++ if (argc == 1) { ++ if (!realpath(argv[0], full_path)) ++ return 3; ++ return file_update(full_path, NULL); ++ } ++ if (argc == 2) { ++ if (strcmp("--trust-file", argv[0])) ++ return 2; ++ return file_update("/", argv[1]); ++ } ++ if (argc == 3) { ++ if (!realpath(argv[0], full_path)) ++ return 3; ++ if (strcmp("--trust-file", argv[1])) ++ return 2; ++ return file_update(full_path, argv[2]); + } ++ return 2; ++} + +- return rc ? 1 : 0; ++static int do_manage_files(int argc, char * const argv[]) ++{ ++ int rc = 0; + +-args_err: +- fprintf(stderr, "Wrong number of arguments\n\n"); +- fprintf(stderr, "%s", usage); ++ if (argc < 1 || argc > 4) { ++ fprintf(stderr, "Wrong number of arguments\n"); ++ fprintf(stderr, "\n%s", usage); ++ return 1; ++ } ++ ++ if (!strcmp("add", argv[0])) ++ rc = do_file_add(argc - 1, argv + 1); ++ else if (!strcmp("delete", argv[0])) ++ rc = do_file_delete(argc - 1, argv + 1); ++ else if (!strcmp("update", argv[0])) ++ rc = do_file_update(argc - 1, argv + 1); ++ else { ++ fprintf(stderr, "%s is not a valid option, choose one of add|delete|update\n", argv[0]); ++ fprintf(stderr, "\n%s", usage); ++ return 1; ++ } + ++ switch (rc) { ++ case 0: // no error ++ return 0; ++ case 2: // args error ++ fprintf(stderr, "Wrong number of arguments\n"); ++ fprintf(stderr, "\n%s", usage); ++ break; ++ case 3: // realpath error ++ fprintf(stderr, "Can't obtain realpath from: %s\n", argv[1]); ++ fprintf(stderr, "\n%s", usage); ++ break; ++ default: // file function errors ++ break; ++ } + return 1; + } + diff --git a/SOURCES/fapolicyd-documentation.patch b/SOURCES/fapolicyd-documentation.patch new file mode 100644 index 0000000..0915497 --- /dev/null +++ b/SOURCES/fapolicyd-documentation.patch @@ -0,0 +1,16 @@ +diff --color -ru a/doc/fapolicyd.trust.5 b/doc/fapolicyd.trust.5 +--- a/doc/fapolicyd.trust.5 2021-11-12 20:21:54.000000000 +0100 ++++ b/doc/fapolicyd.trust.5 2021-12-07 13:28:18.358213561 +0100 +@@ -7,6 +7,12 @@ + contains list of trusted files/binaries for the application whitelisting daemon. You may add comments to the file by starting the line with a '#' character. + Each line has to contain three columns and space is a valid separator. The first column contains full path to the file, the second is size of the file in bytes + and the third is valid sha256 hash. ++.sp ++The directory \fI/etc/fapolicyd/trust\&.d\fR can be used to store multiple trust files\&. ++This way a privileged user can split the trust database into multiple files and manage them separately through \fBfapolicyd\-cli\fR\&. ++Functionally, the fapolicy daemon will behave the same way as if the whole trust database has been defined inside \fBfapolicyd\&.trust\fR file\&. ++Syntax and semantics of trust files inside \fBtrust\&.d\fR directory are the same as for \fBfapolicyd\&.trust\fR file (described above)\&. ++Trust files can either be created manually inside \fBtrust\&.d\fR directory or via \fBfapolicyd\-cli\fR\& (the latter option is recommended). + + .SH EXAMPLE + .PP diff --git a/SOURCES/fapolicyd-fix-escaping.patch b/SOURCES/fapolicyd-fix-escaping.patch new file mode 100644 index 0000000..8b32b05 --- /dev/null +++ b/SOURCES/fapolicyd-fix-escaping.patch @@ -0,0 +1,209 @@ +diff --color -ru a/init/fapolicyd.trust b/init/fapolicyd.trust +--- a/init/fapolicyd.trust 2021-11-12 20:21:54.000000000 +0100 ++++ b/init/fapolicyd.trust 2021-12-08 13:25:43.441187113 +0100 +@@ -1,3 +1,4 @@ ++# AUTOGENERATED FILE VERSION 2 + # This file contains a list of trusted files + # + # FULL PATH SIZE SHA256 +diff --color -ru a/src/cli/file-cli.c b/src/cli/file-cli.c +--- a/src/cli/file-cli.c 2021-11-12 20:21:54.000000000 +0100 ++++ b/src/cli/file-cli.c 2021-12-08 13:25:43.441187113 +0100 +@@ -89,9 +89,6 @@ + return 0; + } + +- +- +- + int file_append(const char *path, const char *fname) + { + set_message_mode(MSG_STDERR, DBG_NO); +@@ -110,11 +107,14 @@ + + char *dest = fname ? fapolicyd_strcat(TRUST_DIR_PATH, fname) : + TRUST_FILE_PATH; ++ + int rc = trust_file_append(dest, &add_list); + ++ list_empty(&add_list); ++ + if (fname) + free(dest); +- list_empty(&add_list); ++ + return rc ? -1 : 0; + } + +diff --color -ru a/src/library/trust-file.c b/src/library/trust-file.c +--- a/src/library/trust-file.c 2021-11-12 20:21:54.000000000 +0100 ++++ b/src/library/trust-file.c 2021-12-08 15:42:15.787206923 +0100 +@@ -51,6 +51,7 @@ + #define FTW_NOPENFD 1024 + #define FTW_FLAGS (FTW_ACTIONRETVAL | FTW_PHYS) + ++#define HEADER0 "# AUTOGENERATED FILE VERSION 2\n" + #define HEADER1 "# This file contains a list of trusted files\n" + #define HEADER2 "#\n" + #define HEADER3 "# FULL PATH SIZE SHA256\n" +@@ -137,12 +138,19 @@ + return 1; + } + +- size_t hlen = strlen(HEADER1); ++ size_t hlen; ++ hlen = strlen(HEADER0); ++ fwrite(HEADER0, hlen, 1, f); ++ ++ hlen = strlen(HEADER1); + fwrite(HEADER1, hlen, 1, f); ++ + hlen = strlen(HEADER2); + fwrite(HEADER2, hlen, 1, f); ++ + hlen = strlen(HEADER3); + fwrite(HEADER3, hlen, 1, f); ++ + hlen = strlen(HEADER4); + fwrite(HEADER4, hlen, 1, f); + +@@ -163,50 +171,49 @@ + return 0; + } + +- +- +-int trust_file_append(const char *fpath, const list_t *list) { +- int fd = open(fpath, O_CREAT | O_WRONLY | O_APPEND, 0600); +- if (fd == -1) { +- msg(LOG_ERR, "Cannot open %s", fpath); ++int trust_file_append(const char *fpath, list_t *list) ++{ ++ list_t content; ++ list_init(&content); ++ int rc = trust_file_load(fpath, &content); ++ if (rc) + return 1; +- } + + for (list_item_t *lptr = list->first; lptr; lptr = lptr->next) { +- int count = 1; +- char *line = make_path_string(lptr->index, &count); +- if (!line) +- continue; +- +- if (write(fd, line, count) == -1) { +- msg(LOG_ERR, "failed writing to %s\n", fpath); +- free(line); +- close(fd); +- return 2; +- } +- free(line); ++ int i = 0; ++ lptr->data = make_path_string(lptr->index, &i); + } + +- close(fd); +- return 0; ++ list_merge(&content, list); ++ write_out_list(&content, fpath); ++ list_empty(&content); ++ return rc ? 1 : 0; + } + + int trust_file_load(const char *fpath, list_t *list) + { ++ char buffer[BUFFER_SIZE]; ++ int escaped = 0; ++ long line = 0; ++ + FILE *file = fopen(fpath, "r"); + if (!file) { + msg(LOG_ERR, "Cannot open %s", fpath); + return 1; + } + +- char buffer[BUFFER_SIZE]; + while (fgets(buffer, BUFFER_SIZE, file)) { +- char name[4097], sha[65], *index, *data; ++ char name[4097], sha[65], *index = NULL, *data = NULL; + unsigned long sz; + unsigned int tsource = SRC_FILE_DB; + +- if (iscntrl(buffer[0]) || buffer[0] == '#') ++ line++; ++ ++ if (iscntrl(buffer[0]) || buffer[0] == '#') { ++ if (line == 1 && strncmp(buffer, HEADER0, strlen(HEADER0)) == 0) ++ escaped = 1; + continue; ++ } + + if (sscanf(buffer, FILE_READ_FORMAT, name, &sz, sha) != 3) { + msg(LOG_WARNING, "Can't parse %s", buffer); +@@ -217,7 +224,7 @@ + if (asprintf(&data, DATA_FORMAT, tsource, sz, sha) == -1) + data = NULL; + +- index = unescape(name); ++ index = escaped ? unescape(name) : strdup(name); + if (index == NULL) { + msg(LOG_ERR, "Could not unescape %s from %s", name, fpath); + free(data); +@@ -311,33 +318,22 @@ + + int trust_file_rm_duplicates(const char *fpath, list_t *list) + { +- FILE *file = fopen(fpath, "r"); +- if (!file) { +- msg(LOG_ERR, "Cannot open %s", fpath); +- return 1; +- } +- +- char buffer[BUFFER_SIZE]; +- while (fgets(buffer, BUFFER_SIZE, file)) { +- char thash[65], tpath[4097]; +- long unsigned size; ++ list_t trust_file; ++ list_init(&trust_file); + +- if (iscntrl(buffer[0]) || buffer[0] == '#') +- continue; ++ int rc = trust_file_load(fpath, &trust_file); ++ if (rc) ++ goto cleanup; + +- if (sscanf(buffer, FILE_READ_FORMAT, tpath, &size, thash) != 3) { +- msg(LOG_WARNING, "Can't parse %s", buffer); +- fclose(file); +- return 2; +- } +- +- list_remove(list, tpath); ++ for (list_item_t *lptr = trust_file.first; lptr; lptr = lptr->next) { ++ list_remove(list, lptr->index); + if (list->count == 0) + break; + } + +- fclose(file); +- return 0; ++cleanup: ++ list_empty(&trust_file); ++ return rc; + } + + +diff --color -ru a/src/library/trust-file.h b/src/library/trust-file.h +--- a/src/library/trust-file.h 2021-11-12 20:21:54.000000000 +0100 ++++ b/src/library/trust-file.h 2021-12-08 13:25:43.441187113 +0100 +@@ -30,8 +30,7 @@ + #define TRUST_FILE_PATH "/etc/fapolicyd/fapolicyd.trust" + #define TRUST_DIR_PATH "/etc/fapolicyd/trust.d/" + +-int trust_file_append(const char *fpath, const list_t *list); +- ++int trust_file_append(const char *fpath, list_t *list); + int trust_file_load(const char *fpath, list_t *list); + int trust_file_update_path(const char *fpath, const char *path); + int trust_file_delete_path(const char *fpath, const char *path); diff --git a/SOURCES/fapolicyd-selinux-allow-boot-home.patch b/SOURCES/fapolicyd-selinux-allow-boot-home.patch deleted file mode 100644 index f676d59..0000000 --- a/SOURCES/fapolicyd-selinux-allow-boot-home.patch +++ /dev/null @@ -1,40 +0,0 @@ -From a1a9a59f93ebfe6d0c9d725ed0712210994e6d64 Mon Sep 17 00:00:00 2001 -From: Zdenek Pytela -Date: Tue, 6 Apr 2021 16:06:48 +0200 -Subject: [PATCH] Allow fapolicyd watch boot and home directories - -The fapolicyd service needs watch_mount and watch_with_perm permissions -for fanotify/inotify/dnotify calls on the following directories: -- /boot and /boot/efi directories -- /home directories - -Note the /boot/efi directory has the dosfs_t label. ---- - fapolicyd.te | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/fapolicyd-selinux-0.4/fapolicyd.te b/fapolicyd-selinux-0.4/fapolicyd.te -index f5d0052..c12f385 100644 ---- a/fapolicyd-selinux-0.4/fapolicyd.te -+++ b/fapolicyd-selinux-0.4/fapolicyd.te -@@ -63,14 +63,20 @@ domain_read_all_domains_state(fapolicyd_t) - - files_mmap_usr_files(fapolicyd_t) - files_read_all_files(fapolicyd_t) -+files_watch_mount_boot_dirs(fapolicyd_t) -+files_watch_with_perm_boot_dirs(fapolicyd_t) - files_watch_mount_generic_tmp_dirs(fapolicyd_t) - files_watch_with_perm_generic_tmp_dirs(fapolicyd_t) -+files_watch_mount_home(fapolicyd_t) -+files_watch_with_perm_home(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) -+fs_watch_mount_dos_dirs(fapolicyd_t) -+fs_watch_with_perm_dos_dirs(fapolicyd_t) - - logging_send_syslog_msg(fapolicyd_t) - dbus_system_bus_client(fapolicyd_t) diff --git a/SOURCES/fapolicyd-selinux-watch-perm.patch b/SOURCES/fapolicyd-selinux-watch-perm.patch deleted file mode 100644 index 4128b8e..0000000 --- a/SOURCES/fapolicyd-selinux-watch-perm.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6a966a3ee89233a0a055712f39ca564ba91183bf Mon Sep 17 00:00:00 2001 -From: Zdenek Pytela -Date: Thu, 15 Apr 2021 16:56:08 +0200 -Subject: [PATCH] Allow fapolicyd watch_mount/watch_with_perm all files and - directories - -For the fanotify_mark() syscall, fapolicyd uses the FAN_MARK_MOUNT flag -to mark the file's mount point to monitor. As this can be any file or -directory on the filesystem, the SELinux watch_mount and watch_with_perm -permissions are allowed for the file_type attribute. ---- - fapolicyd.te | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/fapolicyd-selinux-0.4/fapolicyd.te b/fapolicyd-selinux-0.4/fapolicyd.te -index c12f385..582e03f 100644 ---- a/fapolicyd-selinux-0.4/fapolicyd.te -+++ b/fapolicyd-selinux-0.4/fapolicyd.te -@@ -36,6 +36,12 @@ allow fapolicyd_t self:process { setcap setsched }; - allow fapolicyd_t self:unix_stream_socket create_stream_socket_perms; - allow fapolicyd_t self:unix_dgram_socket create_socket_perms; - -+gen_require(` -+ attribute file_type; -+') -+allow fapolicyd_t file_type:dir { watch_mount watch_with_perm }; -+allow fapolicyd_t file_type:file { watch_mount watch_with_perm }; -+ - 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 new file mode 100644 index 0000000..58b3146 --- /dev/null +++ b/SOURCES/fapolicyd-selinux.patch @@ -0,0 +1,170 @@ +diff --color -ru a/fapolicyd-selinux-0.4/fapolicyd.if b/fapolicyd-selinux-0.4/fapolicyd.if +--- a/fapolicyd-selinux-0.4/fapolicyd.if 2021-03-23 10:21:31.000000000 +0100 ++++ b/fapolicyd-selinux-0.4/fapolicyd.if 2021-12-14 13:35:17.842430123 +0100 +@@ -2,6 +2,122 @@ + + ######################################## + ## ++## Watch_mount directories in /boot. ++## ++## ++## ++## Domain allowed access. ++## ++## ++# ++ ++ifndef(`files_watch_mount_boot_dirs',` ++ interface(`files_watch_mount_boot_dirs',` ++ gen_require(` ++ type boot_t; ++ ') ++ ++ allow $1 boot_t:dir watch_mount_dir_perms; ++ ') ++') ++ ++ ++######################################## ++## ++## Watch_mount home directories. ++## ++## ++## ++## Domain allowed access. ++## ++## ++# ++ ++ifndef(`files_watch_mount_home',` ++ interface(`files_watch_mount_home',` ++ gen_require(` ++ type home_root_t; ++ ') ++ ++ allow $1 home_root_t:dir watch_mount_dir_perms; ++ ') ++') ++ ++ ++######################################## ++## ++## Watch_with_perm home directories. ++## ++## ++## ++## Domain allowed access. ++## ++## ++# ++ ++ifndef(`files_watch_with_perm_home',` ++interface(`files_watch_with_perm_home',` ++ gen_require(` ++ type home_root_t; ++ ') ++ ++ allow $1 home_root_t:dir watch_with_perm_dir_perms; ++') ++') ++ ++ ++######################################## ++## ++## Watch_mount dirs on a DOS filesystem. ++## ++## ++## ++## Domain allowed access. ++## ++## ++# ++ ++ifndef(`fs_watch_mount_dos_dirs',` ++interface(`fs_watch_mount_dos_dirs',` ++ gen_require(` ++ type dosfs_t; ++ ') ++ ++ watch_mount_dirs_pattern($1, dosfs_t, dosfs_t) ++') ++') ++ ++ ++ ++######################################## ++## ++## Watch_with_perm dirs on a DOS filesystem. ++## ++## ++## ++## Domain allowed access. ++## ++## ++# ++ ++ifndef(`fs_watch_with_perm_dos_dirs',` ++interface(`fs_watch_with_perm_dos_dirs',` ++ gen_require(` ++ type dosfs_t; ++ ') ++ ++ watch_with_perm_dirs_pattern($1, dosfs_t, dosfs_t) ++') ++') ++ ++ ++################################################################################################### ++ ++ ++ ++ ++######################################## ++## + ## Execute fapolicyd_exec_t in the fapolicyd domain. + ## + ## +diff --color -ru a/fapolicyd-selinux-0.4/fapolicyd.te b/fapolicyd-selinux-0.4/fapolicyd.te +--- a/fapolicyd-selinux-0.4/fapolicyd.te 2021-03-23 10:21:31.000000000 +0100 ++++ b/fapolicyd-selinux-0.4/fapolicyd.te 2021-12-14 13:35:17.842430123 +0100 +@@ -1,5 +1,6 @@ + policy_module(fapolicyd, 1.0.0) + ++ + ######################################## + # + # Declarations +@@ -36,6 +37,12 @@ + allow fapolicyd_t self:unix_stream_socket create_stream_socket_perms; + allow fapolicyd_t self:unix_dgram_socket create_socket_perms; + ++gen_require(` ++ attribute file_type; ++') ++allow fapolicyd_t file_type:dir { watch_mount watch_with_perm }; ++allow fapolicyd_t file_type:file { watch_mount watch_with_perm }; ++ + manage_files_pattern(fapolicyd_t, fapolicyd_log_t, fapolicyd_log_t) + logging_log_filetrans(fapolicyd_t, fapolicyd_log_t, file) + +@@ -63,14 +70,20 @@ + + files_mmap_usr_files(fapolicyd_t) + files_read_all_files(fapolicyd_t) ++files_watch_mount_boot_dirs(fapolicyd_t) ++files_watch_with_perm_boot_dirs(fapolicyd_t) + files_watch_mount_generic_tmp_dirs(fapolicyd_t) + files_watch_with_perm_generic_tmp_dirs(fapolicyd_t) ++files_watch_mount_home(fapolicyd_t) ++files_watch_with_perm_home(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) ++fs_watch_mount_dos_dirs(fapolicyd_t) ++fs_watch_with_perm_dos_dirs(fapolicyd_t) + + logging_send_syslog_msg(fapolicyd_t) + dbus_system_bus_client(fapolicyd_t) diff --git a/SOURCES/fapolicyd-trust-file-append.patch b/SOURCES/fapolicyd-trust-file-append.patch new file mode 100644 index 0000000..99fb854 --- /dev/null +++ b/SOURCES/fapolicyd-trust-file-append.patch @@ -0,0 +1,117 @@ +diff --color -ru a/src/library/trust-file.c b/src/library/trust-file.c +--- a/src/library/trust-file.c 2021-12-13 09:37:56.633741747 +0100 ++++ b/src/library/trust-file.c 2021-12-13 13:44:13.689151921 +0100 +@@ -176,8 +176,11 @@ + list_t content; + list_init(&content); + int rc = trust_file_load(fpath, &content); +- if (rc) ++ // if trust file does not exist, we ignore it as it will be created while writing ++ if (rc == 2) { ++ // exit on parse error, we dont want invalid entries to be removed + return 1; ++ } + + for (list_item_t *lptr = list->first; lptr; lptr = lptr->next) { + int i = 0; +@@ -187,9 +190,16 @@ + list_merge(&content, list); + write_out_list(&content, fpath); + list_empty(&content); +- return rc ? 1 : 0; ++ return 0; + } + ++/** ++ * @brief Load trust file into list ++ * ++ * @param fpath Full path to trust file ++ * @param list Trust file will be loaded into this list ++ * @return 0 on success, 1 if file can't be open, 2 on parsing error ++ */ + int trust_file_load(const char *fpath, list_t *list) + { + char buffer[BUFFER_SIZE]; +@@ -197,10 +207,8 @@ + long line = 0; + + FILE *file = fopen(fpath, "r"); +- if (!file) { +- msg(LOG_ERR, "Cannot open %s", fpath); ++ if (!file) + return 1; +- } + + while (fgets(buffer, BUFFER_SIZE, file)) { + char name[4097], sha[65], *index = NULL, *data = NULL; +@@ -257,7 +265,17 @@ + { + list_t list; + list_init(&list); +- trust_file_load(fpath, &list); ++ int rc = trust_file_load(fpath, &list); ++ switch (rc) { ++ case 1: ++ msg(LOG_ERR, "Cannot open %s", fpath); ++ return 0; ++ case 2: ++ list_empty(&list); ++ return -1; ++ default: ++ break; ++ } + + int count = 0; + size_t path_len = strlen(path); +@@ -295,7 +313,17 @@ + { + list_t list; + list_init(&list); +- trust_file_load(fpath, &list); ++ int rc = trust_file_load(fpath, &list); ++ switch (rc) { ++ case 1: ++ msg(LOG_ERR, "Cannot open %s", fpath); ++ return 0; ++ case 2: ++ list_empty(&list); ++ return -1; ++ default: ++ break; ++ } + + int count = 0; + size_t path_len = strlen(path); +@@ -320,20 +348,26 @@ + { + list_t trust_file; + list_init(&trust_file); +- + int rc = trust_file_load(fpath, &trust_file); +- if (rc) +- goto cleanup; +- ++ switch (rc) { ++ case 1: ++ msg(LOG_ERR, "Cannot open %s", fpath); ++ return -1; ++ case 2: ++ list_empty(&trust_file); ++ return -1; ++ default: ++ break; ++ } ++ + for (list_item_t *lptr = trust_file.first; lptr; lptr = lptr->next) { + list_remove(list, lptr->index); + if (list->count == 0) + break; + } + +-cleanup: + list_empty(&trust_file); +- return rc; ++ return 0; + } + + diff --git a/SOURCES/fapolicyd-uthash-bundle.patch b/SOURCES/fapolicyd-uthash-bundle.patch index c482992..0131884 100644 --- a/SOURCES/fapolicyd-uthash-bundle.patch +++ b/SOURCES/fapolicyd-uthash-bundle.patch @@ -1,7 +1,7 @@ -diff -up ./configure.ac.uthash ./configure.ac ---- ./configure.ac.uthash 2021-03-25 22:12:48.164450403 +0100 -+++ ./configure.ac 2021-03-25 22:13:01.067282788 +0100 -@@ -67,10 +67,6 @@ AC_CHECK_HEADER(sys/fanotify.h, , [AC_MS +diff --color -ru a/configure.ac b/configure.ac +--- a/configure.ac 2021-11-12 20:21:54.000000000 +0100 ++++ b/configure.ac 2021-12-14 13:47:11.890649552 +0100 +@@ -67,10 +67,6 @@ ["Couldn't find sys/fanotify.h...your kernel might not be new enough"] )]) AC_CHECK_FUNCS(fexecve, [], []) @@ -12,9 +12,9 @@ diff -up ./configure.ac.uthash ./configure.ac echo . echo Checking for required libraries AC_CHECK_LIB(udev, udev_device_get_devnode, , [AC_MSG_ERROR([libudev not found])], -ludev) -diff -up ./src/library/rpm-backend.c.uthash ./src/library/rpm-backend.c ---- ./src/library/rpm-backend.c.uthash 2021-01-05 16:27:53.000000000 +0100 -+++ ./src/library/rpm-backend.c 2021-03-25 22:12:33.212644641 +0100 +diff --color -ru a/src/library/rpm-backend.c b/src/library/rpm-backend.c +--- a/src/library/rpm-backend.c 2021-11-12 20:21:54.000000000 +0100 ++++ b/src/library/rpm-backend.c 2021-12-14 13:47:26.833926203 +0100 @@ -32,7 +32,7 @@ #include #include @@ -23,11 +23,11 @@ diff -up ./src/library/rpm-backend.c.uthash ./src/library/rpm-backend.c +#include "uthash.h" #include "message.h" - -diff -up ./src/Makefile.am.uthash ./src/Makefile.am ---- ./src/Makefile.am.uthash 2021-01-05 16:27:53.000000000 +0100 -+++ ./src/Makefile.am 2021-03-25 22:12:33.212644641 +0100 -@@ -5,6 +5,9 @@ AM_CPPFLAGS = \ + #include "gcc-attributes.h" +diff --color -ru a/src/Makefile.am b/src/Makefile.am +--- a/src/Makefile.am 2021-11-12 20:21:54.000000000 +0100 ++++ b/src/Makefile.am 2021-12-14 13:48:03.218599808 +0100 +@@ -5,6 +5,9 @@ -I${top_srcdir} \ -I${top_srcdir}/src/library diff --git a/SOURCES/selinux-backport.patch b/SOURCES/selinux-backport.patch deleted file mode 100644 index 9666860..0000000 --- a/SOURCES/selinux-backport.patch +++ /dev/null @@ -1,136 +0,0 @@ -diff -up ./fapolicyd-selinux-0.4/fapolicyd.if.backport ./fapolicyd-selinux-0.4/fapolicyd.if ---- ./fapolicyd-selinux-0.4/fapolicyd.if.backport 2021-03-23 10:21:31.000000000 +0100 -+++ ./fapolicyd-selinux-0.4/fapolicyd.if 2021-07-20 17:38:51.266053356 +0200 -@@ -2,6 +2,122 @@ - - ######################################## - ## -+## Watch_mount directories in /boot. -+## -+## -+## -+## Domain allowed access. -+## -+## -+# -+ -+ifndef(`files_watch_mount_boot_dirs',` -+ interface(`files_watch_mount_boot_dirs',` -+ gen_require(` -+ type boot_t; -+ ') -+ -+ allow $1 boot_t:dir watch_mount_dir_perms; -+ ') -+') -+ -+ -+######################################## -+## -+## Watch_mount home directories. -+## -+## -+## -+## Domain allowed access. -+## -+## -+# -+ -+ifndef(`files_watch_mount_home',` -+ interface(`files_watch_mount_home',` -+ gen_require(` -+ type home_root_t; -+ ') -+ -+ allow $1 home_root_t:dir watch_mount_dir_perms; -+ ') -+') -+ -+ -+######################################## -+## -+## Watch_with_perm home directories. -+## -+## -+## -+## Domain allowed access. -+## -+## -+# -+ -+ifndef(`files_watch_with_perm_home',` -+interface(`files_watch_with_perm_home',` -+ gen_require(` -+ type home_root_t; -+ ') -+ -+ allow $1 home_root_t:dir watch_with_perm_dir_perms; -+') -+') -+ -+ -+######################################## -+## -+## Watch_mount dirs on a DOS filesystem. -+## -+## -+## -+## Domain allowed access. -+## -+## -+# -+ -+ifndef(`fs_watch_mount_dos_dirs',` -+interface(`fs_watch_mount_dos_dirs',` -+ gen_require(` -+ type dosfs_t; -+ ') -+ -+ watch_mount_dirs_pattern($1, dosfs_t, dosfs_t) -+') -+') -+ -+ -+ -+######################################## -+## -+## Watch_with_perm dirs on a DOS filesystem. -+## -+## -+## -+## Domain allowed access. -+## -+## -+# -+ -+ifndef(`fs_watch_with_perm_dos_dirs',` -+interface(`fs_watch_with_perm_dos_dirs',` -+ gen_require(` -+ type dosfs_t; -+ ') -+ -+ watch_with_perm_dirs_pattern($1, dosfs_t, dosfs_t) -+') -+') -+ -+ -+################################################################################################### -+ -+ -+ -+ -+######################################## -+## - ## Execute fapolicyd_exec_t in the fapolicyd domain. - ## - ## -diff -up ./fapolicyd-selinux-0.4/fapolicyd.te.backport ./fapolicyd-selinux-0.4/fapolicyd.te ---- ./fapolicyd-selinux-0.4/fapolicyd.te.backport 2021-07-20 17:31:12.161166538 +0200 -+++ ./fapolicyd-selinux-0.4/fapolicyd.te 2021-07-20 17:31:12.162166524 +0200 -@@ -1,5 +1,6 @@ - policy_module(fapolicyd, 1.0.0) - -+ - ######################################## - # - # Declarations diff --git a/SPECS/fapolicyd.spec b/SPECS/fapolicyd.spec index efeea55..4d77892 100644 --- a/SPECS/fapolicyd.spec +++ b/SPECS/fapolicyd.spec @@ -4,8 +4,8 @@ Summary: Application Whitelisting Daemon Name: fapolicyd -Version: 1.0.3 -Release: 4%{?dist} +Version: 1.0.4 +Release: 101%{?dist} License: GPLv3+ URL: http://people.redhat.com/sgrubb/fapolicyd Source0: https://people.redhat.com/sgrubb/fapolicyd/%{name}-%{version}.tar.gz @@ -31,11 +31,12 @@ Requires(preun): systemd-units Requires(postun): systemd-units Patch1: fapolicyd-uthash-bundle.patch -Patch2: fapolicyd-selinux-allow-boot-home.patch -Patch3: fapolicyd-selinux-watch-perm.patch - -# hardcode missing selinux definitions from selinux-policy -Patch4: selinux-backport.patch +Patch2: fapolicyd-selinux.patch +Patch3: fapolicyd-do-manage-files.patch +Patch4: fapolicyd-documentation.patch +Patch5: fapolicyd-fix-escaping.patch +Patch6: fapolicyd-trust-file-append.patch +Patch7: fapolicyd-detect-sharedlib.patch %description Fapolicyd (File Access Policy Daemon) implements application whitelisting @@ -81,10 +82,12 @@ Don't use dnf and rpm plugin together. %patch1 -p1 -b .uthash %endif -%patch2 -p1 -b .home-boot -%patch3 -p1 -b .watch-perm - -%patch4 -p1 -b .backport +%patch2 -p1 -b .selinux +%patch3 -p1 -b .do-manage-files +%patch4 -p1 -b .documentation +%patch5 -p1 -b .fix-escaping +%patch6 -p1 -b .trust-file-append +%patch7 -p1 -b .detect-sharedlib sed -i "s/%python2_path%/`readlink -f %{__python2} | sed 's/\//\\\\\//g'`/g" init/%{name}.rules.* sed -i "s/%python3_path%/`readlink -f %{__python3} | sed 's/\//\\\\\//g'`/g" init/%{name}.rules.* @@ -119,6 +122,7 @@ install -p -m 644 -D init/%{name}-tmpfiles.conf %{buildroot}/%{_tmpfilesdir}/%{n install -p -m 644 init/%{name}.rules.known-libs %{buildroot}/%{_sysconfdir}/%{name}/%{name}.rules mkdir -p %{buildroot}/%{_localstatedir}/lib/%{name} mkdir -p %{buildroot}/run/%{name} +mkdir -p %{buildroot}%{_sysconfdir}/%{name}/trust.d # selinux install -d %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} @@ -170,6 +174,7 @@ end %attr(755,root,%{name}) %dir %{_datadir}/%{name} %attr(644,root,%{name}) %{_datadir}/%{name}/%{name}.rules.* %attr(750,root,%{name}) %dir %{_sysconfdir}/%{name} +%attr(750,root,%{name}) %dir %{_sysconfdir}/%{name}/trust.d %config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}.conf %config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}.trust %config(noreplace) %attr(644,root,%{name}) %{_sysconfdir}/%{name}/%{name}.rules @@ -190,7 +195,7 @@ end %files selinux %{_datadir}/selinux/packages/%{selinuxtype}/%{name}.pp.bz2 -%ghost %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{name} +%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{name} %{_datadir}/selinux/devel/include/%{moduletype}/ipp-%{name}.if %post selinux @@ -211,6 +216,19 @@ fi %changelog +* Tue Dec 14 2021 Zoltan Fridrich - 1.0.4-101 +RHEL 9.0.0 ERRATUM +- rebase to 1.0.4 +- added rpm_sha256_only option +- added trust.d directory +- allow file names with whitespaces in trust files +- use full paths in trust files +Resolves: rhbz#2032408 +- fix libc.so getting identified as application/x-executable +Resolves: rhbz#2015307 +- fix selinux DSP module definition in spec file +Resolves: rhbz#2014449 + * Mon Aug 09 2021 Mohan Boddu - 1.0.3-4 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688