libbinder: require shell/root UID for shell
The APIs under SHELL_COMMAND_TRANSACTION are considered to be
development APIs and are not suitable for actual usage on the device,
especially where the APIs need to be stable over long periods of
time.
Bug: N/A
Test: as follows
walleye:/ # su root cmd package list packages
<successful output>
walleye:/ # su shell cmd package list packages
<successful output>
walleye:/ # su system cmd package list packages
cmd: Failure calling service package: Operation not permitted (1)
Change-Id: I236281ba0346711f89507d026eadd5ae3c9337b1
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 96ee295..7324cf5 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -17,12 +17,15 @@
#include <binder/Binder.h>
#include <atomic>
-#include <utils/misc.h>
#include <binder/BpBinder.h>
#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/IShellCallback.h>
#include <binder/Parcel.h>
+#include <cutils/android_filesystem_config.h>
+#include <cutils/compiler.h>
+#include <utils/misc.h>
#include <stdio.h>
@@ -125,6 +128,19 @@
{
data.setDataPosition(0);
+ // Shell command transaction is conventionally implemented by
+ // overriding onTransact by copy/pasting the parceling code from
+ // this file. So, we must check permissions for it before we call
+ // onTransact. This check is here because shell APIs aren't
+ // guaranteed to be stable, and so they should only be used by
+ // developers.
+ if (CC_UNLIKELY(code == SHELL_COMMAND_TRANSACTION)) {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ if (uid != AID_SHELL && uid != AID_ROOT) {
+ return PERMISSION_DENIED;
+ }
+ }
+
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION: