blob: b2fb57d6b9b236dd4530ed3922d0e0264ee5997f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/init.h>
11#include <linux/kernel.h>
12#include <linux/kmod.h>
13#include <linux/module.h>
14#include <linux/personality.h>
Alexey Dobriyan6e627752008-10-04 14:28:09 +040015#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/sched.h>
Alexey Dobriyan6e627752008-10-04 14:28:09 +040017#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/syscalls.h>
19#include <linux/sysctl.h>
20#include <linux/types.h>
Al Viro5ad4e532009-03-29 19:50:06 -040021#include <linux/fs_struct.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
Linus Torvalds1da177e2005-04-16 15:20:36 -070023static void default_handler(int, struct pt_regs *);
Oleg Nesterov485d5272010-06-04 14:14:58 -070024static unsigned long ident_map[32] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 0, 1, 2, 3, 4, 5, 6, 7,
26 8, 9, 10, 11, 12, 13, 14, 15,
27 16, 17, 18, 19, 20, 21, 22, 23,
28 24, 25, 26, 27, 28, 29, 30, 31
29};
30
31struct exec_domain default_exec_domain = {
32 .name = "Linux", /* name */
33 .handler = default_handler, /* lcall7 causes a seg fault. */
Fabian Frederickb9e5db62014-06-04 16:11:20 -070034 .pers_low = 0, /* PER_LINUX personality. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 .pers_high = 0, /* PER_LINUX personality. */
36 .signal_map = ident_map, /* Identity map signals. */
37 .signal_invmap = ident_map, /* - both ways. */
38};
39
40
41static void
42default_handler(int segment, struct pt_regs *regp)
43{
44 set_personality(0);
45
46 if (current_thread_info()->exec_domain->handler != default_handler)
47 current_thread_info()->exec_domain->handler(segment, regp);
48 else
49 send_sig(SIGSEGV, current, 1);
50}
51
Oleg Nesterov2ee7c922010-08-09 17:20:30 -070052int __set_personality(unsigned int personality)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053{
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 current->personality = personality;
Oleg Nesterov2ee7c922010-08-09 17:20:30 -070055
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 return 0;
57}
Fabian Frederickb9e5db62014-06-04 16:11:20 -070058EXPORT_SYMBOL(__set_personality);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Alexey Dobriyan6e627752008-10-04 14:28:09 +040060#ifdef CONFIG_PROC_FS
61static int execdomains_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062{
Richard Weinberger973f9112015-03-30 08:14:16 +020063 seq_puts(m, "0-0\tLinux \t[kernel]\n");
Alexey Dobriyan6e627752008-10-04 14:28:09 +040064 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065}
66
Alexey Dobriyan6e627752008-10-04 14:28:09 +040067static int execdomains_proc_open(struct inode *inode, struct file *file)
68{
69 return single_open(file, execdomains_proc_show, NULL);
70}
71
72static const struct file_operations execdomains_proc_fops = {
73 .open = execdomains_proc_open,
74 .read = seq_read,
75 .llseek = seq_lseek,
76 .release = single_release,
77};
78
79static int __init proc_execdomains_init(void)
80{
81 proc_create("execdomains", 0, NULL, &execdomains_proc_fops);
82 return 0;
83}
84module_init(proc_execdomains_init);
85#endif
86
Oleg Nesterov485d5272010-06-04 14:14:58 -070087SYSCALL_DEFINE1(personality, unsigned int, personality)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088{
Oleg Nesterov485d5272010-06-04 14:14:58 -070089 unsigned int old = current->personality;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
Oleg Nesterov2ee7c922010-08-09 17:20:30 -070091 if (personality != 0xffffffff)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 set_personality(personality);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Oleg Nesterov485d5272010-06-04 14:14:58 -070094 return old;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095}