This source file includes following definitions.
- init_modules
- 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
85
86
87 asmlinkage unsigned long
88 sys_create_module(char *module_name, unsigned long size)
89 {
90 struct module *mp;
91 void* addr;
92 int error;
93 int npages;
94 int sspace = sizeof(struct module) + MOD_MAX_NAME;
95 char name[MOD_MAX_NAME];
96
97 if (!suser())
98 return -EPERM;
99 if (module_name == NULL || size == 0)
100 return -EINVAL;
101 if ((error = get_mod_name(module_name, name)) != 0)
102 return error;
103 if (find_module(name) != NULL) {
104 return -EEXIST;
105 }
106
107 if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
108 return -ENOMEM;
109 }
110 strcpy((char *)(mp + 1), name);
111
112 npages = (size + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE;
113 if ((addr = vmalloc(npages * PAGE_SIZE)) == 0) {
114 kfree_s(mp, sspace);
115 return -ENOMEM;
116 }
117
118 mp->next = module_list;
119 mp->ref = NULL;
120 mp->symtab = NULL;
121 mp->name = (char *)(mp + 1);
122 mp->size = npages;
123 mp->addr = addr;
124 mp->state = MOD_UNINITIALIZED;
125 mp->cleanup = NULL;
126
127 * (long *) addr = 0;
128 module_list = mp;
129
130 PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
131 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
132 return (unsigned long) addr;
133 }
134
135
136
137
138 asmlinkage int
139 sys_init_module(char *module_name, char *code, unsigned codesize,
140 struct mod_routines *routines,
141 struct symbol_table *symtab)
142 {
143 struct module *mp;
144 struct symbol_table *newtab;
145 char name[MOD_MAX_NAME];
146 int error;
147 struct mod_routines rt;
148
149 if (!suser())
150 return -EPERM;
151
152 #ifdef __i386__
153
154
155 if (symtab && ((unsigned long)symtab > 0xb0000000)) {
156 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
157 symtab = NULL;
158 }
159 #endif
160
161
162
163
164
165
166 free_modules();
167
168 if ((error = get_mod_name(module_name, name)) != 0)
169 return error;
170 PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
171 name, codesize, codesize));
172 memcpy_fromfs(&rt, routines, sizeof rt);
173 if ((mp = find_module(name)) == NULL)
174 return -ENOENT;
175 if (codesize & MOD_AUTOCLEAN) {
176
177
178
179
180 codesize &= ~MOD_AUTOCLEAN;
181 GET_USE_COUNT(mp) = MOD_AUTOCLEAN;
182 }
183 if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
184 return -EINVAL;
185 memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
186 memset((char *)mp->addr + sizeof (long) + codesize, 0,
187 mp->size * PAGE_SIZE - (codesize + sizeof (long)));
188 PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
189 (unsigned long) rt.init, (unsigned long) rt.cleanup));
190 mp->cleanup = rt.cleanup;
191
192
193 if (symtab) {
194 struct internal_symbol *sym;
195 struct module_ref *ref;
196 int size;
197 int i;
198 int legal_start;
199
200 if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
201 return error;
202 size = get_user(&symtab->size);
203
204 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
205 return -ENOMEM;
206 }
207
208 if ((error = verify_area(VERIFY_READ, symtab, size))) {
209 kfree_s(newtab, size);
210 return error;
211 }
212 memcpy_fromfs((char *)(newtab), symtab, size);
213
214
215 legal_start = sizeof(struct symbol_table) +
216 newtab->n_symbols * sizeof(struct internal_symbol) +
217 newtab->n_refs * sizeof(struct module_ref);
218
219 if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
220 printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
221 newtab->n_symbols, newtab->n_refs);
222 kfree_s(newtab, size);
223 return -EINVAL;
224 }
225
226
227 for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
228 if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
229 printk("Rejecting illegal symbol table\n");
230 kfree_s(newtab, size);
231 return -EINVAL;
232 }
233
234 sym->name += (long)newtab;
235 }
236 mp->symtab = newtab;
237
238
239
240
241
242
243
244
245
246 for (ref = (struct module_ref *)sym, i = 0;
247 i < newtab->n_refs; ++ref, ++i) {
248
249
250 struct module *link = module_list;
251 while (link && (ref->module != link))
252 link = link->next;
253
254 if (link == (struct module *)0) {
255 printk("Non-module reference! Rejected!\n");
256 return -EINVAL;
257 }
258
259 ref->next = ref->module->ref;
260 ref->module->ref = ref;
261 ref->module = mp;
262 }
263 }
264
265 module_init_flag = 1;
266 if ((*rt.init)() != 0) {
267 module_init_flag = 0;
268 return -EBUSY;
269 }
270 module_init_flag = 0;
271 mp->state = MOD_RUNNING;
272
273 return 0;
274 }
275
276 asmlinkage int
277 sys_delete_module(char *module_name)
278 {
279 struct module *mp;
280 char name[MOD_MAX_NAME];
281 int error;
282
283 if (!suser())
284 return -EPERM;
285
286 if (module_name != NULL) {
287 if ((error = get_mod_name(module_name, name)) != 0)
288 return error;
289 if ((mp = find_module(name)) == NULL)
290 return -ENOENT;
291 if ((mp->ref != NULL) || ((GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN) != 0))
292 return -EBUSY;
293 GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
294 if (mp->state == MOD_RUNNING)
295 (*mp->cleanup)();
296 mp->state = MOD_DELETED;
297 free_modules();
298 }
299
300 else {
301 for (mp = module_list; mp != &kernel_module; mp = mp->next) {
302 if ((mp->ref == NULL) && (GET_USE_COUNT(mp) == MOD_AUTOCLEAN) &&
303 (mp->state == MOD_RUNNING)) {
304 GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
305 (*mp->cleanup)();
306 mp->state = MOD_DELETED;
307 free_modules();
308 }
309 }
310 }
311 return 0;
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 asmlinkage int
337 sys_get_kernel_syms(struct kernel_sym *table)
338 {
339 struct internal_symbol *from;
340 struct kernel_sym isym;
341 struct kernel_sym *to;
342 struct module *mp = module_list;
343 int i;
344 int nmodsyms = 0;
345
346 for (mp = module_list; mp; mp = mp->next) {
347 if (mp->symtab && mp->symtab->n_symbols) {
348
349 nmodsyms += mp->symtab->n_symbols + 1;
350 }
351 else
352
353 nmodsyms += 1;
354 }
355
356 if (table != NULL) {
357 to = table;
358
359 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
360 return i;
361
362
363 for (mp = module_list; mp; mp = mp->next) {
364 if (mp->state == MOD_RUNNING) {
365
366 isym.value = (unsigned long)mp;
367 sprintf(isym.name, "#%s", mp->name);
368 memcpy_tofs(to, &isym, sizeof isym);
369 ++to;
370
371 if (mp->symtab != NULL) {
372 for (i = mp->symtab->n_symbols,
373 from = mp->symtab->symbol;
374 i > 0; --i, ++from, ++to) {
375
376 isym.value = (unsigned long)from->addr;
377 strncpy(isym.name, from->name, sizeof isym.name);
378 memcpy_tofs(to, &isym, sizeof isym);
379 }
380 }
381 }
382 }
383 }
384
385 return nmodsyms;
386 }
387
388
389
390
391
392 int
393 get_mod_name(char *user_name, char *buf)
394 {
395 int i;
396
397 i = 0;
398 for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
399 if (++i >= MOD_MAX_NAME)
400 return -E2BIG;
401 }
402 return 0;
403 }
404
405
406
407
408
409 struct module *
410 find_module( const char *name)
411 {
412 struct module *mp;
413
414 for (mp = module_list ; mp ; mp = mp->next) {
415 if (mp->state == MOD_DELETED)
416 continue;
417 if (!strcmp(mp->name, name))
418 break;
419 }
420 return mp;
421 }
422
423 static void
424 drop_refs(struct module *mp)
425 {
426 struct module *step;
427 struct module_ref *prev;
428 struct module_ref *ref;
429
430 for (step = module_list; step; step = step->next) {
431 for (prev = ref = step->ref; ref; ref = prev->next) {
432 if (ref->module == mp) {
433 if (ref == step->ref)
434 step->ref = ref->next;
435 else
436 prev->next = ref->next;
437 break;
438 }
439 else
440 prev = ref;
441 }
442 }
443 }
444
445
446
447
448
449 int
450 free_modules( void)
451 {
452 struct module *mp;
453 struct module **mpp;
454 int did_deletion;
455
456 did_deletion = 0;
457 freeing_modules = 0;
458 mpp = &module_list;
459 while ((mp = *mpp) != NULL) {
460 if (mp->state != MOD_DELETED) {
461 mpp = &mp->next;
462 } else {
463 if ((GET_USE_COUNT(mp) != 0) || (mp->ref != NULL)) {
464 freeing_modules = 1;
465 mpp = &mp->next;
466 } else {
467 *mpp = mp->next;
468 if (mp->symtab) {
469 if (mp->symtab->n_refs)
470 drop_refs(mp);
471 if (mp->symtab->size)
472 kfree_s(mp->symtab, mp->symtab->size);
473 }
474 vfree(mp->addr);
475 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
476 did_deletion = 1;
477 }
478 }
479 }
480 return did_deletion;
481 }
482
483
484
485
486
487 int get_module_list(char *buf)
488 {
489 char *p;
490 const char *q;
491 int i;
492 struct module *mp;
493 struct module_ref *ref;
494 char size[32];
495
496 p = buf;
497
498 for (mp = module_list ; mp && mp->next; mp = mp->next) {
499 if (p - buf > 4096 - 100)
500 break;
501 q = mp->name;
502 if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
503 continue;
504 i = 20;
505 while (*q) {
506 *p++ = *q++;
507 i--;
508 }
509 sprintf(size, "%d", mp->size);
510 i -= strlen(size);
511 if (i <= 0)
512 i = 1;
513 while (--i >= 0)
514 *p++ = ' ';
515 q = size;
516 while (*q)
517 *p++ = *q++;
518 if (mp->state == MOD_UNINITIALIZED)
519 q = " (uninitialized)";
520 else if (mp->state == MOD_RUNNING)
521 q = "";
522 else if (mp->state == MOD_DELETED)
523 q = " (deleted)";
524 else
525 q = " (bad state)";
526 while (*q)
527 *p++ = *q++;
528
529 if ((ref = mp->ref) != NULL) {
530 *p++ = '\t';
531 *p++ = '[';
532 for (; ref; ref = ref->next) {
533 q = ref->module->name;
534 while (*q)
535 *p++ = *q++;
536 if (ref->next)
537 *p++ = ' ';
538 }
539 *p++ = ']';
540 }
541 if (mp->state == MOD_RUNNING) {
542 sprintf(size,"\t%ld%s",
543 GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN,
544 ((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
545 " (autoclean)":""));
546 q = size;
547 while (*q)
548 *p++ = *q++;
549 }
550 *p++ = '\n';
551 }
552 return p - buf;
553 }
554
555
556
557
558
559 int get_ksyms_list(char *buf, char **start, off_t offset, int length)
560 {
561 struct module *mp;
562 struct internal_symbol *sym;
563 int i;
564 char *p = buf;
565 int len = 0;
566 off_t pos = 0;
567 off_t begin = 0;
568
569 for (mp = module_list; mp; mp = mp->next) {
570 if ((mp->state == MOD_RUNNING) &&
571 (mp->symtab != NULL) &&
572 (mp->symtab->n_symbols > 0)) {
573 for (i = mp->symtab->n_symbols,
574 sym = mp->symtab->symbol;
575 i > 0; --i, ++sym) {
576
577 p = buf + len;
578 if (mp->name[0]) {
579 len += sprintf(p, "%08lx %s\t[%s]\n",
580 (long)sym->addr,
581 sym->name, mp->name);
582 } else {
583 len += sprintf(p, "%08lx %s\n",
584 (long)sym->addr,
585 sym->name);
586 }
587 pos = begin + len;
588 if (pos < offset) {
589 len = 0;
590 begin = pos;
591 }
592 pos = begin + len;
593 if (pos > offset+length)
594 goto leave_the_loop;
595 }
596 }
597 }
598 leave_the_loop:
599 *start = buf + (offset - begin);
600 len -= (offset - begin);
601 if (len > length)
602 len = length;
603 return len;
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 && (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 }
762
763 #else
764
765
766
767 asmlinkage unsigned long sys_create_module(void)
768 {
769 return -ENOSYS;
770 }
771
772 asmlinkage int sys_init_module(void)
773 {
774 return -ENOSYS;
775 }
776
777 asmlinkage int sys_delete_module(void)
778 {
779 return -ENOSYS;
780 }
781
782 asmlinkage int sys_get_kernel_syms(void)
783 {
784 return -ENOSYS;
785 }
786
787 int register_symtab(struct symbol_table *intab)
788 {
789 return 0;
790 }
791
792 #endif
793