Package: mmdebstrap
Version: 1.5.7-1+deb13u1
Severity: wishlist
Tags: patch upstream

Hi,

newuidmap / newgidmap consult /etc/nsswitch.conf to decide where to
get information on allowed sbuids from.
The /etc/subuid and /etc/subgid files are only used if the subid filed
in /etc/nsswitch.conf is either unset or set to files (see subuid(5)).
Otherwise the information is retrived by calling some function in a
shared object file derived from the subid value in /etc/nsswitch.conf.

I propose the retrieve the subuids/subgids by calling the getsubids
command included in the uidmap package.

I proposed a similar change to sbuild here:
https://salsa.debian.org/debian/sbuild/-/merge_requests/222


Regards,

Tobias Wiese
>From 1e5a477b197f166e14fcd53abba2a71a3566656d Mon Sep 17 00:00:00 2001
Message-ID: <1e5a477b197f166e14fcd53abba2a71a3566656d.1767754632.git.tob...@tobiaswiese.com>
From: Tobias Wiese <[email protected]>
Date: Wed, 7 Jan 2026 03:57:03 +0100
Subject: [PATCH] Support subid delegation via /etc/nsswitch.conf

newuidmap / newgidmap consult /etc/nsswitch.conf to decide where to
get information on allowed sbuids from.
The /etc/subuid and /etc/subgid files are only used if the subid filed
in /etc/nsswitch.conf is either unset or set to files (see subuid(5)).
Otherwise the information is retrived by calling some function in a
shared object file derived from the subid value in /etc/nsswitch.conf.

This will use the getsubids command to retrieve the subids that will
also be used by newuidmap/newgidmap.

This does not create an additional package dependency as getsubids is
included in the uidmap package, as is newuidmap / newgidmap.

Alternatives:
- do ffi in perl to load and call the libsubid plugin

Test Plan:
build a chroot tar with mmdebstrap on a systems with subids managed by
files and sssd using unshare mode.

Signed-off-by: Tobias Wiese <[email protected]>
---
 mmdebstrap | 79 ++++++++++--------------------------------------------
 1 file changed, 14 insertions(+), 65 deletions(-)

diff --git a/mmdebstrap b/mmdebstrap
--- a/mmdebstrap
+++ b/mmdebstrap
@@ -1429,7 +1429,7 @@ sub read_subuid_subgid {
     my $verbose  = shift;
     my @result   = ();
     my $username = getpwuid $REAL_USER_ID;
-    my ($subid, $num_subid, $fh, $n);
+    my ($fh, $line, $subid, $num_subid);
 
     local *maybe_warn = sub {
         my $msg = shift;
@@ -1439,82 +1439,31 @@ sub read_subuid_subgid {
             debug $msg;
         }
     };
-    if (!-e "/etc/subuid") {
-        maybe_warn("/etc/subuid doesn't exist");
-        return;
-    }
-    if (!-r "/etc/subuid") {
-        maybe_warn("/etc/subuid is not readable");
-        return;
-    }
 
-    open $fh, "<", "/etc/subuid"
-      or maybe_warn("cannot open /etc/subuid for reading: $!");
-    if (!$fh) {
-        return;
-    }
-    while (my $line = <$fh>) {
-        ($n, $subid, $num_subid) = split(/:/, $line, 3);
-        last if ($n eq $username);
-    }
-    close $fh;
-    if (!length $subid) {
-        maybe_warn("/etc/subuid is empty");
+    unless (open $fh, "-|", "getsubids", $username) {
+        maybe_warn("cannot execute getsubids: $!");
         return;
     }
-    if ($n ne $username) {
-        maybe_warn("no entry in /etc/subuid for $username");
+    $line = <$fh>;
+    unless (close $fh and defined($line)) {
+        maybe_warn("No subuid entry for $username");
         return;
     }
+
+    (undef, undef, $subid, $num_subid) = split(/ /, $line, 4);
     push @result, ["u", 0, $subid, $num_subid];
 
-    if (scalar(@result) < 1) {
-        maybe_warn("/etc/subuid does not contain an entry for $username");
-        return;
-    }
-    if (scalar(@result) > 1) {
-        maybe_warn("/etc/subuid contains multiple entries for $username");
+    open $fh, "-|", "getsubids", "-g", $username
+      or die "cannot execute getsubids: $!";
+    $line = <$fh>;
+    unless (close $fh and defined($line)) {
+        maybe_warn("No subgid entry for $username");
         return;
     }
 
-    if (!-e "/etc/subgid") {
-        maybe_warn("/etc/subgid doesn't exist");
-        return;
-    }
-    if (!-r "/etc/subgid") {
-        maybe_warn("/etc/subgid is not readable");
-        return;
-    }
-
-    open $fh, "<", "/etc/subgid"
-      or maybe_warn("cannot open /etc/subgid for reading: $!");
-    if (!$fh) {
-        return;
-    }
-    while (my $line = <$fh>) {
-        ($n, $subid, $num_subid) = split(/:/, $line, 3);
-        last if ($n eq $username);
-    }
-    close $fh;
-    if (!length $subid) {
-        maybe_warn("/etc/subgid is empty");
-        return;
-    }
-    if ($n ne $username) {
-        maybe_warn("no entry in /etc/subgid for $username");
-        return;
-    }
+    (undef, undef, $subid, $num_subid) = split(/ /, $line, 4);
     push @result, ["g", 0, $subid, $num_subid];
 
-    if (scalar(@result) < 2) {
-        maybe_warn("/etc/subgid does not contain an entry for $username");
-        return;
-    }
-    if (scalar(@result) > 2) {
-        maybe_warn("/etc/subgid contains multiple entries for $username");
-        return;
-    }
-
     return @result;
 }
 
-- 
2.47.3

Reply via email to