~ruther/guix-local

fdb46ae7b19d45a6a1f5adb660283981bf4b7a1d — Giacomo Leidi 3 months ago 94b26ff
system: Relax subordinate ID validation.

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 (<unused-id-range>)[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 <ludo@gnu.org>
Merges: #4235
2 files changed, 33 insertions(+), 9 deletions(-)

M gnu/build/accounts.scm
M tests/accounts.scm
M gnu/build/accounts.scm => gnu/build/accounts.scm +16 -9
@@ 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 <subid-range>.  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))

M tests/accounts.scm => tests/accounts.scm +17 -0
@@ 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))