Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.6 298 lines 7.3 kB view raw
1/* 2 * linux/fs/binfmt_som.c 3 * 4 * These are the functions used to load SOM format executables as used 5 * by HP-UX. 6 * 7 * Copyright 1999 Matthew Wilcox <willy@bofh.ai> 8 * based on binfmt_elf which is 9 * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). 10 */ 11 12#include <linux/module.h> 13 14#include <linux/fs.h> 15#include <linux/stat.h> 16#include <linux/sched.h> 17#include <linux/mm.h> 18#include <linux/mman.h> 19#include <linux/errno.h> 20#include <linux/signal.h> 21#include <linux/binfmts.h> 22#include <linux/som.h> 23#include <linux/string.h> 24#include <linux/file.h> 25#include <linux/fcntl.h> 26#include <linux/ptrace.h> 27#include <linux/slab.h> 28#include <linux/shm.h> 29#include <linux/personality.h> 30#include <linux/init.h> 31 32#include <asm/uaccess.h> 33#include <asm/pgtable.h> 34 35 36#include <linux/elf.h> 37 38static int load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs); 39static int load_som_library(struct file *); 40 41/* 42 * If we don't support core dumping, then supply a NULL so we 43 * don't even try. 44 */ 45#if 0 46static int som_core_dump(struct coredump_params *cprm); 47#else 48#define som_core_dump NULL 49#endif 50 51#define SOM_PAGESTART(_v) ((_v) & ~(unsigned long)(SOM_PAGESIZE-1)) 52#define SOM_PAGEOFFSET(_v) ((_v) & (SOM_PAGESIZE-1)) 53#define SOM_PAGEALIGN(_v) (((_v) + SOM_PAGESIZE - 1) & ~(SOM_PAGESIZE - 1)) 54 55static struct linux_binfmt som_format = { 56 .module = THIS_MODULE, 57 .load_binary = load_som_binary, 58 .load_shlib = load_som_library, 59 .core_dump = som_core_dump, 60 .min_coredump = SOM_PAGESIZE 61}; 62 63/* 64 * create_som_tables() parses the env- and arg-strings in new user 65 * memory and creates the pointer tables from them, and puts their 66 * addresses on the "stack", returning the new stack pointer value. 67 */ 68static void create_som_tables(struct linux_binprm *bprm) 69{ 70 char **argv, **envp; 71 int argc = bprm->argc; 72 int envc = bprm->envc; 73 unsigned long p; 74 unsigned long *sp; 75 76 /* Word-align the stack pointer */ 77 sp = (unsigned long *)((bprm->p + 3) & ~3); 78 79 envp = (char **) sp; 80 sp += envc + 1; 81 argv = (char **) sp; 82 sp += argc + 1; 83 84 __put_user((unsigned long) envp,++sp); 85 __put_user((unsigned long) argv,++sp); 86 87 __put_user(argc, ++sp); 88 89 bprm->p = (unsigned long) sp; 90 91 p = current->mm->arg_start; 92 while (argc-- > 0) { 93 __put_user((char *)p,argv++); 94 p += strlen_user((char *)p); 95 } 96 __put_user(NULL, argv); 97 current->mm->arg_end = current->mm->env_start = p; 98 while (envc-- > 0) { 99 __put_user((char *)p,envp++); 100 p += strlen_user((char *)p); 101 } 102 __put_user(NULL, envp); 103 current->mm->env_end = p; 104} 105 106static int check_som_header(struct som_hdr *som_ex) 107{ 108 int *buf = (int *)som_ex; 109 int i, ck; 110 111 if (som_ex->system_id != SOM_SID_PARISC_1_0 && 112 som_ex->system_id != SOM_SID_PARISC_1_1 && 113 som_ex->system_id != SOM_SID_PARISC_2_0) 114 return -ENOEXEC; 115 116 if (som_ex->a_magic != SOM_EXEC_NONSHARE && 117 som_ex->a_magic != SOM_EXEC_SHARE && 118 som_ex->a_magic != SOM_EXEC_DEMAND) 119 return -ENOEXEC; 120 121 if (som_ex->version_id != SOM_ID_OLD && 122 som_ex->version_id != SOM_ID_NEW) 123 return -ENOEXEC; 124 125 ck = 0; 126 for (i=0; i<32; i++) 127 ck ^= buf[i]; 128 if (ck != 0) 129 return -ENOEXEC; 130 131 return 0; 132} 133 134static int map_som_binary(struct file *file, 135 const struct som_exec_auxhdr *hpuxhdr) 136{ 137 unsigned long code_start, code_size, data_start, data_size; 138 unsigned long bss_start, som_brk; 139 int retval; 140 int prot = PROT_READ | PROT_EXEC; 141 int flags = MAP_FIXED|MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; 142 143 mm_segment_t old_fs = get_fs(); 144 set_fs(get_ds()); 145 146 code_start = SOM_PAGESTART(hpuxhdr->exec_tmem); 147 code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); 148 current->mm->start_code = code_start; 149 current->mm->end_code = code_start + code_size; 150 retval = vm_mmap(file, code_start, code_size, prot, 151 flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); 152 if (retval < 0 && retval > -1024) 153 goto out; 154 155 data_start = SOM_PAGESTART(hpuxhdr->exec_dmem); 156 data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); 157 current->mm->start_data = data_start; 158 current->mm->end_data = bss_start = data_start + data_size; 159 retval = vm_mmap(file, data_start, data_size, 160 prot | PROT_WRITE, flags, 161 SOM_PAGESTART(hpuxhdr->exec_dfile)); 162 if (retval < 0 && retval > -1024) 163 goto out; 164 165 som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); 166 current->mm->start_brk = current->mm->brk = som_brk; 167 retval = vm_mmap(NULL, bss_start, som_brk - bss_start, 168 prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); 169 if (retval > 0 || retval < -1024) 170 retval = 0; 171out: 172 set_fs(old_fs); 173 return retval; 174} 175 176 177/* 178 * These are the functions used to load SOM executables and shared 179 * libraries. There is no binary dependent code anywhere else. 180 */ 181 182static int 183load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) 184{ 185 int retval; 186 unsigned int size; 187 unsigned long som_entry; 188 struct som_hdr *som_ex; 189 struct som_exec_auxhdr *hpuxhdr; 190 191 /* Get the exec-header */ 192 som_ex = (struct som_hdr *) bprm->buf; 193 194 retval = check_som_header(som_ex); 195 if (retval != 0) 196 goto out; 197 198 /* Now read in the auxiliary header information */ 199 200 retval = -ENOMEM; 201 size = som_ex->aux_header_size; 202 if (size > SOM_PAGESIZE) 203 goto out; 204 hpuxhdr = kmalloc(size, GFP_KERNEL); 205 if (!hpuxhdr) 206 goto out; 207 208 retval = kernel_read(bprm->file, som_ex->aux_header_location, 209 (char *) hpuxhdr, size); 210 if (retval != size) { 211 if (retval >= 0) 212 retval = -EIO; 213 goto out_free; 214 } 215 216 /* Flush all traces of the currently running executable */ 217 retval = flush_old_exec(bprm); 218 if (retval) 219 goto out_free; 220 221 /* OK, This is the point of no return */ 222 current->personality = PER_HPUX; 223 setup_new_exec(bprm); 224 225 /* Set the task size for HP-UX processes such that 226 * the gateway page is outside the address space. 227 * This can be fixed later, but for now, this is much 228 * easier. 229 */ 230 231 current->thread.task_size = 0xc0000000; 232 233 /* Set map base to allow enough room for hp-ux heap growth */ 234 235 current->thread.map_base = 0x80000000; 236 237 retval = map_som_binary(bprm->file, hpuxhdr); 238 if (retval < 0) 239 goto out_free; 240 241 som_entry = hpuxhdr->exec_entry; 242 kfree(hpuxhdr); 243 244 set_binfmt(&som_format); 245 install_exec_creds(bprm); 246 setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); 247 248 create_som_tables(bprm); 249 250 current->mm->start_stack = bprm->p; 251 252#if 0 253 printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk); 254 printk("(end_code) %08lx\n" , (unsigned long) current->mm->end_code); 255 printk("(start_code) %08lx\n" , (unsigned long) current->mm->start_code); 256 printk("(end_data) %08lx\n" , (unsigned long) current->mm->end_data); 257 printk("(start_stack) %08lx\n" , (unsigned long) current->mm->start_stack); 258 printk("(brk) %08lx\n" , (unsigned long) current->mm->brk); 259#endif 260 261 map_hpux_gateway_page(current,current->mm); 262 263 start_thread_som(regs, som_entry, bprm->p); 264 return 0; 265 266 /* error cleanup */ 267out_free: 268 kfree(hpuxhdr); 269out: 270 return retval; 271} 272 273static int load_som_library(struct file *f) 274{ 275/* No lib support in SOM yet. gizza chance.. */ 276 return -ENOEXEC; 277} 278 /* Install the SOM loader. 279 * N.B. We *rely* on the table being the right size with the 280 * right number of free slots... 281 */ 282 283static int __init init_som_binfmt(void) 284{ 285 register_binfmt(&som_format); 286 return 0; 287} 288 289static void __exit exit_som_binfmt(void) 290{ 291 /* Remove the SOM loader. */ 292 unregister_binfmt(&som_format); 293} 294 295core_initcall(init_som_binfmt); 296module_exit(exit_som_binfmt); 297 298MODULE_LICENSE("GPL");