[git commit] libbb: Enable support for !CONFIG_MULTIUSER

Denys Vlasenko vda.linux at googlemail.com
Tue May 12 21:59:57 UTC 2015


commit: http://git.busybox.net/busybox/commit/?id=a818777d4249e934ef7c9e6e7df8475d6692f315
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Linux recently gained a new config option, CONFIG_MULTIUSER, that makes
support for non-root users optional. This results in a number of syscalls
being disabled: setuid, setregid, setgid, setreuid, setresuid, getresuid,
setresgid, getresgid, setgroups, getgroups, setfsuid, setfsgid, capget,
capset.

Currently a number of busybox applets, including login, struggle to run
when CONFIG_MULTIUSER is disabled. Even the root user is unable to login:
  login: can't set groups: Functi

This patch adds code to make change_identity() a nop on single user
systems. It works by recognising the signature errno value (ENOSYS, due
to the system calls being disabled) and, to avoid security risks, only
deploys when the current uid and target uid is the same.

After the patch is applied any attempt to switch to a non-root user will
fail. Thus a badly configured userspace (for example, one that tries to
start a daemon as a non-root user when the kernel cannot support this)
will report errors as one would expect.

Signed-off-by: Daniel Thompson <daniel.thompson at linaro.org>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 libbb/change_identity.c |   23 +++++++++++++++++++++--
 1 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/libbb/change_identity.c b/libbb/change_identity.c
index 619db09..d48d863 100644
--- a/libbb/change_identity.c
+++ b/libbb/change_identity.c
@@ -33,9 +33,28 @@
 /* Become the user and group(s) specified by PW.  */
 void FAST_FUNC change_identity(const struct passwd *pw)
 {
-	if (initgroups(pw->pw_name, pw->pw_gid) == -1)
-		bb_perror_msg_and_die("can't set groups");
+	int res;
+
+	res = initgroups(pw->pw_name, pw->pw_gid);
 	endgrent(); /* helps to close a fd used internally by libc */
+
+	if (res != 0) {
+		/*
+		 * If initgroups() fails because a system call is unimplemented
+		 * then we are running on a Linux kernel compiled without multiuser
+		 * support (CONFIG_MULTIUSER is not defined).
+		 *
+		 * If we are running without multiuser support *and* the target uid
+		 * already matches the current uid then we can skip the change of
+		 * identity.
+		 */
+		if (errno == ENOSYS && pw->pw_uid == getuid()) {
+			return;
+		}
+
+		bb_perror_msg_and_die("can't set groups");
+	}
+
 	xsetgid(pw->pw_gid);
 	xsetuid(pw->pw_uid);
 }


More information about the busybox-cvs mailing list