This source file includes following definitions.
- set_brk
- do_aout_core_dump
- aout_core_dump
- 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 inline int
205 do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
206 {
207 struct exec ex;
208 struct file * file;
209 int fd;
210 unsigned long error;
211 unsigned long p = bprm->p;
212 unsigned long fd_offset;
213 unsigned long rlim;
214
215 ex = *((struct exec *) bprm->buf);
216 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
217 N_MAGIC(ex) != QMAGIC) ||
218 N_TRSIZE(ex) || N_DRSIZE(ex) ||
219 bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
220 return -ENOEXEC;
221 }
222
223 current->personality = PER_LINUX;
224 fd_offset = N_TXTOFF(ex);
225
226 #ifdef __i386__
227 if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
228 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
229 return -ENOEXEC;
230 }
231
232 if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
233 (fd_offset < bprm->inode->i_sb->s_blocksize)) {
234 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
235 return -ENOEXEC;
236 }
237 #endif
238
239
240
241
242
243 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
244 if (rlim >= RLIM_INFINITY)
245 rlim = ~0;
246 if (ex.a_data + ex.a_bss > rlim)
247 return -ENOMEM;
248
249
250 flush_old_exec(bprm);
251
252 current->mm->end_code = ex.a_text +
253 (current->mm->start_code = N_TXTADDR(ex));
254 current->mm->end_data = ex.a_data +
255 (current->mm->start_data = N_DATADDR(ex));
256 current->mm->brk = ex.a_bss +
257 (current->mm->start_brk = N_BSSADDR(ex));
258
259 current->mm->rss = 0;
260 current->mm->mmap = NULL;
261 current->suid = current->euid = current->fsuid = bprm->e_uid;
262 current->sgid = current->egid = current->fsgid = bprm->e_gid;
263 if (N_MAGIC(ex) == OMAGIC) {
264 #ifdef __alpha__
265 do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
266 ex.a_text+ex.a_data + PAGE_SIZE - 1,
267 PROT_READ|PROT_WRITE|PROT_EXEC,
268 MAP_FIXED|MAP_PRIVATE, 0);
269 read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
270 ex.a_text+ex.a_data, 0);
271 #else
272 do_mmap(NULL, 0, ex.a_text+ex.a_data,
273 PROT_READ|PROT_WRITE|PROT_EXEC,
274 MAP_FIXED|MAP_PRIVATE, 0);
275 read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0);
276 #endif
277 } else {
278 if (ex.a_text & 0xfff || ex.a_data & 0xfff)
279 printk(KERN_NOTICE "executable not page aligned\n");
280
281 fd = open_inode(bprm->inode, O_RDONLY);
282
283 if (fd < 0)
284 return fd;
285 file = current->files->fd[fd];
286 if (!file->f_op || !file->f_op->mmap) {
287 sys_close(fd);
288 do_mmap(NULL, 0, ex.a_text+ex.a_data,
289 PROT_READ|PROT_WRITE|PROT_EXEC,
290 MAP_FIXED|MAP_PRIVATE, 0);
291 read_exec(bprm->inode, fd_offset,
292 (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
293 goto beyond_if;
294 }
295
296 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
297 PROT_READ | PROT_EXEC,
298 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
299 fd_offset);
300
301 if (error != N_TXTADDR(ex)) {
302 sys_close(fd);
303 send_sig(SIGKILL, current, 0);
304 return error;
305 }
306
307 error = do_mmap(file, N_DATADDR(ex), ex.a_data,
308 PROT_READ | PROT_WRITE | PROT_EXEC,
309 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
310 fd_offset + ex.a_text);
311 sys_close(fd);
312 if (error != N_DATADDR(ex)) {
313 send_sig(SIGKILL, current, 0);
314 return error;
315 }
316 }
317 beyond_if:
318 if (current->exec_domain && current->exec_domain->use_count)
319 (*current->exec_domain->use_count)--;
320 if (current->binfmt && current->binfmt->use_count)
321 (*current->binfmt->use_count)--;
322 current->exec_domain = lookup_exec_domain(current->personality);
323 current->binfmt = &aout_format;
324 if (current->exec_domain && current->exec_domain->use_count)
325 (*current->exec_domain->use_count)++;
326 if (current->binfmt && current->binfmt->use_count)
327 (*current->binfmt->use_count)++;
328
329 set_brk(current->mm->start_brk, current->mm->brk);
330
331 fd_offset = setup_arg_pages(ex.a_text,bprm->page) - MAX_ARG_PAGES*PAGE_SIZE;
332 p += fd_offset;
333 if (bprm->loader)
334 bprm->loader += fd_offset;
335 bprm->exec += fd_offset;
336
337 p = (unsigned long)create_tables((char *)p, bprm,
338 current->personality != PER_LINUX);
339 current->mm->start_stack = p;
340 #ifdef __alpha__
341 regs->gp = ex.a_gpvalue;
342 #endif
343 start_thread(regs, ex.a_entry, p);
344 if (current->flags & PF_PTRACED)
345 send_sig(SIGTRAP, current, 0);
346 return 0;
347 }
348
349 static int
350 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
351 {
352 int retval;
353
354 MOD_INC_USE_COUNT;
355 retval = do_load_aout_binary(bprm, regs);
356 MOD_DEC_USE_COUNT;
357 return retval;
358 }
359
360 static inline int
361 do_load_aout_library(int fd)
362 {
363 struct file * file;
364 struct exec ex;
365 struct inode * inode;
366 unsigned int len;
367 unsigned int bss;
368 unsigned int start_addr;
369 unsigned long error;
370
371 file = current->files->fd[fd];
372 inode = file->f_inode;
373
374 if (!file || !file->f_op)
375 return -EACCES;
376
377
378 if (file->f_op->lseek) {
379 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
380 return -ENOEXEC;
381 } else
382 file->f_pos = 0;
383
384 set_fs(KERNEL_DS);
385 error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
386 set_fs(USER_DS);
387 if (error != sizeof(ex))
388 return -ENOEXEC;
389
390
391 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
392 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
393 inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
394 return -ENOEXEC;
395 }
396 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
397 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
398 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
399 return -ENOEXEC;
400 }
401
402 if (N_FLAGS(ex)) return -ENOEXEC;
403
404
405
406
407 start_addr = ex.a_entry & 0xfffff000;
408
409
410 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
411 PROT_READ | PROT_WRITE | PROT_EXEC,
412 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
413 N_TXTOFF(ex));
414 if (error != start_addr)
415 return error;
416 len = PAGE_ALIGN(ex.a_text + ex.a_data);
417 bss = ex.a_text + ex.a_data + ex.a_bss;
418 if (bss > len)
419 do_mmap(NULL, start_addr + len, bss-len,
420 PROT_READ|PROT_WRITE|PROT_EXEC,
421 MAP_PRIVATE|MAP_FIXED, 0);
422 return 0;
423 }
424
425 static int
426 load_aout_library(int fd)
427 {
428 int retval;
429
430 MOD_INC_USE_COUNT;
431 retval = do_load_aout_library(fd);
432 MOD_DEC_USE_COUNT;
433 return retval;
434 }
435
436
437 int init_aout_binfmt(void) {
438 return register_binfmt(&aout_format);
439 }
440
441 #ifdef MODULE
442 int init_module(void) {
443 return init_aout_binfmt();
444 }
445
446 void cleanup_module( void) {
447 unregister_binfmt(&aout_format);
448 }
449 #endif
450