]> git.ipfire.org Git - people/stevee/pakfire.git/commitdiff
jail: Map/unmap any UID/GIDs
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 16 Aug 2022 13:16:50 +0000 (13:16 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 16 Aug 2022 13:16:50 +0000 (13:16 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/pwd.h
src/libpakfire/pakfire.c

index dc50e02dd0443e97c7eb8929661c02f86c937949..dc8cdc6869fa36cd3348aa088e8307d26cbf1644 100644 (file)
@@ -28,7 +28,7 @@
 
 struct pakfire_subid {
        char name[NAME_MAX];
-       uid_t id;
+       unsigned int id;
        size_t length;
 };
 
index c9f905757ab2722811fb5ea93d720d78a52c3c5e..4d24238ed7bd481e0a4266ec2188678ca8b07f7f 100644 (file)
@@ -162,6 +162,50 @@ const struct pakfire_subid* pakfire_subgid(struct pakfire* pakfire) {
        return &pakfire->subgid;
 }
 
+/*
+       Maps any UID/GIDs to the SUBUID/SUBGIDs so that we can transparently
+       copy files in and out of the jail environment.
+*/
+static unsigned int pakfire_map_id(struct pakfire* pakfire,
+               const struct pakfire_subid* subid, const unsigned int id) {
+       // Nothing to do if we are running on root
+       if (pakfire_on_root(pakfire))
+               return id;
+
+       // Map the ID
+       unsigned int mapped_id = subid->id + id;
+
+       // Check if the ID is in range
+       if (id > subid->length) {
+               ERROR(pakfire, "Mapped ID is out of range. Setting to %u\n", subid->id);
+               mapped_id = subid->id;
+       }
+
+       DEBUG(pakfire, "Mapping UID/GID %u to %u\n", id, mapped_id);
+
+       return mapped_id;
+}
+
+static unsigned int pakfire_unmap_id(struct pakfire* pakfire,
+               const struct pakfire_subid* subid, const unsigned int id) {
+       // Nothing to do if we are running on root
+       if (pakfire_on_root(pakfire))
+               return id;
+
+       // Unmap the ID
+       int unmapped_id = id - subid->id;
+
+       // Check if the ID is in range
+       if (unmapped_id < 0) {
+               ERROR(pakfire, "Mapped ID is out of range. Setting to %d\n", subid->id);
+               unmapped_id = subid->id;
+       }
+
+       DEBUG(pakfire, "Mapping UID/GID %d from %d\n", unmapped_id, id);
+
+       return unmapped_id;
+}
+
 static int log_priority(const char* priority) {
        char* end;
 
@@ -1430,6 +1474,11 @@ int pakfire_confirm(struct pakfire* pakfire, const char* message, const char* qu
 static const char* pakfire_user_lookup(void* data, la_int64_t uid) {
        struct pakfire* pakfire = (struct pakfire*)data;
 
+       DEBUG(pakfire, "Looking up name for UID %ld\n", uid);
+
+       // Unmap the UID first
+       uid = pakfire_unmap_id(pakfire, &pakfire->subuid, uid);
+
        // Fast path for "root"
        if (uid == 0)
                return "root";
@@ -1449,6 +1498,11 @@ static const char* pakfire_user_lookup(void* data, la_int64_t uid) {
 static const char* pakfire_group_lookup(void* data, la_int64_t gid) {
        struct pakfire* pakfire = (struct pakfire*)data;
 
+       DEBUG(pakfire, "Looking up name for GID %ld\n", gid);
+
+       // Unmap the GID first
+       gid = pakfire_unmap_id(pakfire, &pakfire->subgid, gid);
+
        // Fast path for "root"
        if (gid == 0)
                return "root";
@@ -1493,39 +1547,43 @@ struct archive* pakfire_make_archive_disk_reader(struct pakfire* pakfire, int in
 static la_int64_t pakfire_uid_lookup(void* data, const char* name, la_int64_t uid) {
        struct pakfire* pakfire = (struct pakfire*)data;
 
+       DEBUG(pakfire, "Looking up UID for '%s' (%ld)\n", name, uid);
+
        // Fast path for "root"
        if (strcmp(name, "root") == 0)
-               return 0;
+               return pakfire_map_id(pakfire, &pakfire->subuid, 0);
 
        // Find a matching entry in /etc/passwd
        struct passwd* entry = pakfire_getpwnam(pakfire, name);
        if (!entry) {
                ERROR(pakfire, "Could not retrieve UID for '%s': %m\n", name);
-               return 0;
+               return pakfire_map_id(pakfire, &pakfire->subuid, 0);
        }
 
        DEBUG(pakfire, "Mapping %s to UID %d\n", name, entry->pw_uid);
 
-       return entry->pw_uid;
+       return pakfire_map_id(pakfire, &pakfire->subuid, entry->pw_uid);
 }
 
-static la_int64_t pakfire_gid_lookup(void* data, const char* name, la_int64_t uid) {
+static la_int64_t pakfire_gid_lookup(void* data, const char* name, la_int64_t gid) {
        struct pakfire* pakfire = (struct pakfire*)data;
 
+       DEBUG(pakfire, "Looking up GID for '%s' (%ld)\n", name, gid);
+
        // Fast path for "root"
        if (strcmp(name, "root") == 0)
-               return 0;
+               return pakfire_map_id(pakfire, &pakfire->subgid, 0);
 
        // Find a matching entry in /etc/group
        struct group* entry = pakfire_getgrnam(pakfire, name);
        if (!entry) {
                ERROR(pakfire, "Could not retrieve GID for '%s': %m\n", name);
-               return 0;
+               return pakfire_map_id(pakfire, &pakfire->subgid, 0);
        }
 
        DEBUG(pakfire, "Mapping %s to GID %d\n", name, entry->gr_gid);
 
-       return entry->gr_gid;
+       return pakfire_map_id(pakfire, &pakfire->subgid, entry->gr_gid);
 }
 
 struct archive* pakfire_make_archive_disk_writer(struct pakfire* pakfire, int internal) {