From e6d2aa979cea1a4d98f588a66b01d742f685971a Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Wed, 13 Aug 2025 11:03:08 +0200 Subject: support parsing /etc/sub?id files keyed on UID Link: https://bugs.debian.org/1110876 --- linuxnamespaces/idmap.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/linuxnamespaces/idmap.py b/linuxnamespaces/idmap.py index d9cf0eb..f66456d 100644 --- a/linuxnamespaces/idmap.py +++ b/linuxnamespaces/idmap.py @@ -7,7 +7,7 @@ namespace. import bisect import dataclasses -import getpass +import pwd import os import subprocess import typing @@ -16,17 +16,36 @@ from .atlocation import AtLocation, AtLocationLike def subidranges( - kind: typing.Literal["uid", "gid"], login: str | None = None + kind: typing.Literal["uid", "gid"], + login: str | None = None, + uid: int | None = None, ) -> typing.Iterator[tuple[int, int]]: """Parse a `/etc/sub?id` file for ranges allocated to the given or current user. Return all ranges as (start, count) pairs. """ + if uid is None: + if login is None: + uid = os.getuid() + else: + try: + uid = pwd.getpwnam(login).pw_uid + except KeyError: + pass if login is None: - login = getpass.getuser() + try: + login = pwd.getpwuid(uid).pw_name + except KeyError: + pass with open(f"/etc/sub{kind}") as filelike: for line in filelike: parts = line.strip().split(":") - if parts[0] == login: + try: + curuid = int(parts[0]) + except ValueError: + curuid = None + if (login is not None and parts[0] == login) or ( + curuid is not None and uid is not None and curuid == uid + ): yield (int(parts[1]), int(parts[2])) @@ -95,13 +114,16 @@ class IDAllocation: @classmethod def loadsubid( - cls, kind: typing.Literal["uid", "gid"], login: str | None = None, + cls, + kind: typing.Literal["uid", "gid"], + login: str | None = None, + uid: int | None = None, ) -> "IDAllocation": """Load a `/etc/sub?id` file and return ids allocated to the given login or current user. """ self = cls() - for start, count in subidranges(kind, login): + for start, count in subidranges(kind, login, uid): self.add_range(start, count) return self -- cgit v1.2.3