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