modutils.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. const char *from;
  46. if (filename == NULL)
  47. return NULL;
  48. if (modname == NULL)
  49. modname = xmalloc(MODULE_NAME_LEN);
  50. // Disabled since otherwise "modprobe dir/name" would work
  51. // as if it is "modprobe name". It is unclear why
  52. // 'basenamization' was here in the first place.
  53. //from = bb_get_last_path_component_nostrip(filename);
  54. from = filename;
  55. for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
  56. modname[i] = (from[i] == '-') ? '_' : from[i];
  57. modname[i] = '\0';
  58. return modname;
  59. }
  60. char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces)
  61. {
  62. char *options;
  63. int optlen;
  64. options = xzalloc(1);
  65. optlen = 0;
  66. while (*++argv) {
  67. const char *fmt;
  68. const char *var;
  69. const char *val;
  70. var = *argv;
  71. options = xrealloc(options, optlen + 2 + strlen(var) + 2);
  72. fmt = "%.*s%s ";
  73. val = strchrnul(var, '=');
  74. if (quote_spaces) {
  75. /*
  76. * modprobe (module-init-tools version 3.11.1) compat:
  77. * quote only value:
  78. * var="val with spaces", not "var=val with spaces"
  79. * (note: var *name* is not checked for spaces!)
  80. */
  81. if (*val) { /* has var=val format. skip '=' */
  82. val++;
  83. if (strchr(val, ' '))
  84. fmt = "%.*s\"%s\" ";
  85. }
  86. }
  87. optlen += sprintf(options + optlen, fmt, (int)(val - var), var, val);
  88. }
  89. /* Remove trailing space. Disabled */
  90. /* if (optlen != 0) options[optlen-1] = '\0'; */
  91. return options;
  92. }
  93. #if ENABLE_FEATURE_INSMOD_TRY_MMAP
  94. void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
  95. {
  96. /* We have user reports of failure to load 3MB module
  97. * on a 16MB RAM machine. Apparently even a transient
  98. * memory spike to 6MB during module load
  99. * is too big for that system. */
  100. void *image;
  101. struct stat st;
  102. int fd;
  103. fd = xopen(filename, O_RDONLY);
  104. fstat(fd, &st);
  105. image = NULL;
  106. /* st.st_size is off_t, we can't just pass it to mmap */
  107. if (st.st_size <= *image_size_p) {
  108. size_t image_size = st.st_size;
  109. image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0);
  110. if (image == MAP_FAILED) {
  111. image = NULL;
  112. } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) {
  113. /* No ELF signature. Compressed module? */
  114. munmap(image, image_size);
  115. image = NULL;
  116. } else {
  117. /* Success. Report the size */
  118. *image_size_p = image_size;
  119. }
  120. }
  121. close(fd);
  122. return image;
  123. }
  124. #endif
  125. /* Return:
  126. * 0 on success,
  127. * -errno on open/read error,
  128. * errno on init_module() error
  129. */
  130. int FAST_FUNC bb_init_module(const char *filename, const char *options)
  131. {
  132. size_t image_size;
  133. char *image;
  134. int rc;
  135. bool mmaped;
  136. if (!options)
  137. options = "";
  138. //TODO: audit bb_init_module_24 to match error code convention
  139. #if ENABLE_FEATURE_2_4_MODULES
  140. if (get_linux_version_code() < KERNEL_VERSION(2,6,0))
  141. return bb_init_module_24(filename, options);
  142. #endif
  143. image_size = INT_MAX - 4095;
  144. mmaped = 0;
  145. image = try_to_mmap_module(filename, &image_size);
  146. if (image) {
  147. mmaped = 1;
  148. } else {
  149. errno = ENOMEM; /* may be changed by e.g. open errors below */
  150. image = xmalloc_open_zipped_read_close(filename, &image_size);
  151. if (!image)
  152. return -errno;
  153. }
  154. errno = 0;
  155. init_module(image, image_size, options);
  156. rc = errno;
  157. if (mmaped)
  158. munmap(image, image_size);
  159. else
  160. free(image);
  161. return rc;
  162. }
  163. int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
  164. {
  165. errno = 0;
  166. delete_module(module, flags);
  167. return errno;
  168. }
  169. const char* FAST_FUNC moderror(int err)
  170. {
  171. switch (err) {
  172. case -1: /* btw: it's -EPERM */
  173. return "no such module";
  174. case ENOEXEC:
  175. return "invalid module format";
  176. case ENOENT:
  177. return "unknown symbol in module, or unknown parameter";
  178. case ESRCH:
  179. return "module has wrong symbol version";
  180. case ENOSYS:
  181. return "kernel does not support requested operation";
  182. }
  183. if (err < 0) /* should always be */
  184. err = -err;
  185. return strerror(err);
  186. }