Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/nscd: DynamicUser and other cleanups #64268

Merged
merged 7 commits into from
Jul 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions nixos/modules/services/system/nscd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,28 @@
# is not aware of the path in which the nss modules live. As a workaround, we
# have `enable-cache yes` with an explicit ttl of 0
server-user nscd
threads 1
paranoia no
debug-level 0

enable-cache passwd yes
positive-time-to-live passwd 0
negative-time-to-live passwd 0
suggested-size passwd 211
check-files passwd yes
persistent passwd no
shared passwd yes

enable-cache group yes
positive-time-to-live group 0
negative-time-to-live group 0
suggested-size group 211
check-files group yes
persistent group no
shared group yes

enable-cache netgroup yes
positive-time-to-live netgroup 0
negative-time-to-live netgroup 0
suggested-size netgroup 211
check-files netgroup yes
persistent netgroup no
shared netgroup yes

enable-cache hosts yes
positive-time-to-live hosts 600
negative-time-to-live hosts 0
suggested-size hosts 211
check-files hosts yes
persistent hosts no
shared hosts yes

enable-cache services yes
positive-time-to-live services 0
negative-time-to-live services 0
suggested-size services 211
check-files services yes
persistent services no
shared services yes
31 changes: 9 additions & 22 deletions nixos/modules/services/system/nscd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,30 @@ in
config = mkIf cfg.enable {
environment.etc."nscd.conf".text = cfg.config;

users.users.nscd =
{ isSystemUser = true;
description = "Name service cache daemon user";
};

systemd.services.nscd =
{ description = "Name Service Cache Daemon";

wantedBy = [ "nss-lookup.target" "nss-user-lookup.target" ];

environment = { LD_LIBRARY_PATH = nssModulesPath; };

preStart =
''
mkdir -m 0755 -p /run/nscd
rm -f /run/nscd/nscd.pid
mkdir -m 0755 -p /var/db/nscd
'';

restartTriggers = [
config.environment.etc.hosts.source
config.environment.etc."nsswitch.conf".source
config.environment.etc."nscd.conf".source
];

# We use DynamicUser because in default configurations nscd doesn't
# create any files that need to survive restarts. However, in some
# configurations, nscd needs to be started as root; it will drop
# privileges after all the NSS modules have read their configuration
# files. So prefix the ExecStart command with "!" to prevent systemd
# from dropping privileges early. See ExecStart in systemd.service(5).
serviceConfig =
{ ExecStart = "@${pkgs.glibc.bin}/sbin/nscd nscd";
{ ExecStart = "!@${pkgs.glibc.bin}/sbin/nscd nscd";
Type = "forking";
DynamicUser = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that means that systemd will no longer try to use nscd to check the dynamic user? How do they implement that?

Copy link
Member

@arianvp arianvp Jul 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, DynamicUser should only work when nscd is on, as nscd dispatches to the correct nss_systemd.so . So this indeed sounds like something that is not gonna work, given that nscd is not running when nscd is starting up :P

However, note I think that nscd bypasses delegating to nscd when doing any nss related syscalls itself (for good reason; otherwise it would end up in an endless loop), so maybe all the nss related syscalls in the nscd binary hit the same codepath as requests from others programs that go through the nscd socket? Because in that case, this will work.

Non of this is documented so we could find out by reading the C source code... Or just disable DynamicUser for nscd so that we're on the safe side.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glibc always has to be able to answer passwd queries and such whether nscd is running or not. How does it know? It tries opening the socket that nscd listens on, and if that fails, it does the lookup itself. (There's also a glibc-internal function which nscd itself calls to prevent even checking for the socket, as you noted.)

So this works fine: systemd does the lookup of a user and group named nscd before it has started the service, the socket doesn't work, so glibc falls back to having libnss_files.so handle the query in-process. If you want to configure a static user for nscd, you can do it in /etc/passwd and systemd will find it.

Also: any code in the systemd package doesn't need nscd to find its own nsswitch modules, because they're already in its library path. So without nscd, systemd would only get the wrong answers for these passwd/group lookups on systems configured with nsswitch modules that are neither the glibc builtins nor systemd's extras.

That means the real constraint here is that you can't override this DynamicUser setting by defining an nscd user in LDAP, Google OS Login, etc. Maybe that's worth documenting, but it's really a nonsense thing to even try doing...

This does make me want to try getting the username nscd on some large LDAP-based network somewhere and see how much I can break though. 😈

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Any service started under DynamicUser must have either libnss_systemd.so in its LD_LIBRARY_PATH or have access to the nscd socket in order for DynamicUser to work.

My worry was because nscd itself doesn't access the socket it wouldn't work. But obviously nscd has libnss_systemd.so in LD_LIBRARY_PATH so it will indeed work.
So indeed, it seems we can leave DynamicUser = true with no issues.

On a related note, I think you can drop the User = nscd option by the way. Because the service name is nscd.service and DynamicUser = true, systemd already automatically sets User = nscd

The user and group name to use may be configured via
User= and Group= (see above). If these options are not used and
dynamic user/group allocation is enabled for a unit, the name of
the dynamic user/group is implicitly derived from the unit name. If
the unit name without the type suffix qualifies as valid user name
it is used directly, otherwise a name incorporating a hash of it is
used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point about removing User, thanks! I've retested with that change and indeed the selected username is still "nscd", as expected.

RuntimeDirectory = "nscd";
PIDFile = "/run/nscd/nscd.pid";
Restart = "always";
ExecReload =
Expand All @@ -75,15 +71,6 @@ in
"${pkgs.glibc.bin}/sbin/nscd --invalidate hosts"
];
};

# Urgggggh... Nscd forks before opening its socket and writing
# its pid. So wait until it's ready.
postStart =
''
while ! ${pkgs.glibc.bin}/sbin/nscd -g > /dev/null; do
sleep 0.2
done
'';
};

};
Expand Down