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 current->flags |= PF_DUMPCORE;
133 strncpy(dump.u_comm, current->comm, sizeof(current->comm));
134 dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
135 dump.signal = signr;
136 dump_thread(regs, &dump);
137
138
139
140 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
141 current->rlim[RLIMIT_CORE].rlim_cur)
142 dump.u_dsize = 0;
143
144
145 if ((dump.u_ssize+1) * PAGE_SIZE >
146 current->rlim[RLIMIT_CORE].rlim_cur)
147 dump.u_ssize = 0;
148
149
150 set_fs(USER_DS);
151 if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
152 dump.u_dsize = 0;
153 if (verify_area(VERIFY_READ, (void *) dump.start_stack, dump.u_ssize << PAGE_SHIFT))
154 dump.u_ssize = 0;
155
156 set_fs(KERNEL_DS);
157
158 DUMP_WRITE(&dump,sizeof(dump));
159
160 DUMP_SEEK(PAGE_SIZE);
161
162 set_fs(USER_DS);
163
164 if (dump.u_dsize != 0) {
165 dump_start = START_DATA(dump);
166 dump_size = dump.u_dsize << PAGE_SHIFT;
167 DUMP_WRITE(dump_start,dump_size);
168 }
169
170 if (dump.u_ssize != 0) {
171 dump_start = dump.start_stack;
172 dump_size = dump.u_ssize << PAGE_SHIFT;
173 DUMP_WRITE(dump_start,dump_size);
174 }
175
176 set_fs(KERNEL_DS);
177 DUMP_WRITE(current,sizeof(*current));
178 close_coredump:
179 if (file.f_op->release)
180 file.f_op->release(inode,&file);
181 done_coredump:
182 put_write_access(inode);
183 end_coredump:
184 set_fs(fs);
185 iput(inode);
186 return has_dumped;
187 }
188
189 static int
190 aout_core_dump(long signr, struct pt_regs * regs)
191 {
192 int retval;
193
194 MOD_INC_USE_COUNT;
195 retval = do_aout_core_dump(signr, regs);
196 MOD_DEC_USE_COUNT;
197 return retval;
198 }
199
200
201
202
203
204
205 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
206 {
207 unsigned long *argv,*envp;
208 unsigned long * sp;
209 int argc = bprm->argc;
210 int envc = bprm->envc;
211
212 sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
213 #ifdef __alpha__
214
215 put_user(0, --sp);
216 put_user(0, --sp);
217 if (bprm->loader) {
218 put_user(0, --sp);
219 put_user(0x3eb, --sp);
220 put_user(bprm->loader, --sp);
221 put_user(0x3ea, --sp);
222 }
223 put_user(bprm->exec, --sp);
224 put_user(0x3e9, --sp);
225 #endif
226 sp -= envc+1;
227 envp = sp;
228 sp -= argc+1;
229 argv = sp;
230 #ifdef __i386__
231 put_user(envp,--sp);
232 put_user(argv,--sp);
233 #endif
234 put_user(argc,--sp);
235 current->mm->arg_start = (unsigned long) p;
236 while (argc-->0) {
237 put_user(p,argv++);
238 while (get_user(p++)) ;
239 }
240 put_user(NULL,argv);
241 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
242 while (envc-->0) {
243 put_user(p,envp++);
244 while (get_user(p++)) ;
245 }
246 put_user(NULL,envp);
247 current->mm->env_end = (unsigned long) p;
248 return sp;
249 }
250
251
252
253
254
255
256 static inline int
257 do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
258 {
259 struct exec ex;
260 struct file * file;
261 int fd;
262 unsigned long error;
263 unsigned long p = bprm->p;
264 unsigned long fd_offset;
265 unsigned long rlim;
266
267 ex = *((struct exec *) bprm->buf);
268 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
269 N_MAGIC(ex) != QMAGIC) ||
270 N_TRSIZE(ex) || N_DRSIZE(ex) ||
271 bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
272 return -ENOEXEC;
273 }
274
275 current->personality = PER_LINUX;
276 fd_offset = N_TXTOFF(ex);
277
278 #ifdef __i386__
279 if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
280 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
281 return -ENOEXEC;
282 }
283
284 if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
285 (fd_offset < bprm->inode->i_sb->s_blocksize)) {
286 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
287 return -ENOEXEC;
288 }
289 #endif
290
291
292
293
294
295 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
296 if (rlim >= RLIM_INFINITY)
297 rlim = ~0;
298 if (ex.a_data + ex.a_bss > rlim)
299 return -ENOMEM;
300
301
302 flush_old_exec(bprm);
303
304 current->mm->end_code = ex.a_text +
305 (current->mm->start_code = N_TXTADDR(ex));
306 current->mm->end_data = ex.a_data +
307 (current->mm->start_data = N_DATADDR(ex));
308 current->mm->brk = ex.a_bss +
309 (current->mm->start_brk = N_BSSADDR(ex));
310
311 current->mm->rss = 0;
312 current->mm->mmap = NULL;
313 current->suid = current->euid = current->fsuid = bprm->e_uid;
314 current->sgid = current->egid = current->fsgid = bprm->e_gid;
315 current->flags &= ~PF_FORKNOEXEC;
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->mm->start_stack = p;
388 #ifdef __alpha__
389 regs->gp = ex.a_gpvalue;
390 #endif
391 start_thread(regs, ex.a_entry, p);
392 if (current->flags & PF_PTRACED)
393 send_sig(SIGTRAP, current, 0);
394 return 0;
395 }
396
397 static int
398 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
399 {
400 int retval;
401
402 MOD_INC_USE_COUNT;
403 retval = do_load_aout_binary(bprm, regs);
404 MOD_DEC_USE_COUNT;
405 return retval;
406 }
407
408 static inline int
409 do_load_aout_library(int fd)
410 {
411 struct file * file;
412 struct exec ex;
413 struct inode * inode;
414 unsigned int len;
415 unsigned int bss;
416 unsigned int start_addr;
417 unsigned long error;
418
419 file = current->files->fd[fd];
420 inode = file->f_inode;
421
422 if (!file || !file->f_op)
423 return -EACCES;
424
425
426 if (file->f_op->lseek) {
427 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
428 return -ENOEXEC;
429 } else
430 file->f_pos = 0;
431
432 set_fs(KERNEL_DS);
433 error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
434 set_fs(USER_DS);
435 if (error != sizeof(ex))
436 return -ENOEXEC;
437
438
439 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
440 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
441 inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
442 return -ENOEXEC;
443 }
444 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
445 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
446 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
447 return -ENOEXEC;
448 }
449
450 if (N_FLAGS(ex)) return -ENOEXEC;
451
452
453
454
455 start_addr = ex.a_entry & 0xfffff000;
456
457
458 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
459 PROT_READ | PROT_WRITE | PROT_EXEC,
460 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
461 N_TXTOFF(ex));
462 if (error != start_addr)
463 return error;
464 len = PAGE_ALIGN(ex.a_text + ex.a_data);
465 bss = ex.a_text + ex.a_data + ex.a_bss;
466 if (bss > len) {
467 error = do_mmap(NULL, start_addr + len, bss-len,
468 PROT_READ|PROT_WRITE|PROT_EXEC,
469 MAP_PRIVATE|MAP_FIXED, 0);
470 if (error != start_addr + len)
471 return error;
472 }
473 return 0;
474 }
475
476 static int
477 load_aout_library(int fd)
478 {
479 int retval;
480
481 MOD_INC_USE_COUNT;
482 retval = do_load_aout_library(fd);
483 MOD_DEC_USE_COUNT;
484 return retval;
485 }
486
487
488 int init_aout_binfmt(void) {
489 return register_binfmt(&aout_format);
490 }
491
492 #ifdef MODULE
493 int init_module(void) {
494 return init_aout_binfmt();
495 }
496
497 void cleanup_module( void) {
498 unregister_binfmt(&aout_format);
499 }
500 #endif
501