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.15 299 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); 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) 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 struct pt_regs *regs = current_pt_regs(); 191 192 /* Get the exec-header */ 193 som_ex = (struct som_hdr *) bprm->buf; 194 195 retval = check_som_header(som_ex); 196 if (retval != 0) 197 goto out; 198 199 /* Now read in the auxiliary header information */ 200 201 retval = -ENOMEM; 202 size = som_ex->aux_header_size; 203 if (size > SOM_PAGESIZE) 204 goto out; 205 hpuxhdr = kmalloc(size, GFP_KERNEL); 206 if (!hpuxhdr) 207 goto out; 208 209 retval = kernel_read(bprm->file, som_ex->aux_header_location, 210 (char *) hpuxhdr, size); 211 if (retval != size) { 212 if (retval >= 0) 213 retval = -EIO; 214 goto out_free; 215 } 216 217 /* Flush all traces of the currently running executable */ 218 retval = flush_old_exec(bprm); 219 if (retval) 220 goto out_free; 221 222 /* OK, This is the point of no return */ 223 current->personality = PER_HPUX; 224 setup_new_exec(bprm); 225 226 /* Set the task size for HP-UX processes such that 227 * the gateway page is outside the address space. 228 * This can be fixed later, but for now, this is much 229 * easier. 230 */ 231 232 current->thread.task_size = 0xc0000000; 233 234 /* Set map base to allow enough room for hp-ux heap growth */ 235 236 current->thread.map_base = 0x80000000; 237 238 retval = map_som_binary(bprm->file, hpuxhdr); 239 if (retval < 0) 240 goto out_free; 241 242 som_entry = hpuxhdr->exec_entry; 243 kfree(hpuxhdr); 244 245 set_binfmt(&som_format); 246 install_exec_creds(bprm); 247 setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); 248 249 create_som_tables(bprm); 250 251 current->mm->start_stack = bprm->p; 252 253#if 0 254 printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk); 255 printk("(end_code) %08lx\n" , (unsigned long) current->mm->end_code); 256 printk("(start_code) %08lx\n" , (unsigned long) current->mm->start_code); 257 printk("(end_data) %08lx\n" , (unsigned long) current->mm->end_data); 258 printk("(start_stack) %08lx\n" , (unsigned long) current->mm->start_stack); 259 printk("(brk) %08lx\n" , (unsigned long) current->mm->brk); 260#endif 261 262 map_hpux_gateway_page(current,current->mm); 263 264 start_thread_som(regs, som_entry, bprm->p); 265 return 0; 266 267 /* error cleanup */ 268out_free: 269 kfree(hpuxhdr); 270out: 271 return retval; 272} 273 274static int load_som_library(struct file *f) 275{ 276/* No lib support in SOM yet. gizza chance.. */ 277 return -ENOEXEC; 278} 279 /* Install the SOM loader. 280 * N.B. We *rely* on the table being the right size with the 281 * right number of free slots... 282 */ 283 284static int __init init_som_binfmt(void) 285{ 286 register_binfmt(&som_format); 287 return 0; 288} 289 290static void __exit exit_som_binfmt(void) 291{ 292 /* Remove the SOM loader. */ 293 unregister_binfmt(&som_format); 294} 295 296core_initcall(init_som_binfmt); 297module_exit(exit_som_binfmt); 298 299MODULE_LICENSE("GPL");