OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [kernel/] [exec_domain.c] - Blame information for rev 86

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
 
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/syscalls.h>
17
#include <linux/sysctl.h>
18
#include <linux/types.h>
19
 
20
 
21
static void default_handler(int, struct pt_regs *);
22
 
23
static struct exec_domain *exec_domains = &default_exec_domain;
24
static DEFINE_RWLOCK(exec_domains_lock);
25
 
26
 
27
static u_long ident_map[32] = {
28
        0,       1,      2,      3,      4,      5,      6,      7,
29
        8,      9,      10,     11,     12,     13,     14,     15,
30
        16,     17,     18,     19,     20,     21,     22,     23,
31
        24,     25,     26,     27,     28,     29,     30,     31
32
};
33
 
34
struct exec_domain default_exec_domain = {
35
        .name           = "Linux",              /* name */
36
        .handler        = default_handler,      /* lcall7 causes a seg fault. */
37
        .pers_low       = 0,                     /* PER_LINUX personality. */
38
        .pers_high      = 0,                     /* PER_LINUX personality. */
39
        .signal_map     = ident_map,            /* Identity map signals. */
40
        .signal_invmap  = ident_map,            /*  - both ways. */
41
};
42
 
43
 
44
static void
45
default_handler(int segment, struct pt_regs *regp)
46
{
47
        set_personality(0);
48
 
49
        if (current_thread_info()->exec_domain->handler != default_handler)
50
                current_thread_info()->exec_domain->handler(segment, regp);
51
        else
52
                send_sig(SIGSEGV, current, 1);
53
}
54
 
55
static struct exec_domain *
56
lookup_exec_domain(u_long personality)
57
{
58
        struct exec_domain *    ep;
59
        u_long                  pers = personality(personality);
60
 
61
        read_lock(&exec_domains_lock);
62
        for (ep = exec_domains; ep; ep = ep->next) {
63
                if (pers >= ep->pers_low && pers <= ep->pers_high)
64
                        if (try_module_get(ep->module))
65
                                goto out;
66
        }
67
 
68
#ifdef CONFIG_KMOD
69
        read_unlock(&exec_domains_lock);
70
        request_module("personality-%ld", pers);
71
        read_lock(&exec_domains_lock);
72
 
73
        for (ep = exec_domains; ep; ep = ep->next) {
74
                if (pers >= ep->pers_low && pers <= ep->pers_high)
75
                        if (try_module_get(ep->module))
76
                                goto out;
77
        }
78
#endif
79
 
80
        ep = &default_exec_domain;
81
out:
82
        read_unlock(&exec_domains_lock);
83
        return (ep);
84
}
85
 
86
int
87
register_exec_domain(struct exec_domain *ep)
88
{
89
        struct exec_domain      *tmp;
90
        int                     err = -EBUSY;
91
 
92
        if (ep == NULL)
93
                return -EINVAL;
94
 
95
        if (ep->next != NULL)
96
                return -EBUSY;
97
 
98
        write_lock(&exec_domains_lock);
99
        for (tmp = exec_domains; tmp; tmp = tmp->next) {
100
                if (tmp == ep)
101
                        goto out;
102
        }
103
 
104
        ep->next = exec_domains;
105
        exec_domains = ep;
106
        err = 0;
107
 
108
out:
109
        write_unlock(&exec_domains_lock);
110
        return (err);
111
}
112
 
113
int
114
unregister_exec_domain(struct exec_domain *ep)
115
{
116
        struct exec_domain      **epp;
117
 
118
        epp = &exec_domains;
119
        write_lock(&exec_domains_lock);
120
        for (epp = &exec_domains; *epp; epp = &(*epp)->next) {
121
                if (ep == *epp)
122
                        goto unregister;
123
        }
124
        write_unlock(&exec_domains_lock);
125
        return -EINVAL;
126
 
127
unregister:
128
        *epp = ep->next;
129
        ep->next = NULL;
130
        write_unlock(&exec_domains_lock);
131
        return 0;
132
}
133
 
134
int
135
__set_personality(u_long personality)
136
{
137
        struct exec_domain      *ep, *oep;
138
 
139
        ep = lookup_exec_domain(personality);
140
        if (ep == current_thread_info()->exec_domain) {
141
                current->personality = personality;
142
                module_put(ep->module);
143
                return 0;
144
        }
145
 
146
        if (atomic_read(&current->fs->count) != 1) {
147
                struct fs_struct *fsp, *ofsp;
148
 
149
                fsp = copy_fs_struct(current->fs);
150
                if (fsp == NULL) {
151
                        module_put(ep->module);
152
                        return -ENOMEM;
153
                }
154
 
155
                task_lock(current);
156
                ofsp = current->fs;
157
                current->fs = fsp;
158
                task_unlock(current);
159
 
160
                put_fs_struct(ofsp);
161
        }
162
 
163
        /*
164
         * At that point we are guaranteed to be the sole owner of
165
         * current->fs.
166
         */
167
 
168
        current->personality = personality;
169
        oep = current_thread_info()->exec_domain;
170
        current_thread_info()->exec_domain = ep;
171
        set_fs_altroot();
172
 
173
        module_put(oep->module);
174
        return 0;
175
}
176
 
177
int
178
get_exec_domain_list(char *page)
179
{
180
        struct exec_domain      *ep;
181
        int                     len = 0;
182
 
183
        read_lock(&exec_domains_lock);
184
        for (ep = exec_domains; ep && len < PAGE_SIZE - 80; ep = ep->next)
185
                len += sprintf(page + len, "%d-%d\t%-16s\t[%s]\n",
186
                               ep->pers_low, ep->pers_high, ep->name,
187
                               module_name(ep->module));
188
        read_unlock(&exec_domains_lock);
189
        return (len);
190
}
191
 
192
asmlinkage long
193
sys_personality(u_long personality)
194
{
195
        u_long old = current->personality;
196
 
197
        if (personality != 0xffffffff) {
198
                set_personality(personality);
199
                if (current->personality != personality)
200
                        return -EINVAL;
201
        }
202
 
203
        return (long)old;
204
}
205
 
206
 
207
EXPORT_SYMBOL(register_exec_domain);
208
EXPORT_SYMBOL(unregister_exec_domain);
209
EXPORT_SYMBOL(__set_personality);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.