Simplify SU requests, binary should be much superior now

This commit is contained in:
topjohnwu 2017-05-30 01:27:10 +08:00
parent 5af07c4531
commit a573baea03
6 changed files with 62 additions and 83 deletions

View File

@ -108,11 +108,10 @@ public class MagiskManager extends Application {
} }
magiskHide = prefs.getBoolean("magiskhide", false); magiskHide = prefs.getBoolean("magiskhide", false);
updateNotification = prefs.getBoolean("notification", true); updateNotification = prefs.getBoolean("notification", true);
initSU();
// Always start a new root shell manually, just for safety // Always start a new root shell manually, just for safety
Shell.init(); Shell.init();
updateMagiskInfo(); updateMagiskInfo();
initSuAccess();
initSuConfigs();
// Initialize busybox // Initialize busybox
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox"); File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) { if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
@ -141,13 +140,14 @@ public class MagiskManager extends Application {
Shell.su("PATH=$PATH:" + busybox.getParent()); Shell.su("PATH=$PATH:" + busybox.getParent());
} }
public void initSuConfigs() { public void initSU() {
// Create the app data directory, so su binary can work properly
new File(getApplicationInfo().dataDir).mkdirs();
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10); suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0); suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1); suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
}
public void initSuAccess() {
List<String> ret = Shell.sh("su -v"); List<String> ret = Shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) { if (Utils.isValidShellResponse(ret)) {
suVersion = ret.get(0); suVersion = ret.get(0);

View File

@ -3,6 +3,8 @@ package com.topjohnwu.magisk.services;
import android.app.IntentService; import android.app.IntentService;
import android.content.Intent; import android.content.Intent;
import com.topjohnwu.magisk.MagiskManager;
public class BootupIntentService extends IntentService { public class BootupIntentService extends IntentService {
public BootupIntentService() { public BootupIntentService() {
@ -11,10 +13,6 @@ public class BootupIntentService extends IntentService {
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
/* Currently no bootup task to do ((MagiskManager) getApplication()).initSU();
MagiskManager magiskManager = Utils.getMagiskManager(this);
magiskManager.initSuAccess();
magiskManager.updateMagiskInfo();
*/
} }
} }

View File

@ -11,7 +11,7 @@ public class Policy {
public static final int DENY = 1; public static final int DENY = 1;
public static final int ALLOW = 2; public static final int ALLOW = 2;
public int uid, policy; public int uid, policy = INTERACTIVE;
public long until; public long until;
public boolean logging = true, notification = true; public boolean logging = true, notification = true;
public String packageName, appName; public String packageName, appName;

View File

@ -17,7 +17,7 @@ public class RequestActivity extends Activity {
return; return;
} }
getApplicationContext().initSuConfigs(); getApplicationContext().initSU();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class);
startActivity(intent); startActivity(intent);
finish(); finish();

View File

@ -56,7 +56,7 @@ public class SuReceiver extends BroadcastReceiver {
} }
} }
magiskManager.initSuConfigs(); magiskManager.initSU();
SuLogEntry log = new SuLogEntry(policy); SuLogEntry log = new SuLogEntry(policy);

View File

@ -23,20 +23,18 @@ import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.Activity; import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.SuDatabaseHelper; import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.utils.CallbackEvent; import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
public class SuRequestActivity extends Activity implements CallbackEvent.Listener<Policy> { public class SuRequestActivity extends Activity {
private static final int[] timeoutList = {0, -1, 10, 20, 30, 60}; private static final int[] timeoutList = {0, -1, 10, 20, 30, 60};
private static final int SU_PROTOCOL_PARAM_MAX = 20;
private static final int SU_PROTOCOL_NAME_MAX = 20;
private static final int SU_PROTOCOL_VALUE_MAX = 256;
private static final int PROMPT = 0; private static final int PROMPT = 0;
private static final int AUTO_DENY = 1; private static final int AUTO_DENY = 1;
private static final int AUTO_ALLOW = 2; private static final int AUTO_ALLOW = 2;
@ -53,13 +51,11 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
private LocalSocket socket; private LocalSocket socket;
private PackageManager pm; private PackageManager pm;
private MagiskManager magiskManager; private MagiskManager magiskManager;
private SuDatabaseHelper suDB;
private int uid;
private boolean hasTimeout; private boolean hasTimeout;
private Policy policy; private Policy policy;
private CountDownTimer timer; private CountDownTimer timer;
private CallbackEvent.Listener<Policy> self;
private CallbackEvent<Policy> event = null;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -68,19 +64,16 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
pm = getPackageManager(); pm = getPackageManager();
magiskManager = getApplicationContext(); magiskManager = getApplicationContext();
suDB = new SuDatabaseHelper(this);
Intent intent = getIntent(); Intent intent = getIntent();
socketPath = intent.getStringExtra("socket"); socketPath = intent.getStringExtra("socket");
hasTimeout = intent.getBooleanExtra("timeout", true); hasTimeout = intent.getBooleanExtra("timeout", true);
self = this;
new FileObserver(socketPath) { new FileObserver(socketPath) {
@Override @Override
public void onEvent(int fileEvent, String path) { public void onEvent(int fileEvent, String path) {
if (fileEvent == FileObserver.DELETE_SELF) { if (fileEvent == FileObserver.DELETE_SELF) {
if (event != null) {
event.trigger();
}
finish(); finish();
} }
} }
@ -97,6 +90,8 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
private void showRequest() { private void showRequest() {
Logger.debug("Show request");
switch (magiskManager.suResponseType) { switch (magiskManager.suResponseType) {
case AUTO_DENY: case AUTO_DENY:
handleAction(Policy.DENY, 0); handleAction(Policy.DENY, 0);
@ -108,6 +103,12 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
default: default:
} }
// If not interactive, response directly
if (policy.policy != Policy.INTERACTIVE) {
handleAction();
return;
}
setContentView(R.layout.activity_request); setContentView(R.layout.activity_request);
ButterKnife.bind(this); ButterKnife.bind(this);
@ -128,13 +129,19 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
@Override @Override
public void onFinish() { public void onFinish() {
deny_btn.setText(getString(R.string.deny_with_str, "(0)")); deny_btn.setText(getString(R.string.deny_with_str, "(0)"));
event.trigger(); handleAction(Policy.DENY);
} }
}; };
grant_btn.setOnClickListener(v -> handleAction(Policy.ALLOW)); grant_btn.setOnClickListener(v -> {
deny_btn.setOnClickListener(v -> handleAction(Policy.DENY)); handleAction(Policy.ALLOW);
suPopup.setOnClickListener((v) -> cancelTimeout()); timer.cancel();
});
deny_btn.setOnClickListener(v -> {
handleAction(Policy.DENY);
timer.cancel();
});
suPopup.setOnClickListener(v -> cancelTimeout());
timeout.setOnTouchListener((v, event) -> cancelTimeout()); timeout.setOnTouchListener((v, event) -> cancelTimeout());
if (hasTimeout) { if (hasTimeout) {
@ -146,19 +153,25 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
@Override @Override
public void onBackPressed() { public void onBackPressed() {
event.trigger(); if (policy != null) {
handleAction(Policy.DENY);
}
finish();
} }
@Override void handleAction() {
public void onTrigger(CallbackEvent<Policy> event) { String response;
Policy policy = event.getResult(); if (policy.policy == Policy.ALLOW) {
String response = "socket:DENY";
if (policy != null &&policy.policy == Policy.ALLOW ) {
response = "socket:ALLOW"; response = "socket:ALLOW";
} else {
response = "socket:DENY";
} }
try { try {
socket.getOutputStream().write((response).getBytes()); socket.getOutputStream().write((response).getBytes());
} catch (Exception ignored) {} socket.close();
} catch (IOException e) {
e.printStackTrace();
}
finish(); finish();
} }
@ -168,16 +181,16 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
void handleAction(int action, int time) { void handleAction(int action, int time) {
policy.policy = action; policy.policy = action;
event.trigger(policy);
if (time >= 0) { if (time >= 0) {
policy.until = time == 0 ? 0 : (System.currentTimeMillis() / 1000 + time * 60); policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
new SuDatabaseHelper(this).addPolicy(policy); new SuDatabaseHelper(this).addPolicy(policy);
} }
handleAction();
} }
private class SocketManager extends ParallelTask<Void, Void, Boolean> { private class SocketManager extends ParallelTask<Void, Void, Boolean> {
public SocketManager(Activity context) { SocketManager(Activity context) {
super(context); super(context);
} }
@ -188,40 +201,33 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
socket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM)); socket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM));
DataInputStream is = new DataInputStream(socket.getInputStream()); DataInputStream is = new DataInputStream(socket.getInputStream());
ContentValues payload = new ContentValues(); ContentValues payload = new ContentValues();
for (int i = 0; i < SU_PROTOCOL_PARAM_MAX; i++) { while (true) {
int nameLen = is.readInt(); int nameLen = is.readInt();
if (nameLen > SU_PROTOCOL_NAME_MAX)
throw new IllegalArgumentException("name length too long: " + nameLen);
byte[] nameBytes = new byte[nameLen]; byte[] nameBytes = new byte[nameLen];
is.readFully(nameBytes); is.readFully(nameBytes);
String name = new String(nameBytes); String name = new String(nameBytes);
if (TextUtils.equals(name, "eof")) if (TextUtils.equals(name, "eof"))
break; break;
int dataLen = is.readInt(); int dataLen = is.readInt();
if (dataLen > SU_PROTOCOL_VALUE_MAX)
throw new IllegalArgumentException(name + " data length too long: " + dataLen);
byte[] dataBytes = new byte[dataLen]; byte[] dataBytes = new byte[dataLen];
is.readFully(dataBytes); is.readFully(dataBytes);
String data = new String(dataBytes); String data = new String(dataBytes);
payload.put(name, data); payload.put(name, data);
} }
if (payload.getAsInteger("uid") == null) if (payload.getAsInteger("uid") == null) {
return false; return false;
uid = payload.getAsInteger("uid"); }
} catch (IOException e) { int uid = payload.getAsInteger("uid");
policy = suDB.getPolicy(uid);
if (policy == null) {
policy = new Policy(uid, pm);
}
} catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
} }
@ -230,35 +236,10 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
@Override @Override
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
if (!result) { if (result) {
showRequest();
} else {
finish(); finish();
return;
}
boolean showRequest = false;
event = magiskManager.uidSuRequest.get(uid);
if (event == null) {
showRequest = true;
event = new CallbackEvent<Policy>() {
@Override
public void trigger(Policy result) {
super.trigger(result);
unRegister();
magiskManager.uidSuRequest.remove(uid);
}
};
magiskManager.uidSuRequest.put(uid, event);
}
event.register(self);
try {
if (showRequest) {
policy = new Policy(uid, pm);
showRequest();
} else {
finish();
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
event.trigger();
} }
} }
} }