Import 2.1.124pre1
[davej-history.git] / kernel / exec_domain.c
blob5d7e2f056c9cd15abb81e91f900cba052b6239a3
1 #include <linux/personality.h>
2 #include <linux/ptrace.h>
3 #include <linux/sched.h>
4 #include <linux/mm.h>
5 #include <linux/smp.h>
6 #include <linux/smp_lock.h>
7 #include <linux/module.h>
9 static asmlinkage void no_lcall7(struct pt_regs * regs);
12 static unsigned long ident_map[32] = {
13 0, 1, 2, 3, 4, 5, 6, 7,
14 8, 9, 10, 11, 12, 13, 14, 15,
15 16, 17, 18, 19, 20, 21, 22, 23,
16 24, 25, 26, 27, 28, 29, 30, 31
19 struct exec_domain default_exec_domain = {
20 "Linux", /* name */
21 no_lcall7, /* lcall7 causes a seg fault. */
22 0, 0xff, /* All personalities. */
23 ident_map, /* Identity map signals. */
24 ident_map, /* - both ways. */
25 NULL, /* No usage counter. */
26 NULL /* Nothing after this in the list. */
29 static struct exec_domain *exec_domains = &default_exec_domain;
32 static asmlinkage void no_lcall7(struct pt_regs * regs)
36 * This may have been a static linked SVr4 binary, so we would have the
37 * personality set incorrectly. Check to see whether SVr4 is available,
38 * and use it, otherwise give the user a SEGV.
40 if (current->exec_domain && current->exec_domain->module)
41 __MOD_DEC_USE_COUNT(current->exec_domain->module);
43 current->personality = PER_SVR4;
44 current->exec_domain = lookup_exec_domain(current->personality);
46 if (current->exec_domain && current->exec_domain->module)
47 __MOD_INC_USE_COUNT(current->exec_domain->module);
49 if (current->exec_domain && current->exec_domain->handler
50 && current->exec_domain->handler != no_lcall7) {
51 current->exec_domain->handler(regs);
52 return;
55 send_sig(SIGSEGV, current, 1);
58 struct exec_domain *lookup_exec_domain(unsigned long personality)
60 unsigned long pers = personality & PER_MASK;
61 struct exec_domain *it;
63 for (it=exec_domains; it; it=it->next)
64 if (pers >= it->pers_low
65 && pers <= it->pers_high)
66 return it;
68 /* Should never get this far. */
69 printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
70 return NULL;
73 int register_exec_domain(struct exec_domain *it)
75 struct exec_domain *tmp;
77 if (!it)
78 return -EINVAL;
79 if (it->next)
80 return -EBUSY;
81 for (tmp=exec_domains; tmp; tmp=tmp->next)
82 if (tmp == it)
83 return -EBUSY;
84 it->next = exec_domains;
85 exec_domains = it;
86 return 0;
89 int unregister_exec_domain(struct exec_domain *it)
91 struct exec_domain ** tmp;
93 tmp = &exec_domains;
94 while (*tmp) {
95 if (it == *tmp) {
96 *tmp = it->next;
97 it->next = NULL;
98 return 0;
100 tmp = &(*tmp)->next;
102 return -EINVAL;
105 asmlinkage int sys_personality(unsigned long personality)
107 struct exec_domain *it;
108 unsigned long old_personality;
109 int ret;
111 lock_kernel();
112 ret = current->personality;
113 if (personality == 0xffffffff)
114 goto out;
116 ret = -EINVAL;
117 it = lookup_exec_domain(personality);
118 if (!it)
119 goto out;
121 old_personality = current->personality;
122 if (current->exec_domain && current->exec_domain->module)
123 __MOD_DEC_USE_COUNT(current->exec_domain->module);
124 current->personality = personality;
125 current->exec_domain = it;
126 if (current->exec_domain->module)
127 __MOD_INC_USE_COUNT(current->exec_domain->module);
128 ret = old_personality;
129 out:
130 unlock_kernel();
131 return ret;