aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2015-05-12 07:56:04 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2015-05-12 23:59:57 +0200
commita818777d4249e934ef7c9e6e7df8475d6692f315 (patch)
tree48fe04df6ff834591f419be413ee5602c74bdcb0
parent7ca5c51cc8c54f35b6265d815d8a8be19e0821b0 (diff)
downloadbusybox-w32-a818777d4249e934ef7c9e6e7df8475d6692f315.tar.gz
busybox-w32-a818777d4249e934ef7c9e6e7df8475d6692f315.tar.bz2
busybox-w32-a818777d4249e934ef7c9e6e7df8475d6692f315.zip
libbb: Enable support for !CONFIG_MULTIUSER
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@linaro.org> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--libbb/change_identity.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/libbb/change_identity.c b/libbb/change_identity.c
index 619db09a8..d48d86326 100644
--- a/libbb/change_identity.c
+++ b/libbb/change_identity.c
@@ -33,9 +33,28 @@
33/* Become the user and group(s) specified by PW. */ 33/* Become the user and group(s) specified by PW. */
34void FAST_FUNC change_identity(const struct passwd *pw) 34void FAST_FUNC change_identity(const struct passwd *pw)
35{ 35{
36 if (initgroups(pw->pw_name, pw->pw_gid) == -1) 36 int res;
37 bb_perror_msg_and_die("can't set groups"); 37
38 res = initgroups(pw->pw_name, pw->pw_gid);
38 endgrent(); /* helps to close a fd used internally by libc */ 39 endgrent(); /* helps to close a fd used internally by libc */
40
41 if (res != 0) {
42 /*
43 * If initgroups() fails because a system call is unimplemented
44 * then we are running on a Linux kernel compiled without multiuser
45 * support (CONFIG_MULTIUSER is not defined).
46 *
47 * If we are running without multiuser support *and* the target uid
48 * already matches the current uid then we can skip the change of
49 * identity.
50 */
51 if (errno == ENOSYS && pw->pw_uid == getuid()) {
52 return;
53 }
54
55 bb_perror_msg_and_die("can't set groups");
56 }
57
39 xsetgid(pw->pw_gid); 58 xsetgid(pw->pw_gid);
40 xsetuid(pw->pw_uid); 59 xsetuid(pw->pw_uid);
41} 60}