1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2012-2013 ProFUSION embedded systems
3*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2012-2013 Lucas De Marchi <[email protected]>
4*cc4ad7daSAndroid Build Coastguard Worker *
5*cc4ad7daSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
6*cc4ad7daSAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
7*cc4ad7daSAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
8*cc4ad7daSAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
9*cc4ad7daSAndroid Build Coastguard Worker *
10*cc4ad7daSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*cc4ad7daSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*cc4ad7daSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13*cc4ad7daSAndroid Build Coastguard Worker * Lesser General Public License for more details.
14*cc4ad7daSAndroid Build Coastguard Worker *
15*cc4ad7daSAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
16*cc4ad7daSAndroid Build Coastguard Worker * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17*cc4ad7daSAndroid Build Coastguard Worker */
18*cc4ad7daSAndroid Build Coastguard Worker
19*cc4ad7daSAndroid Build Coastguard Worker #ifndef HAVE_FINIT_MODULE
20*cc4ad7daSAndroid Build Coastguard Worker #define HAVE_FINIT_MODULE 1
21*cc4ad7daSAndroid Build Coastguard Worker #endif
22*cc4ad7daSAndroid Build Coastguard Worker
23*cc4ad7daSAndroid Build Coastguard Worker #include <assert.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <dlfcn.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <elf.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <fcntl.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <stddef.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
34*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
35*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
36*cc4ad7daSAndroid Build Coastguard Worker #include <sys/mman.h>
37*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
38*cc4ad7daSAndroid Build Coastguard Worker #include <sys/syscall.h>
39*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
40*cc4ad7daSAndroid Build Coastguard Worker #include <sys/utsname.h>
41*cc4ad7daSAndroid Build Coastguard Worker
42*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
43*cc4ad7daSAndroid Build Coastguard Worker
44*cc4ad7daSAndroid Build Coastguard Worker /* kmod_elf_get_section() is not exported, we need the private header */
45*cc4ad7daSAndroid Build Coastguard Worker #include <libkmod/libkmod-internal.h>
46*cc4ad7daSAndroid Build Coastguard Worker
47*cc4ad7daSAndroid Build Coastguard Worker /* FIXME: hack, change name so we don't clash */
48*cc4ad7daSAndroid Build Coastguard Worker #undef ERR
49*cc4ad7daSAndroid Build Coastguard Worker #include "testsuite.h"
50*cc4ad7daSAndroid Build Coastguard Worker #include "stripped-module.h"
51*cc4ad7daSAndroid Build Coastguard Worker
52*cc4ad7daSAndroid Build Coastguard Worker struct mod {
53*cc4ad7daSAndroid Build Coastguard Worker struct mod *next;
54*cc4ad7daSAndroid Build Coastguard Worker int ret;
55*cc4ad7daSAndroid Build Coastguard Worker int errcode;
56*cc4ad7daSAndroid Build Coastguard Worker char name[];
57*cc4ad7daSAndroid Build Coastguard Worker };
58*cc4ad7daSAndroid Build Coastguard Worker
59*cc4ad7daSAndroid Build Coastguard Worker static struct mod *modules;
60*cc4ad7daSAndroid Build Coastguard Worker static bool need_init = true;
61*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_ctx *ctx;
62*cc4ad7daSAndroid Build Coastguard Worker
parse_retcodes(struct mod * _modules,const char * s)63*cc4ad7daSAndroid Build Coastguard Worker static void parse_retcodes(struct mod *_modules, const char *s)
64*cc4ad7daSAndroid Build Coastguard Worker {
65*cc4ad7daSAndroid Build Coastguard Worker const char *p;
66*cc4ad7daSAndroid Build Coastguard Worker
67*cc4ad7daSAndroid Build Coastguard Worker if (s == NULL)
68*cc4ad7daSAndroid Build Coastguard Worker return;
69*cc4ad7daSAndroid Build Coastguard Worker
70*cc4ad7daSAndroid Build Coastguard Worker for (p = s;;) {
71*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
72*cc4ad7daSAndroid Build Coastguard Worker const char *modname;
73*cc4ad7daSAndroid Build Coastguard Worker char *end;
74*cc4ad7daSAndroid Build Coastguard Worker size_t modnamelen;
75*cc4ad7daSAndroid Build Coastguard Worker int ret, errcode;
76*cc4ad7daSAndroid Build Coastguard Worker long l;
77*cc4ad7daSAndroid Build Coastguard Worker
78*cc4ad7daSAndroid Build Coastguard Worker modname = p;
79*cc4ad7daSAndroid Build Coastguard Worker if (modname == NULL || modname[0] == '\0')
80*cc4ad7daSAndroid Build Coastguard Worker break;
81*cc4ad7daSAndroid Build Coastguard Worker
82*cc4ad7daSAndroid Build Coastguard Worker modnamelen = strcspn(s, ":");
83*cc4ad7daSAndroid Build Coastguard Worker if (modname[modnamelen] != ':')
84*cc4ad7daSAndroid Build Coastguard Worker break;
85*cc4ad7daSAndroid Build Coastguard Worker
86*cc4ad7daSAndroid Build Coastguard Worker p = modname + modnamelen + 1;
87*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL)
88*cc4ad7daSAndroid Build Coastguard Worker break;
89*cc4ad7daSAndroid Build Coastguard Worker
90*cc4ad7daSAndroid Build Coastguard Worker l = strtol(p, &end, 0);
91*cc4ad7daSAndroid Build Coastguard Worker if (end == p || *end != ':')
92*cc4ad7daSAndroid Build Coastguard Worker break;
93*cc4ad7daSAndroid Build Coastguard Worker ret = (int) l;
94*cc4ad7daSAndroid Build Coastguard Worker p = end + 1;
95*cc4ad7daSAndroid Build Coastguard Worker
96*cc4ad7daSAndroid Build Coastguard Worker l = strtol(p, &end, 0);
97*cc4ad7daSAndroid Build Coastguard Worker if (*end == ':')
98*cc4ad7daSAndroid Build Coastguard Worker p = end + 1;
99*cc4ad7daSAndroid Build Coastguard Worker else if (*end != '\0')
100*cc4ad7daSAndroid Build Coastguard Worker break;
101*cc4ad7daSAndroid Build Coastguard Worker
102*cc4ad7daSAndroid Build Coastguard Worker errcode = (int) l;
103*cc4ad7daSAndroid Build Coastguard Worker
104*cc4ad7daSAndroid Build Coastguard Worker mod = malloc(sizeof(*mod) + modnamelen + 1);
105*cc4ad7daSAndroid Build Coastguard Worker if (mod == NULL)
106*cc4ad7daSAndroid Build Coastguard Worker break;
107*cc4ad7daSAndroid Build Coastguard Worker
108*cc4ad7daSAndroid Build Coastguard Worker memcpy(mod->name, modname, modnamelen);
109*cc4ad7daSAndroid Build Coastguard Worker mod->name[modnamelen] = '\0';
110*cc4ad7daSAndroid Build Coastguard Worker mod->ret = ret;
111*cc4ad7daSAndroid Build Coastguard Worker mod->errcode = errcode;
112*cc4ad7daSAndroid Build Coastguard Worker mod->next = _modules;
113*cc4ad7daSAndroid Build Coastguard Worker _modules = mod;
114*cc4ad7daSAndroid Build Coastguard Worker }
115*cc4ad7daSAndroid Build Coastguard Worker }
116*cc4ad7daSAndroid Build Coastguard Worker
write_one_line_file(const char * fn,const char * line,int len)117*cc4ad7daSAndroid Build Coastguard Worker static int write_one_line_file(const char *fn, const char *line, int len)
118*cc4ad7daSAndroid Build Coastguard Worker {
119*cc4ad7daSAndroid Build Coastguard Worker FILE *f;
120*cc4ad7daSAndroid Build Coastguard Worker int r;
121*cc4ad7daSAndroid Build Coastguard Worker
122*cc4ad7daSAndroid Build Coastguard Worker assert(fn);
123*cc4ad7daSAndroid Build Coastguard Worker assert(line);
124*cc4ad7daSAndroid Build Coastguard Worker
125*cc4ad7daSAndroid Build Coastguard Worker f = fopen(fn, "we");
126*cc4ad7daSAndroid Build Coastguard Worker if (!f)
127*cc4ad7daSAndroid Build Coastguard Worker return -errno;
128*cc4ad7daSAndroid Build Coastguard Worker
129*cc4ad7daSAndroid Build Coastguard Worker errno = 0;
130*cc4ad7daSAndroid Build Coastguard Worker if (fputs(line, f) < 0) {
131*cc4ad7daSAndroid Build Coastguard Worker r = -errno;
132*cc4ad7daSAndroid Build Coastguard Worker goto finish;
133*cc4ad7daSAndroid Build Coastguard Worker }
134*cc4ad7daSAndroid Build Coastguard Worker
135*cc4ad7daSAndroid Build Coastguard Worker fflush(f);
136*cc4ad7daSAndroid Build Coastguard Worker
137*cc4ad7daSAndroid Build Coastguard Worker if (ferror(f)) {
138*cc4ad7daSAndroid Build Coastguard Worker if (errno != 0)
139*cc4ad7daSAndroid Build Coastguard Worker r = -errno;
140*cc4ad7daSAndroid Build Coastguard Worker else
141*cc4ad7daSAndroid Build Coastguard Worker r = -EIO;
142*cc4ad7daSAndroid Build Coastguard Worker } else
143*cc4ad7daSAndroid Build Coastguard Worker r = 0;
144*cc4ad7daSAndroid Build Coastguard Worker
145*cc4ad7daSAndroid Build Coastguard Worker finish:
146*cc4ad7daSAndroid Build Coastguard Worker fclose(f);
147*cc4ad7daSAndroid Build Coastguard Worker return r;
148*cc4ad7daSAndroid Build Coastguard Worker }
149*cc4ad7daSAndroid Build Coastguard Worker
create_sysfs_files(const char * modname)150*cc4ad7daSAndroid Build Coastguard Worker static int create_sysfs_files(const char *modname)
151*cc4ad7daSAndroid Build Coastguard Worker {
152*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX];
153*cc4ad7daSAndroid Build Coastguard Worker const char *sysfsmod = "/sys/module/";
154*cc4ad7daSAndroid Build Coastguard Worker int len = strlen(sysfsmod);
155*cc4ad7daSAndroid Build Coastguard Worker
156*cc4ad7daSAndroid Build Coastguard Worker memcpy(buf, sysfsmod, len);
157*cc4ad7daSAndroid Build Coastguard Worker strcpy(buf + len, modname);
158*cc4ad7daSAndroid Build Coastguard Worker len += strlen(modname);
159*cc4ad7daSAndroid Build Coastguard Worker
160*cc4ad7daSAndroid Build Coastguard Worker assert(mkdir_p(buf, len, 0755) >= 0);
161*cc4ad7daSAndroid Build Coastguard Worker
162*cc4ad7daSAndroid Build Coastguard Worker strcpy(buf + len, "/initstate");
163*cc4ad7daSAndroid Build Coastguard Worker return write_one_line_file(buf, "live\n", strlen("live\n"));
164*cc4ad7daSAndroid Build Coastguard Worker }
165*cc4ad7daSAndroid Build Coastguard Worker
find_module(struct mod * _modules,const char * modname)166*cc4ad7daSAndroid Build Coastguard Worker static struct mod *find_module(struct mod *_modules, const char *modname)
167*cc4ad7daSAndroid Build Coastguard Worker {
168*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
169*cc4ad7daSAndroid Build Coastguard Worker
170*cc4ad7daSAndroid Build Coastguard Worker for (mod = _modules; mod != NULL; mod = mod->next) {
171*cc4ad7daSAndroid Build Coastguard Worker if (streq(mod->name, modname))
172*cc4ad7daSAndroid Build Coastguard Worker return mod;
173*cc4ad7daSAndroid Build Coastguard Worker }
174*cc4ad7daSAndroid Build Coastguard Worker
175*cc4ad7daSAndroid Build Coastguard Worker return NULL;
176*cc4ad7daSAndroid Build Coastguard Worker }
177*cc4ad7daSAndroid Build Coastguard Worker
init_retcodes(void)178*cc4ad7daSAndroid Build Coastguard Worker static void init_retcodes(void)
179*cc4ad7daSAndroid Build Coastguard Worker {
180*cc4ad7daSAndroid Build Coastguard Worker const char *s;
181*cc4ad7daSAndroid Build Coastguard Worker
182*cc4ad7daSAndroid Build Coastguard Worker if (!need_init)
183*cc4ad7daSAndroid Build Coastguard Worker return;
184*cc4ad7daSAndroid Build Coastguard Worker
185*cc4ad7daSAndroid Build Coastguard Worker need_init = false;
186*cc4ad7daSAndroid Build Coastguard Worker s = getenv(S_TC_INIT_MODULE_RETCODES);
187*cc4ad7daSAndroid Build Coastguard Worker if (s == NULL) {
188*cc4ad7daSAndroid Build Coastguard Worker fprintf(stderr, "TRAP init_module(): missing export %s?\n",
189*cc4ad7daSAndroid Build Coastguard Worker S_TC_INIT_MODULE_RETCODES);
190*cc4ad7daSAndroid Build Coastguard Worker }
191*cc4ad7daSAndroid Build Coastguard Worker
192*cc4ad7daSAndroid Build Coastguard Worker ctx = kmod_new(NULL, NULL);
193*cc4ad7daSAndroid Build Coastguard Worker
194*cc4ad7daSAndroid Build Coastguard Worker parse_retcodes(modules, s);
195*cc4ad7daSAndroid Build Coastguard Worker }
196*cc4ad7daSAndroid Build Coastguard Worker
module_is_inkernel(const char * modname)197*cc4ad7daSAndroid Build Coastguard Worker static inline bool module_is_inkernel(const char *modname)
198*cc4ad7daSAndroid Build Coastguard Worker {
199*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *mod;
200*cc4ad7daSAndroid Build Coastguard Worker int state;
201*cc4ad7daSAndroid Build Coastguard Worker bool ret;
202*cc4ad7daSAndroid Build Coastguard Worker
203*cc4ad7daSAndroid Build Coastguard Worker if (kmod_module_new_from_name(ctx, modname, &mod) < 0)
204*cc4ad7daSAndroid Build Coastguard Worker return false;
205*cc4ad7daSAndroid Build Coastguard Worker
206*cc4ad7daSAndroid Build Coastguard Worker state = kmod_module_get_initstate(mod);
207*cc4ad7daSAndroid Build Coastguard Worker
208*cc4ad7daSAndroid Build Coastguard Worker if (state == KMOD_MODULE_LIVE ||
209*cc4ad7daSAndroid Build Coastguard Worker state == KMOD_MODULE_BUILTIN)
210*cc4ad7daSAndroid Build Coastguard Worker ret = true;
211*cc4ad7daSAndroid Build Coastguard Worker else
212*cc4ad7daSAndroid Build Coastguard Worker ret = false;
213*cc4ad7daSAndroid Build Coastguard Worker
214*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(mod);
215*cc4ad7daSAndroid Build Coastguard Worker
216*cc4ad7daSAndroid Build Coastguard Worker return ret;
217*cc4ad7daSAndroid Build Coastguard Worker }
218*cc4ad7daSAndroid Build Coastguard Worker
elf_identify(void * mem)219*cc4ad7daSAndroid Build Coastguard Worker static uint8_t elf_identify(void *mem)
220*cc4ad7daSAndroid Build Coastguard Worker {
221*cc4ad7daSAndroid Build Coastguard Worker uint8_t *p = mem;
222*cc4ad7daSAndroid Build Coastguard Worker return p[EI_CLASS];
223*cc4ad7daSAndroid Build Coastguard Worker }
224*cc4ad7daSAndroid Build Coastguard Worker
225*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT long init_module(void *mem, unsigned long len, const char *args);
226*cc4ad7daSAndroid Build Coastguard Worker
227*cc4ad7daSAndroid Build Coastguard Worker /*
228*cc4ad7daSAndroid Build Coastguard Worker * Default behavior is to try to mimic init_module behavior inside the kernel.
229*cc4ad7daSAndroid Build Coastguard Worker * If it is a simple test that you know the error code, set the return code
230*cc4ad7daSAndroid Build Coastguard Worker * in TESTSUITE_INIT_MODULE_RETCODES env var instead.
231*cc4ad7daSAndroid Build Coastguard Worker *
232*cc4ad7daSAndroid Build Coastguard Worker * The exception is when the module name is not find in the memory passed.
233*cc4ad7daSAndroid Build Coastguard Worker * This is because we want to be able to pass dummy modules (and not real
234*cc4ad7daSAndroid Build Coastguard Worker * ones) and it still work.
235*cc4ad7daSAndroid Build Coastguard Worker */
init_module(void * mem,unsigned long len,const char * args)236*cc4ad7daSAndroid Build Coastguard Worker long init_module(void *mem, unsigned long len, const char *args)
237*cc4ad7daSAndroid Build Coastguard Worker {
238*cc4ad7daSAndroid Build Coastguard Worker const char *modname;
239*cc4ad7daSAndroid Build Coastguard Worker struct kmod_elf *elf;
240*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
241*cc4ad7daSAndroid Build Coastguard Worker const void *buf;
242*cc4ad7daSAndroid Build Coastguard Worker uint64_t bufsize;
243*cc4ad7daSAndroid Build Coastguard Worker int err;
244*cc4ad7daSAndroid Build Coastguard Worker uint8_t class;
245*cc4ad7daSAndroid Build Coastguard Worker off_t offset;
246*cc4ad7daSAndroid Build Coastguard Worker
247*cc4ad7daSAndroid Build Coastguard Worker init_retcodes();
248*cc4ad7daSAndroid Build Coastguard Worker
249*cc4ad7daSAndroid Build Coastguard Worker elf = kmod_elf_new(mem, len);
250*cc4ad7daSAndroid Build Coastguard Worker if (elf == NULL)
251*cc4ad7daSAndroid Build Coastguard Worker return 0;
252*cc4ad7daSAndroid Build Coastguard Worker
253*cc4ad7daSAndroid Build Coastguard Worker err = kmod_elf_get_section(elf, ".gnu.linkonce.this_module", &buf,
254*cc4ad7daSAndroid Build Coastguard Worker &bufsize);
255*cc4ad7daSAndroid Build Coastguard Worker kmod_elf_unref(elf);
256*cc4ad7daSAndroid Build Coastguard Worker
257*cc4ad7daSAndroid Build Coastguard Worker /* We couldn't parse the ELF file. Just exit as if it was successful */
258*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
259*cc4ad7daSAndroid Build Coastguard Worker return 0;
260*cc4ad7daSAndroid Build Coastguard Worker
261*cc4ad7daSAndroid Build Coastguard Worker /* We need to open both 32 and 64 bits module - hack! */
262*cc4ad7daSAndroid Build Coastguard Worker class = elf_identify(mem);
263*cc4ad7daSAndroid Build Coastguard Worker if (class == ELFCLASS64)
264*cc4ad7daSAndroid Build Coastguard Worker offset = MODULE_NAME_OFFSET_64;
265*cc4ad7daSAndroid Build Coastguard Worker else
266*cc4ad7daSAndroid Build Coastguard Worker offset = MODULE_NAME_OFFSET_32;
267*cc4ad7daSAndroid Build Coastguard Worker
268*cc4ad7daSAndroid Build Coastguard Worker modname = (char *)buf + offset;
269*cc4ad7daSAndroid Build Coastguard Worker mod = find_module(modules, modname);
270*cc4ad7daSAndroid Build Coastguard Worker if (mod != NULL) {
271*cc4ad7daSAndroid Build Coastguard Worker errno = mod->errcode;
272*cc4ad7daSAndroid Build Coastguard Worker err = mod->ret;
273*cc4ad7daSAndroid Build Coastguard Worker } else if (module_is_inkernel(modname)) {
274*cc4ad7daSAndroid Build Coastguard Worker err = -1;
275*cc4ad7daSAndroid Build Coastguard Worker errno = EEXIST;
276*cc4ad7daSAndroid Build Coastguard Worker } else
277*cc4ad7daSAndroid Build Coastguard Worker err = 0;
278*cc4ad7daSAndroid Build Coastguard Worker
279*cc4ad7daSAndroid Build Coastguard Worker if (err == 0)
280*cc4ad7daSAndroid Build Coastguard Worker create_sysfs_files(modname);
281*cc4ad7daSAndroid Build Coastguard Worker
282*cc4ad7daSAndroid Build Coastguard Worker return err;
283*cc4ad7daSAndroid Build Coastguard Worker }
284*cc4ad7daSAndroid Build Coastguard Worker
check_kernel_version(int major,int minor)285*cc4ad7daSAndroid Build Coastguard Worker static int check_kernel_version(int major, int minor)
286*cc4ad7daSAndroid Build Coastguard Worker {
287*cc4ad7daSAndroid Build Coastguard Worker struct utsname u;
288*cc4ad7daSAndroid Build Coastguard Worker const char *p;
289*cc4ad7daSAndroid Build Coastguard Worker int maj = 0, min = 0;
290*cc4ad7daSAndroid Build Coastguard Worker
291*cc4ad7daSAndroid Build Coastguard Worker if (uname(&u) < 0)
292*cc4ad7daSAndroid Build Coastguard Worker return false;
293*cc4ad7daSAndroid Build Coastguard Worker for (p = u.release; *p >= '0' && *p <= '9'; p++)
294*cc4ad7daSAndroid Build Coastguard Worker maj = maj * 10 + *p - '0';
295*cc4ad7daSAndroid Build Coastguard Worker if (*p == '.')
296*cc4ad7daSAndroid Build Coastguard Worker for (p++; *p >= '0' && *p <= '9'; p++)
297*cc4ad7daSAndroid Build Coastguard Worker min = min * 10 + *p - '0';
298*cc4ad7daSAndroid Build Coastguard Worker if (maj > major || (maj == major && min >= minor))
299*cc4ad7daSAndroid Build Coastguard Worker return true;
300*cc4ad7daSAndroid Build Coastguard Worker return false;
301*cc4ad7daSAndroid Build Coastguard Worker }
302*cc4ad7daSAndroid Build Coastguard Worker
303*cc4ad7daSAndroid Build Coastguard Worker
304*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT int finit_module(const int fd, const char *args, const int flags);
305*cc4ad7daSAndroid Build Coastguard Worker
finit_module(const int fd,const char * args,const int flags)306*cc4ad7daSAndroid Build Coastguard Worker int finit_module(const int fd, const char *args, const int flags)
307*cc4ad7daSAndroid Build Coastguard Worker {
308*cc4ad7daSAndroid Build Coastguard Worker int err;
309*cc4ad7daSAndroid Build Coastguard Worker void *mem;
310*cc4ad7daSAndroid Build Coastguard Worker unsigned long len;
311*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
312*cc4ad7daSAndroid Build Coastguard Worker
313*cc4ad7daSAndroid Build Coastguard Worker if (!check_kernel_version(3, 8)) {
314*cc4ad7daSAndroid Build Coastguard Worker errno = ENOSYS;
315*cc4ad7daSAndroid Build Coastguard Worker return -1;
316*cc4ad7daSAndroid Build Coastguard Worker }
317*cc4ad7daSAndroid Build Coastguard Worker if (fstat(fd, &st) < 0)
318*cc4ad7daSAndroid Build Coastguard Worker return -1;
319*cc4ad7daSAndroid Build Coastguard Worker
320*cc4ad7daSAndroid Build Coastguard Worker len = st.st_size;
321*cc4ad7daSAndroid Build Coastguard Worker mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
322*cc4ad7daSAndroid Build Coastguard Worker if (mem == MAP_FAILED)
323*cc4ad7daSAndroid Build Coastguard Worker return -1;
324*cc4ad7daSAndroid Build Coastguard Worker
325*cc4ad7daSAndroid Build Coastguard Worker err = init_module(mem, len, args);
326*cc4ad7daSAndroid Build Coastguard Worker munmap(mem, len);
327*cc4ad7daSAndroid Build Coastguard Worker
328*cc4ad7daSAndroid Build Coastguard Worker return err;
329*cc4ad7daSAndroid Build Coastguard Worker }
330*cc4ad7daSAndroid Build Coastguard Worker
syscall(long int __sysno,...)331*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT long int syscall(long int __sysno, ...)
332*cc4ad7daSAndroid Build Coastguard Worker {
333*cc4ad7daSAndroid Build Coastguard Worker va_list ap;
334*cc4ad7daSAndroid Build Coastguard Worker long ret;
335*cc4ad7daSAndroid Build Coastguard Worker
336*cc4ad7daSAndroid Build Coastguard Worker if (__sysno == -1) {
337*cc4ad7daSAndroid Build Coastguard Worker errno = ENOSYS;
338*cc4ad7daSAndroid Build Coastguard Worker return -1;
339*cc4ad7daSAndroid Build Coastguard Worker }
340*cc4ad7daSAndroid Build Coastguard Worker
341*cc4ad7daSAndroid Build Coastguard Worker if (__sysno == __NR_finit_module) {
342*cc4ad7daSAndroid Build Coastguard Worker const char *args;
343*cc4ad7daSAndroid Build Coastguard Worker int flags;
344*cc4ad7daSAndroid Build Coastguard Worker int fd;
345*cc4ad7daSAndroid Build Coastguard Worker
346*cc4ad7daSAndroid Build Coastguard Worker va_start(ap, __sysno);
347*cc4ad7daSAndroid Build Coastguard Worker
348*cc4ad7daSAndroid Build Coastguard Worker fd = va_arg(ap, int);
349*cc4ad7daSAndroid Build Coastguard Worker args = va_arg(ap, const char *);
350*cc4ad7daSAndroid Build Coastguard Worker flags = va_arg(ap, int);
351*cc4ad7daSAndroid Build Coastguard Worker
352*cc4ad7daSAndroid Build Coastguard Worker ret = finit_module(fd, args, flags);
353*cc4ad7daSAndroid Build Coastguard Worker
354*cc4ad7daSAndroid Build Coastguard Worker va_end(ap);
355*cc4ad7daSAndroid Build Coastguard Worker return ret;
356*cc4ad7daSAndroid Build Coastguard Worker }
357*cc4ad7daSAndroid Build Coastguard Worker
358*cc4ad7daSAndroid Build Coastguard Worker if (__sysno == __NR_gettid) {
359*cc4ad7daSAndroid Build Coastguard Worker static void *nextlib = NULL;
360*cc4ad7daSAndroid Build Coastguard Worker static long (*nextlib_syscall)(long number, ...);
361*cc4ad7daSAndroid Build Coastguard Worker
362*cc4ad7daSAndroid Build Coastguard Worker if (nextlib_syscall == NULL) {
363*cc4ad7daSAndroid Build Coastguard Worker #ifdef RTLD_NEXT
364*cc4ad7daSAndroid Build Coastguard Worker nextlib = RTLD_NEXT;
365*cc4ad7daSAndroid Build Coastguard Worker #else
366*cc4ad7daSAndroid Build Coastguard Worker nextlib = dlopen("libc.so.6", RTLD_LAZY);
367*cc4ad7daSAndroid Build Coastguard Worker #endif
368*cc4ad7daSAndroid Build Coastguard Worker nextlib_syscall = dlsym(nextlib, "syscall");
369*cc4ad7daSAndroid Build Coastguard Worker if (nextlib_syscall == NULL) {
370*cc4ad7daSAndroid Build Coastguard Worker fprintf(stderr, "FIXME FIXME FIXME: could not load syscall symbol: %s\n",
371*cc4ad7daSAndroid Build Coastguard Worker dlerror());
372*cc4ad7daSAndroid Build Coastguard Worker abort();
373*cc4ad7daSAndroid Build Coastguard Worker }
374*cc4ad7daSAndroid Build Coastguard Worker }
375*cc4ad7daSAndroid Build Coastguard Worker
376*cc4ad7daSAndroid Build Coastguard Worker return nextlib_syscall(__NR_gettid);
377*cc4ad7daSAndroid Build Coastguard Worker }
378*cc4ad7daSAndroid Build Coastguard Worker
379*cc4ad7daSAndroid Build Coastguard Worker /*
380*cc4ad7daSAndroid Build Coastguard Worker * FIXME: no way to call the libc function due since this is a
381*cc4ad7daSAndroid Build Coastguard Worker * variadic argument function and we don't have a vsyscall() variant
382*cc4ad7daSAndroid Build Coastguard Worker * this may fail if a library or process is trying to call syscall()
383*cc4ad7daSAndroid Build Coastguard Worker * directly, for example to implement gettid().
384*cc4ad7daSAndroid Build Coastguard Worker */
385*cc4ad7daSAndroid Build Coastguard Worker fprintf(stderr, "FIXME FIXME FIXME: could not wrap call to syscall(%ld), this should not happen\n",
386*cc4ad7daSAndroid Build Coastguard Worker __sysno);
387*cc4ad7daSAndroid Build Coastguard Worker
388*cc4ad7daSAndroid Build Coastguard Worker abort();
389*cc4ad7daSAndroid Build Coastguard Worker }
390*cc4ad7daSAndroid Build Coastguard Worker
391*cc4ad7daSAndroid Build Coastguard Worker /* the test is going away anyway, but lets keep valgrind happy */
392*cc4ad7daSAndroid Build Coastguard Worker void free_resources(void) __attribute__((destructor));
free_resources(void)393*cc4ad7daSAndroid Build Coastguard Worker void free_resources(void)
394*cc4ad7daSAndroid Build Coastguard Worker {
395*cc4ad7daSAndroid Build Coastguard Worker while (modules) {
396*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod = modules->next;
397*cc4ad7daSAndroid Build Coastguard Worker free(modules);
398*cc4ad7daSAndroid Build Coastguard Worker modules = mod;
399*cc4ad7daSAndroid Build Coastguard Worker }
400*cc4ad7daSAndroid Build Coastguard Worker
401*cc4ad7daSAndroid Build Coastguard Worker if (ctx)
402*cc4ad7daSAndroid Build Coastguard Worker kmod_unref(ctx);
403*cc4ad7daSAndroid Build Coastguard Worker }
404