diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 7783f13b14b1d..f1ddd377ed01a 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -100,6 +100,36 @@ let
description = "The path to the user's shell.";
};
+ subUidRanges = mkOption {
+ type = types.listOf types.optionSet;
+ default = [];
+ example = [
+ { startUid = 1000; count = 1; }
+ { startUid = 100001; count = 65534; }
+ ];
+ options = [ subordinateUidRange ];
+ description = ''
+ Subordinate user ids that user is allowed to use.
+ They are set into /etc/subuid and are used
+ by newuidmap for user namespaces.
+ '';
+ };
+
+ subGidRanges = mkOption {
+ type = types.listOf types.optionSet;
+ default = [];
+ example = [
+ { startGid = 100; count = 1; }
+ { startGid = 1001; count = 999; }
+ ];
+ options = [ subordinateGidRange ];
+ description = ''
+ Subordinate group ids that user is allowed to use.
+ They are set into /etc/subgid and are used
+ by newgidmap for user namespaces.
+ '';
+ };
+
createHome = mkOption {
type = types.bool;
default = false;
@@ -211,6 +241,36 @@ let
};
+ subordinateUidRange = {
+ startUid = mkOption {
+ type = types.int;
+ description = ''
+ Start of the range of subordinate user ids that user is
+ allowed to use.
+ '';
+ };
+ count = mkOption {
+ type = types.int;
+ default = 1;
+ description = ''Count of subordinate user ids'';
+ };
+ };
+
+ subordinateGidRange = {
+ startGid = mkOption {
+ type = types.int;
+ description = ''
+ Start of the range of subordinate group ids that user is
+ allowed to use.
+ '';
+ };
+ count = mkOption {
+ type = types.int;
+ default = 1;
+ description = ''Count of subordinate group ids'';
+ };
+ };
+
getGroup = gname:
let
groups = mapAttrsToList (n: g: g) (
@@ -265,6 +325,20 @@ let
))
);
+ mkSubuidEntry = user: concatStrings (
+ map (range: "${user.name}:${toString range.startUid}:${toString range.count}\n")
+ user.subUidRanges);
+
+ subuidFile = concatStrings (map mkSubuidEntry (
+ sortOn "uid" (attrValues cfg.extraUsers)));
+
+ mkSubgidEntry = user: concatStrings (
+ map (range: "${user.name}:${toString range.startGid}:${toString range.count}\n")
+ user.subGidRanges);
+
+ subgidFile = concatStrings (map mkSubgidEntry (
+ sortOn "uid" (attrValues cfg.extraUsers)));
+
# If mutableUsers is true, this script adds all users/groups defined in
# users.extra{Users,Groups} to /etc/{passwd,group} iff there isn't any
# existing user/group with the same name in those files.
@@ -504,6 +578,15 @@ in {
# for backwards compatibility
system.activationScripts.groups = stringAfter [ "users" ] "";
+ environment.etc."subuid" = {
+ text = subuidFile;
+ mode = "0644";
+ };
+ environment.etc."subgid" = {
+ text = subgidFile;
+ mode = "0644";
+ };
+
assertions = [
{ assertion = !cfg.enforceIdUniqueness || (uidsAreUnique && gidsAreUnique);
message = "uids and gids must be unique!";
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 658b08b3d8708..5a467e112c232 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -100,7 +100,9 @@ in
chgpasswd = { rootOK = true; };
};
- security.setuidPrograms = [ "passwd" "chfn" "su" "newgrp" ];
+ security.setuidPrograms = [ "passwd" "chfn" "su" "newgrp"
+ "newuidmap" "newgidmap" # new in shadow 4.2.x
+ ];
};
diff --git a/pkgs/os-specific/linux/shadow/default.nix b/pkgs/os-specific/linux/shadow/default.nix
index b52801cacff76..f928dc8e657c6 100644
--- a/pkgs/os-specific/linux/shadow/default.nix
+++ b/pkgs/os-specific/linux/shadow/default.nix
@@ -15,11 +15,11 @@ let
in
stdenv.mkDerivation rec {
- name = "shadow-4.1.5.1";
+ name = "shadow-4.2.1";
src = fetchurl {
- url = "http://pkg-shadow.alioth.debian.org/releases/${name}.tar.bz2";
- sha256 = "1yvqx57vzih0jdy3grir8vfbkxp0cl0myql37bnmi2yn90vk6cma";
+ url = "http://pkg-shadow.alioth.debian.org/releases/${name}.tar.xz";
+ sha256 = "0h9x1zdbq0pqmygmc1x459jraiqw4gqz8849v268crk78z8r621v";
};
buildInputs = stdenv.lib.optional (pam != null && stdenv.isLinux) pam;