Skip to content

Commit ac4bbae

Browse files
acroreiserbackslashxx
authored andcommitted
kernel: throne_tracker: move throne_tracker to kthread with spinlocks
Run throne_tracker() in kthread instead of blocking the caller. Prevents full lockup during installation and removing the manager. First run remains synchronous for compatibility purposes. Changes: - look for manager UID in /data/system/packages.list - run track_throne() in a kthread after the first synchronous run - prevents duplicate thread creation with a single-instance check - use spinlock-based access control (spin_trylock/spin_unlock), instead of mutex - add missing path_put() - add smp_mb around single instance check Based on the following changes: `kernelsu: move throne_tracker() to kthread` - acroreiser/android_kernel_lge_hammerhead@8783bad `kernelsu: check locking before accessing files and dirs during searching manager` - acroreiser/android_kernel_lge_hammerhead@b8a00ee `kernelsu: look for manager UID in /data/system/packages.list, not /data/system/packages.list.tmp` - acroreiser/android_kernel_lge_hammerhead@0b05e92 Signed-off-by: backslashxx <[email protected]>
1 parent 10bd614 commit ac4bbae

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

kernel/apk_sign.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ static __always_inline bool check_v2_signature(char *path,
187187
bool v3_1_signing_exist = false;
188188

189189
int i;
190+
struct path kpath;
191+
if (kern_path(path, 0, &kpath))
192+
return false;
193+
194+
if (!spin_trylock(&kpath.dentry->d_lock)) {
195+
path_put(&kpath);
196+
return false;
197+
}
198+
spin_unlock(&kpath.dentry->d_lock);
199+
path_put(&kpath);
200+
190201
struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0);
191202
if (IS_ERR(fp)) {
192203
pr_err("open %s error.\n", path);

kernel/throne_tracker.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
#include "throne_tracker.h"
1414
#include "kernel_compat.h"
1515

16+
#include <linux/kthread.h>
17+
#include <linux/sched.h>
18+
1619
uid_t ksu_manager_uid = KSU_INVALID_UID;
1720

18-
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list.tmp"
21+
static struct task_struct *throne_thread;
22+
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
1923

2024
struct uid_data {
2125
struct list_head list;
@@ -243,6 +247,17 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
243247
.depth = pos->depth,
244248
.stop = &stop };
245249
struct file *file;
250+
struct path kpath;
251+
252+
if (kern_path(path, 0, &kpath))
253+
goto skip_iterate;
254+
255+
if (!spin_trylock(&kpath.dentry->d_lock)) {
256+
path_put(&kpath);
257+
goto skip_iterate;
258+
}
259+
spin_unlock(&kpath.dentry->d_lock);
260+
path_put(&kpath);
246261

247262
if (!stop) {
248263
file = ksu_filp_open_compat(pos->dirpath, O_RDONLY | O_NOFOLLOW, 0);
@@ -302,7 +317,7 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
302317
return exist;
303318
}
304319

305-
void track_throne()
320+
static void track_throne_function()
306321
{
307322
struct file *fp =
308323
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
@@ -397,6 +412,37 @@ void track_throne()
397412
}
398413
}
399414

415+
static int throne_tracker_thread(void *data)
416+
{
417+
pr_info("%s: pid: %d started\n", __func__, current->pid);
418+
track_throne_function();
419+
throne_thread = NULL;
420+
smp_mb();
421+
pr_info("%s: pid: %d exit!\n", __func__, current->pid);
422+
return 0;
423+
}
424+
425+
void track_throne()
426+
{
427+
static bool throne_tracker_first_run = true;
428+
if (throne_tracker_first_run) {
429+
// be locking on first run, workaround for some kernels
430+
track_throne_function();
431+
throne_tracker_first_run = false;
432+
return;
433+
}
434+
435+
smp_mb();
436+
if (throne_thread != NULL) // single instance lock
437+
return;
438+
439+
throne_thread = kthread_run(throne_tracker_thread, NULL, "throne_tracker");
440+
if (IS_ERR(throne_thread)) {
441+
throne_thread = NULL;
442+
return;
443+
}
444+
}
445+
400446
void ksu_throne_tracker_init()
401447
{
402448
// nothing to do

0 commit comments

Comments
 (0)