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, int ibcs)
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 if (!ibcs) {
232 put_user(envp,--sp);
233 put_user(argv,--sp);
234 }
235 #endif
236 put_user(argc,--sp);
237 current->mm->arg_start = (unsigned long) p;
238 while (argc-->0) {
239 put_user(p,argv++);
240 while (get_user(p++)) ;
241 }
242 put_user(NULL,argv);
243 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
244 while (envc-->0) {
245 put_user(p,envp++);
246 while (get_user(p++)) ;
247 }
248 put_user(NULL,envp);
249 current->mm->env_end = (unsigned long) p;
250 return sp;
251 }
252
253
254
255
256
257
258 static inline int
259 do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
260 {
261 struct exec ex;
262 struct file * file;
263 int fd;
264 unsigned long error;
265 unsigned long p = bprm->p;
266 unsigned long fd_offset;
267 unsigned long rlim;
268
269 ex = *((struct exec *) bprm->buf);
270 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
271 N_MAGIC(ex) != QMAGIC) ||
272 N_TRSIZE(ex) || N_DRSIZE(ex) ||
273 bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
274 return -ENOEXEC;
275 }
276
277 current->personality = PER_LINUX;
278 fd_offset = N_TXTOFF(ex);
279
280 #ifdef __i386__
281 if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
282 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
283 return -ENOEXEC;
284 }
285
286 if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
287 (fd_offset < bprm->inode->i_sb->s_blocksize)) {
288 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
289 return -ENOEXEC;
290 }
291 #endif
292
293
294
295
296
297 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
298 if (rlim >= RLIM_INFINITY)
299 rlim = ~0;
300 if (ex.a_data + ex.a_bss > rlim)
301 return -ENOMEM;
302
303
304 flush_old_exec(bprm);
305
306 current->mm->end_code = ex.a_text +
307 (current->mm->start_code = N_TXTADDR(ex));
308 current->mm->end_data = ex.a_data +
309 (current->mm->start_data = N_DATADDR(ex));
310 current->mm->brk = ex.a_bss +
311 (current->mm->start_brk = N_BSSADDR(ex));
312
313 current->mm->rss = 0;
314 current->mm->mmap = NULL;
315 current->suid = current->euid = current->fsuid = bprm->e_uid;
316 current->sgid = current->egid = current->fsgid = bprm->e_gid;
317 current->flags &= ~PF_FORKNOEXEC;
318 if (N_MAGIC(ex) == OMAGIC) {
319 #ifdef __alpha__
320 do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
321 ex.a_text+ex.a_data + PAGE_SIZE - 1,
322 PROT_READ|PROT_WRITE|PROT_EXEC,
323 MAP_FIXED|MAP_PRIVATE, 0);
324 read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
325 ex.a_text+ex.a_data, 0);
326 #else
327 do_mmap(NULL, 0, ex.a_text+ex.a_data,
328 PROT_READ|PROT_WRITE|PROT_EXEC,
329 MAP_FIXED|MAP_PRIVATE, 0);
330 read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0);
331 #endif
332 } else {
333 if (ex.a_text & 0xfff || ex.a_data & 0xfff)
334 printk(KERN_NOTICE "executable not page aligned\n");
335
336 fd = open_inode(bprm->inode, O_RDONLY);
337
338 if (fd < 0)
339 return fd;
340 file = current->files->fd[fd];
341 if (!file->f_op || !file->f_op->mmap) {
342 sys_close(fd);
343 do_mmap(NULL, 0, ex.a_text+ex.a_data,
344 PROT_READ|PROT_WRITE|PROT_EXEC,
345 MAP_FIXED|MAP_PRIVATE, 0);
346 read_exec(bprm->inode, fd_offset,
347 (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
348 goto beyond_if;
349 }
350
351 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
352 PROT_READ | PROT_EXEC,
353 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
354 fd_offset);
355
356 if (error != N_TXTADDR(ex)) {
357 sys_close(fd);
358 send_sig(SIGKILL, current, 0);
359 return error;
360 }
361
362 error = do_mmap(file, N_DATADDR(ex), ex.a_data,
363 PROT_READ | PROT_WRITE | PROT_EXEC,
364 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
365 fd_offset + ex.a_text);
366 sys_close(fd);
367 if (error != N_DATADDR(ex)) {
368 send_sig(SIGKILL, current, 0);
369 return error;
370 }
371 }
372 beyond_if:
373 if (current->exec_domain && current->exec_domain->use_count)
374 (*current->exec_domain->use_count)--;
375 if (current->binfmt && current->binfmt->use_count)
376 (*current->binfmt->use_count)--;
377 current->exec_domain = lookup_exec_domain(current->personality);
378 current->binfmt = &aout_format;
379 if (current->exec_domain && current->exec_domain->use_count)
380 (*current->exec_domain->use_count)++;
381 if (current->binfmt && current->binfmt->use_count)
382 (*current->binfmt->use_count)++;
383
384 set_brk(current->mm->start_brk, current->mm->brk);
385
386 p = setup_arg_pages(p, bprm);
387
388 p = (unsigned long) create_aout_tables((char *)p, bprm,
389 current->personality != PER_LINUX);
390 current->mm->start_stack = p;
391 #ifdef __alpha__
392 regs->gp = ex.a_gpvalue;
393 #endif
394 start_thread(regs, ex.a_entry, p);
395 if (current->flags & PF_PTRACED)
396 send_sig(SIGTRAP, current, 0);
397 return 0;
398 }
399
400 static int
401 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
402 {
403 int retval;
404
405 MOD_INC_USE_COUNT;
406 retval = do_load_aout_binary(bprm, regs);
407 MOD_DEC_USE_COUNT;
408 return retval;
409 }
410
411 static inline int
412 do_load_aout_library(int fd)
413 {
414 struct file * file;
415 struct exec ex;
416 struct inode * inode;
417 unsigned int len;
418 unsigned int bss;
419 unsigned int start_addr;
420 unsigned long error;
421
422 file = current->files->fd[fd];
423 inode = file->f_inode;
424
425 if (!file || !file->f_op)
426 return -EACCES;
427
428
429 if (file->f_op->lseek) {
430 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
431 return -ENOEXEC;
432 } else
433 file->f_pos = 0;
434
435 set_fs(KERNEL_DS);
436 error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
437 set_fs(USER_DS);
438 if (error != sizeof(ex))
439 return -ENOEXEC;
440
441
442 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
443 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
444 inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
445 return -ENOEXEC;
446 }
447 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
448 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
449 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
450 return -ENOEXEC;
451 }
452
453 if (N_FLAGS(ex)) return -ENOEXEC;
454
455
456
457
458 start_addr = ex.a_entry & 0xfffff000;
459
460
461 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
462 PROT_READ | PROT_WRITE | PROT_EXEC,
463 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
464 N_TXTOFF(ex));
465 if (error != start_addr)
466 return error;
467 len = PAGE_ALIGN(ex.a_text + ex.a_data);
468 bss = ex.a_text + ex.a_data + ex.a_bss;
469 if (bss > len) {
470 error = do_mmap(NULL, start_addr + len, bss-len,
471 PROT_READ|PROT_WRITE|PROT_EXEC,
472 MAP_PRIVATE|MAP_FIXED, 0);
473 if (error != start_addr + len)
474 return error;
475 }
476 return 0;
477 }
478
479 static int
480 load_aout_library(int fd)
481 {
482 int retval;
483
484 MOD_INC_USE_COUNT;
485 retval = do_load_aout_library(fd);
486 MOD_DEC_USE_COUNT;
487 return retval;
488 }
489
490
491 int init_aout_binfmt(void) {
492 return register_binfmt(&aout_format);
493 }
494
495 #ifdef MODULE
496 int init_module(void) {
497 return init_aout_binfmt();
498 }
499
500 void cleanup_module( void) {
501 unregister_binfmt(&aout_format);
502 }
503 #endif
504