From: Michael Tremer Date: Tue, 16 Aug 2022 13:16:50 +0000 (+0000) Subject: jail: Map/unmap any UID/GIDs X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=07f7d0fe29fa57d093a6ef0b55edfbe3f8395b5e;p=people%2Fstevee%2Fpakfire.git jail: Map/unmap any UID/GIDs Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/pwd.h b/src/libpakfire/include/pakfire/pwd.h index dc50e02d..dc8cdc68 100644 --- a/src/libpakfire/include/pakfire/pwd.h +++ b/src/libpakfire/include/pakfire/pwd.h @@ -28,7 +28,7 @@ struct pakfire_subid { char name[NAME_MAX]; - uid_t id; + unsigned int id; size_t length; }; diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index c9f90575..4d24238e 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -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) {