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