-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Only use base 10 for numeric uids/gids #15991
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
Conversation
We would parse numbers with base prefixes as user identifiers. For example, "0x2b3bfa0" would be interpreted as UID==45334432 and "01750" would be interpreted as UID==1000. This parsing was used also in cases where either a user/group name or number may be specified. This means that names like 0x2b3bfa0 would be ambiguous: they are a valid user name according to our documented relaxed rules, but they would also be parsed as numeric uids. This behaviour is definitely not expected by users, since tools generally only accept decimal numbers (e.g. id, getent passwd), while other tools only accept user names and thus will interpret such strings as user names without even attempting to convert them to numbers (su, ssh). So let's follow suit and only accept numbers in decimal notation. Effectively this means that we will reject such strings as a username/uid/groupname/gid where strict mode is used, and try to look up a user/group with such a name in relaxed mode. Since the function changed is fairly low-level and fairly widely used, this affects multiple tools: loginctl show-user/enable-linger/disable-linger foo', the third argument in sysusers.d, fourth and fifth arguments in tmpfiles.d, etc. Fixes systemd#15985.
| r = parse_uid("65535", &uid); | ||
| assert_se(r == -ENXIO); | ||
| assert_se(uid == 100); | ||
|
|
||
| r = parse_uid("0x1234", &uid); | ||
| assert_se(r == -EINVAL); | ||
| assert_se(uid == 100); | ||
|
|
||
| r = parse_uid("01234", &uid); | ||
| assert_se(r == 0); | ||
| assert_se(uid == 1234); | ||
|
|
||
| r = parse_uid("asdsdas", &uid); | ||
| assert_se(r == -EINVAL); | ||
| assert_se(uid == 1234); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| r = parse_uid("65535", &uid); | |
| assert_se(r == -ENXIO); | |
| assert_se(uid == 100); | |
| r = parse_uid("0x1234", &uid); | |
| assert_se(r == -EINVAL); | |
| assert_se(uid == 100); | |
| r = parse_uid("01234", &uid); | |
| assert_se(r == 0); | |
| assert_se(uid == 1234); | |
| r = parse_uid("asdsdas", &uid); | |
| assert_se(r == -EINVAL); | |
| assert_se(uid == 1234); | |
| r = parse_uid("65535", &uid); | |
| assert_se(r == -ENXIO); | |
| r = parse_uid("0x1234", &uid); | |
| assert_se(r == -EINVAL); | |
| r = parse_uid("01234", &uid); | |
| assert_se(uid == 1234); | |
| assert_se(r == 0); | |
| r = parse_uid("asdsdas", &uid); | |
| assert_se(r == -EINVAL); |
I find rather confusing the unneeded checks to the uid value that remains from the last successful execution. Could we simply check the error if the function is expected to fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's on purpose. It is testing that the function does not touch the output variable on failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a last question: would assigning UINT32_MAX to uid in case of error instead of leaving it untouched make any sense? It adds complexity to the code, but effectively avoids using a initialization value like 0 in case of error validation fault.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. The convention is to not touch the output variable on error. In this case it doesn't matter much either way, but in other cases we make use of this. Having the same convention over all the code base makes the code easier to follow.
For example:
int output = DEFAULT_VALUE;
r = parse_something(value_from_config_file, &output);
if (r < 0)
log_warning("Failed to parse..., ignoring");
...
r = parse_something(value_from_environment_variable, &output);
if (r < 0)
log_warning("Failed to parse..., ingorign"):
...
use_value(output);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌 Thank you for the clarification!
Thank you! Your implementation is definitely much nicer and includes tests. By the way: does f7091f4 belong to this pull request? |
I put it there on purpose... I was looking at loginctl.c first, and noticed that this modernization can be done. We attach such cleanup patches to other PRs, because it's not worth to fire up the whole CI (which takes ~4 hours to run) for a trivial patch like that. |
|
LGTM. |
|
i wonder if we should refuse uids beginning with "0" too, to avoid the ambiguity with octal? |
|
I thought about that, but |
The original pull request (#15987) explicitly refused octal numbers, but as @keszybz stated, most of the existing tools ignore the leading zeros and parse any |
|
hmm, so "id" also accepts "+0" as alias for root, but not "-0"... which is super weird. Maybe it's not the best model to follow? (we accept +0, too currently, and probably shouldn't, will prep patch for that) |
|
and " 0" is accepted too (i.e. leading whitespace), and probably shouldn't either |
|
Good point. 🤔 I'm starting to think that #15987 wasn't such a bad idea after all. |
|
Yeah, we should not accept "+0" or "-0" or " 0". |
|
i have a patch mostly ready for ding that |
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991
|
I posted #16033 now. ptal |
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991 (cherry picked from commit 707e93a)
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991 (cherry picked from commit 707e93a)
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991 CVE: CVE_2020-13776 Upstream-Status: Backport [systemd@707e93a] Signed-off-by: Dan Tran <dantran@microsoft.com>
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991 CVE: CVE_2020-13776 Upstream-Status: Backport [systemd@707e93a] Signed-off-by: Dan Tran <dantran@microsoft.com>
This allows disabling a few alternative ways to decode integers formatted as strings, for safety reasons. See: systemd#15991 Backport of 707e93a
No description provided.