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
- register_symtab
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #ifdef DEBUG_MODULE
40 #define PRINTK(a) printk a
41 #else
42 #define PRINTK(a)
43 #endif
44
45 static struct module kernel_module;
46 static struct module *module_list = &kernel_module;
47
48 static int freeing_modules;
49
50 static struct module *find_module( const char *name);
51 static int get_mod_name( char *user_name, char *buf);
52 static int free_modules( void);
53
54 static int module_init_flag = 0;
55
56
57
58
59 void init_modules(void) {
60 extern struct symbol_table symbol_table;
61 struct internal_symbol *sym;
62 int i;
63
64 for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
65 ;
66 symbol_table.n_symbols = i;
67
68 kernel_module.symtab = &symbol_table;
69 kernel_module.state = MOD_RUNNING;
70 kernel_module.name = "";
71 }
72
73 int
74 rename_module_symbol(char *old_name, char *new_name)
75 {
76 struct internal_symbol *sym;
77 int i = 0;
78
79 if (module_list->symtab) {
80 sym = module_list->symtab->symbol;
81 for (i = module_list->symtab->n_symbols; i > 0; ++sym, --i) {
82 if (strcmp(sym->name, old_name) == 0) {
83 sym->name = new_name;
84 PRINTK(("renamed %s to %s\n", old_name, new_name));
85 return 1;
86 }
87 }
88 }
89 printk("rename %s to %s failed!\n", old_name, new_name);
90 return 0;
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
117
118
119
120
121
122
123
124
125
126
127 }
128
129
130
131
132 asmlinkage unsigned long
133 sys_create_module(char *module_name, unsigned long size)
134 {
135 struct module *mp;
136 void* addr;
137 int error;
138 int npages;
139 int sspace = sizeof(struct module) + MOD_MAX_NAME;
140 char name[MOD_MAX_NAME];
141
142 if (!suser())
143 return -EPERM;
144 if (module_name == NULL || size == 0)
145 return -EINVAL;
146 if ((error = get_mod_name(module_name, name)) != 0)
147 return error;
148 if (find_module(name) != NULL) {
149 return -EEXIST;
150 }
151
152 if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
153 return -ENOMEM;
154 }
155 strcpy((char *)(mp + 1), name);
156
157 npages = (size + sizeof (int) + 4095) / 4096;
158 if ((addr = vmalloc(npages * 4096)) == 0) {
159 kfree_s(mp, sspace);
160 return -ENOMEM;
161 }
162
163 mp->next = module_list;
164 mp->ref = NULL;
165 mp->symtab = NULL;
166 mp->name = (char *)(mp + 1);
167 mp->size = npages;
168 mp->addr = addr;
169 mp->state = MOD_UNINITIALIZED;
170 mp->cleanup = NULL;
171
172 * (int *) addr = 0;
173 module_list = mp;
174
175 PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
176 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
177 return (unsigned long) addr;
178 }
179
180
181
182
183 asmlinkage int
184 sys_init_module(char *module_name, char *code, unsigned codesize,
185 struct mod_routines *routines,
186 struct symbol_table *symtab)
187 {
188 struct module *mp;
189 struct symbol_table *newtab;
190 char name[MOD_MAX_NAME];
191 int error;
192 struct mod_routines rt;
193
194 if (!suser())
195 return -EPERM;
196
197
198 if (symtab && ((unsigned long)symtab > 0xb0000000)) {
199 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
200 symtab = NULL;
201 }
202
203
204
205
206
207
208 free_modules();
209
210 if ((error = get_mod_name(module_name, name)) != 0)
211 return error;
212 PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
213 name, codesize, codesize));
214 memcpy_fromfs(&rt, routines, sizeof rt);
215 if ((mp = find_module(name)) == NULL)
216 return -ENOENT;
217 if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
218 return -EINVAL;
219 memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
220 memset((char *)mp->addr + sizeof (int) + codesize, 0,
221 mp->size * 4096 - (codesize + sizeof (int)));
222 PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
223 (unsigned long) rt.init, (unsigned long) rt.cleanup));
224 mp->cleanup = rt.cleanup;
225
226
227 if (symtab) {
228 struct internal_symbol *sym;
229 struct module_ref *ref;
230 int size;
231 int i;
232 int legal_start;
233
234 if ((error = verify_area(VERIFY_READ, symtab, sizeof(int))))
235 return error;
236 memcpy_fromfs((char *)(&(size)), symtab, sizeof(int));
237
238 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
239 return -ENOMEM;
240 }
241
242 if ((error = verify_area(VERIFY_READ, symtab, size))) {
243 kfree_s(newtab, size);
244 return error;
245 }
246 memcpy_fromfs((char *)(newtab), symtab, size);
247
248
249 legal_start = sizeof(struct symbol_table) +
250 newtab->n_symbols * sizeof(struct internal_symbol) +
251 newtab->n_refs * sizeof(struct module_ref);
252
253 if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) ||
254 (legal_start > size)) {
255 printk("Illegal symbol table! Rejected!\n");
256 kfree_s(newtab, size);
257 return -EINVAL;
258 }
259
260
261 for (sym = &(newtab->symbol[0]), i = 0;
262 i < newtab->n_symbols; ++sym, ++i) {
263 if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
264 printk("Illegal symbol table! Rejected!\n");
265 kfree_s(newtab, size);
266 return -EINVAL;
267 }
268
269 sym->name += (long)newtab;
270 }
271 mp->symtab = newtab;
272
273
274
275
276
277
278
279
280
281 for (ref = (struct module_ref *)sym, i = 0;
282 i < newtab->n_refs; ++ref, ++i) {
283
284
285 struct module *link = module_list;
286 while (link && (ref->module != link))
287 link = link->next;
288
289 if (link == (struct module *)0) {
290 printk("Non-module reference! Rejected!\n");
291 return -EINVAL;
292 }
293
294 ref->next = ref->module->ref;
295 ref->module->ref = ref;
296 ref->module = mp;
297 }
298 }
299
300 module_init_flag = 1;
301 if ((*rt.init)() != 0) {
302 module_init_flag = 0;
303 return -EBUSY;
304 }
305 module_init_flag = 0;
306 mp->state = MOD_RUNNING;
307
308 return 0;
309 }
310
311 asmlinkage int
312 sys_delete_module(char *module_name)
313 {
314 struct module *mp;
315 char name[MOD_MAX_NAME];
316 int error;
317
318 if (!suser())
319 return -EPERM;
320
321 if (module_name != NULL) {
322 if ((error = get_mod_name(module_name, name)) != 0)
323 return error;
324 if ((mp = find_module(name)) == NULL)
325 return -ENOENT;
326 if ((mp->ref != NULL) || (GET_USE_COUNT(mp) != 0))
327 return -EBUSY;
328 if (mp->state == MOD_RUNNING)
329 (*mp->cleanup)();
330 mp->state = MOD_DELETED;
331 }
332 free_modules();
333 return 0;
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 asmlinkage int
359 sys_get_kernel_syms(struct kernel_sym *table)
360 {
361 struct internal_symbol *from;
362 struct kernel_sym isym;
363 struct kernel_sym *to;
364 struct module *mp = module_list;
365 int i;
366 int nmodsyms = 0;
367
368 for (mp = module_list; mp; mp = mp->next) {
369 if (mp->symtab && mp->symtab->n_symbols) {
370
371 nmodsyms += mp->symtab->n_symbols + 1;
372 }
373 else
374
375 nmodsyms += 1;
376 }
377
378 if (table != NULL) {
379 to = table;
380
381 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
382 return i;
383
384
385 for (mp = module_list; mp; mp = mp->next) {
386 if (mp->state == MOD_RUNNING) {
387
388 isym.value = (unsigned long)mp;
389 sprintf(isym.name, "#%s", mp->name);
390 memcpy_tofs(to, &isym, sizeof isym);
391 ++to;
392
393 if (mp->symtab != NULL) {
394 for (i = mp->symtab->n_symbols,
395 from = mp->symtab->symbol;
396 i > 0; --i, ++from, ++to) {
397
398 isym.value = (unsigned long)from->addr;
399 strncpy(isym.name, from->name, sizeof isym.name);
400 memcpy_tofs(to, &isym, sizeof isym);
401 }
402 }
403 }
404 }
405 }
406
407 return nmodsyms;
408 }
409
410
411
412
413
414 int
415 get_mod_name(char *user_name, char *buf)
416 {
417 int i;
418
419 i = 0;
420 for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
421 if (++i >= MOD_MAX_NAME)
422 return -E2BIG;
423 }
424 return 0;
425 }
426
427
428
429
430
431 struct module *
432 find_module( const char *name)
433 {
434 struct module *mp;
435
436 for (mp = module_list ; mp ; mp = mp->next) {
437 if (mp->state == MOD_DELETED)
438 continue;
439 if (!strcmp(mp->name, name))
440 break;
441 }
442 return mp;
443 }
444
445 static void
446 drop_refs(struct module *mp)
447 {
448 struct module *step;
449 struct module_ref *prev;
450 struct module_ref *ref;
451
452 for (step = module_list; step; step = step->next) {
453 for (prev = ref = step->ref; ref; ref = prev->next) {
454 if (ref->module == mp) {
455 if (ref == step->ref)
456 step->ref = ref->next;
457 else
458 prev->next = ref->next;
459 break;
460 }
461 else
462 prev = ref;
463 }
464 }
465 }
466
467
468
469
470
471 int
472 free_modules( void)
473 {
474 struct module *mp;
475 struct module **mpp;
476 int did_deletion;
477
478 did_deletion = 0;
479 freeing_modules = 0;
480 mpp = &module_list;
481 while ((mp = *mpp) != NULL) {
482 if (mp->state != MOD_DELETED) {
483 mpp = &mp->next;
484 } else {
485 if (GET_USE_COUNT(mp) != 0) {
486 freeing_modules = 1;
487 mpp = &mp->next;
488 } else {
489 *mpp = mp->next;
490 if (mp->symtab) {
491 if (mp->symtab->n_refs)
492 drop_refs(mp);
493 if (mp->symtab->size)
494 kfree_s(mp->symtab, mp->symtab->size);
495 }
496 vfree(mp->addr);
497 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
498 did_deletion = 1;
499 }
500 }
501 }
502 return did_deletion;
503 }
504
505
506
507
508
509 int get_module_list(char *buf)
510 {
511 char *p;
512 char *q;
513 int i;
514 struct module *mp;
515 struct module_ref *ref;
516 char size[32];
517
518 p = buf;
519
520 for (mp = module_list ; mp && mp->next; mp = mp->next) {
521 if (p - buf > 4096 - 100)
522 break;
523 q = mp->name;
524 i = 20;
525 while (*q) {
526 *p++ = *q++;
527 i--;
528 }
529 sprintf(size, "%d", mp->size);
530 i -= strlen(size);
531 if (i <= 0)
532 i = 1;
533 while (--i >= 0)
534 *p++ = ' ';
535 q = size;
536 while (*q)
537 *p++ = *q++;
538 if (mp->state == MOD_UNINITIALIZED)
539 q = " (uninitialized)";
540 else if (mp->state == MOD_RUNNING)
541 q = "";
542 else if (mp->state == MOD_DELETED)
543 q = " (deleted)";
544 else
545 q = " (bad state)";
546 while (*q)
547 *p++ = *q++;
548
549 if ((ref = mp->ref) != NULL) {
550 *p++ = '\t';
551 *p++ = '[';
552 for (; ref; ref = ref->next) {
553 q = ref->module->name;
554 while (*q)
555 *p++ = *q++;
556 if (ref->next)
557 *p++ = ' ';
558 }
559 *p++ = ']';
560 }
561 *p++ = '\n';
562 }
563 return p - buf;
564 }
565
566
567
568
569
570 int get_ksyms_list(char *buf)
571 {
572 struct module *mp;
573 struct internal_symbol *sym;
574 int i;
575 char *p = buf;
576
577 for (mp = module_list; mp; mp = mp->next) {
578 if ((mp->state == MOD_RUNNING) &&
579 (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
580 for (i = mp->symtab->n_symbols,
581 sym = mp->symtab->symbol;
582 i > 0; --i, ++sym) {
583
584 if (p - buf > 4096 - 100) {
585 strcat(p, "...\n");
586 p += strlen(p);
587 return p - buf;
588 }
589
590 if (mp->name[0]) {
591 sprintf(p, "%08lx %s\t[%s]\n",
592 (long)sym->addr, sym->name, mp->name);
593 }
594 else {
595 sprintf(p, "%08lx %s\n",
596 (long)sym->addr, sym->name);
597 }
598 p += strlen(p);
599 }
600 }
601 }
602
603 return p - buf;
604 }
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624 #define INTSIZ sizeof(struct internal_symbol)
625 #define REFSIZ sizeof(struct module_ref)
626 #define SYMSIZ sizeof(struct symbol_table)
627 #define MODSIZ sizeof(struct module)
628 static struct symbol_table nulltab;
629
630 int
631 register_symtab(struct symbol_table *intab)
632 {
633 struct module *mp;
634 struct module *link;
635 struct symbol_table *oldtab;
636 struct symbol_table *newtab;
637 struct module_ref *newref;
638 int size;
639
640 if (intab && (intab->n_symbols == 0)) {
641 struct internal_symbol *sym;
642
643
644 for (sym = intab->symbol; sym->name; ++sym)
645 intab->n_symbols +=1;
646 }
647
648 #if 1
649 if (module_init_flag == 0) {
650 #else
651 if (module_list == &kernel_module) {
652 #endif
653
654 if (!intab)
655 return 0;
656
657
658 if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
659
660 printk("Out of memory for new symbol table!\n");
661 return -ENOMEM;
662 }
663
664 memset(mp, 0, MODSIZ);
665 mp->state = MOD_RUNNING;
666 mp->name = "";
667 mp->symtab = intab;
668
669
670 mp->next = kernel_module.next;
671 kernel_module.next = mp;
672
673 return 0;
674 }
675
676
677
678
679
680
681
682
683 mp = module_list;
684
685
686 if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
687
688 mp->symtab = intab;
689 return 0;
690 }
691
692
693 #if 0
694 if (oldtab->n_symbols > 0) {
695
696 printk("Warning, dropping old symbols\n");
697 }
698 #endif
699
700 if (oldtab->n_refs == 0) {
701 mp->symtab = intab;
702
703 if (oldtab->size > 0)
704 kfree_s(oldtab, oldtab->size);
705
706 return 0;
707 }
708
709
710
711
712 if (intab == (struct symbol_table*)0)
713 intab = &nulltab;
714
715
716
717
718 if (!(newtab = (struct symbol_table*)kmalloc(
719 size = SYMSIZ + intab->n_symbols * INTSIZ +
720 oldtab->n_refs * REFSIZ,
721 GFP_KERNEL))) {
722
723 printk("Out of memory for new symbol table!\n");
724 return -ENOMEM;
725 }
726
727
728 memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
729
730 newtab->size = size;
731 newtab->n_refs = oldtab->n_refs;
732
733
734 memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
735 ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
736 oldtab->n_refs * REFSIZ);
737
738
739
740
741 newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
742
743
744 for ( link = module_list;
745 link && (link != &kernel_module);
746 link = link->next) {
747
748 if (link->ref->module == mp)
749 link->ref = newref++;
750 }
751
752 mp->symtab = newtab;
753
754
755
756
757 if (oldtab->size > 0)
758 kfree_s(oldtab, oldtab->size);
759
760 return 0;
761 }