xref: /aosp_15_r20/external/kmod/testsuite/init_module.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
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