Merge "Make init handle reboots"
diff --git a/adb/adb.c b/adb/adb.c
index 9d2b86e..6580c6e 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -1199,9 +1199,8 @@
#endif
int i;
for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
- if (i == CAP_SETUID || i == CAP_SETGID || i == CAP_SYS_BOOT) {
+ if (i == CAP_SETUID || i == CAP_SETGID) {
// CAP_SETUID CAP_SETGID needed by /system/bin/run-as
- // CAP_SYS_BOOT needed by /system/bin/reboot
continue;
}
int err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
@@ -1302,13 +1301,6 @@
/* don't listen on a port (default 5037) if running in secure mode */
/* don't run as root if we are running in secure mode */
if (should_drop_privileges()) {
- struct __user_cap_header_struct header;
- struct __user_cap_data_struct cap[2];
-
- if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
- exit(1);
- }
-
drop_capabilities_bounding_set_if_needed();
/* add extra groups:
@@ -1338,16 +1330,6 @@
exit(1);
}
- memset(&header, 0, sizeof(header));
- memset(cap, 0, sizeof(cap));
-
- /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
- header.version = _LINUX_CAPABILITY_VERSION_3;
- header.pid = 0;
- cap[CAP_TO_INDEX(CAP_SYS_BOOT)].effective |= CAP_TO_MASK(CAP_SYS_BOOT);
- cap[CAP_TO_INDEX(CAP_SYS_BOOT)].permitted |= CAP_TO_MASK(CAP_SYS_BOOT);
- capset(&header, cap);
-
D("Local port disabled\n");
} else {
char local_name[30];
diff --git a/adb/services.c b/adb/services.c
index 54d21a8..e82a0ea 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -165,6 +165,7 @@
void reboot_service(int fd, void *arg)
{
char buf[100];
+ char property_val[PROPERTY_VALUE_MAX];
int pid, ret;
sync();
@@ -182,11 +183,19 @@
waitpid(pid, &ret, 0);
}
- ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
+ ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg);
+ if (ret >= (int) sizeof(property_val)) {
+ snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
+ writex(fd, buf, strlen(buf));
+ goto cleanup;
+ }
+
+ ret = property_set(ANDROID_RB_PROPERTY, property_val);
if (ret < 0) {
- snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
+ snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
writex(fd, buf, strlen(buf));
}
+cleanup:
free(arg);
adb_close(fd);
}
diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h
index 0c79be7..8c30e8e 100644
--- a/include/cutils/android_reboot.h
+++ b/include/cutils/android_reboot.h
@@ -24,9 +24,8 @@
#define ANDROID_RB_POWEROFF 0xDEAD0002
#define ANDROID_RB_RESTART2 0xDEAD0003
-/* Flags */
-#define ANDROID_RB_FLAG_NO_SYNC 0x1
-#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2
+/* Properties */
+#define ANDROID_RB_PROPERTY "sys.powerctl"
int android_reboot(int cmd, int flags, char *arg);
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 850e0bd..d69b332 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -230,7 +230,6 @@
/* the following files have enhanced capabilities and ARE included in user builds. */
{ 00750, AID_ROOT, AID_SHELL, (1 << CAP_SETUID) | (1 << CAP_SETGID), "system/bin/run-as" },
- { 00750, AID_ROOT, AID_SHELL, 1 << CAP_SYS_BOOT, "system/bin/reboot" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" },
diff --git a/init/builtins.c b/init/builtins.c
index 0f9f131..9ae9ba3 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -32,6 +32,7 @@
#include <sys/wait.h>
#include <linux/loop.h>
#include <cutils/partition_utils.h>
+#include <cutils/android_reboot.h>
#include <sys/system_properties.h>
#include <fs_mgr.h>
@@ -599,6 +600,43 @@
return 0;
}
+int do_powerctl(int nargs, char **args)
+{
+ char command[PROP_VALUE_MAX];
+ int res;
+ int len = 0;
+ int cmd = 0;
+ char *reboot_target;
+
+ res = expand_props(command, args[1], sizeof(command));
+ if (res) {
+ ERROR("powerctl: cannot expand '%s'\n", args[1]);
+ return -EINVAL;
+ }
+
+ if (strncmp(command, "shutdown", 8) == 0) {
+ cmd = ANDROID_RB_POWEROFF;
+ len = 8;
+ } else if (strncmp(command, "reboot", 6) == 0) {
+ cmd = ANDROID_RB_RESTART2;
+ len = 6;
+ } else {
+ ERROR("powerctl: unrecognized command '%s'\n", command);
+ return -EINVAL;
+ }
+
+ if (command[len] == ',') {
+ reboot_target = &command[len + 1];
+ } else if (command[len] == '\0') {
+ reboot_target = "";
+ } else {
+ ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);
+ return -EINVAL;
+ }
+
+ return android_reboot(cmd, 0, reboot_target);
+}
+
int do_trigger(int nargs, char **args)
{
action_for_each_trigger(args[1], action_add_queue_tail);
diff --git a/init/init_parser.c b/init/init_parser.c
index 686640e..a1d2423 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -130,6 +130,8 @@
if (!strcmp(s, "neshot")) return K_oneshot;
if (!strcmp(s, "nrestart")) return K_onrestart;
break;
+ case 'p':
+ if (!strcmp(s, "owerctl")) return K_powerctl;
case 'r':
if (!strcmp(s, "estart")) return K_restart;
if (!strcmp(s, "estorecon")) return K_restorecon;
diff --git a/init/keywords.h b/init/keywords.h
index f188db5..f147506 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -14,6 +14,7 @@
int do_mkdir(int nargs, char **args);
int do_mount_all(int nargs, char **args);
int do_mount(int nargs, char **args);
+int do_powerctl(int nargs, char **args);
int do_restart(int nargs, char **args);
int do_restorecon(int nargs, char **args);
int do_rm(int nargs, char **args);
@@ -66,6 +67,7 @@
KEYWORD(on, SECTION, 0, 0)
KEYWORD(oneshot, OPTION, 0, 0)
KEYWORD(onrestart, OPTION, 0, 0)
+ KEYWORD(powerctl, COMMAND, 1, do_powerctl)
KEYWORD(restart, COMMAND, 1, do_restart)
KEYWORD(restorecon, COMMAND, 1, do_restorecon)
KEYWORD(rm, COMMAND, 1, do_rm)
diff --git a/init/property_service.c b/init/property_service.c
old mode 100755
new mode 100644
index 5780001..6bf06b4
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -77,6 +77,7 @@
{ "runtime.", AID_SYSTEM, 0 },
{ "hw.", AID_SYSTEM, 0 },
{ "sys.", AID_SYSTEM, 0 },
+ { "sys.powerctl", AID_SHELL, 0 },
{ "service.", AID_SYSTEM, 0 },
{ "wlan.", AID_SYSTEM, 0 },
{ "bluetooth.", AID_BLUETOOTH, 0 },
diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c
index 33a7358..16f82bb 100644
--- a/libcutils/android_reboot.c
+++ b/libcutils/android_reboot.c
@@ -105,11 +105,8 @@
{
int ret;
- if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
- sync();
-
- if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
- remount_ro();
+ sync();
+ remount_ro();
switch (cmd) {
case ANDROID_RB_RESTART:
diff --git a/reboot/reboot.c b/reboot/reboot.c
index 45d8a8e..0e5170d 100644
--- a/reboot/reboot.c
+++ b/reboot/reboot.c
@@ -17,35 +17,34 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <cutils/properties.h>
#include <cutils/android_reboot.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int ret;
- int nosync = 0;
- int poweroff = 0;
- int flags = 0;
+ size_t prop_len;
+ char property_val[PROPERTY_VALUE_MAX];
+ const char *cmd = "reboot";
+ char *optarg = "";
opterr = 0;
do {
int c;
- c = getopt(argc, argv, "np");
+ c = getopt(argc, argv, "p");
if (c == EOF) {
break;
}
switch (c) {
- case 'n':
- nosync = 1;
- break;
case 'p':
- poweroff = 1;
+ cmd = "shutdown";
break;
case '?':
- fprintf(stderr, "usage: %s [-n] [-p] [rebootcommand]\n", argv[0]);
+ fprintf(stderr, "usage: %s [-p] [rebootcommand]\n", argv[0]);
exit(EXIT_FAILURE);
}
} while (1);
@@ -55,20 +54,20 @@
exit(EXIT_FAILURE);
}
- if(nosync)
- /* also set NO_REMOUNT_RO as remount ro includes an implicit sync */
- flags = ANDROID_RB_FLAG_NO_SYNC | ANDROID_RB_FLAG_NO_REMOUNT_RO;
+ if (argc > optind)
+ optarg = argv[optind];
- if(poweroff)
- ret = android_reboot(ANDROID_RB_POWEROFF, flags, 0);
- else if(argc > optind)
- ret = android_reboot(ANDROID_RB_RESTART2, flags, argv[optind]);
- else
- ret = android_reboot(ANDROID_RB_RESTART, flags, 0);
+ prop_len = snprintf(property_val, sizeof(property_val), "%s,%s", cmd, optarg);
+ if (prop_len >= sizeof(property_val)) {
+ fprintf(stderr, "reboot command too long: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+
+ ret = property_set(ANDROID_RB_PROPERTY, property_val);
if(ret < 0) {
perror("reboot");
exit(EXIT_FAILURE);
}
- fprintf(stderr, "reboot returned\n");
+ fprintf(stderr, "Done\n");
return 0;
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c3ef503..f783768 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -398,6 +398,9 @@
class_reset late_start
class_reset main
+on property:sys.powerctl=*
+ powerctl ${sys.powerctl}
+
## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd