|
|
c2c80e |
From 534fd1f0c84b12ba6080a46e07c57ef913c77cba Mon Sep 17 00:00:00 2001
|
|
|
c2c80e |
From: Radovan Sroka <rsroka@redhat.com>
|
|
|
c2c80e |
Date: Thu, 25 Aug 2022 15:38:01 +0200
|
|
|
c2c80e |
Subject: [PATCH] fapolicyd: Make write() nonblocking
|
|
|
c2c80e |
|
|
|
c2c80e |
- switch to read only and non blocking mode for pipe
|
|
|
c2c80e |
- add 1 minute loop to wait for pipe to reappear
|
|
|
c2c80e |
|
|
|
c2c80e |
Sometimes during the system update/upgrade fapolicyd
|
|
|
c2c80e |
get restarted e.g. when systemd gets updated.
|
|
|
c2c80e |
That can lead to the situation where fapolicyd pipe
|
|
|
c2c80e |
has been removed and created again.
|
|
|
c2c80e |
In such cases rpm-plugin-fapolicyd gets stuck on
|
|
|
c2c80e |
write() to the pipe which does not exist anymore.
|
|
|
c2c80e |
After switching to non blocking file descriptor
|
|
|
c2c80e |
we can try to reopen the pipe if there is an error
|
|
|
c2c80e |
from write(). Assuming that a new pipe should appear
|
|
|
c2c80e |
when fapolicyd daemon starts again.
|
|
|
c2c80e |
If not then after 1 minute of waiting we expect
|
|
|
c2c80e |
fapolicyd daemon to be not active and we let the
|
|
|
c2c80e |
transaction continue.
|
|
|
c2c80e |
|
|
|
c2c80e |
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
|
|
|
c2c80e |
---
|
|
|
c2c80e |
plugins/fapolicyd.c | 74 +++++++++++++++++++++++++++++++++++++++------
|
|
|
c2c80e |
1 file changed, 65 insertions(+), 9 deletions(-)
|
|
|
c2c80e |
|
|
|
c2c80e |
diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
|
|
|
c2c80e |
index 1ff50c30f..6c6322941 100644
|
|
|
c2c80e |
--- a/plugins/fapolicyd.c
|
|
|
c2c80e |
+++ b/plugins/fapolicyd.c
|
|
|
c2c80e |
@@ -27,7 +27,7 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
|
|
|
c2c80e |
int fd = -1;
|
|
|
c2c80e |
struct stat s;
|
|
|
c2c80e |
|
|
|
c2c80e |
- fd = open(state->fifo_path, O_RDWR);
|
|
|
c2c80e |
+ fd = open(state->fifo_path, O_WRONLY|O_NONBLOCK);
|
|
|
c2c80e |
if (fd == -1) {
|
|
|
c2c80e |
rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
|
|
|
c2c80e |
goto bad;
|
|
|
c2c80e |
@@ -55,15 +55,26 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
|
|
|
c2c80e |
}
|
|
|
c2c80e |
|
|
|
c2c80e |
state->fd = fd;
|
|
|
c2c80e |
+
|
|
|
c2c80e |
/* considering success */
|
|
|
c2c80e |
return RPMRC_OK;
|
|
|
c2c80e |
|
|
|
c2c80e |
bad:
|
|
|
c2c80e |
if (fd >= 0)
|
|
|
c2c80e |
close(fd);
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ state->fd = -1;
|
|
|
c2c80e |
return RPMRC_FAIL;
|
|
|
c2c80e |
}
|
|
|
c2c80e |
|
|
|
c2c80e |
+static void close_fifo(struct fapolicyd_data* state)
|
|
|
c2c80e |
+{
|
|
|
c2c80e |
+ if (state->fd > 0)
|
|
|
c2c80e |
+ (void) close(state->fd);
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ state->fd = -1;
|
|
|
c2c80e |
+}
|
|
|
c2c80e |
+
|
|
|
c2c80e |
static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
|
|
|
c2c80e |
{
|
|
|
c2c80e |
ssize_t len = strlen(str);
|
|
|
c2c80e |
@@ -86,6 +97,54 @@ static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
|
|
|
c2c80e |
return RPMRC_FAIL;
|
|
|
c2c80e |
}
|
|
|
c2c80e |
|
|
|
c2c80e |
+static void try_to_write_to_fifo(struct fapolicyd_data* state, const char * str)
|
|
|
c2c80e |
+{
|
|
|
c2c80e |
+ int reload = 0;
|
|
|
c2c80e |
+ int printed = 0;
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ /* 1min/60s */
|
|
|
c2c80e |
+ const int timeout = 60;
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ /* wait up to X seconds */
|
|
|
c2c80e |
+ for (int i = 0; i < timeout; i++) {
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ if (reload) {
|
|
|
c2c80e |
+ if (!printed) {
|
|
|
c2c80e |
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: waiting for the service connection to resume, it can take up to %d seconds\n", timeout);
|
|
|
c2c80e |
+ printed = 1;
|
|
|
c2c80e |
+ }
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ (void) close_fifo(state);
|
|
|
c2c80e |
+ (void) open_fifo(state);
|
|
|
c2c80e |
+ }
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ if (state->fd >= 0) {
|
|
|
c2c80e |
+ if (write_fifo(state, str) == RPMRC_OK) {
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ /* write was successful after few reopens */
|
|
|
c2c80e |
+ if (reload)
|
|
|
c2c80e |
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has resumed\n");
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ break;
|
|
|
c2c80e |
+ }
|
|
|
c2c80e |
+ }
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ /* failed write or reopen */
|
|
|
c2c80e |
+ reload = 1;
|
|
|
c2c80e |
+ sleep(1);
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ /* the last iteration */
|
|
|
c2c80e |
+ /* consider failure */
|
|
|
c2c80e |
+ if (i == timeout-1) {
|
|
|
c2c80e |
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has not resumed\n");
|
|
|
c2c80e |
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: continuing without the service\n");
|
|
|
c2c80e |
+ }
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+ }
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+}
|
|
|
c2c80e |
+
|
|
|
c2c80e |
+
|
|
|
c2c80e |
static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
|
|
|
c2c80e |
{
|
|
|
c2c80e |
if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
|
|
|
c2c80e |
@@ -102,10 +161,7 @@ static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
|
|
|
c2c80e |
|
|
|
c2c80e |
static void fapolicyd_cleanup(rpmPlugin plugin)
|
|
|
c2c80e |
{
|
|
|
c2c80e |
- if (fapolicyd_state.fd > 0)
|
|
|
c2c80e |
- (void) close(fapolicyd_state.fd);
|
|
|
c2c80e |
-
|
|
|
c2c80e |
- fapolicyd_state.fd = -1;
|
|
|
c2c80e |
+ (void) close_fifo(&fapolicyd_state);
|
|
|
c2c80e |
}
|
|
|
c2c80e |
|
|
|
c2c80e |
static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
|
|
|
c2c80e |
@@ -116,9 +172,9 @@ static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
|
|
|
c2c80e |
/* we are ready */
|
|
|
c2c80e |
if (fapolicyd_state.fd > 0) {
|
|
|
c2c80e |
/* send a signal that transaction is over */
|
|
|
c2c80e |
- (void) write_fifo(&fapolicyd_state, "1\n");
|
|
|
c2c80e |
+ (void) try_to_write_to_fifo(&fapolicyd_state, "1\n");
|
|
|
c2c80e |
/* flush cache */
|
|
|
c2c80e |
- (void) write_fifo(&fapolicyd_state, "2\n");
|
|
|
c2c80e |
+ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n");
|
|
|
c2c80e |
}
|
|
|
c2c80e |
|
|
|
c2c80e |
end:
|
|
|
c2c80e |
@@ -133,7 +189,7 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
|
|
|
c2c80e |
|
|
|
c2c80e |
if (fapolicyd_state.changed_files > 0) {
|
|
|
c2c80e |
/* send signal to flush cache */
|
|
|
c2c80e |
- (void) write_fifo(&fapolicyd_state, "2\n");
|
|
|
c2c80e |
+ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n");
|
|
|
c2c80e |
|
|
|
c2c80e |
/* optimize flushing */
|
|
|
c2c80e |
/* flush only when there was an actual change */
|
|
|
c2c80e |
@@ -176,7 +232,7 @@ static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
|
|
|
c2c80e |
char * sha = rpmfiFDigestHex(fi, NULL);
|
|
|
c2c80e |
|
|
|
c2c80e |
snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
|
|
|
c2c80e |
- (void) write_fifo(&fapolicyd_state, buffer);
|
|
|
c2c80e |
+ (void) try_to_write_to_fifo(&fapolicyd_state, buffer);
|
|
|
c2c80e |
|
|
|
c2c80e |
free(sha);
|
|
|
c2c80e |
|
|
|
c2c80e |
--
|
|
|
c2c80e |
2.37.3
|
|
|
c2c80e |
|