Discussion:
[systemd-devel] sysusers and login.defs checks
Colin Guthrie
2014-07-20 21:31:52 UTC
Permalink
Hi,

We're still using 500 as our [UG]ID_MIN in /etc/login.defs, but I'm
looking to change that to be more in line with what everyone else seems
to do.

One thing I found while looking at the sysusers code was that the only
values read from /etc/login.defs were SYSTEM_[UG]ID_MAX and they were
only read a compile (or rather configure) time, not at runtime.

While I appreciate sysusers is intended primarily for bootstrapping
/etc, I guess the general consensus is to move package pre/post scripts
over to use sysusers instead anyway. Thus the tool should really check
/etc/login.defs at runtime if it's present before falling back to its
defaults. Those defaults could be set from a compile time check of
login.defs too.

So, I propose the following:

1. Modify configure to check /etc/login.defs for SYSTEM_[UG]ID_MAX but
fall back to [UG]ID_MIN-1 if not found.
2. Modify sysusers.c to do the same check at runtime

If I cook up a patch will that be accepted?

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Colin Guthrie
2014-07-20 21:38:10 UTC
Permalink
Post by Colin Guthrie
Those defaults could be set from a compile time check of
login.defs too.
FWIW, at least here, /etc/login.defs is not readable by regular users so
any build system that builds as non-root won't even get those defaults
anyway, so that's probably another argument for runtime checks too...

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Reindl Harald
2014-07-20 21:52:40 UTC
Permalink
Post by Colin Guthrie
Post by Colin Guthrie
Those defaults could be set from a compile time check of
login.defs too.
FWIW, at least here, /etc/login.defs is not readable by regular users so
any build system that builds as non-root won't even get those defaults
anyway, so that's probably another argument for runtime checks too...
why is it not readable?

[***@srv-rhsoft:~]$ rpm -q --file /etc/login.defs
shadow-utils-4.1.5.1-8.fc20.x86_64

[***@srv-rhsoft:~]$ stat /etc/login.defs
File: '/etc/login.defs'
Size: 1475 Blocks: 8 IO Block: 4096 regular file
Device: 901h/2305d Inode: 1179182 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2011-08-02 14:24:16.000000000 +0200
Modify: 2011-08-02 14:24:16.000000000 +0200
Change: 2014-03-01 21:20:57.113612115 +0100
Colin Guthrie
2014-07-20 22:30:20 UTC
Permalink
Post by Reindl Harald
Post by Colin Guthrie
Post by Colin Guthrie
Those defaults could be set from a compile time check of
login.defs too.
FWIW, at least here, /etc/login.defs is not readable by regular users so
any build system that builds as non-root won't even get those defaults
anyway, so that's probably another argument for runtime checks too...
why is it not readable?
No idea. Probably some pseudo "security" related reason dating back many
years.

Perms here are:
-rw-r----- 1 root shadow

I can't really think of any reason as to why this would genuinely help,
but then I can't think why a regular user.

Not a big deal in this case really tho' - I think the original argument
still stands.

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Zbigniew Jędrzejewski-Szmek
2014-07-21 02:16:43 UTC
Permalink
Post by Colin Guthrie
Post by Reindl Harald
Post by Colin Guthrie
Post by Colin Guthrie
Those defaults could be set from a compile time check of
login.defs too.
FWIW, at least here, /etc/login.defs is not readable by regular users so
any build system that builds as non-root won't even get those defaults
anyway, so that's probably another argument for runtime checks too...
why is it not readable?
No idea. Probably some pseudo "security" related reason dating back many
years.
-rw-r----- 1 root shadow
I can't really think of any reason as to why this would genuinely help,
but then I can't think why a regular user.
Not a big deal in this case really tho' - I think the original argument
still stands.
I agree. Not reading /etc/login.defs makes the tool troublesome for
existing installations.

I've experienced a related problem, where coredumps would not be
visible for my user on a Fedora machine which has been upgraded over
many versions. It turns out that the user had uid 500 or something
like that, and systemd-coredump treated the account as as a system
account.

Zbyszek
Colin Guthrie
2014-07-21 12:11:39 UTC
Permalink
'Twas brillig, and Zbigniew Jędrzejewski-Szmek at 21/07/14 03:16 did
Post by Zbigniew Jędrzejewski-Szmek
I agree. Not reading /etc/login.defs makes the tool troublesome for
existing installations.
I've experienced a related problem, where coredumps would not be
visible for my user on a Fedora machine which has been upgraded over
many versions. It turns out that the user had uid 500 or something
like that, and systemd-coredump treated the account as as a system
account.
Yeah, I see that the SYSTEM_UID_MAX define is used in a few places
(namely the journal and sysusers).

I guess this should be abstracted out and changed such that it reads
login.defs and uses that value at runtime.

That said, it's also not inconceivable that the login.defs is updated
but user accounts still exist that are in the 500-1000 range. So perhaps
we should consider adding the same kind of heuristics for handling the
500->1000 jump that accountsservice has[1]? i.e. we add a
is_system_user() utility function or similar where this heuristic can be
an optional thing (like in accountsservice). What are the thoughts here?
IMO, I'd say that we should just honour login.defs and forget about
heuristics - anything upgraded should keep it's old login.defs values
and not update them. Only if you do a fresh install or manually renumber
your users should you change login.defs otherwise strange things will
happen to you (e.g. on login screen user lists, in user editing GUIs, in
coredump handling and other places). WDYT?




Also, while SYS_[UG]ID_MAX is currently parsed from login.defs during
configure, and I proposed to fall back to [UG]ID_MIN-1, I notice a few
things...

[I'll drop my "[UG]ID" syntax from now on... assume it's there!]

1. When the bump from 500 to 1000 was done in Fedora[2], SYS_UID_MAX was
added. But SYS_UID_MIN was also added. We do not currently parse this,
but perhaps we should and sysusers should refuse to work if we cannot
find a suitable UID to allocate?

2. Or perhaps we should consider whether the SYS_UID_MIN/MAX is useful
at all? Perhaps if not much uses it, it should just be killed off and we
should always just use UID_MIN-1?

Personally, I'd just go with 2 - the fact there are two settings to
represent a boundary point makes no sense to me - although there may be
valid reasons to leave a gap there?

Col


[1] http://cgit.freedesktop.org/accountsservice/tree/src/user-classify.c#n84

[2]
http://pkgs.fedoraproject.org/cgit/shadow-utils.git/commit/shadow-utils.login.defs?id=5d7612da5b7be0c7ce8bad72c4d69a8f347696db
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-07-21 13:59:24 UTC
Permalink
Post by Colin Guthrie
That said, it's also not inconceivable that the login.defs is updated
but user accounts still exist that are in the 500-1000 range. So perhaps
we should consider adding the same kind of heuristics for handling the
500->1000 jump that accountsservice has[1]? i.e. we add a
is_system_user() utility function or similar where this heuristic can be
an optional thing (like in accountsservice). What are the thoughts here?
IMO, I'd say that we should just honour login.defs and forget about
heuristics - anything upgraded should keep it's old login.defs values
and not update them. Only if you do a fresh install or manually renumber
your users should you change login.defs otherwise strange things will
happen to you (e.g. on login screen user lists, in user editing GUIs, in
coredump handling and other places). WDYT?
I am much more open about code that magically detects where the boundary
is, when allocating a new system users... But I don't see how this could
work in real life. The accountssserice code doesn't appear too
convincing to me... There are system users with login sheels, and there
are normal accounts that have been disabled, I really don#t find a logic
bound to either of that particularly striking I must say...

What could work better is to check the home directory. If it is "/" or
something in /var we can be reasonably sure that something is a system
user, but if it isn't we have no clue...
Post by Colin Guthrie
Also, while SYS_[UG]ID_MAX is currently parsed from login.defs during
configure, and I proposed to fall back to [UG]ID_MIN-1, I notice a few
things...
[I'll drop my "[UG]ID" syntax from now on... assume it's there!]
1. When the bump from 500 to 1000 was done in Fedora[2], SYS_UID_MAX was
added. But SYS_UID_MIN was also added. We do not currently parse this,
but perhaps we should and sysusers should refuse to work if we cannot
find a suitable UID to allocate?
2. Or perhaps we should consider whether the SYS_UID_MIN/MAX is useful
at all? Perhaps if not much uses it, it should just be killed off and we
should always just use UID_MIN-1?
Personally, I'd just go with 2 - the fact there are two settings to
represent a boundary point makes no sense to me - although there may be
valid reasons to leave a gap there?
As i understand the current stuff in Fedora's login.defs, the idea is
that 1-200 is left for statically assigned system users, 201-999 for
dynamically assigned system users, and 1000-60000 for normal users.

Based on this, static system users are allocated growing from 1 upwards,
dynamic system users are allocated growing from 999 downwards, and
normal users from 1000 upwards.

In sysusers we don't care much abotu the actual ranges, we just allocate
from some specified start value downards, and that start value is a
compile time option, that defaults to 999 or is SYS_UID_MAX from
login.defs, should that be available...

Lennart
--
Lennart Poettering, Red Hat
Lennart Poettering
2014-07-21 13:47:10 UTC
Permalink
Post by Zbigniew Jędrzejewski-Szmek
Post by Colin Guthrie
I can't really think of any reason as to why this would genuinely help,
but then I can't think why a regular user.
Not a big deal in this case really tho' - I think the original argument
still stands.
I agree. Not reading /etc/login.defs makes the tool troublesome for
existing installations.
I've experienced a related problem, where coredumps would not be
visible for my user on a Fedora machine which has been upgraded over
many versions. It turns out that the user had uid 500 or something
like that, and systemd-coredump treated the account as as a system
account.
Sure, the transition will create problems, but it necessarily will.

What matters really is that we don't allow things that we shouldn't
allow, but if things are not allowed that should be allowed, then that's
much less problematic, but simply a negative cosnequence of the
transition...

Lennart
--
Lennart Poettering, Red Hat
Lennart Poettering
2014-07-21 13:44:50 UTC
Permalink
Post by Colin Guthrie
Post by Colin Guthrie
Those defaults could be set from a compile time check of
login.defs too.
FWIW, at least here, /etc/login.defs is not readable by regular users so
any build system that builds as non-root won't even get those defaults
anyway, so that's probably another argument for runtime checks too...
That sounds snake-oilish and broken, really...

Either way, there's a configure option --with-system-uid-max= (as well
as --with-system-gid-max=) to make the right choice for your
distribution...

Lennart
--
Lennart Poettering, Red Hat
Lennart Poettering
2014-07-21 13:43:13 UTC
Permalink
Post by Colin Guthrie
Hi,
We're still using 500 as our [UG]ID_MIN in /etc/login.defs, but I'm
looking to change that to be more in line with what everyone else seems
to do.
One thing I found while looking at the sysusers code was that the only
values read from /etc/login.defs were SYSTEM_[UG]ID_MAX and they were
only read a compile (or rather configure) time, not at runtime.
Yeah, that's an intended design decision.
Post by Colin Guthrie
While I appreciate sysusers is intended primarily for bootstrapping
/etc, I guess the general consensus is to move package pre/post scripts
over to use sysusers instead anyway. Thus the tool should really check
/etc/login.defs at runtime if it's present before falling back to its
defaults. Those defaults could be set from a compile time check of
login.defs too.
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it. We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...

Also, the specific configuration file contains more configuration
options that are obsolete, than configuration options that aren't. From
chfn settings, to pam_console support, to the ability to override the
timezone or erase characters. Yuck!

I am fully aware that many distributions are transitioning from from 500
system users to 1000 system users, but I also don't see how this
transition would be made any easier by keeping a user configuration file
around for this. I mean, ultimately you will still have the problem that
in the range 500-999 you might end uo with both users interleaved with
each other... The best thing to do is in this case is live with it, and
make sure we never bind strictly security-relevant decisions to the
boundary, but only use it as a hint...
Post by Colin Guthrie
1. Modify configure to check /etc/login.defs for SYSTEM_[UG]ID_MAX but
fall back to [UG]ID_MIN-1 if not found.
2. Modify sysusers.c to do the same check at runtime
If I cook up a patch will that be accepted?
I am totally not convinced that this would be a good idea, sorry.

Lennart
--
Lennart Poettering, Red Hat
Colin Guthrie
2014-07-21 14:15:41 UTC
Permalink
Post by Lennart Poettering
I am totally not convinced that this would be a good idea, sorry.
No worries, that's why I asked first ;)

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-07-21 22:28:52 UTC
Permalink
Post by Lennart Poettering
Post by Colin Guthrie
While I appreciate sysusers is intended primarily for bootstrapping
/etc, I guess the general consensus is to move package pre/post scripts
over to use sysusers instead anyway. Thus the tool should really check
/etc/login.defs at runtime if it's present before falling back to its
defaults. Those defaults could be set from a compile time check of
login.defs too.
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it. We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
Here's another idea: maybe we can bind this to the "users" group. Many
distributions (not all...) have this group and add regular users to
it. Maybe that's what we should use on top of the numeric UID boundary
check: if some user is either >= 1000 or is a member of the "users"
group we will consider him or her a regular user instead of a system
user. In many cases this should magically make things work. And even where
this isn't sufficient we at least have a nice solution to tell people:
make your user a member of "users" and it will properly be recognised as
regular user.

Happy to add a patch for this!

Lennart
--
Lennart Poettering, Red Hat
Colin Guthrie
2014-07-21 22:44:10 UTC
Permalink
Post by Lennart Poettering
Post by Lennart Poettering
Post by Colin Guthrie
While I appreciate sysusers is intended primarily for bootstrapping
/etc, I guess the general consensus is to move package pre/post scripts
over to use sysusers instead anyway. Thus the tool should really check
/etc/login.defs at runtime if it's present before falling back to its
defaults. Those defaults could be set from a compile time check of
login.defs too.
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it. We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
Here's another idea: maybe we can bind this to the "users" group. Many
distributions (not all...) have this group and add regular users to
it. Maybe that's what we should use on top of the numeric UID boundary
check: if some user is either >= 1000 or is a member of the "users"
group we will consider him or her a regular user instead of a system
user. In many cases this should magically make things work. And even where
make your user a member of "users" and it will properly be recognised as
regular user.
Happy to add a patch for this!
And I guess this heuristic would be easy enough to add to
accountsservice too.

I guess it's OK to do this kind of user lookup stuff from the journal
code (i.e. server_fix_perms())?

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-07-22 11:10:58 UTC
Permalink
Post by Colin Guthrie
Post by Lennart Poettering
Post by Lennart Poettering
Post by Colin Guthrie
While I appreciate sysusers is intended primarily for bootstrapping
/etc, I guess the general consensus is to move package pre/post scripts
over to use sysusers instead anyway. Thus the tool should really check
/etc/login.defs at runtime if it's present before falling back to its
defaults. Those defaults could be set from a compile time check of
login.defs too.
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it. We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
Here's another idea: maybe we can bind this to the "users" group. Many
distributions (not all...) have this group and add regular users to
it. Maybe that's what we should use on top of the numeric UID boundary
check: if some user is either >= 1000 or is a member of the "users"
group we will consider him or her a regular user instead of a system
user. In many cases this should magically make things work. And even where
make your user a member of "users" and it will properly be recognised as
regular user.
Happy to add a patch for this!
And I guess this heuristic would be easy enough to add to
accountsservice too.
I guess it's OK to do this kind of user lookup stuff from the journal
code (i.e. server_fix_perms())?
Hmm, yuck. Actually it is really difficult....

It's not OK to do NSS calls from journald, as that might cause
communication with local daemons which in turn want to log, which might
result in a cyclic dep and hence a deadlock.

So if this is implemented, then we'd have to read the auxiliary group
list from the sending process (via /proc/$PID/status) directly, so that
we don't have to involve NSS.... This is awfully racy however.

Bummer, not sure if we can save this idea...

Lennart
--
Lennart Poettering, Red Hat
Colin Guthrie
2014-07-22 17:35:25 UTC
Permalink
Post by Lennart Poettering
Post by Colin Guthrie
I guess it's OK to do this kind of user lookup stuff from the journal
code (i.e. server_fix_perms())?
Hmm, yuck. Actually it is really difficult....
...
Bummer, not sure if we can save this idea...
Yeah, I did wonder about it when you suggested it!

I guess the only option is to either:

a) Do nothing and live with compiled in defaults,
or
b) Parse and honour /etc/login.defs before falling back to compiled in
defaults.

As you've already NAK'ed b) I guess we just have to live with a).

I'll probably carry a downstream patch for b) to be honest as I know a
few users will be tripped up, but I can understand not wanting it
downstream from a purist perspective.

Cheers for the discussion :)

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-07-23 17:31:31 UTC
Permalink
Post by Colin Guthrie
Post by Lennart Poettering
Post by Colin Guthrie
I guess it's OK to do this kind of user lookup stuff from the journal
code (i.e. server_fix_perms())?
Hmm, yuck. Actually it is really difficult....
...
Bummer, not sure if we can save this idea...
Yeah, I did wonder about it when you suggested it!
Talked to Kay about this a bit more. Here's an idea:

There are basically three areas where the system vs. regular user UID
boundary matters:

a) in journald for splitting up journals for individual users
b) in the coredump hook, for similar purposes
c) in sysusers when creating new system users

Solution for a): add a new configuration option to journald.conf for
declaring the UID range to split up journals in. Usage like this:

SplitUserRange=1000-65533

Solution for b): similar, but an option for coredump.conf

Solution for c): a new "r" directive or so for the sysusers snippets
that declares ranges to allocate new system users from:

r - 200-999

In all three cases, if the setting is not set, we default to the
configure time boundary (1000) as before.

To make this generic, we'd actually allow people to configure multiple
ranges freely:

SplitUserRange=1000-2000,10000-6533

or for sysusers.d

r - 200-700
r - 800-999

Now, this alone wouldn't provide compatibility with the dreaded
login.defs file. For that we'd then employ a postinst script that reads
the range from the file, and then automatically generates a sysuers.d
drop-in or a patches journald.conf and coredump.conf should the range
not match the default.

Does this make sense?

As a side effect this would actually even allow us to be closer to
FEdora's current bheaviour, since it reserves UIDs < 200 for static
assignment, which we could then easily exclude from theis logic, too.

Lennart
--
Lennart Poettering, Red Hat
Zbigniew Jędrzejewski-Szmek
2014-07-23 18:50:24 UTC
Permalink
On Wed, Jul 23, 2014 at 07:31:31PM +0200, Lennart Poettering wrote:

[snip]
Post by Lennart Poettering
Now, this alone wouldn't provide compatibility with the dreaded
login.defs file. For that we'd then employ a postinst script that reads
the range from the file, and then automatically generates a sysuers.d
drop-in or a patches journald.conf and coredump.conf should the range
not match the default.
Does this make sense?
Seems like a great big effort to avoid reading a simple configuration
file.

When people want to teach systemd to generate dynamic configuration
based on some other configuration, to pass commandline options and/or
environment variables to a daemon that is starting up, because the
daemon cannot do it on its own, we always tell them: teach the daemon
to do that on its own. We should apply the same principle here, and
not spread the configuration over n automatically generated files.
Post by Lennart Poettering
As a side effect this would actually even allow us to be closer to
FEdora's current bheaviour, since it reserves UIDs < 200 for static
assignment, which we could then easily exclude from theis logic, too.
In practice this might not be useful, because even if all the 800 UIDs
starting from 999 were used up, it would be better to encroach on the
"static" range than to fail.

Zbyszek
Simon McVittie
2014-07-23 19:04:58 UTC
Permalink
Post by Zbigniew Jędrzejewski-Szmek
Post by Lennart Poettering
As a side effect this would actually even allow us to be closer to
FEdora's current bheaviour, since it reserves UIDs < 200 for static
assignment, which we could then easily exclude from theis logic, too.
In practice this might not be useful, because even if all the 800 UIDs
starting from 999 were used up, it would be better to encroach on the
"static" range than to fail.
At least in Debian and its derivatives, the statically-allocated ranges
0-99 and 60000-64999 are basically for two things: "well-known" users
like root/daemon/ftp/www-data, and packages that hard-code a numeric uid
at compile time. Yes, the latter is probably a design flaw in the
package that needs that uid[1]; but as long as such software exists,
installing it will result in it using that uid, whether it's already in
use by something else or not.

In this unlikely situation, it seems better to fail than to operate
insecurely; or if it's absolutely necessary to allocate a new dynamic
uid, taking one from the "real user" range seems less risky than taking
one from a statically-allocated range.

[1] arguably; iirc Apache suexec deliberately hard-codes www-data's uid
at compile time as a security measure, although that admittedly seems
more like security theatre than actual security, because if you can't
trust nsswitch then you've already lost
Lennart Poettering
2014-07-24 10:14:49 UTC
Permalink
Post by Zbigniew Jędrzejewski-Szmek
[snip]
Post by Lennart Poettering
Now, this alone wouldn't provide compatibility with the dreaded
login.defs file. For that we'd then employ a postinst script that reads
the range from the file, and then automatically generates a sysuers.d
drop-in or a patches journald.conf and coredump.conf should the range
not match the default.
Does this make sense?
Seems like a great big effort to avoid reading a simple configuration
file.
When people want to teach systemd to generate dynamic configuration
based on some other configuration, to pass commandline options and/or
environment variables to a daemon that is starting up, because the
daemon cannot do it on its own, we always tell them: teach the daemon
to do that on its own. We should apply the same principle here, and
not spread the configuration over n automatically generated files.
Well, I'd feel easier about it if I actually believed that the
configuration file login.defs was well designed and not just completely
drowned in legacy UNIX cruft...

Also note that the additions I propose actually don't just make the
boundary configurable, but are a lot more generic than that. They make a
subsystem-specific logic configurable, that is by default sourced from
the UID boundary, but it's not the UID boundary you configure.

Hence, the nature of the configuration changed quite a bit. Instead of
making the UID boundary configurable (which I find really wrong
conceptually, because it shouldn't be the choice of the admin, but of
the vendor), we explicitly allow the logic normally based on it to be
configured, natively.

It is philosphically quite a difference whether we expose "SystemUIDMax=" as
journald.conf option or whether we expose "SplitUserRange=" as I
propose. The former would be strictly a duplication of configuration
already existing in login.defs. The latter is much more generic...

Or try to see it from a different perspective: we already introduced
multiple SplitMode= settings, since people wanted to split up non-login
user journals too (we added that on request of David Strauss). A
weakness of those models so far was that this meant that either they get
everything split up, or just the login users, which is usually much too
unprecise. Usually what's actually desired is to split out login users
plus a certain additional range of users used to run multiple httpd
instances or so. With the configuration options I propose you can do
that.
Post by Zbigniew Jędrzejewski-Szmek
Post by Lennart Poettering
As a side effect this would actually even allow us to be closer to
FEdora's current bheaviour, since it reserves UIDs < 200 for static
assignment, which we could then easily exclude from theis logic, too.
In practice this might not be useful, because even if all the 800 UIDs
starting from 999 were used up, it would be better to encroach on the
"static" range than to fail.
Well, hopefully the static UIDs are static for a reason: they are UIDs
that might write files to NFS accessible shares. It might be a better
choice to fail the addition of the system users than to allow the wrong
networked users access...

But anyway, I personally wouldn't bother with statically assigned UIDs,
but then again, I can understand why Fedora has the policy on this it has.

Lennart
--
Lennart Poettering, Red Hat
Simon McVittie
2014-07-23 18:54:32 UTC
Permalink
Post by Lennart Poettering
As a side effect this would actually even allow us to be closer to
FEdora's current bheaviour, since it reserves UIDs < 200 for static
assignment, which we could then easily exclude from theis logic, too.
Debian's uid/gid ranges for comparison, if it helps:
<https://www.debian.org/doc/debian-policy/ch-opersys.html#s9.2>
I think Ubuntu inherits those too, they generally follow Debian policy
if they have no reason not to.

(0-99 system users statically allocated by Debian and normally
pre-created, 100-999 dynamically allocated system users, 1000-59999
dynamically allocated real users, 6000-64999 statically allocated by
Debian but only created on demand, 65000-65533 reserved, 65534
statically allocated as nobody, 65535 reserved because it is or was once
(uid_t)(-1); changing the boundary between the dynamically allocated
ranges in login.defs is best-effort-supported for the benefit of people
whose site-wide real users start at 500 or whatever.)

S
Colin Guthrie
2014-07-23 20:22:54 UTC
Permalink
Post by Lennart Poettering
Post by Colin Guthrie
Post by Lennart Poettering
Post by Colin Guthrie
I guess it's OK to do this kind of user lookup stuff from the journal
code (i.e. server_fix_perms())?
Hmm, yuck. Actually it is really difficult....
...
Bummer, not sure if we can save this idea...
Yeah, I did wonder about it when you suggested it!
There are basically three areas where the system vs. regular user UID
a) in journald for splitting up journals for individual users
b) in the coredump hook, for similar purposes
c) in sysusers when creating new system users
Solution for a): add a new configuration option to journald.conf for
SplitUserRange=1000-65533
Solution for b): similar, but an option for coredump.conf
Solution for c): a new "r" directive or so for the sysusers snippets
r - 200-999
In all three cases, if the setting is not set, we default to the
configure time boundary (1000) as before.
To make this generic, we'd actually allow people to configure multiple
SplitUserRange=1000-2000,10000-6533
or for sysusers.d
r - 200-700
r - 800-999
Now, this alone wouldn't provide compatibility with the dreaded
login.defs file. For that we'd then employ a postinst script that reads
the range from the file, and then automatically generates a sysuers.d
drop-in or a patches journald.conf and coredump.conf should the range
not match the default.
Does this make sense?
To be frank, I really don't think it does make much sense at all. I
mean, something which is currently configured in one place and then used
in tools such as shadow-utils when creating users (both with and without
-s) now has to be configured in three *additional* places. That hardly
seems like an improvement and sounds like a recipe for misconfiguration.
It just makes it more convoluted, where essentially the same data is
repeated in multiple places and then you have some crazy config file
patching system on top of that to distribute it to all those places.

If you were to suggest some new shared configuration file and we could
update shadow-utils and friends to use it then fine (seems kinda
pointless tho'), but I really don't get the logic here.

Ultimately, I guess really don't care much about it. For fresh installs
it's kinda moot, but that said, login.defs is fairly well known and I
really just don't grok the aversion to using it if it exists.

I'd rather we just refactored systemd to have a utility function
"is_system_uid()" or such like which just does the compiled in default
check as it does now (no functional change to how it works now, just
centralised) and then I can just hack in reading and honouring
login.defs into that utility function in a downstream patch. It would be
a couple lines of code and very easy to support downstream if you are so
against it. I'm not against a compiled in default (that's what
shadow-utils does too after all)
Post by Lennart Poettering
As a side effect this would actually even allow us to be closer to
FEdora's current bheaviour, since it reserves UIDs < 200 for static
assignment, which we could then easily exclude from theis logic, too.
Yeah that's one advantage, but I don't really see why this is any better
than just *one* configuration value (e.g. SYS_UID_MIN) in one
configuration file (e.g. /etc/login.defs) which is already honoured by
shadow-utils and no doubt other tools too.

This seems a case were your suggesting a change for changes sake rather
than just saying fine, login.defs is as good a config file as any for
picking vaguely sane defaults. Perhaps I'm missing some background as to
why login.defs is such a horrible config file?

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-07-24 10:59:57 UTC
Permalink
Post by Colin Guthrie
Post by Lennart Poettering
Does this make sense?
To be frank, I really don't think it does make much sense at all. I
mean, something which is currently configured in one place and then used
Well, no, it's not the same setting that is configured at three
places. It's different things you configure. There's conceptually quite
a difference between these settings:

a) Numeric UID boundary

and

1. ranges sysusers dynamically picks UIDs from
2. ranges where journald splits up journals
3. ranges where coredump grant users access to their own coredumps

While #1 configures the part that by default is the bit "below" the UID
boundray, #2 + #4 configure the part that by default is "above" the UID
boundary.

Also, we allow people to actually take benefit of this. As mentioned in
that other mail, being able to configure which users precisely get split
up journal files can be truely useful...

The tools that made use of the UID boundary actually derived very
different things from it. sysusers defined the range to pick dynamic UIDs
from as 1..BOUNDARY. journald picked the range to split of journals
for as BOUNDARY+1..MAXINT-3. The former was simple but not even correct for
Debian nor Fedora. The latter is probably what we should do, but don't
even do (because the "nobody" user shouldn'get his private journal file).

With making the respective ranges explicitly configurable we hence allow
distributions to properly enforce their own policies, and we add true
value to admins. All that while not blessing the crufty /etc/login.defs
file as something we officially want to support in legacy-free systems.

The more I think about all of this the more I actually get convinced
that making the ranges explicitly configurable for their respective
purpose is the right thing to do. I mean, the concept of numeric 32bit
UIDs on UNIX is seriously broken, in particular when it comes to
assigning meaning to specific ranges. Any better designed OS would have
used a namespace that requires no explicit managing (such as UUIDs), and
defined context via true metadata about the users, rather than
mathematical range expressions.

Now, because the namespace is so small, and because semantics have to be
derived from the numeric range a UID is in, I really find it beneficial
if we expose all that logic to the admin/vendor/user, then to strictly
enforce a way too simple view on things, where everything below some
value is one thing and everything above is another thing. In particular
since such a model cannot cover the special cases of UID 0, MAXINT-1,
MAXINT-2.

We have seen now that Debian defines at least 5 ranges with specific
semantics, and Fedora has at least 3 too. In the future we'll probably
see even more ranges, for example for dynamic UID allocation for things
like containers. Trying to cram this all into a single value can never
work.

Or to make this more explicit: somewhere on my TODO list is adding a
mini daemon and NSS module that can dynamically hand out UID ranges for
tools like nspawn for usage in UID namespacing. That daemon would also
have a configuration file. In that configuration file we'd have to
configure an explicit range it shall use. That range is probably going
to be something like 40000-50000 by default, i.e. very far away from the
boundary...
Post by Colin Guthrie
in tools such as shadow-utils when creating users (both with and without
-s) now has to be configured in three *additional* places. That hardly
seems like an improvement and sounds like a recipe for misconfiguration.
It just makes it more convoluted, where essentially the same data is
repeated in multiple places and then you have some crazy config file
patching system on top of that to distribute it to all those places.
It's very different data actually.
Post by Colin Guthrie
If you were to suggest some new shared configuration file and we could
update shadow-utils and friends to use it then fine (seems kinda
pointless tho'), but I really don't get the logic here.
Well, login.defs might have configuration options to tell adduser from
which range to allocate regular and system users from, but it doesn't
have options to configure in which ranges to split up journal files,
in which ranges to provide access to your own coredump files, and from
which ranges to allocate dynamic throw-away UIDs for user namespacing
from. And it shouldn't have, as much of that is logic specific to the
subsystem, and is not orthogonal (by which I mean, that where to split
up journal files might or might not have overlapping ranges with where
to allocate system users from, if you follow what i mean).
Post by Colin Guthrie
I'd rather we just refactored systemd to have a utility function
"is_system_uid()" or such like which just does the compiled in default
check as it does now (no functional change to how it works now, just
centralised) and then I can just hack in reading and honouring
login.defs into that utility function in a downstream patch. It would be
a couple lines of code and very easy to support downstream if you are so
against it. I'm not against a compiled in default (that's what
shadow-utils does too after all)
Well, it wouldn't be that. sysusers would have no benefit of
is_system_uid() for starters, it never asks that question. And I am very
convinced that allowing configuration of when to split up
journals/coredumps is something that should probably default to a range
of BOUNDARY+1..MAXINT-3, but be changable by the admin.
Post by Colin Guthrie
This seems a case were your suggesting a change for changes sake rather
than just saying fine, login.defs is as good a config file as any for
picking vaguely sane defaults. Perhaps I'm missing some background as to
why login.defs is such a horrible config file?
Have a look at the man page, for starters. At least this is cruft:

- the bits about "finger"
- the bits about "console"
- the bits about HZ
- the bits about supath
- the bits about TZ
- the bits about eraschar, killchar
- the bits about ftmp or hushlogins
- the bits about making the issue, motd, nologin file configurable
- the bits to configure what to log
- the bits about the login prompt string
- the bits about MAX_MEMBERS_PER_GROUP (not even compatible with shadow-utils itself)
- the bits about MD5_CRYPT_ENAB
- the bits about "obscure checks"
- the bits about "porttime"
- the bits about deriving ulimit/umask from GECOS
- the bits about suname, sulog...
- the bits about ttygroup/ttyperm (this is not configurable, and hasn't been for a long time)

I am pretty sure you will find people who will defend some of this
non-sense, but honestly, this is all is stuff that shouldn't exist.

Lennart
--
Lennart Poettering, Red Hat
Colin Guthrie
2014-07-24 12:32:32 UTC
Permalink
Post by Lennart Poettering
...
snip
...
I am pretty sure you will find people who will defend some of this
non-sense, but honestly, this is all is stuff that shouldn't exist.
OK, that was a fairly convincing message! Many thanks for taking the
time and being so explicit.

I now appreciate why the journal/coredump splitting is desirable and why
it can/should be different from the sysusers range (and from each other
too).


That said, I'm still not convinced that it should be a simple setting in
journald.conf only. If a package wants to install a service with it's
own user and explicitly wants it to have it's own journal (is apache
httpd a good example of this? Dunno, but it's conceivable either way!),
then they would need the appropriate sysusers.d snippet but then they'd
also have to either manipulate the journald.conf file's SplitUserRange
line or use a dropin file that some generator uses to manipulate and
configure the line accordingly. This just feels a bit too clunky.

Would there be a a way to somehow keep SplitUserRange for basic
(administrator) overrides, but also parse e.g. a column in the sysusers
file to specify whether or not that user wants it's own journal [and
another column for coredump]? The SplitUserRange setting could have
syntax that allowed the admin to either extend the info found in
sysusers (which would be the default), or explicitly override some
setting. e.g.

Say I wanted a split journal for UID 99 (a manually created system
user), I could just say:

SplitUserRange=99

and all the packaged preferences in sysusers files would still be
honoured in addition to UID 99.

If the sysusers file for apache's httpd had:

u httpd 440 "HTTP User" y

where "y" is the new "split journal" column, but I, as an admin, wanted
to override that, I could just specify:

SplitUserRange=99,-440

The leading "-" means "remove range".

Of course an alternative would be to just override the sysusers file in
/etc and put an "n" instead of the "y" (or leave it out), but there may
be a desire for the admin to override all the journal splitting easily
by doing something like:

SplitUserRange=-1-65535
or
SplitUserRange=-*



It's maybe crossing a boundary (i.e. journald should maybe not be
parsing sysuser's config files?), but it would certainly simplify
packaging and avoid the need for the "config patching generator thingy".



Iff it's OK to parse sysusers config from journal [and coredump] stuff,
then perhaps it's also OK to parse it from shadow-utils? If so, then
this is one step closer to your goal of killing login.defs. If direct
parsing is NAKed perhaps it could just shell out to a
systemd-sysusers-getnewuserdetails command which spat out a uid:gid pair
(and took an optional --system argument), that way the parsing logic
only needs to live in one place. This is obviously pretty racey, but I
guess shadow-utils should really do some kind of locking on the files
anyway. I've no idea if/how all of this would work when hooking things
up to e.g. LDAP (I'm not even sure adduser+friends can do that?)


I guess my main concern still remains that uid range settings for system
users would now be in two places - one used by sysusers and another by
adduser (I now accept your argument that the other two places are
different configuration data even if it's conceptually similar). I want
to be able to tell a user that the configuration is in one place not
explain that package "system users ranges" are in one place and
adduser's "system user range" is in another.

Of course I'm assuming here that shadow-utils and it's adduser commands
are still expected to be around for a while... perhaps this is
considered legacy too these days (not sure what the replacement would be
tho'!)?


Sorry if this thread is getting a bit annoying, but I am convinced by
most of the arguments now!

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Colin Guthrie
2014-07-24 13:16:56 UTC
Permalink
Post by Colin Guthrie
If direct
parsing is NAKed perhaps it could just shell out to a
systemd-sysusers-getnewuserdetails command which spat out a uid:gid pair
(and took an optional --system argument), that way the parsing logic
only needs to live in one place.
This bit, of course, is braindead! If this is done at all, it should be
via an API in libsystemd. I think my brain was suggesting that a binary
was somehow OK if such a library API didn't want to be officially
blessed, but that's just broken reasoning - such a binary is an API as
much as a library call would be.

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-08-14 15:51:58 UTC
Permalink
Post by Colin Guthrie
I guess my main concern still remains that uid range settings for system
users would now be in two places - one used by sysusers and another by
adduser (I now accept your argument that the other two places are
different configuration data even if it's conceptually similar). I want
to be able to tell a user that the configuration is in one place not
explain that package "system users ranges" are in one place and
adduser's "system user range" is in another.
Well, here's the thing: I reall don't think the boundary should be a user
configuration thing. It should be a vendor configuration thing. And thus
you shouldn't tell your users about how to configure it at all.

I think communicating how to select the users that get split up journals
makes a lot of sense, but not how to shift the boundary in general. And
that's kinda the key of the issue here...

I am still convinced that adding a range command to sysusers and a
SplitUserRange= setting to journald is the right way to go...

Lennart
--
Lennart Poettering, Red Hat
Colin Walters
2014-07-22 20:47:09 UTC
Permalink
Post by Lennart Poettering
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it.
You list one concern below, are there others?
Post by Lennart Poettering
We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
If that's the only issue, surely we could just have it in the
/usr/share/factory dir?

As far as the rationale for having it administrator configurable - I
think the idea is more that upgraded systems have a login.defs file with
a min of 500, so humans in the midrange are still identified as such.

This is called out on
http://fedoraproject.org/wiki/Features/1000SystemAccounts

Making the boundary configurable also allows some users to stay with the
old boundary of 500, if they wish:

Because /etc/login.defs is %config(noreplace), upgrades will retain
the boundary value 500, and nothing should break.
New installations in setups where the UIDs are centrally allocated
(e.g. using LDAP) from 500 could be likewise configured to use the
boundary value 500 by creating /etc/login.defs in a kickstart %pre
script.
Colin Guthrie
2014-07-23 10:29:20 UTC
Permalink
Post by Colin Walters
Post by Lennart Poettering
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it.
You list one concern below, are there others?
Post by Lennart Poettering
We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
If that's the only issue, surely we could just have it in the
/usr/share/factory dir?
While I'm (personally) wanting to support login.defs here, there is
still a chicken+egg that is not really resolvable here (AFAICT)

If there was a /usr/share/factory/etc/login.defs with e.g. 500 boundary
point, then this file would presumably be copied in by tmpfiles to
populate /etc/login.defs

BUT, as tmpfiles often needs users to exist (to do chowning etc), it has
to run after sysusers.

As sysusers would be one of the consumers of a /etc/login.defs parser,
it wouldn't "see" the /etc/login.defs until too late, thus possibly
creating system users with the compiled in default rather than the
"configured" default.

One cracked egg and an angry chicken :)


This was pretty much the same concern I had when Zbigniew patched
sysusers to also look in /etc/sysusers.d/. The same chicken and egg
scenario exists there, but Lennart was OK with it in that context.

To be honest, I'm not really sure why this chicken+egg is different from
the sysusers one, so I'd expect either both to be rejected or both
accepted but I'm not crazy fussed in this case as it should be easy
enough to hack in /etc/login.defs parsing downstream where our primary
use case is supporting "normal" installs where /etc/ is persistent and
often upgraded from older releases.


Col


PS I appreciate that I've "flipped sides" in my chicken+egg debate
compared to the concern I raised with Zbigniew's sysusers patch! I
always reserve the right to contradict myself :p
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Colin Guthrie
2014-07-23 11:11:37 UTC
Permalink
Post by Colin Guthrie
If there was a /usr/share/factory/etc/login.defs with e.g. 500 boundary
point, then this file would presumably be copied in by tmpfiles to
populate /etc/login.defs
Of course one thing that makes this argument slightly invalid is that if
you DO have a /usr/share/factory/etc/login.defs, then this file *should*
be configured with the same boundary as systemd's built in defaults, so
there should be no problem in the context of bootstrapping /etc.

Therefore, if this is the case, then the argument for not reading and
honouring /etc/login.defs if it exists is, IMO, invalid.

Have I won Lennart? Are you now convinced that such a patch would be in
the same category as Zbigniew's sysusers reading /etc/sysusers.d/ patch
that already went in? :p

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Kay Sievers
2014-07-23 11:36:45 UTC
Permalink
Post by Colin Guthrie
Post by Colin Guthrie
If there was a /usr/share/factory/etc/login.defs with e.g. 500 boundary
point, then this file would presumably be copied in by tmpfiles to
populate /etc/login.defs
Of course one thing that makes this argument slightly invalid is that if
you DO have a /usr/share/factory/etc/login.defs, then this file *should*
be configured with the same boundary as systemd's built in defaults, so
there should be no problem in the context of bootstrapping /etc.
Therefore, if this is the case, then the argument for not reading and
honouring /etc/login.defs if it exists is, IMO, invalid.
Have I won Lennart? Are you now convinced that such a patch would be in
the same category as Zbigniew's sysusers reading /etc/sysusers.d/ patch
that already went in? :p
I don't see the rather artificially constructed case of an
/usr/share/factory/etc/login.defs + tmpfiles snippet to copy to /etc
as a valid argument for reading login.defs.

Configuring our own base bootstrap tools with /usr/share/factory/ + a
tmpfiles snippet to copy the stuff over to /etc is a cyclic loop we
just do not support, and which makes not much sense anyway.

Bootstrap-/etc-population is intended for "broken" tools that cannot
be fixed properly, not our own stuff, which does not need /etc
populated.

Kay
Colin Guthrie
2014-07-23 11:49:23 UTC
Permalink
Post by Kay Sievers
I don't see the rather artificially constructed case of an
/usr/share/factory/etc/login.defs + tmpfiles snippet to copy to /etc
as a valid argument for reading login.defs.
Well, my point was that one of Lennart's original arguments for NOT
reading login.defs was that /etc/ wouldn't have it when bootstrapping.

But as you've just confirmed if you *are* bootstrapping /etc, then using
the compiled in defaults makes sense as you are very unlikely to be
copying across a factory version of login.defs anyway. My point was that
if you WERE copying across of a factory version of login.defs it should
really be setup with the same defaults that systemd has compiled in anyway.

So again, this is just furthering the argument that we *should* read
/etc/login.defs at runtime and the "bootstrapping" argument for not
doing so is not really valid.

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Kay Sievers
2014-07-23 12:22:59 UTC
Permalink
Post by Colin Guthrie
Post by Kay Sievers
I don't see the rather artificially constructed case of an
/usr/share/factory/etc/login.defs + tmpfiles snippet to copy to /etc
as a valid argument for reading login.defs.
Well, my point was that one of Lennart's original arguments for NOT
reading login.defs was that /etc/ wouldn't have it when bootstrapping.
The main point was that it should not be *configurable*, but be a *static*
OS property.

Unix/Linux is just so insufficient and broken regarding the uid
namespace and handling, that we should limit ourselves to the simplest
rules possible and live with it, instead of trying to fix something that is so
broken that it can never work properly with all the options people like to
throw at it.
Post by Colin Guthrie
But as you've just confirmed if you *are* bootstrapping /etc, then using
the compiled in defaults makes sense as you are very unlikely to be
copying across a factory version of login.defs anyway. My point was that
if you WERE copying across of a factory version of login.defs it should
really be setup with the same defaults that systemd has compiled in anyway.
Right, anything else would just be broken. Copying login.defs at bootstrap time
would not make any sense in the first place. But, hey, it would be just one of
thousand ways to break a setup. It's nothing we need to care about.
Post by Colin Guthrie
So again, this is just furthering the argument that we *should* read
/etc/login.defs at runtime and the "bootstrapping" argument for not
doing so is not really valid.
No, I still think we should limit the options of the conceptually completely
broken idea of unix uids to the absolute minimum, and not try to fix things
in any way here with layering even more broken options on top.

If we want uids that have meaning and can be managed, they should
become 128 (uuid) or at least 64 bit, so they can be statically
allocated and moved
from one machine to another.

The sysuser vs. normal user is really not significantly more that a convenience
feature, it is not used for authorization or anything. Legacy setups
on new systems
might end up with fewer convenience features, but there are no
features lost really,
which they had before systemd was used.

Kay
Colin Guthrie
2014-07-23 11:11:37 UTC
Permalink
Post by Colin Guthrie
If there was a /usr/share/factory/etc/login.defs with e.g. 500 boundary
point, then this file would presumably be copied in by tmpfiles to
populate /etc/login.defs
Of course one thing that makes this argument slightly invalid is that if
you DO have a /usr/share/factory/etc/login.defs, then this file *should*
be configured with the same boundary as systemd's built in defaults, so
there should be no problem in the context of bootstrapping /etc.

Therefore, if this is the case, then the argument for not reading and
honouring /etc/login.defs if it exists is, IMO, invalid.

Have I won Lennart? Are you now convinced that such a patch would be in
the same category as Zbigniew's sysusers reading /etc/sysusers.d/ patch
that already went in? :p

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Zbigniew Jędrzejewski-Szmek
2014-07-23 14:28:02 UTC
Permalink
Post by Colin Guthrie
Post by Colin Walters
Post by Lennart Poettering
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it.
You list one concern below, are there others?
Post by Lennart Poettering
We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
If that's the only issue, surely we could just have it in the
/usr/share/factory dir?
While I'm (personally) wanting to support login.defs here, there is
still a chicken+egg that is not really resolvable here (AFAICT)
If there was a /usr/share/factory/etc/login.defs with e.g. 500 boundary
point, then this file would presumably be copied in by tmpfiles to
populate /etc/login.defs
I totally agree with Kay here, that /usr/share/factory is *only* for
programs which are broken and have neither compiled-in defaults nor
the ability to read /usr/share for their defaults. We should
aim for empty /usr/share/factory/etc (*), and systemd certainly should
not depend or use anything in it.

And anyway, the file in /usr/share/factory/etc would have the same
defaults as compiled-in into systemd, so it is not useful. I think
that your angry chicken is not a problem.

(*) "Empty" files containing commented-out directives as a way of
documentation are fine.
Post by Colin Guthrie
This was pretty much the same concern I had when Zbigniew patched
sysusers to also look in /etc/sysusers.d/. The same chicken and egg
scenario exists there, but Lennart was OK with it in that context.
To be honest, I'm not really sure why this chicken+egg is different from
the sysusers one, so I'd expect either both to be rejected or both
accepted but I'm not crazy fussed in this case as it should be easy
enough to hack in /etc/login.defs parsing downstream where our primary
use case is supporting "normal" installs where /etc/ is persistent and
often upgraded from older releases.
The fallacy here is trying to support stateless systems with users.
Users (account numbers, their passwords, privileges) are state,
and the most important one at that. But the admin cannot expect to
nuke /etc and have working users, unless the users are defined
remotely.

I think it is fine to have locally defined users, and some way to
determine which of those users are "human". If the admin purges /etc,
the interpretation of which users are human resets to the compiled in
default. IMHO this is fine.

I like Lennarts idea of using 'user' group, since it is more flexible than
static ranges. It might be nice to support in the future if we work out
the details. But there's also a need for backwards compatibility. I know
from my own admin experience and agree with Reindl that UID changes are a
huge pain, and we have to support existing setups without requiring any
renumbering. This basically means that any distribution which supports
upgrades from previous versions will add /etc/login.defs support.
Post by Colin Guthrie
No, I still think we should limit the options of the conceptually completely
broken idea of unix uids to the absolute minimum, and not try to fix things
in any way here with layering even more broken options on top.
Well, systemd uses the user/systemd boundary split in journald and coredump
permissions code, so we *are* layering on top. Even more importantly, we
are using it to allocate numbers in sysusers. Even with distribution
support, it is not possible to arbitrarily redefine UID ranges,
because users' UIDs are something that can be only changed by admin
intervention. I don't see how we can skip /etc/login.defs support
without doing a disservice to our users.

Previously we added the systemd-journal group. It was fine, because
it worked in a backwards-compatible way, and we could document that giving
users access to the journal can be done following a few simple steps.

Anyway, I think that /etc/login.defs support is made out to be something
much more complicated than it really is. IMHO we should:

- read /etc/login.defs and fall back to the compiled in value
- use whatever result we get in coredump, journald, and sysusers

It's not like the implementation would be hard, intrusive, or slow. It'd be
probably +3 lines in one or two places.

If we come up with additional heuristics or rules to determine human
accounts, we can safely add them in a backwards compatible way.

Zbyszek
Kay Sievers
2014-07-23 14:55:59 UTC
Permalink
On Wed, Jul 23, 2014 at 4:28 PM, Zbigniew Jędrzejewski-Szmek
Post by Zbigniew Jędrzejewski-Szmek
Anyway, I think that /etc/login.defs support is made out to be something
- read /etc/login.defs and fall back to the compiled in value
- use whatever result we get in coredump, journald, and sysusers
It's not like the implementation would be hard, intrusive, or slow. It'd be
probably +3 lines in one or two places.
It is not about the effort *how* to do it, it is *why*. And I still
don't think we should have dynamic configuration options for this, it
is all just a huge mess that needs to be limited to the bare minimum,
it is just too broken as a concept to be supported that way.
Post by Zbigniew Jędrzejewski-Szmek
If we come up with additional heuristics or rules to determine human
accounts, we can safely add them in a backwards compatible way.
We cannot do any normal user queries from journald, so none of the
metadata like the primary group is easily for a user is available.

Sysusers is, and probably always will be, limited to the classic
passwd, group file. Maybe we can just read the files ourselves and
find out that a certain uid is a normal user? Like:
- uid >= "1000" --> normal user
- lookup uid in passwd
- user not found --> normal user
- user < 1000 && group == "users" --> normal user
- everything else would be a system user

Kay
Zbigniew Jędrzejewski-Szmek
2014-07-23 15:17:23 UTC
Permalink
Post by Kay Sievers
On Wed, Jul 23, 2014 at 4:28 PM, Zbigniew Jędrzejewski-Szmek
Post by Zbigniew Jędrzejewski-Szmek
Anyway, I think that /etc/login.defs support is made out to be something
- read /etc/login.defs and fall back to the compiled in value
- use whatever result we get in coredump, journald, and sysusers
It's not like the implementation would be hard, intrusive, or slow. It'd be
probably +3 lines in one or two places.
It is not about the effort *how* to do it, it is *why*. And I still
don't think we should have dynamic configuration options for this, it
is all just a huge mess that needs to be limited to the bare minimum,
it is just too broken as a concept to be supported that way.
Post by Zbigniew Jędrzejewski-Szmek
If we come up with additional heuristics or rules to determine human
accounts, we can safely add them in a backwards compatible way.
We cannot do any normal user queries from journald, so none of the
metadata like the primary group is easily for a user is available.
I know.
Post by Kay Sievers
Sysusers is, and probably always will be, limited to the classic
passwd, group file. Maybe we can just read the files ourselves and
- uid >= "1000" --> normal user
- lookup uid in passwd
- user not found --> normal user
- user < 1000 && group == "users" --> normal user
- everything else would be a system user
But please add to this (at the top)
- parse SYS_GID_MIN and SYS_GID_MAX from /etc/login.defs and if
found and users falls within --> system user

This is safe as soon as /etc is accessible and provides backwards
compatibillity.

Also, I'd modify
- user < 1000 && group == "users" --> normal user
to
- group == "users" --> normal user
not to make things too complicated.

I see another angry chicken and broken egg problem now:
- We want to get rid of /etc/login.defs, *but*
- we read /etc/login.defs at compilation time.
This means that we probably should stop looking at that file during
compilation time and stick to an internal default, possibly allowing
overriding with ./configure switch.

Zbyszek
Kay Sievers
2014-07-23 15:30:53 UTC
Permalink
On Wed, Jul 23, 2014 at 5:17 PM, Zbigniew Jędrzejewski-Szmek
Post by Zbigniew Jędrzejewski-Szmek
Post by Kay Sievers
On Wed, Jul 23, 2014 at 4:28 PM, Zbigniew Jędrzejewski-Szmek
Post by Zbigniew Jędrzejewski-Szmek
Anyway, I think that /etc/login.defs support is made out to be something
- read /etc/login.defs and fall back to the compiled in value
- use whatever result we get in coredump, journald, and sysusers
It's not like the implementation would be hard, intrusive, or slow. It'd be
probably +3 lines in one or two places.
It is not about the effort *how* to do it, it is *why*. And I still
don't think we should have dynamic configuration options for this, it
is all just a huge mess that needs to be limited to the bare minimum,
it is just too broken as a concept to be supported that way.
Post by Zbigniew Jędrzejewski-Szmek
If we come up with additional heuristics or rules to determine human
accounts, we can safely add them in a backwards compatible way.
We cannot do any normal user queries from journald, so none of the
metadata like the primary group is easily for a user is available.
I know.
Post by Kay Sievers
Sysusers is, and probably always will be, limited to the classic
passwd, group file. Maybe we can just read the files ourselves and
- uid >= "1000" --> normal user
- lookup uid in passwd
- user not found --> normal user
- user < 1000 && group == "users" --> normal user
- everything else would be a system user
But please add to this (at the top)
- parse SYS_GID_MIN and SYS_GID_MAX from /etc/login.defs and if
found and users falls within --> system user
This is safe as soon as /etc is accessible and provides backwards
compatibillity.
Well, the point is to make the rules in this broken model simpler, not
more complicated as they already are. :)

If we would read login.defs, we should probably not do any magic
heuristics. And at the moment, I still think we should ignore
login.defs.
Post by Zbigniew Jędrzejewski-Szmek
Also, I'd modify
- user < 1000 && group == "users" --> normal user
to
- group == "users" --> normal user
not to make things too complicated.
- We want to get rid of /etc/login.defs, *but*
- we read /etc/login.defs at compilation time.
This means that we probably should stop looking at that file during
compilation time and stick to an internal default, possibly allowing
overriding with ./configure switch.
Maybe, yes. It was just to init the build sys with the current distro defaults.

Kay
Zbigniew Jędrzejewski-Szmek
2014-07-23 16:06:41 UTC
Permalink
Post by Kay Sievers
On Wed, Jul 23, 2014 at 5:17 PM, Zbigniew Jędrzejewski-Szmek
Post by Zbigniew Jędrzejewski-Szmek
Post by Kay Sievers
On Wed, Jul 23, 2014 at 4:28 PM, Zbigniew Jędrzejewski-Szmek
Post by Zbigniew Jędrzejewski-Szmek
Anyway, I think that /etc/login.defs support is made out to be something
- read /etc/login.defs and fall back to the compiled in value
- use whatever result we get in coredump, journald, and sysusers
It's not like the implementation would be hard, intrusive, or slow. It'd be
probably +3 lines in one or two places.
It is not about the effort *how* to do it, it is *why*. And I still
don't think we should have dynamic configuration options for this, it
is all just a huge mess that needs to be limited to the bare minimum,
it is just too broken as a concept to be supported that way.
Post by Zbigniew Jędrzejewski-Szmek
If we come up with additional heuristics or rules to determine human
accounts, we can safely add them in a backwards compatible way.
We cannot do any normal user queries from journald, so none of the
metadata like the primary group is easily for a user is available.
I know.
Post by Kay Sievers
Sysusers is, and probably always will be, limited to the classic
passwd, group file. Maybe we can just read the files ourselves and
- uid >= "1000" --> normal user
- lookup uid in passwd
- user not found --> normal user
- user < 1000 && group == "users" --> normal user
- everything else would be a system user
But please add to this (at the top)
- parse SYS_GID_MIN and SYS_GID_MAX from /etc/login.defs and if
found and users falls within --> system user
This is safe as soon as /etc is accessible and provides backwards
compatibillity.
Well, the point is to make the rules in this broken model simpler, not
more complicated as they already are. :)
If we would read login.defs, we should probably not do any magic
heuristics. And at the moment, I still think we should ignore
login.defs.
If we find it, then certainly, it should override other considerations.
Post by Kay Sievers
Post by Zbigniew Jędrzejewski-Szmek
Also, I'd modify
- user < 1000 && group == "users" --> normal user
to
- group == "users" --> normal user
not to make things too complicated.
- We want to get rid of /etc/login.defs, *but*
- we read /etc/login.defs at compilation time.
This means that we probably should stop looking at that file during
compilation time and stick to an internal default, possibly allowing
overriding with ./configure switch.
Maybe, yes. It was just to init the build sys with the current distro defaults.
Right, but it makes login.defs even more entrenched.

Zbyszek
Reindl Harald
2014-07-22 20:56:19 UTC
Permalink
Post by Colin Walters
Post by Lennart Poettering
I am pretty strongly against this. Making this administrator
configurable apepars very wrong, this really should be a decision for
the distribution vendor, and that's it.
You list one concern below, are there others?
Post by Lennart Poettering
We shouldn't design a system
that comes to completely different results if you boot it up with and
without /etc populated...
If that's the only issue, surely we could just have it in the
/usr/share/factory dir?
As far as the rationale for having it administrator configurable - I
think the idea is more that upgraded systems have a login.defs file with
a min of 500, so humans in the midrange are still identified as such.
This is called out on
http://fedoraproject.org/wiki/Features/1000SystemAccounts
Making the boundary configurable also allows some users to stay with the
Because /etc/login.defs is %config(noreplace), upgrades will retain
the boundary value 500, and nothing should break.
New installations in setups where the UIDs are centrally allocated
(e.g. using LDAP) from 500 could be likewise configured to use the
boundary value 500 by creating /etc/login.defs in a kickstart %pre
script
there are *a lot* of systems out there installed long before systemd
was introduced and you can't safely dig around on dozens of machines
and re-assign the owners of files

there are data far away from /home

don't fix things which ain't broken
all that machines will *never* need dynamic user-id's abvoe 500
Loading...