diff options
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 212 |
1 files changed, 115 insertions, 97 deletions
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index f82e1a94fcb7..a764e4e95314 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -36,38 +36,44 @@ | |||
36 | #undef WARN_OLD | 36 | #undef WARN_OLD |
37 | #undef CORE_DUMP /* probably broken */ | 37 | #undef CORE_DUMP /* probably broken */ |
38 | 38 | ||
39 | static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); | 39 | static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); |
40 | static int load_aout_library(struct file*); | 40 | static int load_aout_library(struct file *); |
41 | 41 | ||
42 | #ifdef CORE_DUMP | 42 | #ifdef CORE_DUMP |
43 | static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit); | 43 | static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, |
44 | unsigned long limit); | ||
44 | 45 | ||
45 | /* | 46 | /* |
46 | * fill in the user structure for a core dump.. | 47 | * fill in the user structure for a core dump.. |
47 | */ | 48 | */ |
48 | static void dump_thread32(struct pt_regs * regs, struct user32 * dump) | 49 | static void dump_thread32(struct pt_regs *regs, struct user32 *dump) |
49 | { | 50 | { |
50 | u32 fs,gs; | 51 | u32 fs, gs; |
51 | 52 | ||
52 | /* changed the size calculations - should hopefully work better. lbt */ | 53 | /* changed the size calculations - should hopefully work better. lbt */ |
53 | dump->magic = CMAGIC; | 54 | dump->magic = CMAGIC; |
54 | dump->start_code = 0; | 55 | dump->start_code = 0; |
55 | dump->start_stack = regs->rsp & ~(PAGE_SIZE - 1); | 56 | dump->start_stack = regs->rsp & ~(PAGE_SIZE - 1); |
56 | dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; | 57 | dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; |
57 | dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; | 58 | dump->u_dsize = ((unsigned long) |
59 | (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; | ||
58 | dump->u_dsize -= dump->u_tsize; | 60 | dump->u_dsize -= dump->u_tsize; |
59 | dump->u_ssize = 0; | 61 | dump->u_ssize = 0; |
60 | dump->u_debugreg[0] = current->thread.debugreg0; | 62 | dump->u_debugreg[0] = current->thread.debugreg0; |
61 | dump->u_debugreg[1] = current->thread.debugreg1; | 63 | dump->u_debugreg[1] = current->thread.debugreg1; |
62 | dump->u_debugreg[2] = current->thread.debugreg2; | 64 | dump->u_debugreg[2] = current->thread.debugreg2; |
63 | dump->u_debugreg[3] = current->thread.debugreg3; | 65 | dump->u_debugreg[3] = current->thread.debugreg3; |
64 | dump->u_debugreg[4] = 0; | 66 | dump->u_debugreg[4] = 0; |
65 | dump->u_debugreg[5] = 0; | 67 | dump->u_debugreg[5] = 0; |
66 | dump->u_debugreg[6] = current->thread.debugreg6; | 68 | dump->u_debugreg[6] = current->thread.debugreg6; |
67 | dump->u_debugreg[7] = current->thread.debugreg7; | 69 | dump->u_debugreg[7] = current->thread.debugreg7; |
68 | 70 | ||
69 | if (dump->start_stack < 0xc0000000) | 71 | if (dump->start_stack < 0xc0000000) { |
70 | dump->u_ssize = ((unsigned long) (0xc0000000 - dump->start_stack)) >> PAGE_SHIFT; | 72 | unsigned long tmp; |
73 | |||
74 | tmp = (unsigned long) (0xc0000000 - dump->start_stack); | ||
75 | dump->u_ssize = tmp >> PAGE_SHIFT; | ||
76 | } | ||
71 | 77 | ||
72 | dump->regs.ebx = regs->rbx; | 78 | dump->regs.ebx = regs->rbx; |
73 | dump->regs.ecx = regs->rcx; | 79 | dump->regs.ecx = regs->rcx; |
@@ -79,7 +85,7 @@ static void dump_thread32(struct pt_regs * regs, struct user32 * dump) | |||
79 | dump->regs.ds = current->thread.ds; | 85 | dump->regs.ds = current->thread.ds; |
80 | dump->regs.es = current->thread.es; | 86 | dump->regs.es = current->thread.es; |
81 | asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; | 87 | asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; |
82 | asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; | 88 | asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; |
83 | dump->regs.orig_eax = regs->orig_rax; | 89 | dump->regs.orig_eax = regs->orig_rax; |
84 | dump->regs.eip = regs->rip; | 90 | dump->regs.eip = regs->rip; |
85 | dump->regs.cs = regs->cs; | 91 | dump->regs.cs = regs->cs; |
@@ -90,7 +96,7 @@ static void dump_thread32(struct pt_regs * regs, struct user32 * dump) | |||
90 | #if 1 /* FIXME */ | 96 | #if 1 /* FIXME */ |
91 | dump->u_fpvalid = 0; | 97 | dump->u_fpvalid = 0; |
92 | #else | 98 | #else |
93 | dump->u_fpvalid = dump_fpu (regs, &dump->i387); | 99 | dump->u_fpvalid = dump_fpu(regs, &dump->i387); |
94 | #endif | 100 | #endif |
95 | } | 101 | } |
96 | 102 | ||
@@ -128,15 +134,19 @@ static int dump_write(struct file *file, const void *addr, int nr) | |||
128 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | 134 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; |
129 | } | 135 | } |
130 | 136 | ||
131 | #define DUMP_WRITE(addr, nr) \ | 137 | #define DUMP_WRITE(addr, nr) \ |
132 | if (!dump_write(file, (void *)(addr), (nr))) \ | 138 | if (!dump_write(file, (void *)(addr), (nr))) \ |
133 | goto end_coredump; | 139 | goto end_coredump; |
134 | 140 | ||
135 | #define DUMP_SEEK(offset) \ | 141 | #define DUMP_SEEK(offset) \ |
136 | if (file->f_op->llseek) { \ | 142 | if (file->f_op->llseek) { \ |
137 | if (file->f_op->llseek(file,(offset),0) != (offset)) \ | 143 | if (file->f_op->llseek(file, (offset), 0) != (offset)) \ |
138 | goto end_coredump; \ | 144 | goto end_coredump; \ |
139 | } else file->f_pos = (offset) | 145 | } else \ |
146 | file->f_pos = (offset) | ||
147 | |||
148 | #define START_DATA() (u.u_tsize << PAGE_SHIFT) | ||
149 | #define START_STACK(u) (u.start_stack) | ||
140 | 150 | ||
141 | /* | 151 | /* |
142 | * Routine writes a core dump image in the current directory. | 152 | * Routine writes a core dump image in the current directory. |
@@ -148,62 +158,70 @@ if (file->f_op->llseek) { \ | |||
148 | * dumping of the process results in another error.. | 158 | * dumping of the process results in another error.. |
149 | */ | 159 | */ |
150 | 160 | ||
151 | static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit) | 161 | static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, |
162 | unsigned long limit) | ||
152 | { | 163 | { |
153 | mm_segment_t fs; | 164 | mm_segment_t fs; |
154 | int has_dumped = 0; | 165 | int has_dumped = 0; |
155 | unsigned long dump_start, dump_size; | 166 | unsigned long dump_start, dump_size; |
156 | struct user32 dump; | 167 | struct user32 dump; |
157 | # define START_DATA(u) (u.u_tsize << PAGE_SHIFT) | ||
158 | # define START_STACK(u) (u.start_stack) | ||
159 | 168 | ||
160 | fs = get_fs(); | 169 | fs = get_fs(); |
161 | set_fs(KERNEL_DS); | 170 | set_fs(KERNEL_DS); |
162 | has_dumped = 1; | 171 | has_dumped = 1; |
163 | current->flags |= PF_DUMPCORE; | 172 | current->flags |= PF_DUMPCORE; |
164 | strncpy(dump.u_comm, current->comm, sizeof(current->comm)); | 173 | strncpy(dump.u_comm, current->comm, sizeof(current->comm)); |
165 | dump.u_ar0 = (u32)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump))); | 174 | dump.u_ar0 = (u32)(((unsigned long)(&dump.regs)) - |
175 | ((unsigned long)(&dump))); | ||
166 | dump.signal = signr; | 176 | dump.signal = signr; |
167 | dump_thread32(regs, &dump); | 177 | dump_thread32(regs, &dump); |
168 | 178 | ||
169 | /* If the size of the dump file exceeds the rlimit, then see what would happen | 179 | /* |
170 | if we wrote the stack, but not the data area. */ | 180 | * If the size of the dump file exceeds the rlimit, then see |
181 | * what would happen if we wrote the stack, but not the data | ||
182 | * area. | ||
183 | */ | ||
171 | if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit) | 184 | if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit) |
172 | dump.u_dsize = 0; | 185 | dump.u_dsize = 0; |
173 | 186 | ||
174 | /* Make sure we have enough room to write the stack and data areas. */ | 187 | /* Make sure we have enough room to write the stack and data areas. */ |
175 | if ((dump.u_ssize + 1) * PAGE_SIZE > limit) | 188 | if ((dump.u_ssize + 1) * PAGE_SIZE > limit) |
176 | dump.u_ssize = 0; | 189 | dump.u_ssize = 0; |
177 | 190 | ||
178 | /* make sure we actually have a data and stack area to dump */ | 191 | /* make sure we actually have a data and stack area to dump */ |
179 | set_fs(USER_DS); | 192 | set_fs(USER_DS); |
180 | if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), dump.u_dsize << PAGE_SHIFT)) | 193 | if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), |
194 | dump.u_dsize << PAGE_SHIFT)) | ||
181 | dump.u_dsize = 0; | 195 | dump.u_dsize = 0; |
182 | if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), dump.u_ssize << PAGE_SHIFT)) | 196 | if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), |
197 | dump.u_ssize << PAGE_SHIFT)) | ||
183 | dump.u_ssize = 0; | 198 | dump.u_ssize = 0; |
184 | 199 | ||
185 | set_fs(KERNEL_DS); | 200 | set_fs(KERNEL_DS); |
186 | /* struct user */ | 201 | /* struct user */ |
187 | DUMP_WRITE(&dump,sizeof(dump)); | 202 | DUMP_WRITE(&dump, sizeof(dump)); |
188 | /* Now dump all of the user data. Include malloced stuff as well */ | 203 | /* Now dump all of the user data. Include malloced stuff as well */ |
189 | DUMP_SEEK(PAGE_SIZE); | 204 | DUMP_SEEK(PAGE_SIZE); |
190 | /* now we start writing out the user space info */ | 205 | /* now we start writing out the user space info */ |
191 | set_fs(USER_DS); | 206 | set_fs(USER_DS); |
192 | /* Dump the data area */ | 207 | /* Dump the data area */ |
193 | if (dump.u_dsize != 0) { | 208 | if (dump.u_dsize != 0) { |
194 | dump_start = START_DATA(dump); | 209 | dump_start = START_DATA(dump); |
195 | dump_size = dump.u_dsize << PAGE_SHIFT; | 210 | dump_size = dump.u_dsize << PAGE_SHIFT; |
196 | DUMP_WRITE(dump_start,dump_size); | 211 | DUMP_WRITE(dump_start, dump_size); |
197 | } | 212 | } |
198 | /* Now prepare to dump the stack area */ | 213 | /* Now prepare to dump the stack area */ |
199 | if (dump.u_ssize != 0) { | 214 | if (dump.u_ssize != 0) { |
200 | dump_start = START_STACK(dump); | 215 | dump_start = START_STACK(dump); |
201 | dump_size = dump.u_ssize << PAGE_SHIFT; | 216 | dump_size = dump.u_ssize << PAGE_SHIFT; |
202 | DUMP_WRITE(dump_start,dump_size); | 217 | DUMP_WRITE(dump_start, dump_size); |
203 | } | 218 | } |
204 | /* Finally dump the task struct. Not be used by gdb, but could be useful */ | 219 | /* |
220 | * Finally dump the task struct. Not be used by gdb, but | ||
221 | * could be useful | ||
222 | */ | ||
205 | set_fs(KERNEL_DS); | 223 | set_fs(KERNEL_DS); |
206 | DUMP_WRITE(current,sizeof(*current)); | 224 | DUMP_WRITE(current, sizeof(*current)); |
207 | end_coredump: | 225 | end_coredump: |
208 | set_fs(fs); | 226 | set_fs(fs); |
209 | return has_dumped; | 227 | return has_dumped; |
@@ -217,35 +235,34 @@ end_coredump: | |||
217 | */ | 235 | */ |
218 | static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm) | 236 | static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm) |
219 | { | 237 | { |
220 | u32 __user *argv; | 238 | u32 __user *argv, *envp, *sp; |
221 | u32 __user *envp; | 239 | int argc = bprm->argc, envc = bprm->envc; |
222 | u32 __user *sp; | ||
223 | int argc = bprm->argc; | ||
224 | int envc = bprm->envc; | ||
225 | 240 | ||
226 | sp = (u32 __user *) ((-(unsigned long)sizeof(u32)) & (unsigned long) p); | 241 | sp = (u32 __user *) ((-(unsigned long)sizeof(u32)) & (unsigned long) p); |
227 | sp -= envc+1; | 242 | sp -= envc+1; |
228 | envp = sp; | 243 | envp = sp; |
229 | sp -= argc+1; | 244 | sp -= argc+1; |
230 | argv = sp; | 245 | argv = sp; |
231 | put_user((unsigned long) envp,--sp); | 246 | put_user((unsigned long) envp, --sp); |
232 | put_user((unsigned long) argv,--sp); | 247 | put_user((unsigned long) argv, --sp); |
233 | put_user(argc,--sp); | 248 | put_user(argc, --sp); |
234 | current->mm->arg_start = (unsigned long) p; | 249 | current->mm->arg_start = (unsigned long) p; |
235 | while (argc-->0) { | 250 | while (argc-- > 0) { |
236 | char c; | 251 | char c; |
237 | put_user((u32)(unsigned long)p,argv++); | 252 | |
253 | put_user((u32)(unsigned long)p, argv++); | ||
238 | do { | 254 | do { |
239 | get_user(c,p++); | 255 | get_user(c, p++); |
240 | } while (c); | 256 | } while (c); |
241 | } | 257 | } |
242 | put_user(0, argv); | 258 | put_user(0, argv); |
243 | current->mm->arg_end = current->mm->env_start = (unsigned long) p; | 259 | current->mm->arg_end = current->mm->env_start = (unsigned long) p; |
244 | while (envc-->0) { | 260 | while (envc-- > 0) { |
245 | char c; | 261 | char c; |
246 | put_user((u32)(unsigned long)p,envp++); | 262 | |
263 | put_user((u32)(unsigned long)p, envp++); | ||
247 | do { | 264 | do { |
248 | get_user(c,p++); | 265 | get_user(c, p++); |
249 | } while (c); | 266 | } while (c); |
250 | } | 267 | } |
251 | put_user(0, envp); | 268 | put_user(0, envp); |
@@ -257,20 +274,18 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm) | |||
257 | * These are the functions used to load a.out style executables and shared | 274 | * These are the functions used to load a.out style executables and shared |
258 | * libraries. There is no binary dependent code anywhere else. | 275 | * libraries. There is no binary dependent code anywhere else. |
259 | */ | 276 | */ |
260 | 277 | static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |
261 | static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | ||
262 | { | 278 | { |
279 | unsigned long error, fd_offset, rlim; | ||
263 | struct exec ex; | 280 | struct exec ex; |
264 | unsigned long error; | ||
265 | unsigned long fd_offset; | ||
266 | unsigned long rlim; | ||
267 | int retval; | 281 | int retval; |
268 | 282 | ||
269 | ex = *((struct exec *) bprm->buf); /* exec-header */ | 283 | ex = *((struct exec *) bprm->buf); /* exec-header */ |
270 | if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && | 284 | if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && |
271 | N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || | 285 | N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || |
272 | N_TRSIZE(ex) || N_DRSIZE(ex) || | 286 | N_TRSIZE(ex) || N_DRSIZE(ex) || |
273 | i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { | 287 | i_size_read(bprm->file->f_path.dentry->d_inode) < |
288 | ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { | ||
274 | return -ENOEXEC; | 289 | return -ENOEXEC; |
275 | } | 290 | } |
276 | 291 | ||
@@ -291,13 +306,13 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
291 | if (retval) | 306 | if (retval) |
292 | return retval; | 307 | return retval; |
293 | 308 | ||
294 | regs->cs = __USER32_CS; | 309 | regs->cs = __USER32_CS; |
295 | regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 = | 310 | regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 = |
296 | regs->r13 = regs->r14 = regs->r15 = 0; | 311 | regs->r13 = regs->r14 = regs->r15 = 0; |
297 | 312 | ||
298 | /* OK, This is the point of no return */ | 313 | /* OK, This is the point of no return */ |
299 | set_personality(PER_LINUX); | 314 | set_personality(PER_LINUX); |
300 | set_thread_flag(TIF_IA32); | 315 | set_thread_flag(TIF_IA32); |
301 | clear_thread_flag(TIF_ABI_PENDING); | 316 | clear_thread_flag(TIF_ABI_PENDING); |
302 | 317 | ||
303 | current->mm->end_code = ex.a_text + | 318 | current->mm->end_code = ex.a_text + |
@@ -311,7 +326,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
311 | 326 | ||
312 | current->mm->mmap = NULL; | 327 | current->mm->mmap = NULL; |
313 | compute_creds(bprm); | 328 | compute_creds(bprm); |
314 | current->flags &= ~PF_FORKNOEXEC; | 329 | current->flags &= ~PF_FORKNOEXEC; |
315 | 330 | ||
316 | if (N_MAGIC(ex) == OMAGIC) { | 331 | if (N_MAGIC(ex) == OMAGIC) { |
317 | unsigned long text_addr, map_size; | 332 | unsigned long text_addr, map_size; |
@@ -338,30 +353,30 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
338 | send_sig(SIGKILL, current, 0); | 353 | send_sig(SIGKILL, current, 0); |
339 | return error; | 354 | return error; |
340 | } | 355 | } |
341 | 356 | ||
342 | flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data); | 357 | flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data); |
343 | } else { | 358 | } else { |
344 | #ifdef WARN_OLD | 359 | #ifdef WARN_OLD |
345 | static unsigned long error_time, error_time2; | 360 | static unsigned long error_time, error_time2; |
346 | if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && | 361 | if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && |
347 | (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ) | 362 | (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ) { |
348 | { | ||
349 | printk(KERN_NOTICE "executable not page aligned\n"); | 363 | printk(KERN_NOTICE "executable not page aligned\n"); |
350 | error_time2 = jiffies; | 364 | error_time2 = jiffies; |
351 | } | 365 | } |
352 | 366 | ||
353 | if ((fd_offset & ~PAGE_MASK) != 0 && | 367 | if ((fd_offset & ~PAGE_MASK) != 0 && |
354 | (jiffies-error_time) > 5*HZ) | 368 | (jiffies - error_time) > 5*HZ) { |
355 | { | 369 | printk(KERN_WARNING |
356 | printk(KERN_WARNING | 370 | "fd_offset is not page aligned. Please convert " |
357 | "fd_offset is not page aligned. Please convert program: %s\n", | 371 | "program: %s\n", |
358 | bprm->file->f_path.dentry->d_name.name); | 372 | bprm->file->f_path.dentry->d_name.name); |
359 | error_time = jiffies; | 373 | error_time = jiffies; |
360 | } | 374 | } |
361 | #endif | 375 | #endif |
362 | 376 | ||
363 | if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { | 377 | if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) { |
364 | loff_t pos = fd_offset; | 378 | loff_t pos = fd_offset; |
379 | |||
365 | down_write(¤t->mm->mmap_sem); | 380 | down_write(¤t->mm->mmap_sem); |
366 | do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); | 381 | do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); |
367 | up_write(¤t->mm->mmap_sem); | 382 | up_write(¤t->mm->mmap_sem); |
@@ -376,9 +391,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
376 | 391 | ||
377 | down_write(¤t->mm->mmap_sem); | 392 | down_write(¤t->mm->mmap_sem); |
378 | error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, | 393 | error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, |
379 | PROT_READ | PROT_EXEC, | 394 | PROT_READ | PROT_EXEC, |
380 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, | 395 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | |
381 | fd_offset); | 396 | MAP_EXECUTABLE | MAP_32BIT, |
397 | fd_offset); | ||
382 | up_write(¤t->mm->mmap_sem); | 398 | up_write(¤t->mm->mmap_sem); |
383 | 399 | ||
384 | if (error != N_TXTADDR(ex)) { | 400 | if (error != N_TXTADDR(ex)) { |
@@ -387,9 +403,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
387 | } | 403 | } |
388 | 404 | ||
389 | down_write(¤t->mm->mmap_sem); | 405 | down_write(¤t->mm->mmap_sem); |
390 | error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, | 406 | error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, |
391 | PROT_READ | PROT_WRITE | PROT_EXEC, | 407 | PROT_READ | PROT_WRITE | PROT_EXEC, |
392 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, | 408 | MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | |
409 | MAP_EXECUTABLE | MAP_32BIT, | ||
393 | fd_offset + ex.a_text); | 410 | fd_offset + ex.a_text); |
394 | up_write(¤t->mm->mmap_sem); | 411 | up_write(¤t->mm->mmap_sem); |
395 | if (error != N_DATADDR(ex)) { | 412 | if (error != N_DATADDR(ex)) { |
@@ -403,9 +420,9 @@ beyond_if: | |||
403 | set_brk(current->mm->start_brk, current->mm->brk); | 420 | set_brk(current->mm->start_brk, current->mm->brk); |
404 | 421 | ||
405 | retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); | 422 | retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); |
406 | if (retval < 0) { | 423 | if (retval < 0) { |
407 | /* Someone check-me: is this error path enough? */ | 424 | /* Someone check-me: is this error path enough? */ |
408 | send_sig(SIGKILL, current, 0); | 425 | send_sig(SIGKILL, current, 0); |
409 | return retval; | 426 | return retval; |
410 | } | 427 | } |
411 | 428 | ||
@@ -414,7 +431,7 @@ beyond_if: | |||
414 | /* start thread */ | 431 | /* start thread */ |
415 | asm volatile("movl %0,%%fs" :: "r" (0)); \ | 432 | asm volatile("movl %0,%%fs" :: "r" (0)); \ |
416 | asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); | 433 | asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); |
417 | load_gs_index(0); | 434 | load_gs_index(0); |
418 | (regs)->rip = ex.a_entry; | 435 | (regs)->rip = ex.a_entry; |
419 | (regs)->rsp = current->mm->start_stack; | 436 | (regs)->rsp = current->mm->start_stack; |
420 | (regs)->eflags = 0x200; | 437 | (regs)->eflags = 0x200; |
@@ -425,7 +442,7 @@ beyond_if: | |||
425 | set_fs(USER_DS); | 442 | set_fs(USER_DS); |
426 | if (unlikely(current->ptrace & PT_PTRACED)) { | 443 | if (unlikely(current->ptrace & PT_PTRACED)) { |
427 | if (current->ptrace & PT_TRACE_EXEC) | 444 | if (current->ptrace & PT_TRACE_EXEC) |
428 | ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); | 445 | ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP); |
429 | else | 446 | else |
430 | send_sig(SIGTRAP, current, 0); | 447 | send_sig(SIGTRAP, current, 0); |
431 | } | 448 | } |
@@ -434,9 +451,8 @@ beyond_if: | |||
434 | 451 | ||
435 | static int load_aout_library(struct file *file) | 452 | static int load_aout_library(struct file *file) |
436 | { | 453 | { |
437 | struct inode * inode; | 454 | struct inode *inode; |
438 | unsigned long bss, start_addr, len; | 455 | unsigned long bss, start_addr, len, error; |
439 | unsigned long error; | ||
440 | int retval; | 456 | int retval; |
441 | struct exec ex; | 457 | struct exec ex; |
442 | 458 | ||
@@ -450,7 +466,8 @@ static int load_aout_library(struct file *file) | |||
450 | /* We come in here for the regular a.out style of shared libraries */ | 466 | /* We come in here for the regular a.out style of shared libraries */ |
451 | if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || | 467 | if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || |
452 | N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || | 468 | N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || |
453 | i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { | 469 | i_size_read(inode) < |
470 | ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { | ||
454 | goto out; | 471 | goto out; |
455 | } | 472 | } |
456 | 473 | ||
@@ -467,10 +484,10 @@ static int load_aout_library(struct file *file) | |||
467 | 484 | ||
468 | #ifdef WARN_OLD | 485 | #ifdef WARN_OLD |
469 | static unsigned long error_time; | 486 | static unsigned long error_time; |
470 | if ((jiffies-error_time) > 5*HZ) | 487 | if ((jiffies-error_time) > 5*HZ) { |
471 | { | 488 | printk(KERN_WARNING |
472 | printk(KERN_WARNING | 489 | "N_TXTOFF is not page aligned. Please convert " |
473 | "N_TXTOFF is not page aligned. Please convert library: %s\n", | 490 | "library: %s\n", |
474 | file->f_path.dentry->d_name.name); | 491 | file->f_path.dentry->d_name.name); |
475 | error_time = jiffies; | 492 | error_time = jiffies; |
476 | } | 493 | } |
@@ -478,11 +495,12 @@ static int load_aout_library(struct file *file) | |||
478 | down_write(¤t->mm->mmap_sem); | 495 | down_write(¤t->mm->mmap_sem); |
479 | do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); | 496 | do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); |
480 | up_write(¤t->mm->mmap_sem); | 497 | up_write(¤t->mm->mmap_sem); |
481 | 498 | ||
482 | file->f_op->read(file, (char __user *)start_addr, | 499 | file->f_op->read(file, (char __user *)start_addr, |
483 | ex.a_text + ex.a_data, &pos); | 500 | ex.a_text + ex.a_data, &pos); |
484 | flush_icache_range((unsigned long) start_addr, | 501 | flush_icache_range((unsigned long) start_addr, |
485 | (unsigned long) start_addr + ex.a_text + ex.a_data); | 502 | (unsigned long) start_addr + ex.a_text + |
503 | ex.a_data); | ||
486 | 504 | ||
487 | retval = 0; | 505 | retval = 0; |
488 | goto out; | 506 | goto out; |