bd1529
From 57d2e6e64ba490054f8de1a2aad4ffae7778eddc Mon Sep 17 00:00:00 2001
bd1529
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
bd1529
Date: Sun, 31 May 2020 18:21:09 +0200
bd1529
Subject: [PATCH] basic/user-util: always use base 10 for user/group numbers
bd1529
bd1529
We would parse numbers with base prefixes as user identifiers. For example,
bd1529
"0x2b3bfa0" would be interpreted as UID==45334432 and "01750" would be
bd1529
interpreted as UID==1000. This parsing was used also in cases where either a
bd1529
user/group name or number may be specified. This means that names like
bd1529
0x2b3bfa0 would be ambiguous: they are a valid user name according to our
bd1529
documented relaxed rules, but they would also be parsed as numeric uids.
bd1529
bd1529
This behaviour is definitely not expected by users, since tools generally only
bd1529
accept decimal numbers (e.g. id, getent passwd), while other tools only accept
bd1529
user names and thus will interpret such strings as user names without even
bd1529
attempting to convert them to numbers (su, ssh). So let's follow suit and only
bd1529
accept numbers in decimal notation. Effectively this means that we will reject
bd1529
such strings as a username/uid/groupname/gid where strict mode is used, and try
bd1529
to look up a user/group with such a name in relaxed mode.
bd1529
bd1529
Since the function changed is fairly low-level and fairly widely used, this
bd1529
affects multiple tools: loginctl show-user/enable-linger/disable-linger foo',
bd1529
the third argument in sysusers.d, fourth and fifth arguments in tmpfiles.d,
bd1529
etc.
bd1529
bd1529
Fixes #15985.
bd1529
bd1529
(cherry picked from commit 156a5fd297b61bce31630d7a52c15614bf784843)
bd1529
bd1529
Resolves: #1848373
bd1529
---
bd1529
 src/basic/parse-util.h    |  8 ++++++--
bd1529
 src/basic/user-util.c     |  2 +-
bd1529
 src/test/test-user-util.c | 10 ++++++++++
bd1529
 3 files changed, 17 insertions(+), 3 deletions(-)
bd1529
bd1529
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
bd1529
index f3267f4cfe..1fc1af7615 100644
bd1529
--- a/src/basic/parse-util.h
bd1529
+++ b/src/basic/parse-util.h
bd1529
@@ -50,9 +50,13 @@ static inline int safe_atoux16(const char *s, uint16_t *ret) {
bd1529
 
bd1529
 int safe_atoi16(const char *s, int16_t *ret);
bd1529
 
bd1529
-static inline int safe_atou32(const char *s, uint32_t *ret_u) {
bd1529
+static inline int safe_atou32_full(const char *s, unsigned base, uint32_t *ret_u) {
bd1529
         assert_cc(sizeof(uint32_t) == sizeof(unsigned));
bd1529
-        return safe_atou(s, (unsigned*) ret_u);
bd1529
+        return safe_atou_full(s, base, (unsigned*) ret_u);
bd1529
+}
bd1529
+
bd1529
+static inline int safe_atou32(const char *s, uint32_t *ret_u) {
bd1529
+        return safe_atou32_full(s, 0, (unsigned*) ret_u);
bd1529
 }
bd1529
 
bd1529
 static inline int safe_atoi32(const char *s, int32_t *ret_i) {
bd1529
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
bd1529
index d92969c966..10eeb256cd 100644
bd1529
--- a/src/basic/user-util.c
bd1529
+++ b/src/basic/user-util.c
bd1529
@@ -49,7 +49,7 @@ int parse_uid(const char *s, uid_t *ret) {
bd1529
         assert(s);
bd1529
 
bd1529
         assert_cc(sizeof(uid_t) == sizeof(uint32_t));
bd1529
-        r = safe_atou32(s, &uid);
bd1529
+        r = safe_atou32_full(s, 10, &uid);
bd1529
         if (r < 0)
bd1529
                 return r;
bd1529
 
bd1529
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
bd1529
index 9114d30b8c..8bf3dcd567 100644
bd1529
--- a/src/test/test-user-util.c
bd1529
+++ b/src/test/test-user-util.c
bd1529
@@ -46,9 +46,19 @@ static void test_parse_uid(void) {
bd1529
 
bd1529
         r = parse_uid("65535", &uid);
bd1529
         assert_se(r == -ENXIO);
bd1529
+        assert_se(uid == 100);
bd1529
+
bd1529
+        r = parse_uid("0x1234", &uid);
bd1529
+        assert_se(r == -EINVAL);
bd1529
+        assert_se(uid == 100);
bd1529
+
bd1529
+        r = parse_uid("01234", &uid);
bd1529
+        assert_se(r == 0);
bd1529
+        assert_se(uid == 1234);
bd1529
 
bd1529
         r = parse_uid("asdsdas", &uid);
bd1529
         assert_se(r == -EINVAL);
bd1529
+        assert_se(uid == 1234);
bd1529
 }
bd1529
 
bd1529
 static void test_uid_ptr(void) {