Skip to content

Instantly share code, notes, and snippets.

@jcpunk
Last active November 11, 2025 16:38
Show Gist options
  • Select an option

  • Save jcpunk/68ba42fbf6aa5f096cbc7bbd8a9a2a57 to your computer and use it in GitHub Desktop.

Select an option

Save jcpunk/68ba42fbf6aa5f096cbc7bbd8a9a2a57 to your computer and use it in GitHub Desktop.

Feature Requirements for dynamic identities for libsubid component of shadow-utils

Introduction

Problem

Manual subid management:

  • When managing large numbers of identities with non-local tools (not useradd), keeping the subid allocations in sync is error prone.

LDAP limitations

  • Not all LDAP servers have the sub identity schema extension applied.
  • Local system admins may not have write access to add the relevant entries in LDAP.
  • Remote locations may not have access to the primary LDAP servers - air-gapped, edge, cloud, etc.

Enterprise Inertia

  • Changing identity management practices in established enterprises is difficult.
  • "Shifting right" allows local admins to test and establish solutions quickly.

Current functionality

The subid range for new users is defined in /etc/login.defs and allocated in /etc/subuid and /etc/subgid upon useradd.

Though nsswitch.conf ranges are mapped back and forth to users via libsubid.

Proposal

An opt-in feature flag added to /etc/login.defs for generating subuid ranges automatically if they are not listed in /etc/sub{u,g}id.

Expected Behaviors

  • The default of shadow-utils/libsubid is to NOT allocate ranges without entries in /etc/sub{u,g}id
  • When the flag is enabled, the ranges from /etc/login.defs are respected. Specifically:
    • UID_MIN, UID_MAX, SUB_UID_MIN, SUB_UID_MAX, SUB_UID_COUNT, SUB_GID_MIN, SUB_GID_MAX, and SUB_GID_COUNT
  • The range allocated should match what would be allocated by useradd
  • The mangpages should contain a warning indicating all users will be granted access to user namespaces

Expected NON-Behaviors

  • Users outside of the range specified by UID_MIN and UID_MAX MUST NOT be granted dynamic IDs
  • There should be no flag for extending this behavior into “SYS_UID_MIN/MAX” range
  • Users listed in /etc/sub{u,g}id get the settings there and not any thing else
    • This is how system identities would get their subids defined

Extra tooling

Extend getsubids (perhaps a -v flag) to indicate what flags were used from /etc/logind.defs and their values to help understand how it was determined along with indications if a user was defined in one or both of /etc/subuid//etc/subgid

Design Concerns

Large ID ranges

Systems with UIDs in the 70,000 range (greater than 16bits) have probably exhausted subid space if each uid is granted 65,536 sub ids (16bits) - the default. POSIX defines UID as uint 32bits. Most likely the newer UIDs will be familiar with newer tools and expect namespace access.
The only way I see around outright locking the newest IDs out is to add an additional feature flag to permit subid wrapping via /etc/login.defs.

Some algorithm like : starting_subid = min_subid + ((user_id / 2) * subids_per_user) % available_range

It is important that a "large uid" not have an identical sub id range with a single user with a "small uid".

This extra flag should come with a whole heap of warnings in both the manpages and directly in comments found in /etc/login.defs as subuids would no longer be uniquely tied to a single user.

The expected behavior would also consist of requiring a sysadmin to manually adjust UID_MAX to cover the large UID range. This should also be noted in the manpage and other documentation.

Blocking Specific Users

  • If a specific UID should not be granted subid access, how would this be indicated?
  • Is a 0 in the ID count sufficient? Would ! be more consistent with the shadow-utils codebase?
  • If a user has multiple lines and one indicates “don’t grant access” but another indicates “use this range” what is the right response?

An example of this should be present in the documentation.

Testplan

Default Behavior

  • Test: All settings at default → no change from current behavior.

Flag Enabled, Custom /etc/sub{u,g}id

  • Test: If /etc/sub{u,g}id differs from generated ranges → return /etc/sub{u,g}id content.

Flag Enabled, User Not in /etc/sub{u,g}id

  • Test: Return range identical to useradd population.

Flag Enabled, User Blocked in /etc/sub{u,g}id

  • Test: Return no ranges.

Out-of-Range Users

  • Test: User outside UID_MIN–UID_MAX → error (as if not listed in /etc/sub{u,g}id).

Large ID Ranges

  • Test 1: Flag enabled, no large ID support, UID 100,000 → error.
  • Test 2: Flag enabled, no large ID support, UID 100,000 listed in /etc/sub{u,g}id → use listed values (no UID_MAX change required).
  • Test 3: Flag enabled, with large ID support, UID_MAX adjusted, UID 100,000 not listed → return predictable values, not exactly equal to a single user from a "small" ID.
  • Test 4: Flag enabled, with large ID support, UID 100,000 listed → use listed values (no UID_MAX change required).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment