@@ -11,20 +11,27 @@ namespace SoList {
11
11
class SoInfo {
12
12
public:
13
13
#ifdef __LP64__
14
- inline static size_t solist_next_offset = 0x30 ;
14
+ inline static size_t solist_size_offset = 0x18 ;
15
+ inline static size_t solist_next_offset = 0x28 ;
15
16
constexpr static size_t solist_realpath_offset = 0x1a8 ;
16
17
#else
18
+ inline static size_t solist_size_offset = 0x90 ;
17
19
inline static size_t solist_next_offset = 0xa4 ;
18
20
constexpr static size_t solist_realpath_offset = 0x174 ;
19
21
#endif
20
22
21
23
inline static const char *(*get_realpath_sym)(SoInfo *) = NULL ;
22
24
inline static const char *(*get_soname_sym)(SoInfo *) = NULL ;
25
+ inline static void (*soinfo_free)(SoInfo *) = NULL;
23
26
24
27
inline SoInfo *get_next () {
25
28
return *(SoInfo **) ((uintptr_t ) this + solist_next_offset);
26
29
}
27
30
31
+ inline size_t get_size () {
32
+ return *(size_t *) ((uintptr_t ) this + solist_size_offset);
33
+ }
34
+
28
35
inline const char *get_path () {
29
36
if (get_realpath_sym) return get_realpath_sym (this );
30
37
@@ -40,6 +47,10 @@ namespace SoList {
40
47
void set_next (SoInfo *si) {
41
48
*(SoInfo **) ((uintptr_t ) this + solist_next_offset) = si;
42
49
}
50
+
51
+ void set_size (size_t size) {
52
+ *(size_t *) ((uintptr_t ) this + solist_size_offset) = size;
53
+ }
43
54
};
44
55
45
56
class ProtectedDataGuard {
@@ -69,8 +80,8 @@ namespace SoList {
69
80
private:
70
81
using FuncType = void (ProtectedDataGuard::*)();
71
82
72
- static FuncType ctor;
73
- static FuncType dtor;
83
+ inline static FuncType ctor = NULL ;
84
+ inline static FuncType dtor = NULL ;
74
85
75
86
union MemFunc {
76
87
FuncType f;
@@ -86,8 +97,9 @@ namespace SoList {
86
97
static SoInfo *solist = NULL ;
87
98
static SoInfo *somain = NULL ;
88
99
static SoInfo **sonext = NULL ;
89
- ProtectedDataGuard::FuncType ProtectedDataGuard::ctor = NULL ;
90
- ProtectedDataGuard::FuncType ProtectedDataGuard::dtor = NULL ;
100
+
101
+ static uint64_t *g_module_load_counter = NULL ;
102
+ static uint64_t *g_module_unload_counter = NULL ;
91
103
92
104
static bool Initialize ();
93
105
@@ -98,28 +110,51 @@ namespace SoList {
98
110
return addr == NULL ? NULL : *addr;
99
111
}
100
112
101
- static void DropSoPath (const char * target_path) {
113
+ static bool DropSoPath (const char * target_path) {
114
+ bool path_found = false ;
102
115
if (solist == NULL && !Initialize ()) {
103
116
LOGE (" Failed to initialize solist" );
104
- return ;
117
+ return path_found ;
105
118
}
106
- SoInfo *prev = NULL ;
107
119
for (auto iter = solist; iter; iter = iter->get_next ()) {
108
- if (prev != NULL && iter->get_name () && iter->get_path () && strstr (iter->get_path (), target_path)) {
120
+ if (iter->get_name () && iter->get_path () && strstr (iter->get_path (), target_path)) {
109
121
SoList::ProtectedDataGuard guard;
110
- prev->set_next (iter->get_next ());
111
- if (iter == *sonext) {
112
- *sonext = prev;
122
+ LOGI (" dropping solist record for %s loaded at %s with size %zu" , iter->get_name (), iter->get_path (), iter->get_size ());
123
+ if (iter->get_size () > 0 ) {
124
+ iter->set_size (0 );
125
+ SoInfo::soinfo_free (iter);
126
+ path_found = true ;
113
127
}
114
- LOGI (" Dropped solist record for %s loaded at %s" , iter->get_name (), iter->get_path ());
115
128
}
116
- prev = iter;
129
+ }
130
+ return path_found;
131
+ }
132
+
133
+ static void ResetCounters (size_t load, size_t unload) {
134
+ if (solist == NULL && !Initialize ()) {
135
+ LOGE (" Failed to initialize solist" );
136
+ return ;
137
+ }
138
+ if (g_module_load_counter == NULL || g_module_unload_counter == NULL ) {
139
+ LOGI (" g_module counters not defined, skip reseting them" );
140
+ return ;
141
+ }
142
+ auto loaded_modules = *g_module_load_counter;
143
+ auto unloaded_modules = *g_module_unload_counter;
144
+ if (loaded_modules >= load) {
145
+ *g_module_load_counter = loaded_modules - load;
146
+ LOGD (" reset g_module_load_counter to %zu" , (size_t ) *g_module_load_counter);
147
+ }
148
+ if (unloaded_modules >= unload) {
149
+ *g_module_unload_counter = unloaded_modules - unload;
150
+ LOGD (" reset g_module_unload_counter to %zu" , (size_t ) *g_module_unload_counter);
117
151
}
118
152
}
119
153
120
154
static bool Initialize () {
121
155
SandHook::ElfImg linker (" /linker" );
122
156
if (!ProtectedDataGuard::setup (linker)) return false ;
157
+ LOGD (" found symbol ProtectedDataGuard" );
123
158
124
159
/* INFO: Since Android 15, the symbol names for the linker have a suffix,
125
160
this makes it impossible to hardcode the symbol names. To allow
@@ -131,6 +166,11 @@ namespace SoList {
131
166
132
167
std::string_view solist_sym_name = linker.findSymbolNameByPrefix (" __dl__ZL6solist" );
133
168
if (solist_sym_name.empty ()) return false ;
169
+ LOGD (" found symbol name %s" , solist_sym_name.data ());
170
+
171
+ std::string_view soinfo_free_name = linker.findSymbolNameByPrefix (" __dl__ZL11soinfo_freeP6soinfo" );
172
+ if (soinfo_free_name.empty ()) return false ;
173
+ LOGD (" found symbol name %s" , soinfo_free_name.data ());
134
174
135
175
/* INFO: The size isn't a magic number, it's the size for the string: .llvm.7690929523238822858 */
136
176
char llvm_sufix[25 + 1 ];
@@ -143,37 +183,60 @@ namespace SoList {
143
183
144
184
solist = getStaticPointer<SoInfo>(linker, solist_sym_name.data ());
145
185
if (solist == NULL ) return false ;
186
+ LOGD (" found symbol solist" );
146
187
147
188
char somain_sym_name[sizeof (" __dl__ZL6somain" ) + sizeof (llvm_sufix)];
148
189
snprintf (somain_sym_name, sizeof (somain_sym_name), " __dl__ZL6somain%s" , llvm_sufix);
149
190
150
191
char sonext_sym_name[sizeof (" __dl__ZL6sonext" ) + sizeof (llvm_sufix)];
151
192
snprintf (sonext_sym_name, sizeof (somain_sym_name), " __dl__ZL6sonext%s" , llvm_sufix);
152
193
153
- char vsdo_sym_name [sizeof (" __dl__ZL4vdso" ) + sizeof (llvm_sufix)];
154
- snprintf (vsdo_sym_name , sizeof (vsdo_sym_name ), " __dl__ZL4vdso%s" , llvm_sufix);
194
+ char vdso_sym_name [sizeof (" __dl__ZL4vdso" ) + sizeof (llvm_sufix)];
195
+ snprintf (vdso_sym_name , sizeof (vdso_sym_name ), " __dl__ZL4vdso%s" , llvm_sufix);
155
196
156
197
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
157
198
if (somain == NULL ) return false ;
199
+ LOGD (" found symbol somain" );
158
200
159
201
sonext = linker.getSymbAddress <SoInfo **>(sonext_sym_name);
160
202
if (sonext == NULL ) return false ;
203
+ LOGD (" found symbol sonext" );
161
204
162
- SoInfo *vsdo = getStaticPointer<SoInfo>(linker, vsdo_sym_name );
163
- if (vsdo == NULL ) return false ;
205
+ SoInfo *vdso = getStaticPointer<SoInfo>(linker, vdso_sym_name );
206
+ if (vdso != NULL ) LOGD ( " found symbol vdso " ) ;
164
207
165
208
SoInfo::get_realpath_sym = reinterpret_cast <decltype (SoInfo::get_realpath_sym)>(linker.getSymbAddress (" __dl__ZNK6soinfo12get_realpathEv" ));
209
+ if (SoInfo::get_realpath_sym == NULL ) return false ;
210
+ LOGD (" found symbol get_realpath_sym" );
211
+
166
212
SoInfo::get_soname_sym = reinterpret_cast <decltype (SoInfo::get_soname_sym)>(linker.getSymbAddress (" __dl__ZNK6soinfo10get_sonameEv" ));
213
+ if (SoInfo::get_soname_sym == NULL ) return false ;
214
+ LOGD (" found symbol get_soname_sym" );
215
+
216
+ SoInfo::soinfo_free = reinterpret_cast <decltype (SoInfo::soinfo_free)>(linker.getSymbAddress (soinfo_free_name));
217
+ if (SoInfo::soinfo_free == NULL ) return false ;
218
+ LOGD (" found symbol soinfo_free" );
219
+
220
+ g_module_load_counter = reinterpret_cast <decltype (g_module_load_counter)>(linker.getSymbAddress (" __dl__ZL21g_module_load_counter" ));
221
+ if (g_module_load_counter != NULL ) LOGD (" found symbol g_module_load_counter" );
222
+
223
+ g_module_unload_counter = reinterpret_cast <decltype (g_module_unload_counter)>(linker.getSymbAddress (" __dl__ZL23g_module_unload_counter" ));
224
+ if (g_module_unload_counter != NULL ) LOGD (" found symbol g_module_unload_counter" );
167
225
168
226
for (size_t i = 0 ; i < 1024 / sizeof (void *); i++) {
169
- auto *possible_next = *(void **) ((uintptr_t ) solist + i * sizeof (void *));
170
- if (possible_next == somain || (vsdo != NULL && possible_next == vsdo)) {
227
+ auto possible_field = (uintptr_t ) solist + i * sizeof (void *);
228
+ auto possible_size_of_somain = *(size_t *)((uintptr_t ) somain + i * sizeof (void *));
229
+ if (possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100 ) {
230
+ SoInfo::solist_size_offset = i * sizeof (void *);
231
+ LOGD (" solist_size_offset is %zu * %zu = %p" , i, sizeof (void *), (void *) SoInfo::solist_size_offset);
232
+ }
233
+ if (*(void **)possible_field == somain || (vdso != NULL && *(void **)possible_field == vdso)) {
171
234
SoInfo::solist_next_offset = i * sizeof (void *);
172
-
235
+ LOGD ( " solist_next_offset is %zu * %zu = %p " , i, sizeof ( void *), ( void *) SoInfo::solist_next_offset);
173
236
break ;
174
237
}
175
238
}
176
239
177
- return (SoInfo::get_realpath_sym != NULL && SoInfo::get_soname_sym != NULL ) ;
240
+ return true ;
178
241
}
179
242
}
0 commit comments