summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adb/adb.c51
-rw-r--r--adb/commandline.c2
-rw-r--r--adb/services.c18
-rw-r--r--adb/sockets.c15
-rwxr-xr-x[-rw-r--r--]adb/tests/test_adb.py21
5 files changed, 70 insertions, 37 deletions
diff --git a/adb/adb.c b/adb/adb.c
index 4258a01..bfc0336 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -1261,35 +1261,36 @@ static void drop_capabilities_bounding_set_if_needed() {
}
}
-static int should_drop_privileges() {
-#ifndef ALLOW_ADBD_ROOT
- return 1;
-#else /* ALLOW_ADBD_ROOT */
- int secure = 0;
+static bool should_drop_privileges() {
+#if defined(ALLOW_ADBD_ROOT)
char value[PROPERTY_VALUE_MAX];
- /* run adbd in secure mode if ro.secure is set and
- ** we are not in the emulator
- */
+ // The emulator is never secure, so don't drop privileges there.
+ // TODO: this seems like a bug --- shouldn't the emulator behave like a device?
property_get("ro.kernel.qemu", value, "");
- if (strcmp(value, "1") != 0) {
- property_get("ro.secure", value, "1");
- if (strcmp(value, "1") == 0) {
- // don't run as root if ro.secure is set...
- secure = 1;
-
- // ... except we allow running as root in userdebug builds if the
- // service.adb.root property has been set by the "adb root" command
- property_get("ro.debuggable", value, "");
- if (strcmp(value, "1") == 0) {
- property_get("service.adb.root", value, "");
- if (strcmp(value, "1") == 0) {
- secure = 0;
- }
- }
- }
+ if (strcmp(value, "1") == 0) {
+ return false;
+ }
+
+ // Don't run as root if ro.secure is set...
+ property_get("ro.secure", value, "1");
+ bool ro_secure = (strcmp(value, "1") == 0);
+
+ // ... except we allow running as root in userdebug builds if the
+ // service.adb.root property has been set by the "adb root" command
+ property_get("ro.debuggable", value, "");
+ bool ro_debuggable = (strcmp(value, "1") == 0);
+
+ property_get("service.adb.root", value, "");
+ bool adb_root = (strcmp(value, "1") == 0);
+ bool adb_unroot = (strcmp(value, "0") == 0);
+ if (adb_unroot) {
+ return true; // The user explicitly wants us to drop privileges.
}
- return secure;
+
+ return ro_secure || !ro_debuggable;
+#else
+ return true; // "adb root" not allowed, always drop privileges.
#endif /* ALLOW_ADBD_ROOT */
}
#endif /* !ADB_HOST */
diff --git a/adb/commandline.c b/adb/commandline.c
index a06885b..830f290 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -210,6 +210,7 @@ void help()
" adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
" adb reboot-bootloader - reboots the device into the bootloader\n"
" adb root - restarts the adbd daemon with root permissions\n"
+ " adb unroot - restarts the adbd daemon without root permissions\n"
" adb usb - restarts the adbd daemon listening on USB\n"
" adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
"networking:\n"
@@ -1473,6 +1474,7 @@ int adb_commandline(int argc, char **argv)
!strcmp(argv[0], "tcpip") ||
!strcmp(argv[0], "usb") ||
!strcmp(argv[0], "root") ||
+ !strcmp(argv[0], "unroot") ||
!strcmp(argv[0], "disable-verity") ||
!strcmp(argv[0], "enable-verity")) {
char command[100];
diff --git a/adb/services.c b/adb/services.c
index e4ce0bc..bd210a8 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -82,6 +82,22 @@ void restart_root_service(int fd, void *cookie)
}
}
+void restart_unroot_service(int fd, void *cookie)
+{
+ char buf[100];
+
+ if (getuid() != 0) {
+ snprintf(buf, sizeof(buf), "adbd not running as root\n");
+ writex(fd, buf, strlen(buf));
+ adb_close(fd);
+ } else {
+ property_set("service.adb.root", "0");
+ snprintf(buf, sizeof(buf), "restarting adbd as non root\n");
+ writex(fd, buf, strlen(buf));
+ adb_close(fd);
+ }
+}
+
void restart_tcp_service(int fd, void *cookie)
{
char buf[100];
@@ -437,6 +453,8 @@ int service_to_fd(const char *name)
ret = create_service_thread(reboot_service, arg);
} else if(!strncmp(name, "root:", 5)) {
ret = create_service_thread(restart_root_service, NULL);
+ } else if(!strncmp(name, "unroot:", 7)) {
+ ret = create_service_thread(restart_unroot_service, NULL);
} else if(!strncmp(name, "backup:", 7)) {
char* arg = strdup(name + 7);
if (arg == NULL) return -1;
diff --git a/adb/sockets.c b/adb/sockets.c
index faa9564..6cdde97 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -430,12 +430,6 @@ asocket *create_local_socket(int fd)
asocket *create_local_service_socket(const char *name)
{
- asocket *s;
- int fd;
-#if !ADB_HOST
- char debug[PROPERTY_VALUE_MAX];
-#endif
-
#if !ADB_HOST
if (!strcmp(name,"jdwp")) {
return create_jdwp_service_socket();
@@ -444,18 +438,19 @@ asocket *create_local_service_socket(const char *name)
return create_jdwp_tracker_service_socket();
}
#endif
- fd = service_to_fd(name);
+ int fd = service_to_fd(name);
if(fd < 0) return 0;
- s = create_local_socket(fd);
+ asocket* s = create_local_socket(fd);
D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
#if !ADB_HOST
+ char debug[PROPERTY_VALUE_MAX];
if (!strncmp(name, "root:", 5))
property_get("ro.debuggable", debug, "");
- if ((!strncmp(name, "root:", 5) && getuid() != 0
- && strcmp(debug, "1") == 0)
+ if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0)
+ || (!strncmp(name, "unroot:", 7) && getuid() == 0)
|| !strncmp(name, "usb:", 4)
|| !strncmp(name, "tcpip:", 6)) {
D("LS(%d): enabling exit_on_close\n", s->id);
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index b0ae07f..4b3baf3 100644..100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -8,11 +8,11 @@ import hashlib
import os
import random
import re
+import shlex
import subprocess
+import sys
import tempfile
import unittest
-import sys
-import shlex
def trace(cmd):
@@ -181,6 +181,12 @@ class AdbWrapper(object):
def usb(self):
return call_checked(self.adb_cmd + "usb")
+ def root(self):
+ return call_checked(self.adb_cmd + "root")
+
+ def unroot(self):
+ return call_checked(self.adb_cmd + "unroot")
+
def forward_remove(self, local):
return call_checked(self.adb_cmd + "forward --remove {}".format(local))
@@ -233,6 +239,17 @@ class AdbBasic(unittest.TestCase):
version_num = True
self.assertTrue(version_num)
+ def test_root_unroot(self):
+ """Make sure that adb root and adb unroot work, using id(1)."""
+ for device in get_device_list():
+ adb = AdbWrapper(device)
+ adb.root()
+ adb.wait()
+ self.assertEqual("root", adb.shell("id -un").strip())
+ adb.unroot()
+ adb.wait()
+ self.assertEqual("shell", adb.shell("id -un").strip())
+
class AdbFile(unittest.TestCase):
SCRATCH_DIR = "/data/local/tmp"