mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 22:10:40 +00:00
sulog: add more info
This commit is contained in:
parent
a5acf33ccd
commit
c6efb51f61
@ -6,7 +6,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Database(version = 1, entities = [SuLog::class], exportSchema = false)
|
@Database(version = 2, entities = [SuLog::class], exportSchema = false)
|
||||||
abstract class SuLogDatabase : RoomDatabase() {
|
abstract class SuLogDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun suLogDao(): SuLogDao
|
abstract fun suLogDao(): SuLogDao
|
||||||
|
@ -14,7 +14,10 @@ class SuLog(
|
|||||||
val packageName: String,
|
val packageName: String,
|
||||||
val appName: String,
|
val appName: String,
|
||||||
val command: String,
|
val command: String,
|
||||||
val action: Boolean,
|
val action: Int,
|
||||||
|
val target: Int,
|
||||||
|
val context: String,
|
||||||
|
val gids: String,
|
||||||
val time: Long = System.currentTimeMillis()
|
val time: Long = System.currentTimeMillis()
|
||||||
) {
|
) {
|
||||||
@PrimaryKey(autoGenerate = true) var id: Int = 0
|
@PrimaryKey(autoGenerate = true) var id: Int = 0
|
||||||
@ -25,7 +28,10 @@ fun PackageManager.createSuLog(
|
|||||||
toUid: Int,
|
toUid: Int,
|
||||||
fromPid: Int,
|
fromPid: Int,
|
||||||
command: String,
|
command: String,
|
||||||
policy: Int
|
policy: Int,
|
||||||
|
target: Int,
|
||||||
|
context: String,
|
||||||
|
gids: String,
|
||||||
): SuLog {
|
): SuLog {
|
||||||
val appInfo = info.applicationInfo
|
val appInfo = info.applicationInfo
|
||||||
return SuLog(
|
return SuLog(
|
||||||
@ -35,7 +41,10 @@ fun PackageManager.createSuLog(
|
|||||||
packageName = getNameForUid(appInfo.uid)!!,
|
packageName = getNameForUid(appInfo.uid)!!,
|
||||||
appName = appInfo.getLabel(this),
|
appName = appInfo.getLabel(this),
|
||||||
command = command,
|
command = command,
|
||||||
action = policy == SuPolicy.ALLOW
|
action = policy,
|
||||||
|
target = target,
|
||||||
|
context = context,
|
||||||
|
gids = gids,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +53,10 @@ fun createSuLog(
|
|||||||
toUid: Int,
|
toUid: Int,
|
||||||
fromPid: Int,
|
fromPid: Int,
|
||||||
command: String,
|
command: String,
|
||||||
policy: Int
|
policy: Int,
|
||||||
|
target: Int,
|
||||||
|
context: String,
|
||||||
|
gids: String,
|
||||||
): SuLog {
|
): SuLog {
|
||||||
return SuLog(
|
return SuLog(
|
||||||
fromUid = fromUid,
|
fromUid = fromUid,
|
||||||
@ -53,6 +65,9 @@ fun createSuLog(
|
|||||||
packageName = "[UID] $fromUid",
|
packageName = "[UID] $fromUid",
|
||||||
appName = "[UID] $fromUid",
|
appName = "[UID] $fromUid",
|
||||||
command = command,
|
command = command,
|
||||||
action = policy == SuPolicy.ALLOW
|
action = policy,
|
||||||
|
target = target,
|
||||||
|
context = context,
|
||||||
|
gids = gids,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -57,17 +57,20 @@ object SuCallbackHandler {
|
|||||||
val toUid = data.getIntComp("to.uid", -1)
|
val toUid = data.getIntComp("to.uid", -1)
|
||||||
val pid = data.getIntComp("pid", -1)
|
val pid = data.getIntComp("pid", -1)
|
||||||
val command = data.getString("command", "")
|
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 pm = context.packageManager
|
||||||
|
|
||||||
val log = runCatching {
|
val log = runCatching {
|
||||||
pm.getPackageInfo(fromUid, pid)?.let {
|
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)
|
if (notify)
|
||||||
notify(context, log.action, log.appName)
|
notify(context, log.action == SuPolicy.ALLOW, log.appName)
|
||||||
|
|
||||||
runBlocking { ServiceLocator.logRepo.insert(log) }
|
runBlocking { ServiceLocator.logRepo.insert(log) }
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.log
|
|||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
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.timeDateFormat
|
||||||
import com.topjohnwu.magisk.core.ktx.toTime
|
import com.topjohnwu.magisk.core.ktx.toTime
|
||||||
import com.topjohnwu.magisk.core.model.su.SuLog
|
import com.topjohnwu.magisk.core.model.su.SuLog
|
||||||
@ -14,7 +15,7 @@ class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem<SuLogRvItem> {
|
|||||||
|
|
||||||
override val layoutRes = R.layout.item_log_access_md2
|
override val layoutRes = R.layout.item_log_access_md2
|
||||||
|
|
||||||
val date = log.time.toTime(timeDateFormat)
|
val info = genInfo()
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isTop = false
|
var isTop = false
|
||||||
@ -25,4 +26,28 @@ class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem<SuLogRvItem> {
|
|||||||
set(value) = set(value, field, { field = it }, BR.bottom)
|
set(value) = set(value, field, { field = it }, BR.bottom)
|
||||||
|
|
||||||
override fun itemSameAs(other: SuLogRvItem) = log.appName == other.log.appName
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/log_track_container"
|
android:id="@+id/log_track_container"
|
||||||
bullet="@{item.log.action ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}"
|
bullet="@{item.log.action == 2 ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}"
|
||||||
isBottom="@{item.isBottom}"
|
isBottom="@{item.isBottom}"
|
||||||
isSelected="@{!item.log.action}"
|
isSelected="@{item.log.action != 2}"
|
||||||
isTop="@{item.isTop}"
|
isTop="@{item.isTop}"
|
||||||
layout="@layout/item_log_track_md2"
|
layout="@layout/item_log_track_md2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -54,48 +54,22 @@
|
|||||||
android:text="@{item.log.appName}"
|
android:text="@{item.log.appName}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/log_date"
|
app:layout_constraintBottom_toTopOf="@+id/log_info"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="@string/magisk" />
|
tools:text="@string/magisk" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/log_date"
|
android:id="@+id/log_info"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@{item.date}"
|
android:text="@{item.info}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/log_app_details"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/log_app_name"
|
app:layout_constraintTop_toBottomOf="@+id/log_app_name"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
tools:text="06:00 PM, 10 Oct 2019" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/log_app_details"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{String.format(`%s %s`, @string/pid(item.log.fromPid), @string/target_uid(item.log.toUid))}"
|
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/log_command"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/log_date"
|
|
||||||
tools:text="PID: 7196 Target UID: 0" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/log_command"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:text="@{item.log.command}"
|
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/log_app_details"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
tools:text="/system/bin/sh" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
@ -88,6 +88,9 @@
|
|||||||
<string name="logs_cleared">Log successfully cleared</string>
|
<string name="logs_cleared">Log successfully cleared</string>
|
||||||
<string name="pid">PID: %1$d</string>
|
<string name="pid">PID: %1$d</string>
|
||||||
<string name="target_uid">Target UID: %1$d</string>
|
<string name="target_uid">Target UID: %1$d</string>
|
||||||
|
<string name="target_pid">Mount ns target PID: %s</string>
|
||||||
|
<string name="selinux_context">SELinux context: %s</string>
|
||||||
|
<string name="supp_group">Supplementary group: %s</string>
|
||||||
|
|
||||||
<!--SafetyNet-->
|
<!--SafetyNet-->
|
||||||
|
|
||||||
|
@ -32,27 +32,28 @@ class Extra {
|
|||||||
enum {
|
enum {
|
||||||
INT,
|
INT,
|
||||||
BOOL,
|
BOOL,
|
||||||
STRING
|
STRING,
|
||||||
|
INTLIST,
|
||||||
} type;
|
} type;
|
||||||
union {
|
union {
|
||||||
int int_val;
|
int int_val;
|
||||||
bool bool_val;
|
bool bool_val;
|
||||||
const char *str_val;
|
const char *str_val;
|
||||||
|
const vector<uint32_t> *intlist_val;
|
||||||
};
|
};
|
||||||
string str;
|
string str;
|
||||||
public:
|
public:
|
||||||
Extra(const char *k, int v): key(k), type(INT), int_val(v) {}
|
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, 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 char *v): key(k), type(STRING), str_val(v) {}
|
||||||
|
Extra(const char *k, const vector<uint32_t> *v): key(k), type(INTLIST), intlist_val(v) {}
|
||||||
|
|
||||||
void add_intent(vector<const char *> &vec) {
|
void add_intent(vector<const char *> &vec) {
|
||||||
char buf[32];
|
|
||||||
const char *val;
|
const char *val;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT:
|
case INT:
|
||||||
vec.push_back("--ei");
|
vec.push_back("--ei");
|
||||||
ssprintf(buf, sizeof(buf), "%d", int_val);
|
str = to_string(int_val);
|
||||||
str = buf;
|
|
||||||
val = str.data();
|
val = str.data();
|
||||||
break;
|
break;
|
||||||
case BOOL:
|
case BOOL:
|
||||||
@ -63,6 +64,15 @@ public:
|
|||||||
vec.push_back("--es");
|
vec.push_back("--es");
|
||||||
val = str_val;
|
val = str_val;
|
||||||
break;
|
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(key);
|
||||||
vec.push_back(val);
|
vec.push_back(val);
|
||||||
@ -92,6 +102,14 @@ public:
|
|||||||
str += str_val;
|
str += str_val;
|
||||||
}
|
}
|
||||||
break;
|
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("--extra");
|
||||||
vec.push_back(str.data());
|
vec.push_back(str.data());
|
||||||
@ -102,8 +120,10 @@ static bool check_no_error(int fd) {
|
|||||||
char buf[1024];
|
char buf[1024];
|
||||||
auto out = xopen_file(fd, "r");
|
auto out = xopen_file(fd, "r");
|
||||||
while (fgets(buf, sizeof(buf), out.get())) {
|
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 false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -163,11 +183,14 @@ static void exec_cmd(const char *action, vector<Extra> &data,
|
|||||||
void app_log(const su_context &ctx) {
|
void app_log(const su_context &ctx) {
|
||||||
if (fork_dont_care() == 0) {
|
if (fork_dont_care() == 0) {
|
||||||
vector<Extra> extras;
|
vector<Extra> extras;
|
||||||
extras.reserve(6);
|
extras.reserve(9);
|
||||||
extras.emplace_back("from.uid", ctx.info->uid);
|
extras.emplace_back("from.uid", ctx.info->uid);
|
||||||
extras.emplace_back("to.uid", static_cast<int>(ctx.req.uid));
|
extras.emplace_back("to.uid", static_cast<int>(ctx.req.uid));
|
||||||
extras.emplace_back("pid", ctx.pid);
|
extras.emplace_back("pid", ctx.pid);
|
||||||
extras.emplace_back("policy", ctx.info->access.policy);
|
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("command", get_cmd(ctx.req));
|
||||||
extras.emplace_back("notify", (bool) ctx.info->access.notify);
|
extras.emplace_back("notify", (bool) ctx.info->access.notify);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user