diff --git a/rpm-4.16.1.3-fapolicyd-make-write-nonblocking.patch b/rpm-4.16.1.3-fapolicyd-make-write-nonblocking.patch new file mode 100644 index 0000000..343bd02 --- /dev/null +++ b/rpm-4.16.1.3-fapolicyd-make-write-nonblocking.patch @@ -0,0 +1,167 @@ +From 534fd1f0c84b12ba6080a46e07c57ef913c77cba Mon Sep 17 00:00:00 2001 +From: Radovan Sroka +Date: Thu, 25 Aug 2022 15:38:01 +0200 +Subject: [PATCH] fapolicyd: Make write() nonblocking + +- switch to read only and non blocking mode for pipe +- add 1 minute loop to wait for pipe to reappear + +Sometimes during the system update/upgrade fapolicyd +get restarted e.g. when systemd gets updated. +That can lead to the situation where fapolicyd pipe +has been removed and created again. +In such cases rpm-plugin-fapolicyd gets stuck on +write() to the pipe which does not exist anymore. +After switching to non blocking file descriptor +we can try to reopen the pipe if there is an error +from write(). Assuming that a new pipe should appear +when fapolicyd daemon starts again. +If not then after 1 minute of waiting we expect +fapolicyd daemon to be not active and we let the +transaction continue. + +Signed-off-by: Radovan Sroka +--- + plugins/fapolicyd.c | 74 +++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 65 insertions(+), 9 deletions(-) + +diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c +index 1ff50c30f..6c6322941 100644 +--- a/plugins/fapolicyd.c ++++ b/plugins/fapolicyd.c +@@ -27,7 +27,7 @@ static rpmRC open_fifo(struct fapolicyd_data* state) + int fd = -1; + struct stat s; + +- fd = open(state->fifo_path, O_RDWR); ++ fd = open(state->fifo_path, O_WRONLY|O_NONBLOCK); + if (fd == -1) { + rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno)); + goto bad; +@@ -55,15 +55,26 @@ static rpmRC open_fifo(struct fapolicyd_data* state) + } + + state->fd = fd; ++ + /* considering success */ + return RPMRC_OK; + + bad: + if (fd >= 0) + close(fd); ++ ++ state->fd = -1; + return RPMRC_FAIL; + } + ++static void close_fifo(struct fapolicyd_data* state) ++{ ++ if (state->fd > 0) ++ (void) close(state->fd); ++ ++ state->fd = -1; ++} ++ + static rpmRC write_fifo(struct fapolicyd_data* state, const char * str) + { + ssize_t len = strlen(str); +@@ -86,6 +97,54 @@ static rpmRC write_fifo(struct fapolicyd_data* state, const char * str) + return RPMRC_FAIL; + } + ++static void try_to_write_to_fifo(struct fapolicyd_data* state, const char * str) ++{ ++ int reload = 0; ++ int printed = 0; ++ ++ /* 1min/60s */ ++ const int timeout = 60; ++ ++ /* wait up to X seconds */ ++ for (int i = 0; i < timeout; i++) { ++ ++ if (reload) { ++ if (!printed) { ++ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: waiting for the service connection to resume, it can take up to %d seconds\n", timeout); ++ printed = 1; ++ } ++ ++ (void) close_fifo(state); ++ (void) open_fifo(state); ++ } ++ ++ if (state->fd >= 0) { ++ if (write_fifo(state, str) == RPMRC_OK) { ++ ++ /* write was successful after few reopens */ ++ if (reload) ++ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has resumed\n"); ++ ++ break; ++ } ++ } ++ ++ /* failed write or reopen */ ++ reload = 1; ++ sleep(1); ++ ++ /* the last iteration */ ++ /* consider failure */ ++ if (i == timeout-1) { ++ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has not resumed\n"); ++ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: continuing without the service\n"); ++ } ++ ++ } ++ ++} ++ ++ + static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts) + { + if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS)) +@@ -102,10 +161,7 @@ static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts) + + static void fapolicyd_cleanup(rpmPlugin plugin) + { +- if (fapolicyd_state.fd > 0) +- (void) close(fapolicyd_state.fd); +- +- fapolicyd_state.fd = -1; ++ (void) close_fifo(&fapolicyd_state); + } + + static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res) +@@ -116,9 +172,9 @@ static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res) + /* we are ready */ + if (fapolicyd_state.fd > 0) { + /* send a signal that transaction is over */ +- (void) write_fifo(&fapolicyd_state, "1\n"); ++ (void) try_to_write_to_fifo(&fapolicyd_state, "1\n"); + /* flush cache */ +- (void) write_fifo(&fapolicyd_state, "2\n"); ++ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n"); + } + + end: +@@ -133,7 +189,7 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name, + + if (fapolicyd_state.changed_files > 0) { + /* send signal to flush cache */ +- (void) write_fifo(&fapolicyd_state, "2\n"); ++ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n"); + + /* optimize flushing */ + /* flush only when there was an actual change */ +@@ -176,7 +232,7 @@ static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, + char * sha = rpmfiFDigestHex(fi, NULL); + + snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha); +- (void) write_fifo(&fapolicyd_state, buffer); ++ (void) try_to_write_to_fifo(&fapolicyd_state, buffer); + + free(sha); + +-- +2.37.3 + diff --git a/rpm.spec b/rpm.spec index d21d853..a90ac35 100644 --- a/rpm.spec +++ b/rpm.spec @@ -32,7 +32,7 @@ %global rpmver 4.16.1.3 #global snapver rc1 -%global rel 17 +%global rel 18 %global sover 9 %global srcver %{rpmver}%{?snapver:-%{snapver}} @@ -83,6 +83,7 @@ Patch111: rpm-4.16.1.3-skip-recorded-symlinks-in-setperms.patch Patch112: rpm-4.16.1.3-fix-regression-reading-rpm-v3-pkgs.patch Patch113: rpm-4.16.1.3-fix-spurious-transfiletriggerpostun-execution.patch Patch114: rpm-4.16.1.3-Make-rpm2cpio.sh-more-robust.patch +Patch115: rpm-4.16.1.3-fapolicyd-make-write-nonblocking.patch # These are not yet upstream Patch906: rpm-4.7.1-geode-i686.patch @@ -614,6 +615,9 @@ fi %doc doc/librpm/html/* %changelog +* Fri Sep 23 2022 Michal Domonkos - 4.16.1.3-18 +- Make write() nonblocking in fapolicyd plugin (#2111251) + * Wed Aug 03 2022 Florian Festi - 4.16.1.3-17 - Make rpm2cpio.sh more robust (#1983015)