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