From 0d31d356ef8905f358555c9ac682da6035090845 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 5 Jan 2025 04:32:47 -0800 Subject: [PATCH] Use SQLite's internal time function --- .../java/com/topjohnwu/magisk/core/Config.kt | 2 +- .../magisk/core/data/magiskdb/MagiskDB.kt | 17 +++++++++---- .../magisk/core/data/magiskdb/PolicyDao.kt | 21 ++++++++++------ .../magisk/core/data/magiskdb/SettingsDao.kt | 4 +-- .../magisk/core/data/magiskdb/StringDao.kt | 4 +-- .../magisk/core/model/su/SuPolicy.kt | 25 +++++++++++++------ .../magisk/core/su/SuRequestHandler.kt | 16 ++++++------ .../topjohnwu/magisk/test/MagiskAppTest.kt | 2 +- native/src/core/su/mod.rs | 10 +++----- native/src/core/su/su_daemon.cpp | 9 +++---- 10 files changed, 62 insertions(+), 48 deletions(-) diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/Config.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/Config.kt index 199833feb..f5f929390 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/Config.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/Config.kt @@ -83,7 +83,7 @@ object Config : PreferenceConfig, DBConfig { const val SU_AUTO_ALLOW = 2 // su timeout - val TIMEOUT_LIST = intArrayOf(0, -1, 10, 20, 30, 60) + val TIMEOUT_LIST = longArrayOf(0, -1, 10, 20, 30, 60) } private val defaultChannel = diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/MagiskDB.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/MagiskDB.kt index cd7dd8a16..ff44ed1f0 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/MagiskDB.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/MagiskDB.kt @@ -7,9 +7,13 @@ import kotlinx.coroutines.withContext open class MagiskDB { - suspend fun exec( + class Literal( + val str: String + ) + + suspend inline fun exec( query: String, - mapper: suspend (Map) -> R + crossinline mapper: (Map) -> R ): List { return withContext(Dispatchers.IO) { val out = Shell.cmd("magisk --sqlite '$query'").await().out @@ -18,13 +22,15 @@ open class MagiskDB { .map { it.split("=", limit = 2) } .filter { it.size == 2 } .associate { it[0] to it[1] } - .let { mapper(it) } + .let(mapper) } } } - suspend inline fun exec(query: String) { - exec(query) {} + suspend fun exec(query: String) { + withContext(Dispatchers.IO) { + Shell.cmd("magisk --sqlite '$query'").await() + } } fun Map.toQuery(): String { @@ -33,6 +39,7 @@ open class MagiskDB { when (it) { is Boolean -> if (it) "1" else "0" is Number -> it.toString() + is Literal -> it.str else -> "\"$it\"" } } diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/PolicyDao.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/PolicyDao.kt index 1ed417fab..df38149e9 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/PolicyDao.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/PolicyDao.kt @@ -3,24 +3,24 @@ package com.topjohnwu.magisk.core.data.magiskdb import com.topjohnwu.magisk.core.AppContext import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.model.su.SuPolicy -import java.util.concurrent.TimeUnit + +private const val SELECT_QUERY = "SELECT (until - strftime(\"%s\", \"now\")) AS remain, *" class PolicyDao : MagiskDB() { suspend fun deleteOutdated() { - val nowSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) val query = "DELETE FROM ${Table.POLICY} WHERE " + - "(until > 0 AND until < $nowSeconds) OR until < 0" + "(until > 0 AND until < strftime(\"%s\", \"now\")) OR until < 0" exec(query) } suspend fun delete(uid: Int) { - val query = "DELETE FROM ${Table.POLICY} WHERE uid == $uid" + val query = "DELETE FROM ${Table.POLICY} WHERE uid=$uid" exec(query) } suspend fun fetch(uid: Int): SuPolicy? { - val query = "SELECT * FROM ${Table.POLICY} WHERE uid == $uid LIMIT 1" + val query = "$SELECT_QUERY FROM ${Table.POLICY} WHERE uid=$uid LIMIT 1" return exec(query, ::toPolicy).firstOrNull() } @@ -35,7 +35,7 @@ class PolicyDao : MagiskDB() { } suspend fun fetchAll(): List { - val query = "SELECT * FROM ${Table.POLICY} WHERE uid/100000 == ${Const.USER_ID}" + val query = "$SELECT_QUERY FROM ${Table.POLICY} WHERE uid/100000=${Const.USER_ID}" return exec(query, ::toPolicy).filterNotNull() } @@ -43,8 +43,15 @@ class PolicyDao : MagiskDB() { val uid = map["uid"]?.toInt() ?: return null val policy = SuPolicy(uid) + map["until"]?.toLong()?.let { until -> + if (until <= 0) { + policy.remain = until + } else { + map["remain"]?.toLong()?.let { policy.remain = it } + } + } + map["policy"]?.toInt()?.let { policy.policy = it } - map["until"]?.toLong()?.let { policy.until = it } map["logging"]?.toInt()?.let { policy.logging = it != 0 } map["notification"]?.toInt()?.let { policy.notification = it != 0 } return policy diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/SettingsDao.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/SettingsDao.kt index b7a8cc9e0..6089caf0a 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/SettingsDao.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/SettingsDao.kt @@ -3,7 +3,7 @@ package com.topjohnwu.magisk.core.data.magiskdb class SettingsDao : MagiskDB() { suspend fun delete(key: String) { - val query = "DELETE FROM ${Table.SETTINGS} WHERE key == \"$key\"" + val query = "DELETE FROM ${Table.SETTINGS} WHERE key=\"$key\"" exec(query) } @@ -14,7 +14,7 @@ class SettingsDao : MagiskDB() { } suspend fun fetch(key: String, default: Int = -1): Int { - val query = "SELECT value FROM ${Table.SETTINGS} WHERE key == \"$key\" LIMIT 1" + val query = "SELECT value FROM ${Table.SETTINGS} WHERE key=\"$key\" LIMIT 1" return exec(query) { it["value"]?.toInt() }.firstOrNull() ?: default } } diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/StringDao.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/StringDao.kt index bdc4c3155..2ea488a59 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/StringDao.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/StringDao.kt @@ -3,7 +3,7 @@ package com.topjohnwu.magisk.core.data.magiskdb class StringDao : MagiskDB() { suspend fun delete(key: String) { - val query = "DELETE FROM ${Table.STRINGS} WHERE key == \"$key\"" + val query = "DELETE FROM ${Table.STRINGS} WHERE key=\"$key\"" exec(query) } @@ -14,7 +14,7 @@ class StringDao : MagiskDB() { } suspend fun fetch(key: String, default: String = ""): String { - val query = "SELECT value FROM ${Table.STRINGS} WHERE key == \"$key\" LIMIT 1" + val query = "SELECT value FROM ${Table.STRINGS} WHERE key=\"$key\" LIMIT 1" return exec(query) { it["value"] }.firstOrNull() ?: default } } diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/model/su/SuPolicy.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/model/su/SuPolicy.kt index b13d22733..f4d1864fe 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/model/su/SuPolicy.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/model/su/SuPolicy.kt @@ -1,9 +1,11 @@ package com.topjohnwu.magisk.core.model.su +import com.topjohnwu.magisk.core.data.magiskdb.MagiskDB + class SuPolicy( val uid: Int, var policy: Int = INTERACTIVE, - var until: Long = -1L, + var remain: Long = -1L, var logging: Boolean = true, var notification: Boolean = true, ) { @@ -13,11 +15,18 @@ class SuPolicy( const val ALLOW = 2 } - fun toMap(): MutableMap = mutableMapOf( - "uid" to uid, - "policy" to policy, - "until" to until, - "logging" to logging, - "notification" to notification - ) + fun toMap(): MutableMap { + val until = if (remain <= 0) { + remain + } else { + MagiskDB.Literal("(strftime(\"%s\", \"now\") + $remain)") + } + return mutableMapOf( + "uid" to uid, + "policy" to policy, + "until" to until, + "logging" to logging, + "notification" to notification + ) + } } diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt index 6ae2c183e..e10f8cccd 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/su/SuRequestHandler.kt @@ -81,15 +81,13 @@ class SuRequestHandler( return true } - suspend fun respond(action: Int, time: Int) { - val until = if (time > 0) - TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) + - TimeUnit.MINUTES.toSeconds(time.toLong()) - else - time.toLong() - + suspend fun respond(action: Int, time: Long) { policy.policy = action - policy.until = until + if (time >= 0) { + policy.remain = TimeUnit.MINUTES.toSeconds(time) + } else { + policy.remain = time + } withContext(Dispatchers.IO) { try { @@ -100,7 +98,7 @@ class SuRequestHandler( } catch (e: IOException) { Timber.e(e) } - if (until >= 0) { + if (time >= 0) { policyDB.update(policy) } } diff --git a/app/core/src/main/java/com/topjohnwu/magisk/test/MagiskAppTest.kt b/app/core/src/main/java/com/topjohnwu/magisk/test/MagiskAppTest.kt index 085659d1a..a359481af 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/test/MagiskAppTest.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/test/MagiskAppTest.kt @@ -45,7 +45,7 @@ class MagiskAppTest : BaseTest { uid = 2000, logging = false, notification = false, - until = 0L + remain = 0L ) runBlocking { ServiceLocator.policyDB.update(policy) diff --git a/native/src/core/su/mod.rs b/native/src/core/su/mod.rs index e4acc1e83..e329f6094 100644 --- a/native/src/core/su/mod.rs +++ b/native/src/core/su/mod.rs @@ -2,8 +2,7 @@ use crate::daemon::MagiskD; use crate::db::DbArg::Integer; use crate::db::{SqlTable, SqliteResult, SqliteReturn}; use crate::ffi::{DbValues, RootSettings, SuPolicy}; -use base::{libc, ResultExt}; -use std::ptr; +use base::ResultExt; impl Default for SuPolicy { fn default() -> Self { @@ -40,11 +39,8 @@ impl MagiskD { fn get_root_settings(&self, uid: i32, settings: &mut RootSettings) -> SqliteResult { self.db_exec_with_rows( "SELECT policy, logging, notification FROM policies \ - WHERE uid=? AND (until=0 OR until>?)", - &[ - Integer(uid as i64), - Integer(unsafe { libc::time(ptr::null_mut()).into() }), - ], + WHERE uid=? AND (until=0 OR until>strftime('%s', 'now'))", + &[Integer(uid as i64)], settings, ) .sql_result() diff --git a/native/src/core/su/su_daemon.cpp b/native/src/core/su/su_daemon.cpp index eac41997d..1ceb7f792 100644 --- a/native/src/core/su/su_daemon.cpp +++ b/native/src/core/su/su_daemon.cpp @@ -111,9 +111,8 @@ bool uid_granted_root(int uid) { } bool granted = false; - db_exec("SELECT policy FROM policies WHERE uid=? AND (until=0 OR until>?)", - { uid, time(nullptr) }, - [&](auto, const DbValues &values) { granted = values.get_int(0) == +SuPolicy::Allow; }); + db_exec("SELECT policy FROM policies WHERE uid=? AND (until=0 OR until>strftime('%s', 'now'))", + { uid }, [&](auto, const DbValues &v) { granted = v.get_int(0) == +SuPolicy::Allow; }); return granted; } @@ -141,9 +140,7 @@ void prune_su_access() { } } for (int uid : rm_uids) { - char query[256]; - ssprintf(query, sizeof(query), "DELETE FROM policies WHERE uid == %d", uid); - db_exec(query); + db_exec("DELETE FROM policies WHERE uid=?", { uid }); } }