#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
return pakfire_path_join(pakfire->path, path);
}
+static const struct pakfire_mountpoint {
+ const char* source;
+ const char* target;
+ const char* fstype;
+ int flags;
+ const char* options;
+} mountpoints[] = {
+ { "pakfire_proc", "proc", "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL },
+
+ // Bind mount /proc/sys as read-only with the following exceptions:
+ // * /proc/sys/net
+ { "/proc/sys", "proc/sys", NULL, MS_BIND, NULL },
+ { "/proc/sys/net", "proc/sys/net", NULL, MS_BIND, NULL },
+ { "/proc/sys", "proc/sys", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL },
+
+ // Bind mount /sys as read-only
+ { "/sys", "sys", NULL, MS_BIND, NULL },
+ { "/sys", "sys", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL },
+
+ // Create a new /dev
+ { "pakfire_dev", "dev", "tmpfs", MS_NOSUID|MS_NOEXEC,
+ "mode=755,size=4m,nr_inodes=64k" },
+ { "/dev/pts", "dev/pts", NULL, MS_BIND, NULL },
+
+ // Create a new /run
+ { "pakfire_tmpfs", "run", "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ "mode=755,size=4m,nr_inodes=1k" },
+
+ // Create a new /tmp
+ { "pakfire_tmpfs", "tmp", "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ "mode=755" },
+
+ // The end
+ { NULL },
+};
+
+static int pakfire_mount(Pakfire pakfire) {
+ int r;
+
+ for (const struct pakfire_mountpoint* mp = mountpoints; mp->source; mp++) {
+ DEBUG(pakfire, "Mounting /%s\n", mp->target);
+
+ char* target = pakfire_path_join(pakfire->path, mp->target);
+
+RETRY:
+ // Perform mount()
+ r = mount(mp->source, target, mp->fstype, mp->flags, mp->options);
+ if (r) {
+ // If the target directory does not exist, we will create it
+ if (errno == ENOENT) {
+ r = pakfire_mkdir(pakfire, target, S_IRUSR|S_IWUSR|S_IXUSR);
+ if (r) {
+ ERROR(pakfire, "Could not create %s\n", target);
+ free(target);
+ return r;
+ }
+
+ goto RETRY;
+ }
+
+ ERROR(pakfire, "Could not mount /%s: %s\n", mp->target, strerror(errno));
+ free(target);
+ return r;
+ }
+
+ free(target);
+ }
+
+ return 0;
+}
+
+static int pakfire_umount(Pakfire pakfire) {
+ // Offset to the last element in mountpoints
+ const size_t s = (sizeof(mountpoints) / sizeof(*mountpoints)) - 1;
+ char* target = NULL;
+ int r = 0;
+
+ // Walk through the array backwards
+ for (const struct pakfire_mountpoint* mp = mountpoints + s; mp-- != mountpoints;) {
+ DEBUG(pakfire, "Umounting /%s\n", mp->target);
+ int flags = 0;
+
+ target = pakfire_path_join(pakfire->path, mp->target);
+
+RETRY:
+ // Perform umount
+ r = umount2(target, flags);
+
+ if (r) {
+ // Skip anything that wasn't mounted
+ if (errno == EINVAL)
+ continue;
+
+ // Attempt a laze umount when busy
+ else if (errno == EBUSY) {
+ flags |= MNT_DETACH;
+ goto RETRY;
+ }
+
+ ERROR(pakfire, "Could not umount %s: %s\n", mp->target, strerror(errno));
+ goto ERROR;
+ }
+ }
+
+ERROR:
+ if (target)
+ free(target);
+
+ return r;
+}
+
+PAKFIRE_EXPORT int pakfire_activate(Pakfire pakfire) {
+ if (strcmp(pakfire->path, "/") == 0)
+ return 0;
+
+ // Mount filesystems
+ int r = pakfire_mount(pakfire);
+ if (r) {
+ pakfire_umount(pakfire);
+
+ return r;
+ }
+
+ return 0;
+}
+
+PAKFIRE_EXPORT int pakfire_deactivate(Pakfire pakfire) {
+ return pakfire_umount(pakfire);
+}
+
PAKFIRE_EXPORT const char* pakfire_get_arch(Pakfire pakfire) {
return pakfire->arch;
}
("pakfire_root", "/", "tmpfs", "defaults"),
]
- mountpoints += [
- # src, dest, fs, options
- ("pakfire_proc", "/proc", "proc", "nosuid,noexec,nodev"),
- ("/proc/sys", "/proc/sys", "bind", "bind"),
- ("/proc/sys", "/proc/sys", "bind", "bind,ro,remount"),
- ("/sys", "/sys", "bind", "bind"),
- ("/sys", "/sys", "bind", "bind,ro,remount"),
- ("pakfire_tmpfs", "/dev", "tmpfs", "mode=755,nosuid"),
- ("/dev/pts", "/dev/pts", "bind", "bind"),
- ("pakfire_tmpfs", "/run", "tmpfs", "mode=755,nosuid,nodev"),
- ("pakfire_tmpfs", "/tmp", "tmpfs", "mode=755,nosuid,nodev"),
- ]
-
- # If selinux is enabled.
- if os.path.exists("/sys/fs/selinux"):
- mountpoints += [
- ("/sys/fs/selinux", "/sys/fs/selinux", "bind", "bind"),
- ("/sys/fs/selinux", "/sys/fs/selinux", "bind", "bind,ro,remount"),
- ]
-
# If ccache support is requested, we bind mount the cache.
if self.settings.get("enable_ccache"):
# Create ccache cache directory if it does not exist.