modutils.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Common modutils related functions for busybox
  3. *
  4. * Copyright (C) 2008 by Timo Teras <timo.teras@iki.fi>
  5. *
  6. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  7. */
  8. #include "modutils.h"
  9. #ifdef __UCLIBC__
  10. extern int init_module(void *module, unsigned long len, const char *options);
  11. extern int delete_module(const char *module, unsigned int flags);
  12. #else
  13. # include <sys/syscall.h>
  14. # define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
  15. # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
  16. #endif
  17. void FAST_FUNC replace(char *s, char what, char with)
  18. {
  19. while (*s) {
  20. if (what == *s)
  21. *s = with;
  22. ++s;
  23. }
  24. }
  25. char* FAST_FUNC replace_underscores(char *s)
  26. {
  27. replace(s, '-', '_');
  28. return s;
  29. }
  30. int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim)
  31. {
  32. char *tok;
  33. int len = 0;
  34. while ((tok = strsep(&string, delim)) != NULL) {
  35. if (tok[0] == '\0')
  36. continue;
  37. llist_add_to_end(llist, xstrdup(tok));
  38. len += strlen(tok);
  39. }
  40. return len;
  41. }
  42. char* FAST_FUNC filename2modname(const char *filename, char *modname)
  43. {
  44. int i;
  45. char *from;
  46. if (filename == NULL)
  47. return NULL;
  48. if (modname == NULL)
  49. modname = xmalloc(MODULE_NAME_LEN);
  50. from = bb_get_last_path_component_nostrip(filename);
  51. for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
  52. modname[i] = (from[i] == '-') ? '_' : from[i];
  53. modname[i] = '\0';
  54. return modname;
  55. }
  56. char* FAST_FUNC parse_cmdline_module_options(char **argv)
  57. {
  58. char *options;
  59. int optlen;
  60. options = xzalloc(1);
  61. optlen = 0;
  62. while (*++argv) {
  63. options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
  64. /* Older versions were enclosing space-containing *argv in "",
  65. * but both modprobe and insmod from module-init-tools 3.11.1
  66. * don't do this anymore. (As to extra trailing space,
  67. * insmod adds it but modprobe does not. We do in both cases)
  68. */
  69. optlen += sprintf(options + optlen, "%s ", *argv);
  70. }
  71. return options;
  72. }
  73. #if ENABLE_FEATURE_INSMOD_TRY_MMAP
  74. void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
  75. {
  76. /* We have user reports of failure to load 3MB module
  77. * on a 16MB RAM machine. Apparently even a transient
  78. * memory spike to 6MB during module load
  79. * is too big for that system. */
  80. void *image;
  81. struct stat st;
  82. int fd;
  83. fd = xopen(filename, O_RDONLY);
  84. fstat(fd, &st);
  85. image = NULL;
  86. /* st.st_size is off_t, we can't just pass it to mmap */
  87. if (st.st_size <= *image_size_p) {
  88. size_t image_size = st.st_size;
  89. image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0);
  90. if (image == MAP_FAILED) {
  91. image = NULL;
  92. } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) {
  93. /* No ELF signature. Compressed module? */
  94. munmap(image, image_size);
  95. image = NULL;
  96. } else {
  97. /* Success. Report the size */
  98. *image_size_p = image_size;
  99. }
  100. }
  101. close(fd);
  102. return image;
  103. }
  104. #endif
  105. /* Return:
  106. * 0 on success,
  107. * -errno on open/read error,
  108. * errno on init_module() error
  109. */
  110. int FAST_FUNC bb_init_module(const char *filename, const char *options)
  111. {
  112. size_t image_size;
  113. char *image;
  114. int rc;
  115. bool mmaped;
  116. if (!options)
  117. options = "";
  118. //TODO: audit bb_init_module_24 to match error code convention
  119. #if ENABLE_FEATURE_2_4_MODULES
  120. if (get_linux_version_code() < KERNEL_VERSION(2,6,0))
  121. return bb_init_module_24(filename, options);
  122. #endif
  123. image_size = INT_MAX - 4095;
  124. mmaped = 0;
  125. image = try_to_mmap_module(filename, &image_size);
  126. if (image) {
  127. mmaped = 1;
  128. } else {
  129. errno = ENOMEM; /* may be changed by e.g. open errors below */
  130. image = xmalloc_open_zipped_read_close(filename, &image_size);
  131. if (!image)
  132. return -errno;
  133. }
  134. errno = 0;
  135. init_module(image, image_size, options);
  136. rc = errno;
  137. if (mmaped)
  138. munmap(image, image_size);
  139. else
  140. free(image);
  141. return rc;
  142. }
  143. int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
  144. {
  145. errno = 0;
  146. delete_module(module, flags);
  147. return errno;
  148. }
  149. const char* FAST_FUNC moderror(int err)
  150. {
  151. switch (err) {
  152. case -1: /* btw: it's -EPERM */
  153. return "no such module";
  154. case ENOEXEC:
  155. return "invalid module format";
  156. case ENOENT:
  157. return "unknown symbol in module, or unknown parameter";
  158. case ESRCH:
  159. return "module has wrong symbol version";
  160. case ENOSYS:
  161. return "kernel does not support requested operation";
  162. }
  163. if (err < 0) /* should always be */
  164. err = -err;
  165. return strerror(err);
  166. }