11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: uidswap.c,v 1.35 2006/08/03 03:34:42 deraadt Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi> 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * All rights reserved 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Code for uid-swapping. 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose. Any derived versions of this 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell". 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h> 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h> 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h> 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h> 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <grp.h> 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "uidswap.h" 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 302f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#ifdef ANDROID 312f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#include <private/android_filesystem_config.h> 3220eda52fd661847ea0b8163f9b97176fa3fe2e8bNick Kralevich#include <sys/capability.h> 332f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#include <linux/prctl.h> 342f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#endif 352f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Note: all these functions must work in all of the following cases: 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. euid=0, ruid=0 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. euid=0, ruid!=0 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 3. euid!=0, ruid!=0 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Additionally, they must work regardless of whether the system has 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * POSIX saved uids or not. 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS) 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Lets assume that posix saved ids also work with seteuid, even though that 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood is not part of the posix specification. */ 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SAVED_IDS_WORK_WITH_SETEUID 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Saved effective uid. */ 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic uid_t saved_euid = 0; 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic gid_t saved_egid = 0; 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Saved effective uid. */ 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int privileged = 0; 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int temporarily_use_uid_effective = 0; 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic gid_t *saved_egroups = NULL, *user_groups = NULL; 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int saved_egroupslen = -1, user_groupslen = -1; 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Temporarily changes to the given uid. If the effective user 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * id is not root, this does nothing. This call cannot be nested. 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtemporarily_use_uid(struct passwd *pw) 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Save the current euid, and egroups. */ 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef SAVED_IDS_WORK_WITH_SETEUID 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood saved_euid = geteuid(); 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood saved_egid = getegid(); 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("temporarily_use_uid: %u/%u (e=%u/%u)", 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (u_int)pw->pw_uid, (u_int)pw->pw_gid, 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (u_int)saved_euid, (u_int)saved_egid); 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_CYGWIN 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (saved_euid != 0) { 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood privileged = 0; 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (geteuid() != 0) { 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood privileged = 0; 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* SAVED_IDS_WORK_WITH_SETEUID */ 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood privileged = 1; 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood temporarily_use_uid_effective = 1; 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood saved_egroupslen = getgroups(0, NULL); 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (saved_egroupslen < 0) 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("getgroups: %.100s", strerror(errno)); 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (saved_egroupslen > 0) { 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood saved_egroups = xrealloc(saved_egroups, 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood saved_egroupslen, sizeof(gid_t)); 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (getgroups(saved_egroupslen, saved_egroups) < 0) 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("getgroups: %.100s", strerror(errno)); 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { /* saved_egroupslen == 0 */ 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (saved_egroups != NULL) 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(saved_egroups); 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* set and save the user's groups */ 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (user_groupslen == -1) { 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (initgroups(pw->pw_name, pw->pw_gid) < 0) 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("initgroups: %s: %.100s", pw->pw_name, 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood user_groupslen = getgroups(0, NULL); 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (user_groupslen < 0) 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("getgroups: %.100s", strerror(errno)); 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (user_groupslen > 0) { 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood user_groups = xrealloc(user_groups, 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood user_groupslen, sizeof(gid_t)); 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (getgroups(user_groupslen, user_groups) < 0) 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("getgroups: %.100s", strerror(errno)); 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { /* user_groupslen == 0 */ 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (user_groups) 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(user_groups); 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Set the effective uid to the given (unprivileged) uid. */ 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setgroups(user_groupslen, user_groups) < 0) 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setgroups: %.100s", strerror(errno)); 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef SAVED_IDS_WORK_WITH_SETEUID 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Propagate the privileged gid to all of our gids. */ 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setgid(getegid()) < 0) 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno)); 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Propagate the privileged uid to all of our uids. */ 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setuid(geteuid()) < 0) 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno)); 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* SAVED_IDS_WORK_WITH_SETEUID */ 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setegid(pw->pw_gid) < 0) 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setegid %u: %.100s", (u_int)pw->pw_gid, 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (seteuid(pw->pw_uid) == -1) 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpermanently_drop_suid(uid_t uid) 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood uid_t old_uid = getuid(); 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("permanently_drop_suid: %u", (u_int)uid); 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID) 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setresuid(uid, uid, uid) < 0) 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno)); 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID) 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setreuid(uid, uid) < 0) 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setreuid %u: %.100s", (u_int)uid, strerror(errno)); 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# ifndef SETEUID_BREAKS_SETUID 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (seteuid(uid) < 0) 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("seteuid %u: %.100s", (u_int)uid, strerror(errno)); 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# endif 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setuid(uid) < 0) 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setuid %u: %.100s", (u_int)uid, strerror(errno)); 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_CYGWIN 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Try restoration of UID if changed (test clearing of saved uid) */ 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (old_uid != uid && 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: was able to restore old [e]uid", __func__); 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Verify UID drop was successful */ 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (getuid() != uid || geteuid() != uid) { 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, (u_int)getuid(), (u_int)geteuid(), (u_int)uid); 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Restores to the original (privileged) uid. 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodrestore_uid(void) 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* it's a no-op unless privileged */ 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!privileged) { 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("restore_uid: (unprivileged)"); 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!temporarily_use_uid_effective) 1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("restore_uid: temporarily_use_uid not effective"); 1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef SAVED_IDS_WORK_WITH_SETEUID 1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid); 1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Set the effective uid back to the saved privileged uid. */ 1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (seteuid(saved_euid) < 0) 1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno)); 1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setegid(saved_egid) < 0) 1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno)); 1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* SAVED_IDS_WORK_WITH_SETEUID */ 1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * We are unable to restore the real uid to its unprivileged value. 2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Propagate the real uid (usually more privileged) to effective uid 2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * as well. 2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood setuid(getuid()); 2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood setgid(getgid()); 2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* SAVED_IDS_WORK_WITH_SETEUID */ 2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setgroups(saved_egroupslen, saved_egroups) < 0) 2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setgroups: %.100s", strerror(errno)); 2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood temporarily_use_uid_effective = 0; 2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permanently sets all uids to the given uid. This cannot be 2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called while temporarily_use_uid is effective. 2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpermanently_set_uid(struct passwd *pw) 2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood uid_t old_uid = getuid(); 2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood gid_t old_gid = getgid(); 2212f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#ifdef ANDROID 2222f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood struct __user_cap_header_struct header; 2232f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood struct __user_cap_data_struct cap; 2242f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#endif 2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pw == NULL) 2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("permanently_set_uid: no user given"); 2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (temporarily_use_uid_effective) 2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("permanently_set_uid: temporarily_use_uid effective"); 2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, 2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (u_int)pw->pw_gid); 2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2332f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#ifdef ANDROID 2342f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood if (pw->pw_uid == AID_SHELL) { 2352f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 2362f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood 2372f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood /* add extra groups needed for shell user: 2382f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_LOG to read system logs (adb logcat) 2392f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_INPUT to diagnose input issues (getevent) 2402f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_INET to diagnose network issues (netcfg, ping) 2412f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_GRAPHICS to access the frame buffer 2422f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump) 2432f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_SDCARD_RW to allow writing to the SD card 2442f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_MOUNT to allow unmounting the SD card before rebooting 2452f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood ** AID_NET_BW_STATS to read out qtaguid statistics 2462f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood */ 2472f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood gid_t groups[] = { AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS, 2482f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW, 2492f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood AID_MOUNT, AID_NET_BW_STATS }; 2502f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood setgroups(sizeof(groups)/sizeof(groups[0]), groups); 2512f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood } 2522f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#endif 2532f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood 2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID) 2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) 2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); 2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID) 2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setregid(pw->pw_gid, pw->pw_gid) < 0) 2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setregid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); 2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setegid(pw->pw_gid) < 0) 2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setegid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); 2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setgid(pw->pw_gid) < 0) 2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); 2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef __APPLE__ 2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OS X requires initgroups after setgid to opt back into 2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * memberd support for >16 supplemental groups. 2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (initgroups(pw->pw_name, pw->pw_gid) < 0) 2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("initgroups %.100s %u: %.100s", 2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); 2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID) 2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) 2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); 2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID) 2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setreuid(pw->pw_uid, pw->pw_uid) < 0) 2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setreuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); 2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# ifndef SETEUID_BREAKS_SETUID 2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (seteuid(pw->pw_uid) < 0) 2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); 2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# endif 2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (setuid(pw->pw_uid) < 0) 2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); 2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_CYGWIN 2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Try restoration of GID if changed (test clearing of saved gid) */ 2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (old_gid != pw->pw_gid && pw->pw_uid != 0 && 2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (setgid(old_gid) != -1 || setegid(old_gid) != -1)) 2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: was able to restore old [e]gid", __func__); 2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Verify GID drop was successful */ 3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) { 3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", 3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, (u_int)getgid(), (u_int)getegid(), 3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (u_int)pw->pw_gid); 3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_CYGWIN 3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Try restoration of UID if changed (test clearing of saved uid) */ 3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (old_uid != pw->pw_uid && 3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) 3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: was able to restore old [e]uid", __func__); 3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Verify UID drop was successful */ 3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { 3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", 3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, (u_int)getuid(), (u_int)geteuid(), 3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (u_int)pw->pw_uid); 3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3192f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood 3202f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#ifdef ANDROID 3212f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood if (pw->pw_uid == AID_SHELL) { 3222f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */ 3232f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood header.version = _LINUX_CAPABILITY_VERSION; 3242f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood header.pid = 0; 3252f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood cap.effective = cap.permitted = (1 << CAP_SYS_BOOT); 3262f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood cap.inheritable = 0; 3272f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood capset(&header, &cap); 3282f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood } 3292f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood#endif 3302f1b934246c78321625e8cb5af8a48ea2c09992fMike Lockwood 3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 332