[Rpm-maint] [rpm-software-management/rpm] [WIP] Added fapolicyd plugin (#1475)
Panu Matilainen
notifications at github.com
Wed Jan 13 10:13:31 UTC 2021
@pmatilai requested changes on this pull request.
See above, bunch of mostly minor issues and some questions to address.
> + return RPMRC_OK;
+ }
+
+ if (stat(state->fifo_path, &s) == -1) {
+ rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
+ close(fd);
+ return RPMRC_OK;
+ } else {
+
+ if (!S_ISFIFO(s.st_mode)) {
+ rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
+ close(fd);
+ return RPMRC_OK;
+ }
+
+ // we require pipe to have 0660 permissions
Rpm coding style is `/* ... */` comments, please adjust for this everywhere.
> + fd = open(state->fifo_path, O_WRONLY);
+ if(fd == -1) {
+ rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
+ return RPMRC_OK;
+ }
+
+ if (stat(state->fifo_path, &s) == -1) {
+ rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
+ close(fd);
+ return RPMRC_OK;
+ } else {
+
+ if (!S_ISFIFO(s.st_mode)) {
+ rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
+ close(fd);
+ return RPMRC_OK;
There are multiple paths closing the fd and returning from this function, this is prone to introducing resource leaks sooner or later. Please refactor to use a common cleanup path for these, typically "goto errxit" style is use within rpm.
> + !(s.st_mode & S_IWOTH) &&
+ !(s.st_mode & S_IXOTH) )) {
+
+ rpmlog(RPMLOG_ERR, "File: %s has 0%d%d%d instead of 0660 \n",
+ state->fifo_path,
+ ((s.st_mode & S_IRUSR) ? 4 : 0) +
+ ((s.st_mode & S_IWUSR) ? 2 : 0) +
+ ((s.st_mode & S_IXUSR) ? 1 : 0),
+
+ ((s.st_mode & S_IRGRP) ? 4 : 0) +
+ ((s.st_mode & S_IWGRP) ? 2 : 0) +
+ ((s.st_mode & S_IXGRP) ? 1 : 0),
+
+ ((s.st_mode & S_IROTH) ? 4 : 0) +
+ ((s.st_mode & S_IWOTH) ? 2 : 0) +
+ ((s.st_mode & S_IXOTH) ? 1 : 0) );
This seems rather excessive for what is just a diagnostic message. Just log the numeric s.st_mode value as is...
> + return RPMRC_OK;
+ }
+ }
+
+ state->fd = fd;
+ state->ready = 1;
+ return RPMRC_OK;
+}
+
+static rpmRC write_fifo(struct fapolicyd_data* state, const char * str, size_t len)
+{
+ ssize_t ret = write(state->fd, str, len);
+
+ if (ret == -1) {
+ rpmlog(RPMLOG_DEBUG, "Write: %s -> %s\n", state->fifo_path, strerror(errno));
+ }
write() can fail with -EINTR, in which case you should just try again.
> +
+ /* Ignore skipped files and unowned directories */
+ if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n",
+ path, dest);
+ return RPMRC_OK;
+ }
+
+ if (!S_ISREG(rpmfiFMode(fi))) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n",
+ path, dest);
+ return RPMRC_OK;
+ }
+
+ if (!fapolicyd_state.ready)
+ return RPMRC_OK;
Here too, multiple early returns. It doesn't allocate any resources now, but if/when it will in the future a simple change becomes more painful than it should because it needs to be handled in multiple places. Please use a `goto exit` idiom to jump out instead.
> + return RPMRC_OK;
+}
+
+static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
+{
+ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST))
+ return RPMRC_OK;
+
+ open_fifo(&fapolicyd_state);
+ return RPMRC_OK;
+}
+
+static void fapolicyd_cleanup(rpmPlugin plugin)
+{
+ if (fapolicyd_state.ready)
+ close(fapolicyd_state.fd);
Do conditionalize the close() on the fd itself, this ensures it gets closed no matter what. Or just leave the condition away, this is just a cleanup whose return we're not checking anyhow so no harm done calling close(-1).
> +
+static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
+{
+ if (fapolicyd_state.ready)
+ write_fifo(&fapolicyd_state, "1", 2);
+
+ return RPMRC_OK;
+}
+
+static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
+ int type)
+{
+ if (fapolicyd_state.ready && fapolicyd_state.first_scriptlet) {
+ // send signal to flush cache
+ write_fifo(&fapolicyd_state, "2", 2);
+ fapolicyd_state.first_scriptlet = 0;
Hmm, doesn't this need to take place once per package, rather than once per transaction? (I could be misunderstanding and/or misremembering the discussion though)
> + fd = open(state->fifo_path, O_WRONLY);
+ if(fd == -1) {
+ rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
+ return RPMRC_OK;
+ }
+
+ if (stat(state->fifo_path, &s) == -1) {
+ rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
+ close(fd);
+ return RPMRC_OK;
+ } else {
+
+ if (!S_ISFIFO(s.st_mode)) {
+ rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
+ close(fd);
+ return RPMRC_OK;
Another thing, more of a question: AIUI fapolicyd can actually prevent upgrades from taking place, so if it's actually active on the system then shouldn't a failure to initialize actually be returned as a failure here - its far, far better to fail early than in the middle of transaction.
> + !(s.st_mode & S_IWOTH) &&
+ !(s.st_mode & S_IXOTH) )) {
+
+ rpmlog(RPMLOG_ERR, "File: %s has 0%d%d%d instead of 0660 \n",
+ state->fifo_path,
+ ((s.st_mode & S_IRUSR) ? 4 : 0) +
+ ((s.st_mode & S_IWUSR) ? 2 : 0) +
+ ((s.st_mode & S_IXUSR) ? 1 : 0),
+
+ ((s.st_mode & S_IRGRP) ? 4 : 0) +
+ ((s.st_mode & S_IWGRP) ? 2 : 0) +
+ ((s.st_mode & S_IXGRP) ? 1 : 0),
+
+ ((s.st_mode & S_IROTH) ? 4 : 0) +
+ ((s.st_mode & S_IWOTH) ? 2 : 0) +
+ ((s.st_mode & S_IXOTH) ? 1 : 0) );
Actually, I'd replace the whole above mode testing + reporting to just (not actually tested, but you get the idea):
```
mode_t mode = s.st_mode & ~S_IFMT;
if (mode != 0660) {
rpmlog(RPMLOG_ERR, "File: %s has %u permissions, 0660 expected\n", state->fifo_path, mode)
goto err;
}
```
> +
+ /* Ignore skipped files and unowned directories */
+ if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n",
+ path, dest);
+ return RPMRC_OK;
+ }
+
+ if (!S_ISREG(rpmfiFMode(fi))) {
+ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n",
+ path, dest);
+ return RPMRC_OK;
+ }
+
+ if (!fapolicyd_state.ready)
+ return RPMRC_OK;
Also, I think this test should be the first in this function - if the plugin is not armed for action then it shouldn't be doing any extra checks and logging about them.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/rpm-software-management/rpm/pull/1475#pullrequestreview-567039144
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rpm.org/pipermail/rpm-maint/attachments/20210113/3860fd29/attachment.html>
More information about the Rpm-maint
mailing list