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 ([email protected]) 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/proc_fs.h> 16 #include <linux/sched.h> 17 #include <linux/seq_file.h> 18 #include <linux/syscalls.h> 19 #include <linux/sysctl.h> 20 #include <linux/types.h> 21 #include <linux/fs_struct.h> 22 23 static void default_handler(int, struct pt_regs *); 24 static unsigned long ident_map[32] = { 25 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 31 struct exec_domain default_exec_domain = { 32 .name = "Linux", /* name */ 33 .handler = default_handler, /* lcall7 causes a seg fault. */ 34 .pers_low = 0, /* PER_LINUX personality. */ 35 .pers_high = 0, /* PER_LINUX personality. */ 36 .signal_map = ident_map, /* Identity map signals. */ 37 .signal_invmap = ident_map, /* - both ways. */ 38 }; 39 40 41 static void 42 default_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 52 int __set_personality(unsigned int personality) 53 { 54 current->personality = personality; 55 56 return 0; 57 } 58 EXPORT_SYMBOL(__set_personality); 59 60 #ifdef CONFIG_PROC_FS 61 static int execdomains_proc_show(struct seq_file *m, void *v) 62 { 63 seq_puts(m, "0-0\tLinux \t[kernel]\n"); 64 return 0; 65 } 66 67 static int execdomains_proc_open(struct inode *inode, struct file *file) 68 { 69 return single_open(file, execdomains_proc_show, NULL); 70 } 71 72 static 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 79 static int __init proc_execdomains_init(void) 80 { 81 proc_create("execdomains", 0, NULL, &execdomains_proc_fops); 82 return 0; 83 } 84 module_init(proc_execdomains_init); 85 #endif 86 87 SYSCALL_DEFINE1(personality, unsigned int, personality) 88 { 89 unsigned int old = current->personality; 90 91 if (personality != 0xffffffff) 92 set_personality(personality); 93 94 return old; 95 } 96