diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3088cc87..adc80d946 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ Changelog
**Next release**
* Fixed restrictions not always showing correct after on demand restricting ([issue](/../../issues/1549))
+* Better matching of *sh* and *su* ([issue](/../../issues/1551))
[Open issues](https://github.com/M66B/XPrivacy/issues?state=open)
diff --git a/README.md b/README.md
index e134f6f5d..2da0e86dc 100644
--- a/README.md
+++ b/README.md
@@ -520,7 +520,9 @@ To import and export XPrivacy's data, you need the [pro version](http://www.xpri
**(10) Can I restrict root access?**
-Yes, via "Shell (commands, superuser) > su".
+Yes, via "Shell (commands, superuser) > su",
+but be aware that applications can acquire root privileges through native libraries too.
+An example is [Android Terminal Emulator](https://play.google.com/store/apps/details?id=jackpal.androidterm).
**(11) Will restrictions be applied immediately?**
diff --git a/src/biz/bokhorst/xprivacy/XProcessBuilder.java b/src/biz/bokhorst/xprivacy/XProcessBuilder.java
index c0c3c38f3..61fa7de2f 100644
--- a/src/biz/bokhorst/xprivacy/XProcessBuilder.java
+++ b/src/biz/bokhorst/xprivacy/XProcessBuilder.java
@@ -43,11 +43,8 @@ protected void before(XParam param) throws Throwable {
// Check commands
if (listProg != null) {
String command = TextUtils.join(" ", listProg);
- if (mCommand == null ? !(command.startsWith("sh") || command.startsWith("su")
- || command.contains("sh ") || command.contains("su ")) : command.startsWith(mCommand)
- || command.contains(mCommand + " "))
- if (isRestrictedExtra(param, command))
- param.setThrowable(new IOException());
+ if (XRuntime.matches(command, mCommand) && isRestrictedExtra(param, command))
+ param.setThrowable(new IOException());
}
} else
Util.log(this, Log.WARN, "Unknown method=" + methodName);
diff --git a/src/biz/bokhorst/xprivacy/XRuntime.java b/src/biz/bokhorst/xprivacy/XRuntime.java
index 0e3821776..fadd06035 100644
--- a/src/biz/bokhorst/xprivacy/XRuntime.java
+++ b/src/biz/bokhorst/xprivacy/XRuntime.java
@@ -65,11 +65,8 @@ protected void before(XParam param) throws Throwable {
// Check programs
if (progs != null) {
String command = TextUtils.join(" ", progs);
- if (mCommand == null ? !(command.startsWith("sh") || command.startsWith("su")
- || command.contains("sh ") || command.contains("su ")) : command.startsWith(mCommand)
- || command.contains(mCommand + " "))
- if (isRestrictedExtra(param, command))
- param.setThrowable(new IOException());
+ if (matches(command, mCommand) && isRestrictedExtra(param, command))
+ param.setThrowable(new IOException());
}
} else if (mMethod == Methods.load || mMethod == Methods.loadLibrary) {
@@ -80,6 +77,25 @@ protected void before(XParam param) throws Throwable {
Util.log(this, Log.WARN, "Unknown method=" + param.method.getName());
}
+ public static boolean matches(String command, String mCommand) {
+ if (mCommand == null)
+ return !isShell(command) && !isSU(command);
+ else if (mCommand.equals("sh"))
+ return isShell(command);
+ else if (mCommand.equals("su"))
+ return isSU(command);
+ else
+ return false;
+ }
+
+ private static boolean isShell(String command) {
+ return command.startsWith("sh") || command.matches("/.*/.*/sh.*") || command.contains("sh ");
+ }
+
+ private static boolean isSU(String command) {
+ return command.startsWith("su") || command.matches("/.*/.*/su.*") || command.contains("su ");
+ }
+
@Override
protected void after(XParam param) throws Throwable {
}