exec_domain.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Handling of different ABIs (personalities).
  3.  *
  4.  * We group personalities into execution domains which have their
  5.  * own handlers for kernel entry points, signal mapping, etc...
  6.  *
  7.  * 2001-05-06 Complete rewrite,  Christoph Hellwig (hch@infradead.org)
  8.  */
  9. #include <linux/config.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/kmod.h>
  13. #include <linux/module.h>
  14. #include <linux/personality.h>
  15. #include <linux/sched.h>
  16. #include <linux/sysctl.h>
  17. #include <linux/types.h>
  18. static void default_handler(int, struct pt_regs *);
  19. static struct exec_domain *exec_domains = &default_exec_domain;
  20. static rwlock_t exec_domains_lock = RW_LOCK_UNLOCKED;
  21. static u_long ident_map[32] = {
  22. 0, 1, 2, 3, 4, 5, 6, 7,
  23. 8, 9, 10, 11, 12, 13, 14, 15,
  24. 16, 17, 18, 19, 20, 21, 22, 23,
  25. 24, 25, 26, 27, 28, 29, 30, 31
  26. };
  27. struct exec_domain default_exec_domain = {
  28. "Linux", /* name */
  29. default_handler, /* lcall7 causes a seg fault. */
  30. 0, 0, /* PER_LINUX personality. */
  31. ident_map, /* Identity map signals. */
  32. ident_map, /*  - both ways. */
  33. };
  34. static void
  35. default_handler(int segment, struct pt_regs *regp)
  36. {
  37. u_long pers = 0;
  38. /*
  39.  * This may have been a static linked SVr4 binary, so we would
  40.  * have the personality set incorrectly. Or it might have been
  41.  * a Solaris/x86 binary. We can tell which because the former
  42.  * uses lcall7, while the latter used lcall 0x27.
  43.  * Try to find or load the appropriate personality, and fall back
  44.  * to just forcing a SEGV.
  45.  *
  46.  * XXX: this is IA32-specific and should be moved to the MD-tree.
  47.  */
  48. switch (segment) {
  49. #ifdef __i386__
  50. case 0x07:
  51. pers = abi_defhandler_lcall7;
  52. break;
  53. case 0x27:
  54. pers = PER_SOLARIS;
  55. break;
  56. #endif
  57. }
  58. set_personality(pers);
  59. if (current->exec_domain->handler != default_handler)
  60. current->exec_domain->handler(segment, regp);
  61. else
  62. send_sig(SIGSEGV, current, 1);
  63. }
  64. static struct exec_domain *
  65. lookup_exec_domain(u_long personality)
  66. {
  67. struct exec_domain * ep;
  68. u_long pers = personality(personality);
  69. read_lock(&exec_domains_lock);
  70. for (ep = exec_domains; ep; ep = ep->next) {
  71. if (pers >= ep->pers_low && pers <= ep->pers_high)
  72. if (try_inc_mod_count(ep->module))
  73. goto out;
  74. }
  75. #ifdef CONFIG_KMOD
  76. read_unlock(&exec_domains_lock);
  77. {
  78. char buffer[30];
  79. sprintf(buffer, "personality-%ld", pers);
  80. request_module(buffer);
  81. }
  82. read_lock(&exec_domains_lock);
  83. for (ep = exec_domains; ep; ep = ep->next) {
  84. if (pers >= ep->pers_low && pers <= ep->pers_high)
  85. if (try_inc_mod_count(ep->module))
  86. goto out;
  87. }
  88. #endif
  89. ep = &default_exec_domain;
  90. out:
  91. read_unlock(&exec_domains_lock);
  92. return (ep);
  93. }
  94. int
  95. register_exec_domain(struct exec_domain *ep)
  96. {
  97. struct exec_domain *tmp;
  98. int err = -EBUSY;
  99. if (ep == NULL)
  100. return -EINVAL;
  101. if (ep->next != NULL)
  102. return -EBUSY;
  103. write_lock(&exec_domains_lock);
  104. for (tmp = exec_domains; tmp; tmp = tmp->next) {
  105. if (tmp == ep)
  106. goto out;
  107. }
  108. ep->next = exec_domains;
  109. exec_domains = ep;
  110. err = 0;
  111. out:
  112. write_unlock(&exec_domains_lock);
  113. return (err);
  114. }
  115. int
  116. unregister_exec_domain(struct exec_domain *ep)
  117. {
  118. struct exec_domain **epp;
  119. epp = &exec_domains;
  120. write_lock(&exec_domains_lock);
  121. for (epp = &exec_domains; *epp; epp = &(*epp)->next) {
  122. if (ep == *epp)
  123. goto unregister;
  124. }
  125. write_unlock(&exec_domains_lock);
  126. return -EINVAL;
  127. unregister:
  128. *epp = ep->next;
  129. ep->next = NULL;
  130. write_unlock(&exec_domains_lock);
  131. return 0;
  132. }
  133. int
  134. __set_personality(u_long personality)
  135. {
  136. struct exec_domain *ep, *oep;
  137. ep = lookup_exec_domain(personality);
  138. if (ep == current->exec_domain) {
  139. current->personality = personality;
  140. return 0;
  141. }
  142. if (atomic_read(&current->fs->count) != 1) {
  143. struct fs_struct *fsp, *ofsp;
  144. fsp = copy_fs_struct(current->fs);
  145. if (fsp == NULL) {
  146. put_exec_domain(ep);
  147. return -ENOMEM;;
  148. }
  149. task_lock(current);
  150. ofsp = current->fs;
  151. current->fs = fsp;
  152. task_unlock(current);
  153. put_fs_struct(ofsp);
  154. }
  155. /*
  156.  * At that point we are guaranteed to be the sole owner of
  157.  * current->fs.
  158.  */
  159. current->personality = personality;
  160. oep = current->exec_domain;
  161. current->exec_domain = ep;
  162. set_fs_altroot();
  163. put_exec_domain(oep);
  164. printk(KERN_DEBUG "[%s:%d]: set personality to %lxn",
  165. current->comm, current->pid, personality);
  166. return 0;
  167. }
  168. int
  169. get_exec_domain_list(char *page)
  170. {
  171. struct exec_domain *ep;
  172. int len = 0;
  173. read_lock(&exec_domains_lock);
  174. for (ep = exec_domains; ep && len < PAGE_SIZE - 80; ep = ep->next)
  175. len += sprintf(page + len, "%d-%dt%-16st[%s]n",
  176. ep->pers_low, ep->pers_high, ep->name,
  177. ep->module ? ep->module->name : "kernel");
  178. read_unlock(&exec_domains_lock);
  179. return (len);
  180. }
  181. asmlinkage long
  182. sys_personality(u_long personality)
  183. {
  184. u_long old = current->personality;;
  185. if (personality != 0xffffffff) {
  186. set_personality(personality);
  187. if (current->personality != personality)
  188. return -EINVAL;
  189. }
  190. return (long)old;
  191. }
  192. EXPORT_SYMBOL(register_exec_domain);
  193. EXPORT_SYMBOL(unregister_exec_domain);
  194. EXPORT_SYMBOL(__set_personality);
  195. /*
  196.  * We have to have all sysctl handling for the Linux-ABI
  197.  * in one place as the dynamic registration of sysctls is
  198.  * horribly crufty in Linux <= 2.4.
  199.  *
  200.  * I hope the new sysctl schemes discussed for future versions
  201.  * will obsolete this.
  202.  *
  203.  *  --hch
  204.  */
  205. u_long abi_defhandler_coff = PER_SCOSVR3;
  206. u_long abi_defhandler_elf = PER_LINUX;
  207. u_long abi_defhandler_lcall7 = PER_SVR4;
  208. u_long abi_defhandler_libcso = PER_SVR4;
  209. u_int abi_traceflg;
  210. int abi_fake_utsname;
  211. static struct ctl_table abi_table[] = {
  212. {ABI_DEFHANDLER_COFF, "defhandler_coff", &abi_defhandler_coff,
  213. sizeof(int), 0644, NULL, &proc_doulongvec_minmax},
  214. {ABI_DEFHANDLER_ELF, "defhandler_elf", &abi_defhandler_elf,
  215. sizeof(int), 0644, NULL, &proc_doulongvec_minmax},
  216. {ABI_DEFHANDLER_LCALL7, "defhandler_lcall7", &abi_defhandler_lcall7,
  217. sizeof(int), 0644, NULL, &proc_doulongvec_minmax},
  218. {ABI_DEFHANDLER_LIBCSO, "defhandler_libcso", &abi_defhandler_libcso,
  219. sizeof(int), 0644, NULL, &proc_doulongvec_minmax},
  220. {ABI_TRACE, "trace", &abi_traceflg,
  221. sizeof(u_int), 0644, NULL, &proc_dointvec},
  222. {ABI_FAKE_UTSNAME, "fake_utsname", &abi_fake_utsname,
  223. sizeof(int), 0644, NULL, &proc_dointvec},
  224. {0}
  225. };
  226. static struct ctl_table abi_root_table[] = {
  227. {CTL_ABI, "abi", NULL, 0, 0555, abi_table},
  228. {0}
  229. };
  230. static int __init
  231. abi_register_sysctl(void)
  232. {
  233. register_sysctl_table(abi_root_table, 1);
  234. return 0;
  235. }
  236. __initcall(abi_register_sysctl);
  237. EXPORT_SYMBOL(abi_defhandler_coff);
  238. EXPORT_SYMBOL(abi_defhandler_elf);
  239. EXPORT_SYMBOL(abi_defhandler_lcall7);
  240. EXPORT_SYMBOL(abi_defhandler_libcso);
  241. EXPORT_SYMBOL(abi_traceflg);
  242. EXPORT_SYMBOL(abi_fake_utsname);