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
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 #ifdef DEBUG_MODULE
29 #define PRINTK(a) printk a
30 #else
31 #define PRINTK(a)
32 #endif
33
34 static struct module kernel_module;
35 static struct module *module_list = &kernel_module;
36
37 static int freeing_modules;
38
39 static struct module *find_module( const char *name);
40 static int get_mod_name( char *user_name, char *buf);
41 static int free_modules( void);
42
43
44
45
46
47 void init_modules(void) {
48 extern struct symbol_table symbol_table;
49 struct internal_symbol *sym;
50 int i;
51
52 for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
53 ;
54 symbol_table.n_symbols = i;
55
56 kernel_module.symtab = &symbol_table;
57 kernel_module.state = MOD_RUNNING;
58 kernel_module.name = "";
59 }
60
61 int
62 rename_module_symbol(char *old_name, char *new_name)
63 {
64 struct internal_symbol *sym;
65 int i = 0;
66
67 if (module_list->symtab) {
68 sym = module_list->symtab->symbol;
69 for (i = module_list->symtab->n_symbols; i > 0; ++sym, --i) {
70 if (strcmp(sym->name, old_name) == 0) {
71 sym->name = new_name;
72 PRINTK(("renamed %s to %s\n", old_name, new_name));
73 return 1;
74 }
75 }
76 }
77 printk("rename %s to %s failed!\n", old_name, new_name);
78 return 0;
79
80
81
82
83
84
85
86
87
88
89
90
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 asmlinkage unsigned long
121 sys_create_module(char *module_name, unsigned long size)
122 {
123 struct module *mp;
124 void* addr;
125 int error;
126 int npages;
127 int sspace = sizeof(struct module) + MOD_MAX_NAME;
128 char name[MOD_MAX_NAME];
129
130 if (!suser())
131 return -EPERM;
132 if (module_name == NULL || size == 0)
133 return -EINVAL;
134 if ((error = get_mod_name(module_name, name)) != 0)
135 return error;
136 if (find_module(name) != NULL) {
137 return -EEXIST;
138 }
139
140 if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
141 return -ENOMEM;
142 }
143 strcpy((char *)(mp + 1), name);
144
145 npages = (size + sizeof (int) + 4095) / 4096;
146 if ((addr = vmalloc(npages * 4096)) == 0) {
147 kfree_s(mp, sspace);
148 return -ENOMEM;
149 }
150
151 mp->next = module_list;
152 mp->ref = NULL;
153 mp->symtab = NULL;
154 mp->name = (char *)(mp + 1);
155 mp->size = npages;
156 mp->addr = addr;
157 mp->state = MOD_UNINITIALIZED;
158 mp->cleanup = NULL;
159
160 * (int *) addr = 0;
161 module_list = mp;
162
163 PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
164 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
165 return (unsigned long) addr;
166 }
167
168
169
170
171 asmlinkage int
172 sys_init_module(char *module_name, char *code, unsigned codesize,
173 struct mod_routines *routines,
174 struct symbol_table *symtab)
175 {
176 struct module *mp;
177 struct symbol_table *newtab;
178 char name[MOD_MAX_NAME];
179 int error;
180 struct mod_routines rt;
181
182 if (!suser())
183 return -EPERM;
184
185
186 if (symtab && ((unsigned long)symtab > 0xb0000000)) {
187 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
188 symtab = NULL;
189 }
190
191
192
193
194
195
196 free_modules();
197
198 if ((error = get_mod_name(module_name, name)) != 0)
199 return error;
200 PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
201 name, codesize, codesize));
202 memcpy_fromfs(&rt, routines, sizeof rt);
203 if ((mp = find_module(name)) == NULL)
204 return -ENOENT;
205 if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
206 return -EINVAL;
207 memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
208 memset((char *)mp->addr + sizeof (int) + codesize, 0,
209 mp->size * 4096 - (codesize + sizeof (int)));
210 PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
211 (unsigned long) rt.init, (unsigned long) rt.cleanup));
212 mp->cleanup = rt.cleanup;
213
214
215 if (symtab) {
216 struct internal_symbol *sym;
217 struct module_ref *ref;
218 int size;
219 int i;
220 int legal_start;
221
222 if ((error = verify_area(VERIFY_READ, symtab, sizeof(int))))
223 return error;
224 memcpy_fromfs((char *)(&(size)), symtab, sizeof(int));
225
226 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
227 return -ENOMEM;
228 }
229
230 if ((error = verify_area(VERIFY_READ, symtab, size))) {
231 kfree_s(newtab, size);
232 return error;
233 }
234 memcpy_fromfs((char *)(newtab), symtab, size);
235
236
237 legal_start = sizeof(struct symbol_table) +
238 newtab->n_symbols * sizeof(struct internal_symbol) +
239 newtab->n_refs * sizeof(struct module_ref);
240
241 if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) ||
242 (legal_start > size)) {
243 printk("Illegal symbol table! Rejected!\n");
244 kfree_s(newtab, size);
245 return -EINVAL;
246 }
247
248
249 for (sym = &(newtab->symbol[0]), i = 0;
250 i < newtab->n_symbols; ++sym, ++i) {
251 if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
252 printk("Illegal symbol table! Rejected!\n");
253 kfree_s(newtab, size);
254 return -EINVAL;
255 }
256
257 sym->name += (long)newtab;
258 }
259 mp->symtab = newtab;
260
261
262
263
264
265
266
267
268
269 for (ref = (struct module_ref *)sym, i = 0;
270 i < newtab->n_refs; ++ref, ++i) {
271
272
273 struct module *link = module_list;
274 while (link && (ref->module != link))
275 link = link->next;
276
277 if (link == (struct module *)0) {
278 printk("Non-module reference! Rejected!\n");
279 return -EINVAL;
280 }
281
282 ref->next = ref->module->ref;
283 ref->module->ref = ref;
284 ref->module = mp;
285 }
286 }
287
288 if ((*rt.init)() != 0)
289 return -EBUSY;
290 mp->state = MOD_RUNNING;
291
292 return 0;
293 }
294
295 asmlinkage int
296 sys_delete_module(char *module_name)
297 {
298 struct module *mp;
299 char name[MOD_MAX_NAME];
300 int error;
301
302 if (!suser())
303 return -EPERM;
304
305 if (module_name != NULL) {
306 if ((error = get_mod_name(module_name, name)) != 0)
307 return error;
308 if ((mp = find_module(name)) == NULL)
309 return -ENOENT;
310 if ((mp->ref != NULL) || (GET_USE_COUNT(mp) != 0))
311 return -EBUSY;
312 if (mp->state == MOD_RUNNING)
313 (*mp->cleanup)();
314 mp->state = MOD_DELETED;
315 }
316 free_modules();
317 return 0;
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342 asmlinkage int
343 sys_get_kernel_syms(struct kernel_sym *table)
344 {
345 struct internal_symbol *from;
346 struct kernel_sym isym;
347 struct kernel_sym *to;
348 struct module *mp = module_list;
349 int i;
350 int nmodsyms = 0;
351
352 for (mp = module_list; mp; mp = mp->next) {
353 if (mp->symtab && mp->symtab->n_symbols) {
354
355 nmodsyms += mp->symtab->n_symbols + 1;
356 }
357 }
358
359 if (table != NULL) {
360 to = table;
361
362 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
363 return i;
364
365
366 for (mp = module_list; mp; mp = mp->next) {
367 if ((mp->state == MOD_RUNNING) &&
368 (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
369
370 isym.value = (unsigned long)mp;
371 sprintf(isym.name, "#%s", mp->name);
372 memcpy_tofs(to, &isym, sizeof isym);
373 ++to;
374
375 for (i = mp->symtab->n_symbols,
376 from = mp->symtab->symbol;
377 i > 0; --i, ++from, ++to) {
378
379 isym.value = (unsigned long)from->addr;
380 strncpy(isym.name, from->name, sizeof isym.name);
381 memcpy_tofs(to, &isym, sizeof isym);
382 }
383 }
384 }
385 }
386
387 return nmodsyms;
388 }
389
390
391
392
393
394 int
395 get_mod_name(char *user_name, char *buf)
396 {
397 int i;
398
399 i = 0;
400 for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
401 if (++i >= MOD_MAX_NAME)
402 return -E2BIG;
403 }
404 return 0;
405 }
406
407
408
409
410
411 struct module *
412 find_module( const char *name)
413 {
414 struct module *mp;
415
416 for (mp = module_list ; mp ; mp = mp->next) {
417 if (mp->state == MOD_DELETED)
418 continue;
419 if (!strcmp(mp->name, name))
420 break;
421 }
422 return mp;
423 }
424
425 static void
426 drop_refs(struct module *mp)
427 {
428 struct module *step;
429 struct module_ref *prev;
430 struct module_ref *ref;
431
432 for (step = module_list; step; step = step->next) {
433 for (prev = ref = step->ref; ref; ref = prev->next) {
434 if (ref->module == mp) {
435 if (ref == step->ref)
436 step->ref = ref->next;
437 else
438 prev->next = ref->next;
439 break;
440 }
441 else
442 prev = ref;
443 }
444 }
445 }
446
447
448
449
450
451 int
452 free_modules( void)
453 {
454 struct module *mp;
455 struct module **mpp;
456 int did_deletion;
457
458 did_deletion = 0;
459 freeing_modules = 0;
460 mpp = &module_list;
461 while ((mp = *mpp) != NULL) {
462 if (mp->state != MOD_DELETED) {
463 mpp = &mp->next;
464 } else {
465 if (GET_USE_COUNT(mp) != 0) {
466 freeing_modules = 1;
467 mpp = &mp->next;
468 } else {
469 *mpp = mp->next;
470 if (mp->symtab) {
471 if (mp->symtab->n_refs)
472 drop_refs(mp);
473 if (mp->symtab->size)
474 kfree_s(mp->symtab, mp->symtab->size);
475 }
476 vfree(mp->addr);
477 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
478 did_deletion = 1;
479 }
480 }
481 }
482 return did_deletion;
483 }
484
485
486
487
488
489 int get_module_list(char *buf)
490 {
491 char *p;
492 char *q;
493 int i;
494 struct module *mp;
495 struct module_ref *ref;
496 char size[32];
497
498 p = buf;
499
500 for (mp = module_list ; mp && mp->next; mp = mp->next) {
501 if (p - buf > 4096 - 100)
502 break;
503 q = mp->name;
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 *p++ = '\n';
542 }
543 return p - buf;
544 }
545
546
547
548
549
550 int get_ksyms_list(char *buf)
551 {
552 struct module *mp;
553 struct internal_symbol *sym;
554 int i;
555 char *p = buf;
556
557 for (mp = module_list; mp; mp = mp->next) {
558 if ((mp->state == MOD_RUNNING) &&
559 (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
560 for (i = mp->symtab->n_symbols,
561 sym = mp->symtab->symbol;
562 i > 0; --i, ++sym) {
563
564 if (p - buf > 4096 - 100) {
565 strcat(p, "...\n");
566 p += strlen(p);
567 return p - buf;
568 }
569
570 if (mp->name[0]) {
571 sprintf(p, "%08lx %s\t[%s]\n",
572 (long)sym->addr, sym->name, mp->name);
573 }
574 else {
575 sprintf(p, "%08lx %s\n",
576 (long)sym->addr, sym->name);
577 }
578 p += strlen(p);
579 }
580 }
581 }
582
583 return p - buf;
584 }