diff --git a/app/src/main/java/com/topjohnwu/magisk/core/data/SuLogDao.kt b/app/src/main/java/com/topjohnwu/magisk/core/data/SuLogDao.kt index 37570115d..1f39177bc 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/data/SuLogDao.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/data/SuLogDao.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.util.* -@Database(version = 1, entities = [SuLog::class], exportSchema = false) +@Database(version = 2, entities = [SuLog::class], exportSchema = false) abstract class SuLogDatabase : RoomDatabase() { abstract fun suLogDao(): SuLogDao diff --git a/app/src/main/java/com/topjohnwu/magisk/core/model/su/SuLog.kt b/app/src/main/java/com/topjohnwu/magisk/core/model/su/SuLog.kt index 96f76c016..f37bc734e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/model/su/SuLog.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/model/su/SuLog.kt @@ -14,7 +14,10 @@ class SuLog( val packageName: String, val appName: String, val command: String, - val action: Boolean, + val action: Int, + val target: Int, + val context: String, + val gids: String, val time: Long = System.currentTimeMillis() ) { @PrimaryKey(autoGenerate = true) var id: Int = 0 @@ -25,7 +28,10 @@ fun PackageManager.createSuLog( toUid: Int, fromPid: Int, command: String, - policy: Int + policy: Int, + target: Int, + context: String, + gids: String, ): SuLog { val appInfo = info.applicationInfo return SuLog( @@ -35,7 +41,10 @@ fun PackageManager.createSuLog( packageName = getNameForUid(appInfo.uid)!!, appName = appInfo.getLabel(this), command = command, - action = policy == SuPolicy.ALLOW + action = policy, + target = target, + context = context, + gids = gids, ) } @@ -44,7 +53,10 @@ fun createSuLog( toUid: Int, fromPid: Int, command: String, - policy: Int + policy: Int, + target: Int, + context: String, + gids: String, ): SuLog { return SuLog( fromUid = fromUid, @@ -53,6 +65,9 @@ fun createSuLog( packageName = "[UID] $fromUid", appName = "[UID] $fromUid", command = command, - action = policy == SuPolicy.ALLOW + action = policy, + target = target, + context = context, + gids = gids, ) } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/su/SuCallbackHandler.kt b/app/src/main/java/com/topjohnwu/magisk/core/su/SuCallbackHandler.kt index 3c9ddea21..cb034c3e4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/su/SuCallbackHandler.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/su/SuCallbackHandler.kt @@ -57,17 +57,20 @@ object SuCallbackHandler { val toUid = data.getIntComp("to.uid", -1) val pid = data.getIntComp("pid", -1) val command = data.getString("command", "") + val target = data.getIntComp("target", -1) + val seContext = data.getString("context", "") + val gids = data.getString("gids", "") val pm = context.packageManager val log = runCatching { pm.getPackageInfo(fromUid, pid)?.let { - pm.createSuLog(it, toUid, pid, command, policy) + pm.createSuLog(it, toUid, pid, command, policy, target, seContext, gids) } - }.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy) + }.getOrNull() ?: createSuLog(fromUid, toUid, pid, command, policy, target, seContext, gids) if (notify) - notify(context, log.action, log.appName) + notify(context, log.action == SuPolicy.ALLOW, log.appName) runBlocking { ServiceLocator.logRepo.insert(log) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/log/SuLogRvItem.kt b/app/src/main/java/com/topjohnwu/magisk/ui/log/SuLogRvItem.kt index b84247a97..65d1c51c2 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/log/SuLogRvItem.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/log/SuLogRvItem.kt @@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.log import androidx.databinding.Bindable import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.R +import com.topjohnwu.magisk.core.di.AppContext import com.topjohnwu.magisk.core.ktx.timeDateFormat import com.topjohnwu.magisk.core.ktx.toTime import com.topjohnwu.magisk.core.model.su.SuLog @@ -14,7 +15,7 @@ class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem { override val layoutRes = R.layout.item_log_access_md2 - val date = log.time.toTime(timeDateFormat) + val info = genInfo() @get:Bindable var isTop = false @@ -25,4 +26,28 @@ class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem { set(value) = set(value, field, { field = it }, BR.bottom) override fun itemSameAs(other: SuLogRvItem) = log.appName == other.log.appName + + private fun genInfo(): String { + val res = AppContext.resources + val sb = StringBuilder() + val date = log.time.toTime(timeDateFormat) + val toUid = res.getString(R.string.target_uid, log.toUid) + val fromPid = res.getString(R.string.pid, log.fromPid) + sb.append("$date\n$toUid $fromPid") + if (log.target != -1) { + val pid = if (log.target == 0) "magiskd" else log.target.toString() + val target = res.getString(R.string.target_pid, pid) + sb.append(" $target") + } + if (log.context.isNotEmpty()) { + val context = res.getString(R.string.selinux_context, log.context) + sb.append("\n$context") + } + if (log.gids.isNotEmpty()) { + val gids = res.getString(R.string.supp_group, log.gids) + sb.append("\n$gids") + } + sb.append("\n${log.command}") + return sb.toString() + } } diff --git a/app/src/main/res/layout/item_log_access_md2.xml b/app/src/main/res/layout/item_log_access_md2.xml index aefa30ca3..146d74177 100644 --- a/app/src/main/res/layout/item_log_access_md2.xml +++ b/app/src/main/res/layout/item_log_access_md2.xml @@ -25,9 +25,9 @@ - - - - + app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7f5b245a0..7c7714b23 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,6 +88,9 @@ Log successfully cleared PID: %1$d Target UID: %1$d + Mount ns target PID: %s + SELinux context: %s + Supplementary group: %s diff --git a/native/src/core/su/connect.cpp b/native/src/core/su/connect.cpp index 9d0ba94f5..8020334d6 100644 --- a/native/src/core/su/connect.cpp +++ b/native/src/core/su/connect.cpp @@ -32,27 +32,28 @@ class Extra { enum { INT, BOOL, - STRING + STRING, + INTLIST, } type; union { int int_val; bool bool_val; const char *str_val; + const vector *intlist_val; }; string str; public: Extra(const char *k, int v): key(k), type(INT), int_val(v) {} Extra(const char *k, bool v): key(k), type(BOOL), bool_val(v) {} Extra(const char *k, const char *v): key(k), type(STRING), str_val(v) {} + Extra(const char *k, const vector *v): key(k), type(INTLIST), intlist_val(v) {} void add_intent(vector &vec) { - char buf[32]; const char *val; switch (type) { case INT: vec.push_back("--ei"); - ssprintf(buf, sizeof(buf), "%d", int_val); - str = buf; + str = to_string(int_val); val = str.data(); break; case BOOL: @@ -63,6 +64,15 @@ public: vec.push_back("--es"); val = str_val; break; + case INTLIST: + vec.push_back("--es"); + for (auto i : *intlist_val) { + str += to_string(i); + str += ","; + } + if (!str.empty()) str.pop_back(); + val = str.data(); + break; } vec.push_back(key); vec.push_back(val); @@ -92,6 +102,14 @@ public: str += str_val; } break; + case INTLIST: + str += ":s:"; + for (auto i : *intlist_val) { + str += to_string(i); + str += ","; + } + if (str.back() == ',') str.pop_back(); + break; } vec.push_back("--extra"); vec.push_back(str.data()); @@ -102,8 +120,10 @@ static bool check_no_error(int fd) { char buf[1024]; auto out = xopen_file(fd, "r"); while (fgets(buf, sizeof(buf), out.get())) { - if (strncmp(buf, "Error", 5) == 0) + if (strncasecmp(buf, "Error", 5) == 0) { + LOGD("exec_cmd: %s\n", buf); return false; + } } return true; } @@ -163,11 +183,14 @@ static void exec_cmd(const char *action, vector &data, void app_log(const su_context &ctx) { if (fork_dont_care() == 0) { vector extras; - extras.reserve(6); + extras.reserve(9); extras.emplace_back("from.uid", ctx.info->uid); extras.emplace_back("to.uid", static_cast(ctx.req.uid)); extras.emplace_back("pid", ctx.pid); extras.emplace_back("policy", ctx.info->access.policy); + extras.emplace_back("target", ctx.req.target); + extras.emplace_back("context", ctx.req.context.data()); + extras.emplace_back("gids", &ctx.req.gids); extras.emplace_back("command", get_cmd(ctx.req)); extras.emplace_back("notify", (bool) ctx.info->access.notify);