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) ||
262 (legal_start > size)) {
263 printk("Illegal symbol table! Rejected!\n");
264 kfree_s(newtab, size);
265 return -EINVAL;
266 }
267
268
269 for (sym = &(newtab->symbol[0]), i = 0;
270 i < newtab->n_symbols; ++sym, ++i) {
271 if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
272 printk("Illegal symbol table! Rejected!\n");
273 kfree_s(newtab, size);
274 return -EINVAL;
275 }
276
277 sym->name += (long)newtab;
278 }
279 mp->symtab = newtab;
280
281
282
283
284
285
286
287
288
289 for (ref = (struct module_ref *)sym, i = 0;
290 i < newtab->n_refs; ++ref, ++i) {
291
292
293 struct module *link = module_list;
294 while (link && (ref->module != link))
295 link = link->next;
296
297 if (link == (struct module *)0) {
298 printk("Non-module reference! Rejected!\n");
299 return -EINVAL;
300 }
301
302 ref->next = ref->module->ref;
303 ref->module->ref = ref;
304 ref->module = mp;
305 }
306 }
307
308 module_init_flag = 1;
309 if ((*rt.init)() != 0) {
310 module_init_flag = 0;
311 return -EBUSY;
312 }
313 module_init_flag = 0;
314 mp->state = MOD_RUNNING;
315
316 return 0;
317 }
318
319 asmlinkage int
320 sys_delete_module(char *module_name)
321 {
322 struct module *mp;
323 char name[MOD_MAX_NAME];
324 int error;
325
326 if (!suser())
327 return -EPERM;
328
329 if (module_name != NULL) {
330 if ((error = get_mod_name(module_name, name)) != 0)
331 return error;
332 if ((mp = find_module(name)) == NULL)
333 return -ENOENT;
334 if ((mp->ref != NULL) || (GET_USE_COUNT(mp) != 0))
335 return -EBUSY;
336 if (mp->state == MOD_RUNNING)
337 (*mp->cleanup)();
338 mp->state = MOD_DELETED;
339 }
340 free_modules();
341 return 0;
342 }
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366 asmlinkage int
367 sys_get_kernel_syms(struct kernel_sym *table)
368 {
369 struct internal_symbol *from;
370 struct kernel_sym isym;
371 struct kernel_sym *to;
372 struct module *mp = module_list;
373 int i;
374 int nmodsyms = 0;
375
376 for (mp = module_list; mp; mp = mp->next) {
377 if (mp->symtab && mp->symtab->n_symbols) {
378
379 nmodsyms += mp->symtab->n_symbols + 1;
380 }
381 else
382
383 nmodsyms += 1;
384 }
385
386 if (table != NULL) {
387 to = table;
388
389 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
390 return i;
391
392
393 for (mp = module_list; mp; mp = mp->next) {
394 if (mp->state == MOD_RUNNING) {
395
396 isym.value = (unsigned long)mp;
397 sprintf(isym.name, "#%s", mp->name);
398 memcpy_tofs(to, &isym, sizeof isym);
399 ++to;
400
401 if (mp->symtab != NULL) {
402 for (i = mp->symtab->n_symbols,
403 from = mp->symtab->symbol;
404 i > 0; --i, ++from, ++to) {
405
406 isym.value = (unsigned long)from->addr;
407 strncpy(isym.name, from->name, sizeof isym.name);
408 memcpy_tofs(to, &isym, sizeof isym);
409 }
410 }
411 }
412 }
413 }
414
415 return nmodsyms;
416 }
417
418
419
420
421
422 int
423 get_mod_name(char *user_name, char *buf)
424 {
425 int i;
426
427 i = 0;
428 for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
429 if (++i >= MOD_MAX_NAME)
430 return -E2BIG;
431 }
432 return 0;
433 }
434
435
436
437
438
439 struct module *
440 find_module( const char *name)
441 {
442 struct module *mp;
443
444 for (mp = module_list ; mp ; mp = mp->next) {
445 if (mp->state == MOD_DELETED)
446 continue;
447 if (!strcmp(mp->name, name))
448 break;
449 }
450 return mp;
451 }
452
453 static void
454 drop_refs(struct module *mp)
455 {
456 struct module *step;
457 struct module_ref *prev;
458 struct module_ref *ref;
459
460 for (step = module_list; step; step = step->next) {
461 for (prev = ref = step->ref; ref; ref = prev->next) {
462 if (ref->module == mp) {
463 if (ref == step->ref)
464 step->ref = ref->next;
465 else
466 prev->next = ref->next;
467 break;
468 }
469 else
470 prev = ref;
471 }
472 }
473 }
474
475
476
477
478
479 int
480 free_modules( void)
481 {
482 struct module *mp;
483 struct module **mpp;
484 int did_deletion;
485
486 did_deletion = 0;
487 freeing_modules = 0;
488 mpp = &module_list;
489 while ((mp = *mpp) != NULL) {
490 if (mp->state != MOD_DELETED) {
491 mpp = &mp->next;
492 } else {
493 if (GET_USE_COUNT(mp) != 0) {
494 freeing_modules = 1;
495 mpp = &mp->next;
496 } else {
497 *mpp = mp->next;
498 if (mp->symtab) {
499 if (mp->symtab->n_refs)
500 drop_refs(mp);
501 if (mp->symtab->size)
502 kfree_s(mp->symtab, mp->symtab->size);
503 }
504 vfree(mp->addr);
505 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
506 did_deletion = 1;
507 }
508 }
509 }
510 return did_deletion;
511 }
512
513
514
515
516
517 int get_module_list(char *buf)
518 {
519 char *p;
520 const char *q;
521 int i;
522 struct module *mp;
523 struct module_ref *ref;
524 char size[32];
525
526 p = buf;
527
528 for (mp = module_list ; mp && mp->next; mp = mp->next) {
529 if (p - buf > 4096 - 100)
530 break;
531 q = mp->name;
532 if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
533 continue;
534 i = 20;
535 while (*q) {
536 *p++ = *q++;
537 i--;
538 }
539 sprintf(size, "%d", mp->size);
540 i -= strlen(size);
541 if (i <= 0)
542 i = 1;
543 while (--i >= 0)
544 *p++ = ' ';
545 q = size;
546 while (*q)
547 *p++ = *q++;
548 if (mp->state == MOD_UNINITIALIZED)
549 q = " (uninitialized)";
550 else if (mp->state == MOD_RUNNING)
551 q = "";
552 else if (mp->state == MOD_DELETED)
553 q = " (deleted)";
554 else
555 q = " (bad state)";
556 while (*q)
557 *p++ = *q++;
558
559 if ((ref = mp->ref) != NULL) {
560 *p++ = '\t';
561 *p++ = '[';
562 for (; ref; ref = ref->next) {
563 q = ref->module->name;
564 while (*q)
565 *p++ = *q++;
566 if (ref->next)
567 *p++ = ' ';
568 }
569 *p++ = ']';
570 }
571 *p++ = '\n';
572 }
573 return p - buf;
574 }
575
576
577
578
579
580 int get_ksyms_list(char *buf, char **start, off_t offset, int length)
581 {
582 struct module *mp;
583 struct internal_symbol *sym;
584 int i;
585 char *p = buf;
586 int len = 0;
587 off_t pos = 0;
588 off_t begin = 0;
589
590 for (mp = module_list; mp; mp = mp->next) {
591 if ((mp->state == MOD_RUNNING) &&
592 (mp->symtab != NULL) &&
593 (mp->symtab->n_symbols > 0)) {
594 for (i = mp->symtab->n_symbols,
595 sym = mp->symtab->symbol;
596 i > 0; --i, ++sym) {
597
598 p = buf + len;
599 if (mp->name[0]) {
600 len += sprintf(p, "%08lx %s\t[%s]\n",
601 (long)sym->addr,
602 sym->name, mp->name);
603 } else {
604 len += sprintf(p, "%08lx %s\n",
605 (long)sym->addr,
606 sym->name);
607 }
608 pos = begin + len;
609 if (pos < offset) {
610 len = 0;
611 begin = pos;
612 }
613 pos = begin + len;
614 if (pos > offset+length)
615 goto leave_the_loop;
616 }
617 }
618 }
619 leave_the_loop:
620 *start = buf + (offset - begin);
621 len -= (offset - begin);
622 if (len > length)
623 len = length;
624 return len;
625 }
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645 #define INTSIZ sizeof(struct internal_symbol)
646 #define REFSIZ sizeof(struct module_ref)
647 #define SYMSIZ sizeof(struct symbol_table)
648 #define MODSIZ sizeof(struct module)
649 static struct symbol_table nulltab;
650
651 int
652 register_symtab(struct symbol_table *intab)
653 {
654 struct module *mp;
655 struct module *link;
656 struct symbol_table *oldtab;
657 struct symbol_table *newtab;
658 struct module_ref *newref;
659 int size;
660
661 if (intab && (intab->n_symbols == 0)) {
662 struct internal_symbol *sym;
663
664
665 for (sym = intab->symbol; sym->name; ++sym)
666 intab->n_symbols +=1;
667 }
668
669 #if 1
670 if (module_init_flag == 0) {
671 #else
672 if (module_list == &kernel_module) {
673 #endif
674
675 if (!intab)
676 return 0;
677
678
679 if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
680
681 printk("Out of memory for new symbol table!\n");
682 return -ENOMEM;
683 }
684
685 memset(mp, 0, MODSIZ);
686 mp->state = MOD_RUNNING;
687 mp->name = "";
688 mp->symtab = intab;
689
690
691 mp->next = kernel_module.next;
692 kernel_module.next = mp;
693
694 return 0;
695 }
696
697
698
699
700
701
702
703
704 mp = module_list;
705
706
707 if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
708
709 mp->symtab = intab;
710 return 0;
711 }
712
713
714 #if 0
715 if (oldtab->n_symbols > 0) {
716
717 printk("Warning, dropping old symbols\n");
718 }
719 #endif
720
721 if (oldtab->n_refs == 0) {
722 mp->symtab = intab;
723
724 if (oldtab->size > 0)
725 kfree_s(oldtab, oldtab->size);
726
727 return 0;
728 }
729
730
731
732
733 if (intab == (struct symbol_table*)0)
734 intab = &nulltab;
735
736
737
738
739 if (!(newtab = (struct symbol_table*)kmalloc(
740 size = SYMSIZ + intab->n_symbols * INTSIZ +
741 oldtab->n_refs * REFSIZ,
742 GFP_KERNEL))) {
743
744 printk("Out of memory for new symbol table!\n");
745 return -ENOMEM;
746 }
747
748
749 memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
750
751 newtab->size = size;
752 newtab->n_refs = oldtab->n_refs;
753
754
755 memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
756 ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
757 oldtab->n_refs * REFSIZ);
758
759
760
761
762 newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
763
764
765 for ( link = module_list;
766 link && (link != &kernel_module);
767 link = link->next) {
768
769 if (link->ref && (link->ref->module == mp))
770 link->ref = newref++;
771 }
772
773 mp->symtab = newtab;
774
775
776
777
778 if (oldtab->size > 0)
779 kfree_s(oldtab, oldtab->size);
780
781 return 0;
782 }