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