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