This source file includes following definitions.
- set_brk
- do_aout_core_dump
- aout_core_dump
- create_aout_tables
- do_load_aout_binary
- load_aout_binary
- do_load_aout_library
- load_aout_library
- init_aout_binfmt
- init_module
- cleanup_module
1
2
3
4
5
6
7 #include <linux/module.h>
8
9 #include <linux/fs.h>
10 #include <linux/sched.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/stat.h>
19 #include <linux/fcntl.h>
20 #include <linux/ptrace.h>
21 #include <linux/user.h>
22 #include <linux/malloc.h>
23 #include <linux/binfmts.h>
24 #include <linux/personality.h>
25
26 #include <asm/system.h>
27 #include <asm/segment.h>
28 #include <asm/pgtable.h>
29
30 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
31 static int load_aout_library(int fd);
32 static int aout_core_dump(long signr, struct pt_regs * regs);
33
34 extern void dump_thread(struct pt_regs *, struct user *);
35
36 static struct linux_binfmt aout_format = {
37 #ifndef MODULE
38 NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
39 #else
40 NULL, &mod_use_count_, load_aout_binary, load_aout_library, aout_core_dump
41 #endif
42 };
43
44 static void set_brk(unsigned long start, unsigned long end)
45 {
46 start = PAGE_ALIGN(start);
47 end = PAGE_ALIGN(end);
48 if (end <= start)
49 return;
50 do_mmap(NULL, start, end - start,
51 PROT_READ | PROT_WRITE | PROT_EXEC,
52 MAP_FIXED | MAP_PRIVATE, 0);
53 }
54
55
56
57
58
59 #define DUMP_WRITE(addr,nr) \
60 while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
61
62 #define DUMP_SEEK(offset) \
63 if (file.f_op->lseek) { \
64 if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
65 goto close_coredump; \
66 } else file.f_pos = (offset)
67
68
69
70
71
72
73
74
75
76
77
78 static inline int
79 do_aout_core_dump(long signr, struct pt_regs * regs)
80 {
81 struct inode * inode = NULL;
82 struct file file;
83 unsigned short fs;
84 int has_dumped = 0;
85 char corefile[6+sizeof(current->comm)];
86 unsigned long dump_start, dump_size;
87 struct user dump;
88 #ifdef __alpha__
89 # define START_DATA(u) (u.start_data)
90 #else
91 # define START_DATA(u) (u.u_tsize << PAGE_SHIFT)
92 #endif
93
94 if (!current->dumpable)
95 return 0;
96 current->dumpable = 0;
97
98
99 if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
100 return 0;
101 fs = get_fs();
102 set_fs(KERNEL_DS);
103 memcpy(corefile,"core.",5);
104 #if 0
105 memcpy(corefile+5,current->comm,sizeof(current->comm));
106 #else
107 corefile[4] = '\0';
108 #endif
109 if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
110 inode = NULL;
111 goto end_coredump;
112 }
113 if (!S_ISREG(inode->i_mode))
114 goto end_coredump;
115 if (!inode->i_op || !inode->i_op->default_file_ops)
116 goto end_coredump;
117 if (get_write_access(inode))
118 goto end_coredump;
119 file.f_mode = 3;
120 file.f_flags = 0;
121 file.f_count = 1;
122 file.f_inode = inode;
123 file.f_pos = 0;
124 file.f_reada = 0;
125 file.f_op = inode->i_op->default_file_ops;
126 if (file.f_op->open)
127 if (file.f_op->open(inode,&file))
128 goto done_coredump;
129 if (!file.f_op->write)
130 goto close_coredump;
131 has_dumped = 1;
132 strncpy(dump.u_comm, current->comm, sizeof(current->comm));
133 dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
134 dump.signal = signr;
135 dump_thread(regs, &dump);
136
137
138
139 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
140 current->rlim[RLIMIT_CORE].rlim_cur)
141 dump.u_dsize = 0;
142
143
144 if ((dump.u_ssize+1) * PAGE_SIZE >
145 current->rlim[RLIMIT_CORE].rlim_cur)
146 dump.u_ssize = 0;
147
148
149 set_fs(USER_DS);
150 if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
151 dump.u_dsize = 0;
152 if (verify_area(VERIFY_READ, (void *) dump.start_stack, dump.u_ssize << PAGE_SHIFT))
153 dump.u_ssize = 0;
154
155 set_fs(KERNEL_DS);
156
157 DUMP_WRITE(&dump,sizeof(dump));
158
159 DUMP_SEEK(PAGE_SIZE);
160
161 set_fs(USER_DS);
162
163 if (dump.u_dsize != 0) {
164 dump_start = START_DATA(dump);
165 dump_size = dump.u_dsize << PAGE_SHIFT;
166 DUMP_WRITE(dump_start,dump_size);
167 }
168
169 if (dump.u_ssize != 0) {
170 dump_start = dump.start_stack;
171 dump_size = dump.u_ssize << PAGE_SHIFT;
172 DUMP_WRITE(dump_start,dump_size);
173 }
174
175 set_fs(KERNEL_DS);
176 DUMP_WRITE(current,sizeof(*current));
177 close_coredump:
178 if (file.f_op->release)
179 file.f_op->release(inode,&file);
180 done_coredump:
181 put_write_access(inode);
182 end_coredump:
183 set_fs(fs);
184 iput(inode);
185 return has_dumped;
186 }
187
188 static int
189 aout_core_dump(long signr, struct pt_regs * regs)
190 {
191 int retval;
192
193 MOD_INC_USE_COUNT;
194 retval = do_aout_core_dump(signr, regs);
195 MOD_DEC_USE_COUNT;
196 return retval;
197 }
198
199
200
201
202
203
204 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm, int ibcs)
205 {
206 unsigned long *argv,*envp;
207 unsigned long * sp;
208 int argc = bprm->argc;
209 int envc = bprm->envc;
210
211 sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
212 #ifdef __alpha__
213
214 put_user(0, --sp);
215 put_user(0, --sp);
216 if (bprm->loader) {
217 put_user(0, --sp);
218 put_user(0x3eb, --sp);
219 put_user(bprm->loader, --sp);
220 put_user(0x3ea, --sp);
221 }
222 put_user(bprm->exec, --sp);
223 put_user(0x3e9, --sp);
224 #endif
225 sp -= envc+1;
226 envp = sp;
227 sp -= argc+1;
228 argv = sp;
229 #ifdef __i386__
230 if (!ibcs) {
231 put_user(envp,--sp);
232 put_user(argv,--sp);
233 }
234 #endif
235 put_user(argc,--sp);
236 current->mm->arg_start = (unsigned long) p;
237 while (argc-->0) {
238 put_user(p,argv++);
239 while (get_user(p++)) ;
240 }
241 put_user(NULL,argv);
242 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
243 while (envc-->0) {
244 put_user(p,envp++);
245 while (get_user(p++)) ;
246 }
247 put_user(NULL,envp);
248 current->mm->env_end = (unsigned long) p;
249 return sp;
250 }
251
252
253
254
255
256
257 static inline int
258 do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
259 {
260 struct exec ex;
261 struct file * file;
262 int fd;
263 unsigned long error;
264 unsigned long p = bprm->p;
265 unsigned long fd_offset;
266 unsigned long rlim;
267
268 ex = *((struct exec *) bprm->buf);
269 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
270 N_MAGIC(ex) != QMAGIC) ||
271 N_TRSIZE(ex) || N_DRSIZE(ex) ||
272 bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
273 return -ENOEXEC;
274 }
275
276 current->personality = PER_LINUX;
277 fd_offset = N_TXTOFF(ex);
278
279 #ifdef __i386__
280 if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
281 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
282 return -ENOEXEC;
283 }
284
285 if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
286 (fd_offset < bprm->inode->i_sb->s_blocksize)) {
287 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
288 return -ENOEXEC;
289 }
290 #endif
291
292
293
294
295
296 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
297 if (rlim >= RLIM_INFINITY)
298 rlim = ~0;
299 if (ex.a_data + ex.a_bss > rlim)
300 return -ENOMEM;
301
302
303 flush_old_exec(bprm);
304
305 current->mm->end_code = ex.a_text +
306 (current->mm->start_code = N_TXTADDR(ex));
307 current->mm->end_data = ex.a_data +
308 (current->mm->start_data = N_DATADDR(ex));
309 current->mm->brk = ex.a_bss +
310 (current->mm->start_brk = N_BSSADDR(ex));
311
312 current->mm->rss = 0;
313 current->mm->mmap = NULL;
314 current->suid = current->euid = current->fsuid = bprm->e_uid;
315 current->sgid = current->egid = current->fsgid = bprm->e_gid;
316 if (N_MAGIC(ex) == OMAGIC) {
317 #ifdef __alpha__
318 do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
319 ex.a_text+ex.a_data + PAGE_SIZE - 1,
320 PROT_READ|PROT_WRITE|PROT_EXEC,
321 MAP_FIXED|MAP_PRIVATE, 0);
322 read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
323 ex.a_text+ex.a_data, 0);
324 #else
325 do_mmap(NULL, 0, ex.a_text+ex.a_data,
326 PROT_READ|PROT_WRITE|PROT_EXEC,
327 MAP_FIXED|MAP_PRIVATE, 0);
328 read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0);
329 #endif
330 } else {
331 if (ex.a_text & 0xfff || ex.a_data & 0xfff)
332 printk(KERN_NOTICE "executable not page aligned\n");
333
334 fd = open_inode(bprm->inode, O_RDONLY);
335
336 if (fd < 0)
337 return fd;
338 file = current->files->fd[fd];
339 if (!file->f_op || !file->f_op->mmap) {
340 sys_close(fd);
341 do_mmap(NULL, 0, ex.a_text+ex.a_data,
342 PROT_READ|PROT_WRITE|PROT_EXEC,
343 MAP_FIXED|MAP_PRIVATE, 0);
344 read_exec(bprm->inode, fd_offset,
345 (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
346 goto beyond_if;
347 }
348
349 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
350 PROT_READ | PROT_EXEC,
351 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
352 fd_offset);
353
354 if (error != N_TXTADDR(ex)) {
355 sys_close(fd);
356 send_sig(SIGKILL, current, 0);
357 return error;
358 }
359
360 error = do_mmap(file, N_DATADDR(ex), ex.a_data,
361 PROT_READ | PROT_WRITE | PROT_EXEC,
362 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
363 fd_offset + ex.a_text);
364 sys_close(fd);
365 if (error != N_DATADDR(ex)) {
366 send_sig(SIGKILL, current, 0);
367 return error;
368 }
369 }
370 beyond_if:
371 if (current->exec_domain && current->exec_domain->use_count)
372 (*current->exec_domain->use_count)--;
373 if (current->binfmt && current->binfmt->use_count)
374 (*current->binfmt->use_count)--;
375 current->exec_domain = lookup_exec_domain(current->personality);
376 current->binfmt = &aout_format;
377 if (current->exec_domain && current->exec_domain->use_count)
378 (*current->exec_domain->use_count)++;
379 if (current->binfmt && current->binfmt->use_count)
380 (*current->binfmt->use_count)++;
381
382 set_brk(current->mm->start_brk, current->mm->brk);
383
384 p = setup_arg_pages(p, bprm);
385
386 p = (unsigned long) create_aout_tables((char *)p, bprm,
387 current->personality != PER_LINUX);
388 current->mm->start_stack = p;
389 #ifdef __alpha__
390 regs->gp = ex.a_gpvalue;
391 #endif
392 start_thread(regs, ex.a_entry, p);
393 if (current->flags & PF_PTRACED)
394 send_sig(SIGTRAP, current, 0);
395 return 0;
396 }
397
398 static int
399 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
400 {
401 int retval;
402
403 MOD_INC_USE_COUNT;
404 retval = do_load_aout_binary(bprm, regs);
405 MOD_DEC_USE_COUNT;
406 return retval;
407 }
408
409 static inline int
410 do_load_aout_library(int fd)
411 {
412 struct file * file;
413 struct exec ex;
414 struct inode * inode;
415 unsigned int len;
416 unsigned int bss;
417 unsigned int start_addr;
418 unsigned long error;
419
420 file = current->files->fd[fd];
421 inode = file->f_inode;
422
423 if (!file || !file->f_op)
424 return -EACCES;
425
426
427 if (file->f_op->lseek) {
428 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
429 return -ENOEXEC;
430 } else
431 file->f_pos = 0;
432
433 set_fs(KERNEL_DS);
434 error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
435 set_fs(USER_DS);
436 if (error != sizeof(ex))
437 return -ENOEXEC;
438
439
440 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
441 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
442 inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
443 return -ENOEXEC;
444 }
445 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
446 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
447 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
448 return -ENOEXEC;
449 }
450
451 if (N_FLAGS(ex)) return -ENOEXEC;
452
453
454
455
456 start_addr = ex.a_entry & 0xfffff000;
457
458
459 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
460 PROT_READ | PROT_WRITE | PROT_EXEC,
461 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
462 N_TXTOFF(ex));
463 if (error != start_addr)
464 return error;
465 len = PAGE_ALIGN(ex.a_text + ex.a_data);
466 bss = ex.a_text + ex.a_data + ex.a_bss;
467 if (bss > len) {
468 error = do_mmap(NULL, start_addr + len, bss-len,
469 PROT_READ|PROT_WRITE|PROT_EXEC,
470 MAP_PRIVATE|MAP_FIXED, 0);
471 if (error != start_addr + len)
472 return error;
473 }
474 return 0;
475 }
476
477 static int
478 load_aout_library(int fd)
479 {
480 int retval;
481
482 MOD_INC_USE_COUNT;
483 retval = do_load_aout_library(fd);
484 MOD_DEC_USE_COUNT;
485 return retval;
486 }
487
488
489 int init_aout_binfmt(void) {
490 return register_binfmt(&aout_format);
491 }
492
493 #ifdef MODULE
494 int init_module(void) {
495 return init_aout_binfmt();
496 }
497
498 void cleanup_module( void) {
499 unregister_binfmt(&aout_format);
500 }
501 #endif
502