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