|
| 1 | +#include "system.h" |
| 2 | + |
| 3 | +#include <sched.h> |
| 4 | +#include <sys/mount.h> |
| 5 | +#include <errno.h> |
| 6 | +#include <string.h> |
| 7 | + |
| 8 | +#include <rpm/rpmts.h> |
| 9 | +#include <rpm/rpmplugin.h> |
| 10 | +#include <rpm/rpmlog.h> |
| 11 | +#include <rpm/rpmmacro.h> |
| 12 | + |
| 13 | +#include "debug.h" |
| 14 | + |
| 15 | +static ARGV_t private_mounts = NULL; |
| 16 | +static int unshare_flags = 0; |
| 17 | + |
| 18 | +static rpmRC unshare_init(rpmPlugin plugin, rpmts ts) |
| 19 | +{ |
| 20 | + char *paths = rpmExpand("%{?__transaction_unshare_paths}", NULL); |
| 21 | + private_mounts = argvSplitString(paths, ":", ARGV_SKIPEMPTY); |
| 22 | + if (private_mounts) |
| 23 | + unshare_flags |= CLONE_NEWNS; |
| 24 | + free(paths); |
| 25 | + |
| 26 | + if (rpmExpandNumeric("%{?__transaction_unshare_nonet}")) |
| 27 | + unshare_flags |= CLONE_NEWNET; |
| 28 | + |
| 29 | + return RPMRC_OK; |
| 30 | +} |
| 31 | + |
| 32 | +static void unshare_cleanup(rpmPlugin plugin) |
| 33 | +{ |
| 34 | + /* ensure clean state for possible next transaction */ |
| 35 | + private_mounts = argvFree(private_mounts); |
| 36 | + unshare_flags = 0; |
| 37 | +} |
| 38 | + |
| 39 | +static rpmRC unshare_scriptlet_fork_post(rpmPlugin plugin, |
| 40 | + const char *path, int type) |
| 41 | +{ |
| 42 | + rpmRC rc = RPMRC_FAIL; |
| 43 | + |
| 44 | + if (unshare_flags && (unshare(unshare_flags) == -1)) { |
| 45 | + rpmlog(RPMLOG_ERR, _("unshare with flags x%x failed: %s\n"), |
| 46 | + unshare_flags, strerror(errno)); |
| 47 | + goto exit; |
| 48 | + } |
| 49 | + |
| 50 | + if (private_mounts) { |
| 51 | + if (mount("/", "/", NULL, MS_REC | MS_PRIVATE, NULL) == -1) { |
| 52 | + rpmlog(RPMLOG_ERR, _("failed to mount private %s: %s\n"), |
| 53 | + "/", strerror(errno)); |
| 54 | + goto exit; |
| 55 | + } |
| 56 | + for (ARGV_t mnt = private_mounts; mnt && *mnt; mnt++) { |
| 57 | + if (mount("none", *mnt, "tmpfs", 0, NULL) == -1) { |
| 58 | + rpmlog(RPMLOG_ERR, _("failed to mount private %s: %s\n"), |
| 59 | + *mnt, strerror(errno)); |
| 60 | + goto exit; |
| 61 | + } |
| 62 | + } |
| 63 | + } |
| 64 | + rc = RPMRC_OK; |
| 65 | + |
| 66 | +exit: |
| 67 | + return rc; |
| 68 | +} |
| 69 | + |
| 70 | +struct rpmPluginHooks_s unshare_hooks = { |
| 71 | + .init = unshare_init, |
| 72 | + .cleanup = unshare_cleanup, |
| 73 | + .scriptlet_fork_post = unshare_scriptlet_fork_post, |
| 74 | +}; |
0 commit comments