From fdb46ae7b19d45a6a1f5adb660283981bf4b7a1d Mon Sep 17 00:00:00 2001 From: Giacomo Leidi Date: Sat, 15 Nov 2025 11:18:40 +0100 Subject: [PATCH] system: Relax subordinate ID validation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://codeberg.org/guix/guix/issues/3925 raised the inabilityy of the subordinate IDs service of handling externally managed sub{u,g}id file entries. This patch relaxes the checks in place for existing ranges, by allowing subid-range records lower than %subordinate-id-min, leaving all the space from subid 0 to %subordinate-id-min - 1 to external users. Generic ranges are still allocated within %subordinate-id-min and %subordinate-id-max. * gnu/build/accounts.scm ()[min]: Change default value to 0, allowing subid-ranges with a start lesser than %subordinate-id-min. (allocate-generic-range): Allocate generic ranges starting from %subordinate-id-min, leaving ranges starting before %subordinate-id-min. (allocate-specific-range): Move bounds check to... (allocate-subids): ...here. Now bound validation is applied only to user provided ranges. * tests/accounts.scm: Test new behavior. Fixes: guix/guix#3925 Change-Id: Id923b122c97a20f148684f5fb144fd9422810612 Signed-off-by: Ludovic Courtès Merges: #4235 --- gnu/build/accounts.scm | 25 ++++++++++++++++--------- tests/accounts.scm | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/gnu/build/accounts.scm b/gnu/build/accounts.scm index 74f49ff9b492dd2c3383100d24850f4cffdbf9f3..5438d59593f11332f5065b36708137e811b8ffe7 100644 --- a/gnu/build/accounts.scm +++ b/gnu/build/accounts.scm @@ -359,7 +359,7 @@ to it atomically and set the appropriate permissions." (left unused-subid-range-left ;previous unused subuid range or #f (default #f)) (min unused-subid-range-min ;lower bound of this unused subuid range - (default %subordinate-id-min)) + (default 0)) (max unused-subid-range-max ;upper bound (default %subordinate-id-max)) (right unused-subid-range-right ;next unused subuid range or #f @@ -555,7 +555,10 @@ will be marked as used in it." (define actual-range (subid-range (inherit range) - (start allocation-start))) + ;; New IDs are only allocated between %subordinate-id-min and + ;; %subordinate-id-max. + (start + (max allocation-start %subordinate-id-min)))) (if (within-interval? allocation actual-range) (values @@ -603,13 +606,6 @@ is visited to find the best unused range that can hold RANGE." (define range-end (subid-range-end range)) - (unless (and (subordinate-id? range-start) - (subordinate-id? range-end)) - (raise - (condition - (&invalid-subid-range-error - (range range))))) - (define less? (< range-end allocation-start)) (define more? @@ -802,12 +798,23 @@ new UIDs." (define* (allocate-subids ranges #:optional (current-ranges '())) "Return a list of subids entries for RANGES, a list of . IDs found in CURRENT-RANGES, a list of subid entries, are reused." + ;; Ranges from disk must always have a start. (let ((generic (any (compose not subid-range-has-start?) current-ranges))) (when generic (raise (condition (&specific-subid-range-expected-error (range generic)))))) + (for-each + (lambda (range) + ;; New ranges must always be included in the current supported set. + (unless (or (not (subid-range-has-start? range)) + (and (subordinate-id? (subid-range-start range)) + (subordinate-id? (subid-range-end range)))) + (raise + (condition (&invalid-subid-range-error (range range)))))) + ranges) + (define sorted-ranges (stable-sort ranges subid-range-less)) diff --git a/tests/accounts.scm b/tests/accounts.scm index 41ed706e9ed1e2800c3a3d9e97b1b93b4d448414..60a8f4bf66d658dbba2df9045beed39ed9ad1dce 100644 --- a/tests/accounts.scm +++ b/tests/accounts.scm @@ -271,6 +271,23 @@ ada:100600:300\n") (start %subordinate-id-min) (count 100))))) +(test-equal "allocate-subids with externally managed state" + (list (subid-entry (name "guix-daemon") (start 904) (count 1)) + (subid-entry (name "alice") (start 1085) (count 100)) + (subid-entry (name "t") (start %subordinate-id-min) (count 899)) + (subid-entry (name "x") (start 100899) (count 200))) + (allocate-subids (list + (subid-range (name "x") (count 200)) + (subid-range (name "t") (count 899))) + ;; Test use case from + ;; https://codeberg.org/guix/guix/issues/3925 + (list (subid-range (name "guix-daemon") + (start 904) + (count 1)) + (subid-range (name "alice") + (start 1085) + (count 100))))) + (test-equal "allocate-subids with requested IDs ranges" ;; Make sure the requested sub ID for "k" and "root" are honored. (list (subid-entry (name "x") (start %subordinate-id-min) (count 200))