This source file includes following definitions.
- init_modules
- rename_module_symbol
- sys_create_module
- sys_init_module
- sys_delete_module
- sys_get_kernel_syms
- get_mod_name
- find_module
- drop_refs
- free_modules
- get_module_list
- get_ksyms_list
1 #include <linux/errno.h>
2 #include <linux/kernel.h>
3 #include <asm/segment.h>
4 #include <linux/mm.h>
5 #include <linux/string.h>
6 #include <linux/module.h>
7 #include <linux/sched.h>
8 #include <linux/malloc.h>
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #ifdef DEBUG_MODULE
25 #define PRINTK(a) printk a
26 #else
27 #define PRINTK(a)
28 #endif
29
30 static struct module kernel_module;
31 static struct module *module_list = &kernel_module;
32
33 static int freeing_modules;
34
35 static struct module *find_module( const char *name);
36 static int get_mod_name( char *user_name, char *buf);
37 static int free_modules( void);
38
39
40
41
42
43 void init_modules(void) {
44 extern struct symbol_table symbol_table;
45 struct internal_symbol *sym;
46 int i;
47
48 for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
49 ;
50 symbol_table.n_symbols = i;
51
52 kernel_module.symtab = &symbol_table;
53 kernel_module.state = MOD_RUNNING;
54 kernel_module.name = "";
55 }
56
57 int
58 rename_module_symbol(char *old_name, char *new_name)
59 {
60 struct internal_symbol *sym;
61 int i = 0;
62
63 if (module_list->symtab) {
64 sym = module_list->symtab->symbol;
65 for (i = module_list->symtab->n_symbols; i > 0; ++sym, --i) {
66 if (strcmp(sym->name, old_name) == 0) {
67 sym->name = new_name;
68 PRINTK(("renamed %s to %s\n", old_name, new_name));
69 return 1;
70 }
71 }
72 }
73 printk("rename %s to %s failed!\n", old_name, new_name);
74 return 0;
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 }
112
113
114
115
116 asmlinkage int
117 sys_create_module(char *module_name, unsigned long size)
118 {
119 struct module *mp;
120 void* addr;
121 int error;
122 int npages;
123 int sspace = sizeof(struct module) + MOD_MAX_NAME;
124 char name[MOD_MAX_NAME];
125
126 if (!suser())
127 return -EPERM;
128 if (module_name == NULL || size == 0)
129 return -EINVAL;
130 if ((error = get_mod_name(module_name, name)) != 0)
131 return error;
132 if (find_module(name) != NULL) {
133 return -EEXIST;
134 }
135
136 if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
137 return -ENOMEM;
138 }
139 strcpy((char *)(mp + 1), name);
140
141 npages = (size + sizeof (int) + 4095) / 4096;
142 if ((addr = vmalloc(npages * 4096)) == 0) {
143 kfree_s(mp, sspace);
144 return -ENOMEM;
145 }
146
147 mp->next = module_list;
148 mp->ref = NULL;
149 mp->symtab = NULL;
150 mp->name = (char *)(mp + 1);
151 mp->size = npages;
152 mp->addr = addr;
153 mp->state = MOD_UNINITIALIZED;
154 mp->cleanup = NULL;
155
156 * (int *) addr = 0;
157 module_list = mp;
158
159 PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
160 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
161 return (int) addr;
162 }
163
164
165
166
167 asmlinkage int
168 sys_init_module(char *module_name, char *code, unsigned codesize,
169 struct mod_routines *routines,
170 struct symbol_table *symtab)
171 {
172 struct module *mp;
173 struct symbol_table *newtab;
174 char name[MOD_MAX_NAME];
175 int error;
176 struct mod_routines rt;
177
178 if (!suser())
179 return -EPERM;
180
181
182 if (symtab && ((unsigned long)symtab > 0xb0000000)) {
183 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
184 symtab = NULL;
185 }
186
187
188
189
190
191
192 free_modules();
193
194 if ((error = get_mod_name(module_name, name)) != 0)
195 return error;
196 PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
197 name, codesize, codesize));
198 memcpy_fromfs(&rt, routines, sizeof rt);
199 if ((mp = find_module(name)) == NULL)
200 return -ENOENT;
201 if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
202 return -EINVAL;
203 memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
204 memset((char *)mp->addr + sizeof (int) + codesize, 0,
205 mp->size * 4096 - (codesize + sizeof (int)));
206 PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
207 (unsigned long) rt.init, (unsigned long) rt.cleanup));
208 mp->cleanup = rt.cleanup;
209
210
211 if (symtab) {
212 struct internal_symbol *sym;
213 struct module_ref *ref;
214 int size;
215 int i;
216
217 if ((error = verify_area(VERIFY_READ, symtab, sizeof(int))))
218 return error;
219 memcpy_fromfs((char *)(&(size)), symtab, sizeof(int));
220
221 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
222 return -ENOMEM;
223 }
224
225 if ((error = verify_area(VERIFY_READ, symtab, size)))
226 return error;
227 memcpy_fromfs((char *)(newtab), symtab, size);
228
229
230 for (sym = &(newtab->symbol[0]), i = 0;
231 i < newtab->n_symbols; ++sym, ++i) {
232 sym->name += (long)newtab;
233 }
234 mp->symtab = newtab;
235
236
237
238
239
240
241 for (ref = (struct module_ref *)sym, i = 0;
242 i < newtab->n_refs; ++ref, ++i) {
243 ref->next = ref->module->ref;
244 ref->module->ref = ref;
245 ref->module = mp;
246 }
247 }
248
249 if ((*rt.init)() != 0)
250 return -EBUSY;
251 mp->state = MOD_RUNNING;
252
253 return 0;
254 }
255
256 asmlinkage int
257 sys_delete_module(char *module_name)
258 {
259 struct module *mp;
260 char name[MOD_MAX_NAME];
261 int error;
262
263 if (!suser())
264 return -EPERM;
265
266 if (module_name != NULL) {
267 if ((error = get_mod_name(module_name, name)) != 0)
268 return error;
269 if ((mp = find_module(name)) == NULL)
270 return -ENOENT;
271 if ((mp->ref != NULL) || (GET_USE_COUNT(mp) != 0))
272 return -EBUSY;
273 if (mp->state == MOD_RUNNING)
274 (*mp->cleanup)();
275 mp->state = MOD_DELETED;
276 }
277 free_modules();
278 return 0;
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 asmlinkage int
304 sys_get_kernel_syms(struct kernel_sym *table)
305 {
306 struct internal_symbol *from;
307 struct kernel_sym isym;
308 struct kernel_sym *to;
309 struct module *mp = module_list;
310 int i;
311 int nmodsyms = 0;
312
313 for (mp = module_list; mp; mp = mp->next) {
314 if (mp->symtab && mp->symtab->n_symbols) {
315
316 nmodsyms += mp->symtab->n_symbols + 1;
317 }
318 }
319
320 if (table != NULL) {
321 to = table;
322
323 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
324 return i;
325
326
327 for (mp = module_list; mp; mp = mp->next) {
328 if ((mp->state == MOD_RUNNING) &&
329 (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
330
331 isym.value = (unsigned long)mp;
332 sprintf(isym.name, "#%s", mp->name);
333 memcpy_tofs(to, &isym, sizeof isym);
334 ++to;
335
336 for (i = mp->symtab->n_symbols,
337 from = mp->symtab->symbol;
338 i > 0; --i, ++from, ++to) {
339
340 isym.value = (unsigned long)from->addr;
341 strncpy(isym.name, from->name, sizeof isym.name);
342 memcpy_tofs(to, &isym, sizeof isym);
343 }
344 }
345 }
346 }
347
348 return nmodsyms;
349 }
350
351
352
353
354
355 int
356 get_mod_name(char *user_name, char *buf)
357 {
358 int i;
359
360 i = 0;
361 for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
362 if (++i >= MOD_MAX_NAME)
363 return -E2BIG;
364 }
365 return 0;
366 }
367
368
369
370
371
372 struct module *
373 find_module( const char *name)
374 {
375 struct module *mp;
376
377 for (mp = module_list ; mp ; mp = mp->next) {
378 if (mp->state == MOD_DELETED)
379 continue;
380 if (!strcmp(mp->name, name))
381 break;
382 }
383 return mp;
384 }
385
386 static void
387 drop_refs(struct module *mp)
388 {
389 struct module *step;
390 struct module_ref *prev;
391 struct module_ref *ref;
392
393 for (step = module_list; step; step = step->next) {
394 for (prev = ref = step->ref; ref; ref = prev->next) {
395 if (ref->module == mp) {
396 if (ref == step->ref)
397 step->ref = ref->next;
398 else
399 prev->next = ref->next;
400 break;
401 }
402 else
403 prev = ref;
404 }
405 }
406 }
407
408
409
410
411
412 int
413 free_modules( void)
414 {
415 struct module *mp;
416 struct module **mpp;
417 int did_deletion;
418
419 did_deletion = 0;
420 freeing_modules = 0;
421 mpp = &module_list;
422 while ((mp = *mpp) != NULL) {
423 if (mp->state != MOD_DELETED) {
424 mpp = &mp->next;
425 } else {
426 if (GET_USE_COUNT(mp) != 0) {
427 freeing_modules = 1;
428 mpp = &mp->next;
429 } else {
430 *mpp = mp->next;
431 if (mp->symtab) {
432 if (mp->symtab->n_refs)
433 drop_refs(mp);
434 if (mp->symtab->size)
435 kfree_s(mp->symtab, mp->symtab->size);
436 }
437 vfree(mp->addr);
438 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
439 did_deletion = 1;
440 }
441 }
442 }
443 return did_deletion;
444 }
445
446
447
448
449
450 int get_module_list(char *buf)
451 {
452 char *p;
453 char *q;
454 int i;
455 struct module *mp;
456 struct module_ref *ref;
457 char size[32];
458
459 p = buf;
460
461 for (mp = module_list ; mp && mp->next; mp = mp->next) {
462 if (p - buf > 4096 - 100)
463 break;
464 q = mp->name;
465 i = 20;
466 while (*q) {
467 *p++ = *q++;
468 i--;
469 }
470 sprintf(size, "%d", mp->size);
471 i -= strlen(size);
472 if (i <= 0)
473 i = 1;
474 while (--i >= 0)
475 *p++ = ' ';
476 q = size;
477 while (*q)
478 *p++ = *q++;
479 if (mp->state == MOD_UNINITIALIZED)
480 q = " (uninitialized)";
481 else if (mp->state == MOD_RUNNING)
482 q = "";
483 else if (mp->state == MOD_DELETED)
484 q = " (deleted)";
485 else
486 q = " (bad state)";
487 while (*q)
488 *p++ = *q++;
489
490 if ((ref = mp->ref) != NULL) {
491 *p++ = '\t';
492 *p++ = '[';
493 for (; ref; ref = ref->next) {
494 q = ref->module->name;
495 while (*q)
496 *p++ = *q++;
497 if (ref->next)
498 *p++ = ' ';
499 }
500 *p++ = ']';
501 }
502 *p++ = '\n';
503 }
504 return p - buf;
505 }
506
507
508
509
510
511 int get_ksyms_list(char *buf)
512 {
513 struct module *mp;
514 struct internal_symbol *sym;
515 int i;
516 char *p = buf;
517
518 for (mp = module_list; mp; mp = mp->next) {
519 if ((mp->state == MOD_RUNNING) &&
520 (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
521 for (i = mp->symtab->n_symbols,
522 sym = mp->symtab->symbol;
523 i > 0; --i, ++sym) {
524
525 if (p - buf > 4096 - 100) {
526 strcat(p, "...\n");
527 p += strlen(p);
528 return p - buf;
529 }
530
531 if (mp->name[0]) {
532 sprintf(p, "%08lx %s\t[%s]\n",
533 (long)sym->addr, sym->name, mp->name);
534 }
535 else {
536 sprintf(p, "%08lx %s\n",
537 (long)sym->addr, sym->name);
538 }
539 p += strlen(p);
540 }
541 }
542 }
543
544 return p - buf;
545 }