• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  a.out loader for x86-64
3  *
4  *  Copyright (C) 1991, 1992, 1996  Linus Torvalds
5  *  Hacked together by Andi Kleen
6  */
7 
8 #include <linux/module.h>
9 
10 #include <linux/time.h>
11 #include <linux/kernel.h>
12 #include <linux/mm.h>
13 #include <linux/mman.h>
14 #include <linux/a.out.h>
15 #include <linux/errno.h>
16 #include <linux/signal.h>
17 #include <linux/string.h>
18 #include <linux/fs.h>
19 #include <linux/file.h>
20 #include <linux/stat.h>
21 #include <linux/fcntl.h>
22 #include <linux/ptrace.h>
23 #include <linux/user.h>
24 #include <linux/binfmts.h>
25 #include <linux/personality.h>
26 #include <linux/init.h>
27 #include <linux/jiffies.h>
28 #include <linux/perf_event.h>
29 
30 #include <asm/uaccess.h>
31 #include <asm/pgalloc.h>
32 #include <asm/cacheflush.h>
33 #include <asm/user32.h>
34 #include <asm/ia32.h>
35 
36 #undef WARN_OLD
37 
38 static int load_aout_binary(struct linux_binprm *);
39 static int load_aout_library(struct file *);
40 
41 #ifdef CONFIG_COREDUMP
42 static int aout_core_dump(struct coredump_params *);
43 
get_dr(int n)44 static unsigned long get_dr(int n)
45 {
46 	struct perf_event *bp = current->thread.ptrace_bps[n];
47 	return bp ? bp->hw.info.address : 0;
48 }
49 
50 /*
51  * fill in the user structure for a core dump..
52  */
dump_thread32(struct pt_regs * regs,struct user32 * dump)53 static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
54 {
55 	u32 fs, gs;
56 	memset(dump, 0, sizeof(*dump));
57 
58 /* changed the size calculations - should hopefully work better. lbt */
59 	dump->magic = CMAGIC;
60 	dump->start_code = 0;
61 	dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
62 	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
63 	dump->u_dsize = ((unsigned long)
64 			 (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
65 	dump->u_dsize -= dump->u_tsize;
66 	dump->u_debugreg[0] = get_dr(0);
67 	dump->u_debugreg[1] = get_dr(1);
68 	dump->u_debugreg[2] = get_dr(2);
69 	dump->u_debugreg[3] = get_dr(3);
70 	dump->u_debugreg[6] = current->thread.debugreg6;
71 	dump->u_debugreg[7] = current->thread.ptrace_dr7;
72 
73 	if (dump->start_stack < 0xc0000000) {
74 		unsigned long tmp;
75 
76 		tmp = (unsigned long) (0xc0000000 - dump->start_stack);
77 		dump->u_ssize = tmp >> PAGE_SHIFT;
78 	}
79 
80 	dump->regs.ebx = regs->bx;
81 	dump->regs.ecx = regs->cx;
82 	dump->regs.edx = regs->dx;
83 	dump->regs.esi = regs->si;
84 	dump->regs.edi = regs->di;
85 	dump->regs.ebp = regs->bp;
86 	dump->regs.eax = regs->ax;
87 	dump->regs.ds = current->thread.ds;
88 	dump->regs.es = current->thread.es;
89 	savesegment(fs, fs);
90 	dump->regs.fs = fs;
91 	savesegment(gs, gs);
92 	dump->regs.gs = gs;
93 	dump->regs.orig_eax = regs->orig_ax;
94 	dump->regs.eip = regs->ip;
95 	dump->regs.cs = regs->cs;
96 	dump->regs.eflags = regs->flags;
97 	dump->regs.esp = regs->sp;
98 	dump->regs.ss = regs->ss;
99 
100 #if 1 /* FIXME */
101 	dump->u_fpvalid = 0;
102 #else
103 	dump->u_fpvalid = dump_fpu(regs, &dump->i387);
104 #endif
105 }
106 
107 #endif
108 
109 static struct linux_binfmt aout_format = {
110 	.module		= THIS_MODULE,
111 	.load_binary	= load_aout_binary,
112 	.load_shlib	= load_aout_library,
113 #ifdef CONFIG_COREDUMP
114 	.core_dump	= aout_core_dump,
115 #endif
116 	.min_coredump	= PAGE_SIZE
117 };
118 
set_brk(unsigned long start,unsigned long end)119 static void set_brk(unsigned long start, unsigned long end)
120 {
121 	start = PAGE_ALIGN(start);
122 	end = PAGE_ALIGN(end);
123 	if (end <= start)
124 		return;
125 	vm_brk(start, end - start);
126 }
127 
128 #ifdef CONFIG_COREDUMP
129 /*
130  * These are the only things you should do on a core-file: use only these
131  * macros to write out all the necessary info.
132  */
133 
134 #include <linux/coredump.h>
135 
136 #define START_DATA(u)	(u.u_tsize << PAGE_SHIFT)
137 #define START_STACK(u)	(u.start_stack)
138 
139 /*
140  * Routine writes a core dump image in the current directory.
141  * Currently only a stub-function.
142  *
143  * Note that setuid/setgid files won't make a core-dump if the uid/gid
144  * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable"
145  * field, which also makes sure the core-dumps won't be recursive if the
146  * dumping of the process results in another error..
147  */
148 
aout_core_dump(struct coredump_params * cprm)149 static int aout_core_dump(struct coredump_params *cprm)
150 {
151 	mm_segment_t fs;
152 	int has_dumped = 0;
153 	unsigned long dump_start, dump_size;
154 	struct user32 dump;
155 
156 	fs = get_fs();
157 	set_fs(KERNEL_DS);
158 	has_dumped = 1;
159 	strncpy(dump.u_comm, current->comm, sizeof(current->comm));
160 	dump.u_ar0 = offsetof(struct user32, regs);
161 	dump.signal = cprm->siginfo->si_signo;
162 	dump_thread32(cprm->regs, &dump);
163 
164 	/*
165 	 * If the size of the dump file exceeds the rlimit, then see
166 	 * what would happen if we wrote the stack, but not the data
167 	 * area.
168 	 */
169 	if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
170 		dump.u_dsize = 0;
171 
172 	/* Make sure we have enough room to write the stack and data areas. */
173 	if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
174 		dump.u_ssize = 0;
175 
176 	/* make sure we actually have a data and stack area to dump */
177 	set_fs(USER_DS);
178 	if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_DATA(dump),
179 		       dump.u_dsize << PAGE_SHIFT))
180 		dump.u_dsize = 0;
181 	if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_STACK(dump),
182 		       dump.u_ssize << PAGE_SHIFT))
183 		dump.u_ssize = 0;
184 
185 	set_fs(KERNEL_DS);
186 	/* struct user */
187 	if (!dump_emit(cprm, &dump, sizeof(dump)))
188 		goto end_coredump;
189 	/* Now dump all of the user data.  Include malloced stuff as well */
190 	if (!dump_skip(cprm, PAGE_SIZE - sizeof(dump)))
191 		goto end_coredump;
192 	/* now we start writing out the user space info */
193 	set_fs(USER_DS);
194 	/* Dump the data area */
195 	if (dump.u_dsize != 0) {
196 		dump_start = START_DATA(dump);
197 		dump_size = dump.u_dsize << PAGE_SHIFT;
198 		if (!dump_emit(cprm, (void *)dump_start, dump_size))
199 			goto end_coredump;
200 	}
201 	/* Now prepare to dump the stack area */
202 	if (dump.u_ssize != 0) {
203 		dump_start = START_STACK(dump);
204 		dump_size = dump.u_ssize << PAGE_SHIFT;
205 		if (!dump_emit(cprm, (void *)dump_start, dump_size))
206 			goto end_coredump;
207 	}
208 end_coredump:
209 	set_fs(fs);
210 	return has_dumped;
211 }
212 #endif
213 
214 /*
215  * create_aout_tables() parses the env- and arg-strings in new user
216  * memory and creates the pointer tables from them, and puts their
217  * addresses on the "stack", returning the new stack pointer value.
218  */
create_aout_tables(char __user * p,struct linux_binprm * bprm)219 static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)
220 {
221 	u32 __user *argv, *envp, *sp;
222 	int argc = bprm->argc, envc = bprm->envc;
223 
224 	sp = (u32 __user *) ((-(unsigned long)sizeof(u32)) & (unsigned long) p);
225 	sp -= envc+1;
226 	envp = sp;
227 	sp -= argc+1;
228 	argv = sp;
229 	put_user((unsigned long) envp, --sp);
230 	put_user((unsigned long) argv, --sp);
231 	put_user(argc, --sp);
232 	current->mm->arg_start = (unsigned long) p;
233 	while (argc-- > 0) {
234 		char c;
235 
236 		put_user((u32)(unsigned long)p, argv++);
237 		do {
238 			get_user(c, p++);
239 		} while (c);
240 	}
241 	put_user(0, argv);
242 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
243 	while (envc-- > 0) {
244 		char c;
245 
246 		put_user((u32)(unsigned long)p, envp++);
247 		do {
248 			get_user(c, p++);
249 		} while (c);
250 	}
251 	put_user(0, envp);
252 	current->mm->env_end = (unsigned long) p;
253 	return sp;
254 }
255 
256 /*
257  * These are the functions used to load a.out style executables and shared
258  * libraries.  There is no binary dependent code anywhere else.
259  */
load_aout_binary(struct linux_binprm * bprm)260 static int load_aout_binary(struct linux_binprm *bprm)
261 {
262 	unsigned long error, fd_offset, rlim;
263 	struct pt_regs *regs = current_pt_regs();
264 	struct exec ex;
265 	int retval;
266 
267 	ex = *((struct exec *) bprm->buf);		/* exec-header */
268 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
269 	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
270 	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
271 	    i_size_read(file_inode(bprm->file)) <
272 	    ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
273 		return -ENOEXEC;
274 	}
275 
276 	fd_offset = N_TXTOFF(ex);
277 
278 	/* Check initial limits. This avoids letting people circumvent
279 	 * size limits imposed on them by creating programs with large
280 	 * arrays in the data or bss.
281 	 */
282 	rlim = rlimit(RLIMIT_DATA);
283 	if (rlim >= RLIM_INFINITY)
284 		rlim = ~0;
285 	if (ex.a_data + ex.a_bss > rlim)
286 		return -ENOMEM;
287 
288 	/* Flush all traces of the currently running executable */
289 	retval = flush_old_exec(bprm);
290 	if (retval)
291 		return retval;
292 
293 	/* OK, This is the point of no return */
294 	set_personality(PER_LINUX);
295 	set_personality_ia32(false);
296 
297 	setup_new_exec(bprm);
298 
299 	regs->cs = __USER32_CS;
300 	regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
301 		regs->r13 = regs->r14 = regs->r15 = 0;
302 
303 	current->mm->end_code = ex.a_text +
304 		(current->mm->start_code = N_TXTADDR(ex));
305 	current->mm->end_data = ex.a_data +
306 		(current->mm->start_data = N_DATADDR(ex));
307 	current->mm->brk = ex.a_bss +
308 		(current->mm->start_brk = N_BSSADDR(ex));
309 
310 	retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT);
311 	if (retval < 0)
312 		return retval;
313 
314 	install_exec_creds(bprm);
315 
316 	if (N_MAGIC(ex) == OMAGIC) {
317 		unsigned long text_addr, map_size;
318 
319 		text_addr = N_TXTADDR(ex);
320 		map_size = ex.a_text+ex.a_data;
321 
322 		error = vm_brk(text_addr & PAGE_MASK, map_size);
323 
324 		if (error != (text_addr & PAGE_MASK))
325 			return error;
326 
327 		error = read_code(bprm->file, text_addr, 32,
328 				  ex.a_text + ex.a_data);
329 		if ((signed long)error < 0)
330 			return error;
331 	} else {
332 #ifdef WARN_OLD
333 		static unsigned long error_time, error_time2;
334 		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
335 		    (N_MAGIC(ex) != NMAGIC) &&
336 				time_after(jiffies, error_time2 + 5*HZ)) {
337 			printk(KERN_NOTICE "executable not page aligned\n");
338 			error_time2 = jiffies;
339 		}
340 
341 		if ((fd_offset & ~PAGE_MASK) != 0 &&
342 			    time_after(jiffies, error_time + 5*HZ)) {
343 			printk(KERN_WARNING
344 			       "fd_offset is not page aligned. Please convert "
345 			       "program: %s\n",
346 			       bprm->file->f_path.dentry->d_name.name);
347 			error_time = jiffies;
348 		}
349 #endif
350 
351 		if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
352 			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
353 			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
354 					ex.a_text+ex.a_data);
355 			goto beyond_if;
356 		}
357 
358 		error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
359 				PROT_READ | PROT_EXEC,
360 				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
361 				MAP_EXECUTABLE | MAP_32BIT,
362 				fd_offset);
363 
364 		if (error != N_TXTADDR(ex))
365 			return error;
366 
367 		error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
368 				PROT_READ | PROT_WRITE | PROT_EXEC,
369 				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
370 				MAP_EXECUTABLE | MAP_32BIT,
371 				fd_offset + ex.a_text);
372 		if (error != N_DATADDR(ex))
373 			return error;
374 	}
375 beyond_if:
376 	set_binfmt(&aout_format);
377 
378 	set_brk(current->mm->start_brk, current->mm->brk);
379 
380 	current->mm->start_stack =
381 		(unsigned long)create_aout_tables((char __user *)bprm->p, bprm);
382 	/* start thread */
383 	loadsegment(fs, 0);
384 	loadsegment(ds, __USER32_DS);
385 	loadsegment(es, __USER32_DS);
386 	load_gs_index(0);
387 	(regs)->ip = ex.a_entry;
388 	(regs)->sp = current->mm->start_stack;
389 	(regs)->flags = 0x200;
390 	(regs)->cs = __USER32_CS;
391 	(regs)->ss = __USER32_DS;
392 	regs->r8 = regs->r9 = regs->r10 = regs->r11 =
393 	regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
394 	set_fs(USER_DS);
395 	return 0;
396 }
397 
load_aout_library(struct file * file)398 static int load_aout_library(struct file *file)
399 {
400 	unsigned long bss, start_addr, len, error;
401 	int retval;
402 	struct exec ex;
403 
404 
405 	retval = -ENOEXEC;
406 	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
407 	if (error != sizeof(ex))
408 		goto out;
409 
410 	/* We come in here for the regular a.out style of shared libraries */
411 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
412 	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
413 	    i_size_read(file_inode(file)) <
414 	    ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
415 		goto out;
416 	}
417 
418 	if (N_FLAGS(ex))
419 		goto out;
420 
421 	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
422 	   this off to get the starting address for the page */
423 
424 	start_addr =  ex.a_entry & 0xfffff000;
425 
426 	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
427 #ifdef WARN_OLD
428 		static unsigned long error_time;
429 		if (time_after(jiffies, error_time + 5*HZ)) {
430 			printk(KERN_WARNING
431 			       "N_TXTOFF is not page aligned. Please convert "
432 			       "library: %s\n",
433 			       file->f_path.dentry->d_name.name);
434 			error_time = jiffies;
435 		}
436 #endif
437 		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
438 
439 		read_code(file, start_addr, N_TXTOFF(ex),
440 			  ex.a_text + ex.a_data);
441 		retval = 0;
442 		goto out;
443 	}
444 	/* Now use mmap to map the library into memory. */
445 	error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
446 			PROT_READ | PROT_WRITE | PROT_EXEC,
447 			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
448 			N_TXTOFF(ex));
449 	retval = error;
450 	if (error != start_addr)
451 		goto out;
452 
453 	len = PAGE_ALIGN(ex.a_text + ex.a_data);
454 	bss = ex.a_text + ex.a_data + ex.a_bss;
455 	if (bss > len) {
456 		error = vm_brk(start_addr + len, bss - len);
457 		retval = error;
458 		if (error != start_addr + len)
459 			goto out;
460 	}
461 	retval = 0;
462 out:
463 	return retval;
464 }
465 
init_aout_binfmt(void)466 static int __init init_aout_binfmt(void)
467 {
468 	register_binfmt(&aout_format);
469 	return 0;
470 }
471 
exit_aout_binfmt(void)472 static void __exit exit_aout_binfmt(void)
473 {
474 	unregister_binfmt(&aout_format);
475 }
476 
477 module_init(init_aout_binfmt);
478 module_exit(exit_aout_binfmt);
479 MODULE_LICENSE("GPL");
480