From 47819f004cec3cc3e911ba69003b8b52bacbebef Mon Sep 17 00:00:00 2001
From: Johannes Heimansberg <git@jhe.dedyn.io>
Date: Sun, 6 Sep 2020 09:22:50 +0200
Subject: start-stop-daemon, supervise-daemon: fix parsing of usernames passed
 via --user that start with a number

start-stop-daemon and supervise-daemon parse usernames and group names
passed via the --user argument as numeric UID/GID if they start with a
number (e.g. user "4foo" will be treated as UID 4). This results in the
process that is being started to run under a totally unexpected user if
that UID exists.

Even though the result of the sscanf calls are tested for a result of
exactly 1, which means exactly one value was extracted, because sscanf's
format string only contains only one placeholder, it will never return
a value greater than 1, even if there are still characters left to be
parsed. This causes start-stop-daemon and supervise-daemon to assume
that usernames starting with a number are just that number. Adding a
second placeholder "%1s" to the format string, which matches a string of
length 1, makes sure that sscanf can distinguish between pure numbers
(in which case it will return 1) and strings either starting with a
number (in which case it will return 2) and any other string (in which
case it will return 0).

This fixes #379.
This fixes #380.
---
 src/rc/start-stop-daemon.c | 5 +++--
 src/rc/supervise-daemon.c  | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

(limited to 'src/rc')

diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index aafada88..99e5b6a0 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -389,10 +389,11 @@ int main(int argc, char **argv)
 			/* falls through */
 		case 'u':  /* --user <username>|<uid> */
 		{
+			char dummy[2];
 			p = optarg;
 			tmp = strsep(&p, ":");
 			changeuser = xstrdup(tmp);
-			if (sscanf(tmp, "%d", &tid) != 1)
+			if (sscanf(tmp, "%d%1s", &tid, dummy) != 1)
 				pw = getpwnam(tmp);
 			else
 				pw = getpwuid((uid_t)tid);
@@ -413,7 +414,7 @@ int main(int argc, char **argv)
 
 			if (p) {
 				tmp = strsep (&p, ":");
-				if (sscanf(tmp, "%d", &tid) != 1)
+				if (sscanf(tmp, "%d%1s", &tid, dummy) != 1)
 					gr = getgrnam(tmp);
 				else
 					gr = getgrgid((gid_t) tid);
diff --git a/src/rc/supervise-daemon.c b/src/rc/supervise-daemon.c
index b3d63589..ea9e5333 100644
--- a/src/rc/supervise-daemon.c
+++ b/src/rc/supervise-daemon.c
@@ -855,10 +855,11 @@ int main(int argc, char **argv)
 
 		case 'u':  /* --user <username>|<uid> */
 		{
+			char dummy[2];
 			p = optarg;
 			tmp = strsep(&p, ":");
 			changeuser = xstrdup(tmp);
-			if (sscanf(tmp, "%d", &tid) != 1)
+			if (sscanf(tmp, "%d%1s", &tid, dummy) != 1)
 				pw = getpwnam(tmp);
 			else
 				pw = getpwuid((uid_t)tid);
@@ -879,7 +880,7 @@ int main(int argc, char **argv)
 
 			if (p) {
 				tmp = strsep (&p, ":");
-				if (sscanf(tmp, "%d", &tid) != 1)
+				if (sscanf(tmp, "%d%1s", &tid, dummy) != 1)
 					gr = getgrnam(tmp);
 				else
 					gr = getgrgid((gid_t) tid);
-- 
cgit v1.2.3