Skip to content

Commit ece212d

Browse files
load package_info when startup
load package_info when startup add reload command in supercall
1 parent 955968a commit ece212d

9 files changed

Lines changed: 305 additions & 4 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.vscode/*
22
.history/
3-
3+
.claude
44
**/.DS_Store
55

66
build

kernel/linux/include/uapi/linux/limits.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
1616
#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
1717
#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
18+
#define UINT_MAX 4294967295U
19+
#define INT_MAX 2147483647
20+
#define INT_MIN (-2147483647 - 1)
1821

1922
#define RTSIG_MAX 32
2023

kernel/patch/android/userd.c

Lines changed: 243 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
#include <linux/umh.h>
3333
#include <uapi/scdefs.h>
3434
#include <uapi/linux/stat.h>
35-
35+
#include <sucompat.h>
36+
#include <userd.h>
37+
#include <uapi/linux/limits.h>
3638

3739
#define REPLACE_RC_FILE "/dev/user_init.rc"
3840

@@ -45,6 +47,7 @@
4547
#define MAGISK_SCTX "u:r:magisk:s0"
4648
#define APD_PATH "/data/adb/apd"
4749
#define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy"
50+
#define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config"
4851

4952

5053

@@ -124,6 +127,244 @@ static loff_t kernel_write_file(const char *path, const void *data, loff_t len,
124127
return off;
125128
}
126129

130+
// Simple CSV field parser helper function
131+
static char *parse_csv_field(char **line_ptr)
132+
{
133+
char *start = *line_ptr;
134+
char *end = start;
135+
136+
if (!start || *start == '\0') return NULL;
137+
138+
// Skip leading whitespace
139+
while (*start == ' ' || *start == '\t') start++;
140+
141+
// Find comma or end of line
142+
end = start;
143+
while (*end && *end != ',' && *end != '\n' && *end != '\r') {
144+
end++;
145+
}
146+
147+
// Preserve delimiter before modifying buffer
148+
{
149+
char delim = *end;
150+
151+
// Remove trailing whitespace only if field is non-empty
152+
if (end > start) {
153+
char *trim_end = end - 1;
154+
while (trim_end > start && (*trim_end == ' ' || *trim_end == '\t')) {
155+
trim_end--;
156+
}
157+
*(trim_end + 1) = '\0';
158+
} else {
159+
// Empty field: terminate at start so caller sees an empty string
160+
*start = '\0';
161+
}
162+
163+
// Update pointer position based on original delimiter
164+
if (delim == ',') {
165+
*line_ptr = end + 1;
166+
} else {
167+
*line_ptr = end;
168+
}
169+
}
170+
171+
return start;
172+
}
173+
174+
// Load APatch package_config configuration file
175+
// Returns: number of entries loaded, or negative error code
176+
int load_ap_package_config()
177+
{
178+
loff_t len = 0;
179+
const char *data = kernel_read_file(AP_PACKAGE_CONFIG_PATH, &len);
180+
181+
if (!data || len <= 0) {
182+
log_boot("package_config not found or empty\n");
183+
return -ENOENT;
184+
}
185+
if (len > 10 * 1024 * 1024){
186+
log_boot("package_config too large: %lld\n", len);
187+
return -EFBIG;
188+
}
189+
190+
log_boot("loading package_config, size: %lld\n", len);
191+
192+
char *content = (char *)data;
193+
char *line_start = content;
194+
int line_num = 0;
195+
int loaded_count = 0;
196+
int skipped_count = 0;
197+
198+
// Parse CSV line by line
199+
while (line_start < content + len) {
200+
char *line_end = line_start;
201+
int has_newline = 0;
202+
203+
// Find end of line
204+
while (line_end < content + len && *line_end != '\n' && *line_end != '\r') {
205+
line_end++;
206+
}
207+
208+
// Check if we found a newline
209+
if (line_end < content + len) {
210+
has_newline = 1;
211+
*line_end = '\0'; // Safe because line_end < content + len
212+
}
213+
214+
line_num++;
215+
216+
// Skip CSV header
217+
if (line_num == 1) {
218+
if (has_newline) {
219+
line_start = line_end + 1;
220+
} else {
221+
break;
222+
}
223+
continue;
224+
}
225+
226+
// Process current line
227+
char *line_ptr = line_start;
228+
int valid_line = 1;
229+
230+
// Parse CSV fields: pkg,exclude,allow,uid,to_uid,sctx
231+
parse_csv_field(&line_ptr); // skip pkg field
232+
char *exclude_str = parse_csv_field(&line_ptr);
233+
char *allow_str = parse_csv_field(&line_ptr);
234+
char *uid_str = parse_csv_field(&line_ptr);
235+
char *to_uid_str = parse_csv_field(&line_ptr);
236+
char *sctx = parse_csv_field(&line_ptr);
237+
238+
// Check required fields
239+
if (!uid_str || !to_uid_str || !sctx) {
240+
log_boot("package_config: line %d missing required fields (uid/to_uid/sctx)\n", line_num);
241+
valid_line = 0;
242+
goto next_line;
243+
}
244+
245+
unsigned long long uid_tmp = 0, to_uid_tmp = 0;
246+
unsigned long long exclude_tmp = 0, allow_tmp = 0;
247+
int ret;
248+
249+
// Convert UID fields - must succeed
250+
ret = kstrtoull(uid_str, 10, &uid_tmp);
251+
if (ret) {
252+
log_boot("package_config: line %d invalid uid '%s': %d\n", line_num, uid_str, ret);
253+
valid_line = 0;
254+
goto next_line;
255+
}
256+
257+
ret = kstrtoull(to_uid_str, 10, &to_uid_tmp);
258+
if (ret) {
259+
log_boot("package_config: line %d invalid to_uid '%s': %d\n", line_num, to_uid_str, ret);
260+
valid_line = 0;
261+
goto next_line;
262+
}
263+
264+
// Range check for uid_t (typically unsigned int)
265+
if (uid_tmp > UINT_MAX) {
266+
log_boot("package_config: line %d uid %llu out of range\n", line_num, uid_tmp);
267+
valid_line = 0;
268+
goto next_line;
269+
}
270+
if (to_uid_tmp > UINT_MAX) {
271+
log_boot("package_config: line %d to_uid %llu out of range\n", line_num, to_uid_tmp);
272+
valid_line = 0;
273+
goto next_line;
274+
}
275+
276+
// Convert optional fields (exclude and allow)
277+
if (exclude_str && *exclude_str) {
278+
ret = kstrtoull(exclude_str, 10, &exclude_tmp);
279+
if (ret) {
280+
log_boot("package_config: line %d invalid exclude '%s': %d, using default 0\n",
281+
line_num, exclude_str, ret);
282+
exclude_tmp = 0;
283+
}
284+
if (exclude_tmp > INT_MAX) {
285+
log_boot("package_config: line %d exclude %llu out of range, clamping\n",
286+
line_num, exclude_tmp);
287+
exclude_tmp = INT_MAX;
288+
}
289+
}
290+
291+
if (allow_str && *allow_str) {
292+
ret = kstrtoull(allow_str, 10, &allow_tmp);
293+
if (ret) {
294+
log_boot("package_config: line %d invalid allow '%s': %d, using default 0\n",
295+
line_num, allow_str, ret);
296+
allow_tmp = 0;
297+
}
298+
if (allow_tmp > INT_MAX) {
299+
log_boot("package_config: line %d allow %llu out of range, clamping\n",
300+
line_num, allow_tmp);
301+
allow_tmp = INT_MAX;
302+
}
303+
}
304+
305+
uid_t uid = (uid_t)uid_tmp;
306+
uid_t to_uid = (uid_t)to_uid_tmp;
307+
int exclude = (int)exclude_tmp;
308+
int allow = (int)allow_tmp;
309+
310+
// Validate sctx is not empty
311+
if (!sctx || !*sctx) {
312+
log_boot("package_config: line %d empty sctx\n", line_num);
313+
valid_line = 0;
314+
goto next_line;
315+
}
316+
317+
// CRITICAL FIX: Safely copy sctx into a fixed-size buffer with NUL termination
318+
// This prevents buffer overflow and ensures proper string handling
319+
char sctx_buf[SUPERCALL_SCONTEXT_LEN];
320+
size_t sctx_len = strlen(sctx);
321+
322+
if (sctx_len >= SUPERCALL_SCONTEXT_LEN) {
323+
// Truncate and log warning
324+
log_boot("package_config: line %d sctx too long (%zu bytes), truncating to %d bytes\n",
325+
line_num, sctx_len, SUPERCALL_SCONTEXT_LEN - 1);
326+
memcpy(sctx_buf, sctx, SUPERCALL_SCONTEXT_LEN - 1);
327+
sctx_buf[SUPERCALL_SCONTEXT_LEN - 1] = '\0';
328+
} else {
329+
// Safe copy with NUL termination
330+
memcpy(sctx_buf, sctx, sctx_len + 1); // +1 includes the NUL terminator
331+
}
332+
333+
// Apply configuration with safe sctx buffer
334+
if (allow) {
335+
int rc = su_add_allow_uid(uid, to_uid, sctx_buf);
336+
if (rc == 0) {
337+
loaded_count++;
338+
} else {
339+
log_boot("package_config: line %d failed to add allow rule: %d\n", line_num, rc);
340+
valid_line = 0;
341+
}
342+
}
343+
344+
// Set exclude flag
345+
if (exclude) {
346+
set_ap_mod_exclude(uid, exclude);
347+
}
348+
349+
next_line:
350+
if (!valid_line) {
351+
skipped_count++;
352+
}
353+
354+
// Move to next line
355+
if (has_newline) {
356+
line_start = line_end + 1;
357+
} else {
358+
break;
359+
}
360+
}
361+
362+
kvfree(data);
363+
log_boot("package_config loaded: %d entries, skipped: %d\n", loaded_count, skipped_count);
364+
return loaded_count;
365+
}
366+
KP_EXPORT_SYMBOL(load_ap_package_config);
367+
127368
static void pre_user_exec_init()
128369
{
129370
log_boot("event: %s\n", EXTRA_EVENT_PRE_EXEC_INIT);
@@ -133,6 +374,7 @@ static void pre_user_exec_init()
133374
static void pre_init_second_stage()
134375
{
135376
log_boot("event: %s\n", EXTRA_EVENT_PRE_SECOND_STAGE);
377+
136378
}
137379

138380
static void on_first_app_process()

kernel/patch/common/supercall.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ static long call_su_get_safemode()
198198
logkfd("[call_su_get_safemode] %d\n", result);
199199
return result;
200200
}
201+
202+
extern int load_ap_package_config(void);
203+
static long call_ap_load_package_config()
204+
{
205+
int result = load_ap_package_config();
206+
logkfd("[call_ap_load_package_config] loaded %d entries\n", result);
207+
return result;
208+
}
201209
#endif
202210

203211
static long call_su_list_allow_uid(uid_t *__user uids, int num)
@@ -273,6 +281,10 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3
273281
return kver;
274282
case SUPERCALL_BUILD_TIME:
275283
return call_buildtime((char *__user)arg1, (int)arg2);
284+
#ifdef ANDROID
285+
case SUPERCALL_AP_LOAD_PACKAGE_CONFIG:
286+
return call_ap_load_package_config();
287+
#endif
276288
}
277289

278290
switch (cmd) {

kernel/patch/common/supercmd.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static const char supercmd_help[] =
6868
" version: Print Kernel version and KernelPatch version.\n"
6969
" buildtime: Print KernelPatch build time.\n "
7070
" eg: 50a0a,a06 means kernel version 5.10.10, KernelPatch version 0.10.6.\n"
71+
" reload-cfg: Reload package configuration.\n "
7172
" -c <COMMAND> [...]: Pass a single COMMAND to the default shell.\n"
7273
" exec <PATH> [...]: Execute command with full PATH.\n"
7374
" sumgr <SubCommand> [...]: SU permission manager\n"
@@ -450,6 +451,12 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv)
450451
} else if (!strcmp("buildtime", cmd)) {
451452
cmd_res.msg = get_build_time();
452453
goto echo;
454+
#ifdef ANDROID
455+
} else if (!strcmp("reload-cfg", cmd)) {
456+
load_ap_package_config();
457+
cmd_res.msg = "reload package config success";
458+
goto echo;
459+
#endif
453460
} else if (!strcmp("sumgr", cmd)) {
454461
handle_cmd_sumgr(u_filename_p, carr, buffer, sizeof(buffer), &cmd_res);
455462
} else if (!strcmp("event", cmd)) {

kernel/patch/common/user_event.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,21 @@
44
*/
55

66
#include <user_event.h>
7-
7+
#include <userd.h>
8+
#include <baselib.h>
89
#include <log.h>
910

1011
int report_user_event(const char *event, const char *args)
1112
{
12-
logki("user report event: %s, args: %s\n", event, args);
13+
const char *safe_event = event ? event : "";
14+
const char *safe_args = args ? args : "";
15+
16+
#ifdef ANDROID
17+
if (lib_strcmp(safe_event, "post-fs-data") == 0 && lib_strcmp(safe_args, "before") == 0) {
18+
logki("post-fs-data before event received, loading ap package config ...\n");
19+
load_ap_package_config();
20+
}
21+
#endif
22+
logki("user report event: %s, args: %s\n", safe_event, safe_args);
1323
return 0;
1424
}

kernel/patch/include/uapi/scdefs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ static inline long hash_key(const char *key)
2727
#define SUPERCALL_KERNELPATCH_VER 0x1008
2828
#define SUPERCALL_KERNEL_VER 0x1009
2929

30+
3031
#define SUPERCALL_SKEY_GET 0x100a
3132
#define SUPERCALL_SKEY_SET 0x100b
3233
#define SUPERCALL_SKEY_ROOT_ENABLE 0x100c
34+
#define SUPERCALL_AP_LOAD_PACKAGE_CONFIG 0x100d
3335

3436
#define SUPERCALL_SU 0x1010
3537
#define SUPERCALL_SU_TASK 0x1011 // syscall(__NR_gettid)
@@ -109,6 +111,8 @@ struct su_profile
109111
#define SUPERCALL_SU_RESET_PATH 0x1111
110112
#define SUPERCALL_SU_GET_SAFEMODE 0x1112
111113

114+
115+
112116
#define SUPERCALL_MAX 0x1200
113117

114118
#define SUPERCALL_RES_SUCCEED 0

kernel/patch/include/userd.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Copyright (C) 2024 bmax121. All Rights Reserved.
4+
*/
5+
6+
#ifndef _KP_USERD_H_
7+
#define _KP_USERD_H_
8+
9+
int load_ap_package_config(void);
10+
11+
#endif

0 commit comments

Comments
 (0)