Import 2.3.30pre1
[davej-history.git] / kernel / exec_domain.c
blobc31678a4e2c088d9fb6060d4d1f38d3cc3e83aa2
1 #include <linux/mm.h>
2 #include <linux/smp_lock.h>
3 #include <linux/module.h>
5 static asmlinkage void no_lcall7(int segment, struct pt_regs * regs);
8 static unsigned long ident_map[32] = {
9 0, 1, 2, 3, 4, 5, 6, 7,
10 8, 9, 10, 11, 12, 13, 14, 15,
11 16, 17, 18, 19, 20, 21, 22, 23,
12 24, 25, 26, 27, 28, 29, 30, 31
15 struct exec_domain default_exec_domain = {
16 "Linux", /* name */
17 no_lcall7, /* lcall7 causes a seg fault. */
18 0, 0xff, /* All personalities. */
19 ident_map, /* Identity map signals. */
20 ident_map, /* - both ways. */
21 NULL, /* No usage counter. */
22 NULL /* Nothing after this in the list. */
25 static struct exec_domain *exec_domains = &default_exec_domain;
28 static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
31 * This may have been a static linked SVr4 binary, so we would have the
32 * personality set incorrectly. Check to see whether SVr4 is available,
33 * and use it, otherwise give the user a SEGV.
35 if (current->exec_domain && current->exec_domain->module)
36 __MOD_DEC_USE_COUNT(current->exec_domain->module);
38 current->personality = PER_SVR4;
39 current->exec_domain = lookup_exec_domain(current->personality);
41 if (current->exec_domain && current->exec_domain->module)
42 __MOD_INC_USE_COUNT(current->exec_domain->module);
44 if (current->exec_domain && current->exec_domain->handler
45 && current->exec_domain->handler != no_lcall7) {
46 current->exec_domain->handler(segment, regs);
47 return;
50 send_sig(SIGSEGV, current, 1);
53 struct exec_domain *lookup_exec_domain(unsigned long personality)
55 unsigned long pers = personality & PER_MASK;
56 struct exec_domain *it;
58 for (it=exec_domains; it; it=it->next)
59 if (pers >= it->pers_low
60 && pers <= it->pers_high)
61 return it;
63 /* Should never get this far. */
64 printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
65 return NULL;
68 int register_exec_domain(struct exec_domain *it)
70 struct exec_domain *tmp;
72 if (!it)
73 return -EINVAL;
74 if (it->next)
75 return -EBUSY;
76 for (tmp=exec_domains; tmp; tmp=tmp->next)
77 if (tmp == it)
78 return -EBUSY;
79 it->next = exec_domains;
80 exec_domains = it;
81 return 0;
84 int unregister_exec_domain(struct exec_domain *it)
86 struct exec_domain ** tmp;
88 tmp = &exec_domains;
89 while (*tmp) {
90 if (it == *tmp) {
91 *tmp = it->next;
92 it->next = NULL;
93 return 0;
95 tmp = &(*tmp)->next;
97 return -EINVAL;
100 asmlinkage long sys_personality(unsigned long personality)
102 struct exec_domain *it;
103 unsigned long old_personality;
104 int ret;
106 lock_kernel();
107 ret = current->personality;
108 if (personality == 0xffffffff)
109 goto out;
111 ret = -EINVAL;
112 it = lookup_exec_domain(personality);
113 if (!it)
114 goto out;
116 old_personality = current->personality;
117 if (current->exec_domain && current->exec_domain->module)
118 __MOD_DEC_USE_COUNT(current->exec_domain->module);
119 current->personality = personality;
120 current->exec_domain = it;
121 if (current->exec_domain->module)
122 __MOD_INC_USE_COUNT(current->exec_domain->module);
123 ret = old_personality;
124 out:
125 unlock_kernel();
126 return ret;
129 int get_exec_domain_list(char * page)
131 int len = 0;
132 struct exec_domain * e;
134 for (e=exec_domains; e && len < PAGE_SIZE - 80; e=e->next)
135 len += sprintf(page+len, "%d-%d\t%-16s\t[%s]\n",
136 e->pers_low, e->pers_high, e->name,
137 e->module ? e->module->name : "kernel");
138 return len;