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

systemd can't handle the process previlege that belongs to user name startswith number, such as 0day #6237

Closed
mapleray opened this Issue Jun 29, 2017 · 37 comments

Comments

@mapleray

mapleray commented Jun 29, 2017

Submission type

  • Bug report

systemd version the issue has been seen with

systemd 232

Used distribution

Linux ubuntu 4.10.0-19-generic #21-Ubuntu SMP Thu Apr 6 17:04:57 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

In case of bug report: Expected behaviour you didn't see

The process started by systemd should be user previlege

In case of bug report: Unexpected behaviour you saw

The process started by systemd was root previlege

In case of bug report: Steps to reproduce the problem

linux user's name : 0day
conf file: socat.service

[Unit]
Description=0day socat service
After=network.target

[Service]
User=0day
Restart=always
Type=simple
WorkingDirectory=/home/0day/
ExecStart=/usr/bin/socat TCP-LISTEN:18086,reuseaddr,fork EXEC:"/opt/run-elf"

[Install]
WantedBy=multi-user.target

and then use systemctl start socat.service to start process, but the previlege is root

P.S.
I searched google and found that it was not right to named a linux user with 0day, it should satisfy "^[a-z][-a-z0-9]*\$ , but when I use xinted to start the service, it can handle the previlege rightly with linux user 0day

@poettering

This comment has been minimized.

Show comment
Hide comment
@poettering

poettering Jun 29, 2017

Member

Yes, as you found out "0day" is not a valid username. I wonder which tool permitted you to create it in the first place. Note that not permitting numeric first characters is done on purpose: to avoid ambiguities between numeric UID and textual user names.

systemd will validate all configuration data you drop at it, making it hard to generate invalid configuration. Hence, yes, it's a feature that we don't permit invalid user names, and I'd consider it a limitation of xinetd that it doesn't refuse an invalid username.

So, yeah, I don't think there's anything to fix in systemd here. I understand this is annoying, but still: the username is clearly not valid.

I hope that makes sense?

Member

poettering commented Jun 29, 2017

Yes, as you found out "0day" is not a valid username. I wonder which tool permitted you to create it in the first place. Note that not permitting numeric first characters is done on purpose: to avoid ambiguities between numeric UID and textual user names.

systemd will validate all configuration data you drop at it, making it hard to generate invalid configuration. Hence, yes, it's a feature that we don't permit invalid user names, and I'd consider it a limitation of xinetd that it doesn't refuse an invalid username.

So, yeah, I don't think there's anything to fix in systemd here. I understand this is annoying, but still: the username is clearly not valid.

I hope that makes sense?

@mapleray

This comment has been minimized.

Show comment
Hide comment
@mapleray

mapleray Jun 29, 2017

Yeah, thanks.

Yeah, thanks.

@divVerent

This comment has been minimized.

Show comment
Hide comment
@divVerent

divVerent Jul 1, 2017

Wouldn't it make sense to refuse User=0day then?

In fact, wouldn't it even make sense to refuse User=0x200 or User=01000 rather than User=512 (in other words, to only allow decimal canonical user IDs) for the same reason?

BTW: where does xinetd come in here?

Wouldn't it make sense to refuse User=0day then?

In fact, wouldn't it even make sense to refuse User=0x200 or User=01000 rather than User=512 (in other words, to only allow decimal canonical user IDs) for the same reason?

BTW: where does xinetd come in here?

@bloerwald

This comment has been minimized.

Show comment
Hide comment
@bloerwald

bloerwald Jul 1, 2017

I wonder which tool permitted you to create it in the first place.

It appears that el7 patches shadow-utils-4.1.5.1/libmisc/chkname.c so that it does allow that kind of usernames, explicitly removing the restrictions: https://gist.github.com/bloerwald/a482791395114fa82636e2ab207cdb11

While it does indeed seem to be a not-a-bug in systemd, one may want to make someone maintaining that el7 patch aware of that the combination of systemd and that patch does pose an issue.

A patch refusing any User= that are invalid would be a nice thing, even if it is not a bug, as noted by @divVerent. That would put the el7 maintainer at the position to explicitly remove that check as well, thinking about their patch allowing usernames without restrictions.

I wonder which tool permitted you to create it in the first place.

It appears that el7 patches shadow-utils-4.1.5.1/libmisc/chkname.c so that it does allow that kind of usernames, explicitly removing the restrictions: https://gist.github.com/bloerwald/a482791395114fa82636e2ab207cdb11

While it does indeed seem to be a not-a-bug in systemd, one may want to make someone maintaining that el7 patch aware of that the combination of systemd and that patch does pose an issue.

A patch refusing any User= that are invalid would be a nice thing, even if it is not a bug, as noted by @divVerent. That would put the el7 maintainer at the position to explicitly remove that check as well, thinking about their patch allowing usernames without restrictions.

@nopil3os

This comment has been minimized.

Show comment
Hide comment
@nopil3os

nopil3os Jul 1, 2017

I wonder which tool permitted you to create it in the first place.

useradd doesn't complain: screenshot

nopil3os commented Jul 1, 2017

I wonder which tool permitted you to create it in the first place.

useradd doesn't complain: screenshot

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jul 1, 2017

Does the POSIX standard deny leading numbers for user names on *nix?

ghost commented Jul 1, 2017

Does the POSIX standard deny leading numbers for user names on *nix?

@Nothing4You

This comment has been minimized.

Show comment
Hide comment
@Nothing4You

Nothing4You Jul 1, 2017

Tested on Debian with shadow-utils 4.4 and adduser 3.115, only adduser complains, useradd doesn't.

# useradd -m 0day
# userdel -r 0day
userdel: 0day mail spool (/var/mail/0day) not found
# adduser 0day
adduser: Please enter a username matching the regular expression configured
via the NAME_REGEX configuration variable.  Use the `--force-badname'
option to relax this check or reconfigure NAME_REGEX.

Tested on Debian with shadow-utils 4.4 and adduser 3.115, only adduser complains, useradd doesn't.

# useradd -m 0day
# userdel -r 0day
userdel: 0day mail spool (/var/mail/0day) not found
# adduser 0day
adduser: Please enter a username matching the regular expression configured
via the NAME_REGEX configuration variable.  Use the `--force-badname'
option to relax this check or reconfigure NAME_REGEX.
@RealDolos

This comment has been minimized.

Show comment
Hide comment
@RealDolos

RealDolos Jul 1, 2017

Let's look if it's actually invalid... Probably not because:

3.276 Portable Filename Character Set
The set of characters from which portable filenames are constructed.
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 . _ -
The last three characters are the period, underscore, and hyphen characters, respectively.

3.426 User Name
A string that is used to identify a user; see also User Database. To be portable across systems conforming to IEEE Std 1003.1-2001, the value is composed of characters from the portable filename character set. The hyphen should not be used as the first character of a portable user name.

http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276

adduser will often refuse it tho, e.g. on debian with NAME_REGEX (calling itself "more conservative by default"), but you can still override that behavior.

So in my humble opinion, it's a valid name and thus systemd has a bug here.

Even if you assume leading numbers are not allowed, systemd running the unit under root is a bug too. It should refuse to run the unit, in particular in the light of:

systemd will validate all configuration data you drop at it
-- @poettering #6237 (comment)

This is clearly not the case, User=0day is clearly not properly validated and silently ignored and it's still a bug (or it's just put into something like atoi and will try to execute 1day as uid 1, not sure about that).

So either way, there is a bug here.

RealDolos commented Jul 1, 2017

Let's look if it's actually invalid... Probably not because:

3.276 Portable Filename Character Set
The set of characters from which portable filenames are constructed.
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 . _ -
The last three characters are the period, underscore, and hyphen characters, respectively.

3.426 User Name
A string that is used to identify a user; see also User Database. To be portable across systems conforming to IEEE Std 1003.1-2001, the value is composed of characters from the portable filename character set. The hyphen should not be used as the first character of a portable user name.

http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276

adduser will often refuse it tho, e.g. on debian with NAME_REGEX (calling itself "more conservative by default"), but you can still override that behavior.

So in my humble opinion, it's a valid name and thus systemd has a bug here.

Even if you assume leading numbers are not allowed, systemd running the unit under root is a bug too. It should refuse to run the unit, in particular in the light of:

systemd will validate all configuration data you drop at it
-- @poettering #6237 (comment)

This is clearly not the case, User=0day is clearly not properly validated and silently ignored and it's still a bug (or it's just put into something like atoi and will try to execute 1day as uid 1, not sure about that).

So either way, there is a bug here.

@redrifle

This comment has been minimized.

Show comment
Hide comment
@redrifle

redrifle Jul 1, 2017

hm yes I'll look into it

redrifle commented Jul 1, 2017

hm yes I'll look into it

@rain-1

This comment has been minimized.

Show comment
Hide comment
@rain-1

rain-1 Jul 1, 2017

I think people are getting distracted with whether or not 0day is a valid name or not.

The real problem here is that the unit is run as root, despite "0day" not describing the root user, isn't it?

Can a systemd developer tell: Will a patch that gives an error in this case be accepted? I can get started on it if so.

rain-1 commented Jul 1, 2017

I think people are getting distracted with whether or not 0day is a valid name or not.

The real problem here is that the unit is run as root, despite "0day" not describing the root user, isn't it?

Can a systemd developer tell: Will a patch that gives an error in this case be accepted? I can get started on it if so.

@Nothing4You

This comment has been minimized.

Show comment
Hide comment
@Nothing4You

Nothing4You Jul 1, 2017

@rain-1 there's 2 bugs - one is that it is still running as root and the other is that it doesn't support usernames starting with numbers.

@rain-1 there's 2 bugs - one is that it is still running as root and the other is that it doesn't support usernames starting with numbers.

@rain-1

This comment has been minimized.

Show comment
Hide comment
@rain-1

rain-1 Jul 1, 2017

I see! please make a separate issue to track the second bug (usernames starting with numbers).

rain-1 commented Jul 1, 2017

I see! please make a separate issue to track the second bug (usernames starting with numbers).

@RealDolos

This comment has been minimized.

Show comment
Hide comment
@RealDolos

RealDolos Jul 1, 2017

Actually, fix the incorrect user name handling thereby fixing the run-as-root issue too. And we kinda made an issue about that already, namely THIS one.

RealDolos commented Jul 1, 2017

Actually, fix the incorrect user name handling thereby fixing the run-as-root issue too. And we kinda made an issue about that already, namely THIS one.

@julian-klode

This comment has been minimized.

Show comment
Hide comment
@julian-klode

julian-klode Jul 1, 2017

This is a severe security issue that should be fixed, and assigned a CVE, and not not-a-bug.

This is a severe security issue that should be fixed, and assigned a CVE, and not not-a-bug.

@rain-1

This comment has been minimized.

Show comment
Hide comment
@rain-1

rain-1 Jul 1, 2017

@julian-klode you might have misunderstood this bug, it cannot be used for priv. esc.

rain-1 commented Jul 1, 2017

@julian-klode you might have misunderstood this bug, it cannot be used for priv. esc.

@julian-klode

This comment has been minimized.

Show comment
Hide comment
@julian-klode

julian-klode Jul 1, 2017

@rain-1 If the process starts, and you expect it to start a user and not as root, then that is a security issue, because your service suddenly runs as root (and you might not notice it until it is too late).

@rain-1 If the process starts, and you expect it to start a user and not as root, then that is a security issue, because your service suddenly runs as root (and you might not notice it until it is too late).

@pRiVi

This comment has been minimized.

Show comment
Hide comment
@pRiVi

pRiVi Jul 1, 2017

So many bugs and issues, and all the time the poettering ignorance... I just cannot stand it...

It does not matter if its free, if you carry such things with it. Sadly the only way leaving it is using devuan...

pRiVi commented Jul 1, 2017

So many bugs and issues, and all the time the poettering ignorance... I just cannot stand it...

It does not matter if its free, if you carry such things with it. Sadly the only way leaving it is using devuan...

@RealDolos

This comment has been minimized.

Show comment
Hide comment
@RealDolos

RealDolos Jul 1, 2017

Seems the stuff is parsed using:

Meaning indeed, User=1day will try to run with UID 1 as well

Edit: See other comments following up on this probably not being the case after all.

RealDolos commented Jul 1, 2017

Seems the stuff is parsed using:

Meaning indeed, User=1day will try to run with UID 1 as well

Edit: See other comments following up on this probably not being the case after all.

@UgnilJoZ

This comment has been minimized.

Show comment
Hide comment
@UgnilJoZ

UgnilJoZ Jul 1, 2017

@RealDolos My systemd v232 says: Invalid user/group name or numeric ID, ignoring: 7oz and starts the service as root also. Likely because the 7oz as a whole is not a valid number.

# /etc/systemd/system/test.service
[Service]
ExecStart=/bin/id
User=7oz

UgnilJoZ commented Jul 1, 2017

@RealDolos My systemd v232 says: Invalid user/group name or numeric ID, ignoring: 7oz and starts the service as root also. Likely because the 7oz as a whole is not a valid number.

# /etc/systemd/system/test.service
[Service]
ExecStart=/bin/id
User=7oz
@red-hood

This comment has been minimized.

Show comment
Hide comment
@red-hood

red-hood Jul 1, 2017

If a user name is indeed allowed to be made up of digits alone, there has to be a way to distinguish it from a UID. I propose to specify the information in the same way GNU coreutiles does, by appending a + whenever a UID is meant, and otherwise try to resolve to a username first.

See also: https://www.gnu.org/software/coreutils/manual/coreutils.html#Disambiguating-names-and-IDs

red-hood commented Jul 1, 2017

If a user name is indeed allowed to be made up of digits alone, there has to be a way to distinguish it from a UID. I propose to specify the information in the same way GNU coreutiles does, by appending a + whenever a UID is meant, and otherwise try to resolve to a username first.

See also: https://www.gnu.org/software/coreutils/manual/coreutils.html#Disambiguating-names-and-IDs

@RealDolos

This comment has been minimized.

Show comment
Hide comment
@RealDolos

RealDolos Jul 1, 2017

@UgnilJoZ do you actually have a user with uid 7?

@UgnilJoZ do you actually have a user with uid 7?

@UgnilJoZ

This comment has been minimized.

Show comment
Hide comment
@UgnilJoZ

UgnilJoZ Jul 1, 2017

@RealDolos Yes, I just created one for testing ;)

UgnilJoZ commented Jul 1, 2017

@RealDolos Yes, I just created one for testing ;)

@julian-klode

This comment has been minimized.

Show comment
Hide comment
@julian-klode

julian-klode Jul 1, 2017

@RealDolos safe_atou checks that it is a valid number, and not a number with something at the end, so the warning here makes sense. But then the bug report is incomplete, because systemd does at least warn about it. I'm not sure it makes sense to start a service if the specified user is invalid, though.

@RealDolos safe_atou checks that it is a valid number, and not a number with something at the end, so the warning here makes sense. But then the bug report is incomplete, because systemd does at least warn about it. I'm not sure it makes sense to start a service if the specified user is invalid, though.

@RealDolos

This comment has been minimized.

Show comment
Hide comment
@RealDolos

RealDolos Jul 1, 2017

@julian-klode

I'm not sure it makes sense to start a service if the specified user is invalid, though.

That one is easy, in my humble opinion: Same as systemd should not pick and run some random binary when the specified ExecStart is invalid, it shouldn't run a service under a random uid if it cannot find the specified user (uid 0 being the random uid fairly picked by the Debian PRNG, of course)

PS: Sorry, @julian-klode, only saw just now that you're actually a Debian dev. My Debian PRNG quip wasn't meant to personally target you.

RealDolos commented Jul 1, 2017

@julian-klode

I'm not sure it makes sense to start a service if the specified user is invalid, though.

That one is easy, in my humble opinion: Same as systemd should not pick and run some random binary when the specified ExecStart is invalid, it shouldn't run a service under a random uid if it cannot find the specified user (uid 0 being the random uid fairly picked by the Debian PRNG, of course)

PS: Sorry, @julian-klode, only saw just now that you're actually a Debian dev. My Debian PRNG quip wasn't meant to personally target you.

@red-hood

This comment has been minimized.

Show comment
Hide comment
@red-hood

red-hood Jul 1, 2017

In

if (parse_uid(*username, &u) >= 0) {
, the entry is first parsed as a UID, and only if that fails, a lookup for the username is done. To be compliant, this order has to be changed.

red-hood commented Jul 1, 2017

In

if (parse_uid(*username, &u) >= 0) {
, the entry is first parsed as a UID, and only if that fails, a lookup for the username is done. To be compliant, this order has to be changed.

@red-hood

This comment has been minimized.

Show comment
Hide comment
@red-hood

red-hood Jul 1, 2017

The line which does the hard-coded fallback to root is here:

if (r < 0)

red-hood commented Jul 1, 2017

The line which does the hard-coded fallback to root is here:

if (r < 0)

@julian-klode

This comment has been minimized.

Show comment
Hide comment
@julian-klode

julian-klode Jul 1, 2017

@red-hood That's not even remotely true - the code is for ConditionUser, and the line mentioned says that if the user could not be parsed (< 0) that the condition is not met (return 0 => false) - and chasing it down step by step in issue comments is not helping anyone.

@red-hood That's not even remotely true - the code is for ConditionUser, and the line mentioned says that if the user could not be parsed (< 0) that the condition is not met (return 0 => false) - and chasing it down step by step in issue comments is not helping anyone.

@divVerent

This comment has been minimized.

Show comment
Hide comment
@divVerent

divVerent Jul 1, 2017

@kentfredric

This comment has been minimized.

Show comment
Hide comment
@kentfredric

kentfredric Jul 2, 2017

Now how can this broader issue be fixed? Hard. Very hard. Making a valid User= directive mandatory would be a good start - but this is horribly backwards incompatible

Maybe a systemd config option that turns such warning cases into errors? Or like, a config file that enumerates the kinds of errors that should be fatal instead of warnings?

Now how can this broader issue be fixed? Hard. Very hard. Making a valid User= directive mandatory would be a good start - but this is horribly backwards incompatible

Maybe a systemd config option that turns such warning cases into errors? Or like, a config file that enumerates the kinds of errors that should be fatal instead of warnings?

@mbiebl

This comment has been minimized.

Show comment
Hide comment
@mbiebl

mbiebl Jul 2, 2017

Contributor

Sigh, since this now attracting the trolls, I'm locking the conversation.

Contributor

mbiebl commented Jul 2, 2017

Sigh, since this now attracting the trolls, I'm locking the conversation.

@systemd systemd locked and limited conversation to collaborators Jul 2, 2017

@systemd systemd deleted a comment from jrmithdobbs Jul 2, 2017

@systemd systemd deleted a comment from sergeyfrolov Jul 2, 2017

@poettering

This comment has been minimized.

Show comment
Hide comment
@poettering

poettering Jul 2, 2017

Member

Just to summarize things:

  1. systemd is not the one coming up with the restrictions on user names, and while some distributions are less restrictive, many do enforce the same restrictions as we do. In order to make systemd unit files portable between systems we'll hence enforce something that resembles more the universally accepted set, rather than accept the most liberal set possible.
  2. User= in unit files is about system users, not regular users, and I am pretty sure we should enforce a stricter regime about system users than regular users.
  3. In systemd we generally follow the rule that when we encounter a unit setting that does not validate syntax-wise we'll log about it and ignore it, for compat reasons. We do the same for User= here as for all other options. Note that if you specify a valid user name but where the user doesn't exist, then we'll instead fail the service on start, because in that case there's not just something wrong with the syntax the service author used but actually something inconsistent on the system, and that should be considered fatal.
Member

poettering commented Jul 2, 2017

Just to summarize things:

  1. systemd is not the one coming up with the restrictions on user names, and while some distributions are less restrictive, many do enforce the same restrictions as we do. In order to make systemd unit files portable between systems we'll hence enforce something that resembles more the universally accepted set, rather than accept the most liberal set possible.
  2. User= in unit files is about system users, not regular users, and I am pretty sure we should enforce a stricter regime about system users than regular users.
  3. In systemd we generally follow the rule that when we encounter a unit setting that does not validate syntax-wise we'll log about it and ignore it, for compat reasons. We do the same for User= here as for all other options. Note that if you specify a valid user name but where the user doesn't exist, then we'll instead fail the service on start, because in that case there's not just something wrong with the syntax the service author used but actually something inconsistent on the system, and that should be considered fatal.
@martinpitt

This comment has been minimized.

Show comment
Hide comment
@martinpitt

martinpitt Jul 2, 2017

Contributor

Agreed about 1 and 2, but I disagree about 3. Setting User=nonexistinguser is syntactically correct, just not semantically. It's perfectly legitimate and consistent to ignore unkonwn keys such as Userr=foo, but we don't have a policy to ignore unknown/invalid values. For example, if a unit has Requires=nonexisting.service, it rightfully fails; we don't just ignore nonexisting.service. For the same reason, a unit with User=nonexistinguser should fail instead of silently running as root. That's the security relevant bit that we ought to fix.

I agree that not handling user names that start with digits can be considered "not a bug".

Contributor

martinpitt commented Jul 2, 2017

Agreed about 1 and 2, but I disagree about 3. Setting User=nonexistinguser is syntactically correct, just not semantically. It's perfectly legitimate and consistent to ignore unkonwn keys such as Userr=foo, but we don't have a policy to ignore unknown/invalid values. For example, if a unit has Requires=nonexisting.service, it rightfully fails; we don't just ignore nonexisting.service. For the same reason, a unit with User=nonexistinguser should fail instead of silently running as root. That's the security relevant bit that we ought to fix.

I agree that not handling user names that start with digits can be considered "not a bug".

@poettering

This comment has been minimized.

Show comment
Hide comment
@poettering

poettering Jul 2, 2017

Member

For the same reason, a unit with User=nonexistinguser should fail instead of silently running as root.

That's exactly what happens, and what I wrote above: if the username is valid but the user doesn't exist we'll let the unit fail on start. If the username is already invalid syntax-wise we'll log about it but proceed.

Hence, if you write:

User=000fooo...@!

Then we'll ignore the assignment altogether (but log about it), since it's syntactically invalid. But if you specify:

User=waldo

and the user "waldo" does not exist (though it is syntactically valid), then we'll accept the setting, but as soon as you actually try to start the unit it will fail with "user not found".

Member

poettering commented Jul 2, 2017

For the same reason, a unit with User=nonexistinguser should fail instead of silently running as root.

That's exactly what happens, and what I wrote above: if the username is valid but the user doesn't exist we'll let the unit fail on start. If the username is already invalid syntax-wise we'll log about it but proceed.

Hence, if you write:

User=000fooo...@!

Then we'll ignore the assignment altogether (but log about it), since it's syntactically invalid. But if you specify:

User=waldo

and the user "waldo" does not exist (though it is syntactically valid), then we'll accept the setting, but as soon as you actually try to start the unit it will fail with "user not found".

@martinpitt

This comment has been minimized.

Show comment
Hide comment
@martinpitt

martinpitt Jul 2, 2017

Contributor

Thanks @poettering for the clarification!

Contributor

martinpitt commented Jul 2, 2017

Thanks @poettering for the clarification!

@haraldh

This comment has been minimized.

Show comment
Hide comment
@haraldh

This comment has been minimized.

Show comment
Hide comment
@haraldh

haraldh Jul 11, 2017

Member

User @roland found that usernames that contain unicode characters also cause this bug.

The bug also affects usernames that contain unicode characters, which can be created with "useradd" without difficulties:

# useradd -m pöttering
# id pöttering
uid=1002(pöttering) gid=1003(pöttering) Gruppen=1003(pöttering)

# cat /etc/systemd/system/test-unicode.service
[Service]
User = pöttering
ExecStart = /usr/bin/touch /tmp/foo

# ls -l /tmp/foo
ls: cannot access '/tmp/foo': No such file or directory
# systemctl daemon-reload
# systemctl start test-unicode.service
# ls -l /tmp/foo
-rw-r--r-- 1 root root 0 Jul 3 17:56 /tmp/foo

Why it may be unlikely that an admin creates a username starting with a zero and wants to run a service with it I think this eventually might happen with usernames that contains umlauts or acute accents.

Member

haraldh commented Jul 11, 2017

User @roland found that usernames that contain unicode characters also cause this bug.

The bug also affects usernames that contain unicode characters, which can be created with "useradd" without difficulties:

# useradd -m pöttering
# id pöttering
uid=1002(pöttering) gid=1003(pöttering) Gruppen=1003(pöttering)

# cat /etc/systemd/system/test-unicode.service
[Service]
User = pöttering
ExecStart = /usr/bin/touch /tmp/foo

# ls -l /tmp/foo
ls: cannot access '/tmp/foo': No such file or directory
# systemctl daemon-reload
# systemctl start test-unicode.service
# ls -l /tmp/foo
-rw-r--r-- 1 root root 0 Jul 3 17:56 /tmp/foo

Why it may be unlikely that an admin creates a username starting with a zero and wants to run a service with it I think this eventually might happen with usernames that contains umlauts or acute accents.

@poettering

This comment has been minimized.

Show comment
Hide comment
@poettering

poettering Jul 11, 2017

Member

@haraldh we stick to the portable set, that the majority of distros agrees on, and umlauts in user names don't work on fedora, nor arch... I am pretty sure it works on a small minority of distros only. here's the output i get on fedora:

# adduser züpp
adduser: invalid user name 'züpp'

Note that fedora/rhel explicitly patch our the upstream rules of shadow-utils:

https://src.fedoraproject.org/cgit/rpms/shadow-utils.git/tree/shadow-4.1.5.1-goodname.patch#n7

Note that neither the upstream nor the fedora rules actually accept umlauts in usernames.

Anyway, systemd is not a tool for generic user management, it's a tool for service management. We make restrictions on the username you may make use of to keep things safe and portable between distributions, hence we stick to the set of user names that are portable, and complain about all others.

I am happy with changing our rules, but before we do that, please work with the POSIX, shadow-utils, libuser communities, as well with the other Linux distributions to come up with a single unified set of rules, and then we are happy to adopt that too in systemd. But until then, I think it's better for systemd to stick to the rules that only permit names that are portable to all of these systems. After all systemd not only consumes these names, it also potentially creates them (via sysusers.d or when DynamicUser=1 is used), and we should make sure systemd cannot beused as a vehicle for creating users that are otherwise not allowed.

Also: don't forget we don't break people's stuff with this, User=/Group= knew no counterpart in sysvinit, because priv dropping had to be implemented by the daemons manually there. If you do decide to let systemd do the priv dropping for you, we politely ask you to use portable names, so that the unit files work everywhere. And the rules we enforce are neither crazy nor random, they are the common core every distro accepts.

Member

poettering commented Jul 11, 2017

@haraldh we stick to the portable set, that the majority of distros agrees on, and umlauts in user names don't work on fedora, nor arch... I am pretty sure it works on a small minority of distros only. here's the output i get on fedora:

# adduser züpp
adduser: invalid user name 'züpp'

Note that fedora/rhel explicitly patch our the upstream rules of shadow-utils:

https://src.fedoraproject.org/cgit/rpms/shadow-utils.git/tree/shadow-4.1.5.1-goodname.patch#n7

Note that neither the upstream nor the fedora rules actually accept umlauts in usernames.

Anyway, systemd is not a tool for generic user management, it's a tool for service management. We make restrictions on the username you may make use of to keep things safe and portable between distributions, hence we stick to the set of user names that are portable, and complain about all others.

I am happy with changing our rules, but before we do that, please work with the POSIX, shadow-utils, libuser communities, as well with the other Linux distributions to come up with a single unified set of rules, and then we are happy to adopt that too in systemd. But until then, I think it's better for systemd to stick to the rules that only permit names that are portable to all of these systems. After all systemd not only consumes these names, it also potentially creates them (via sysusers.d or when DynamicUser=1 is used), and we should make sure systemd cannot beused as a vehicle for creating users that are otherwise not allowed.

Also: don't forget we don't break people's stuff with this, User=/Group= knew no counterpart in sysvinit, because priv dropping had to be implemented by the daemons manually there. If you do decide to let systemd do the priv dropping for you, we politely ask you to use portable names, so that the unit files work everywhere. And the rules we enforce are neither crazy nor random, they are the common core every distro accepts.

fbuihuu pushed a commit to fbuihuu/systemd that referenced this issue Nov 29, 2017

core/load-fragment: refuse units with errors in certain directives
If an error is encountered in any of the Exec* lines, WorkingDirectory,
SELinuxContext, ApparmorProfile, SmackProcessLabel, Service (in .socket
units), User, or Group, refuse to load the unit. If the config stanza
has support, ignore the failure if '-' is present.

For those configuration directives, even if we started the unit, it's
pretty likely that it'll do something unexpected (like write files
in a wrong place, or with a wrong context, or run with wrong permissions,
etc). It seems better to refuse to start the unit and have the admin
clean up the configuration without giving the service a chance to mess
up stuff.

Note that all "security" options that restrict what the unit can do
(Capabilities, AmbientCapabilities, Restrict*, SystemCallFilter, Limit*,
PrivateDevices, Protect*, etc) are _not_ treated like this. Such options are
only supplementary, and are not always available depending on the architecture
and compilation options, so unit authors have to make sure that the service
runs correctly without them anyway.

Fixes #6237, #6277.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.