This source file includes following definitions.
- core_dump
- sys_uselib
- create_tables
- count
- copy_strings
- change_ldt
- read_exec
- do_execve
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <linux/fs.h>
21 #include <linux/sched.h>
22 #include <linux/kernel.h>
23 #include <linux/mm.h>
24 #include <linux/a.out.h>
25 #include <linux/errno.h>
26 #include <linux/signal.h>
27 #include <linux/string.h>
28 #include <linux/stat.h>
29 #include <linux/fcntl.h>
30 #include <linux/ptrace.h>
31 #include <linux/user.h>
32
33 #include <asm/segment.h>
34
35 extern int sys_exit(int exit_code);
36 extern int sys_close(int fd);
37
38
39
40
41
42
43 #define MAX_ARG_PAGES 32
44
45
46
47
48
49 #define DUMP_WRITE(addr,nr) \
50 while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
51
52 #define DUMP_SEEK(offset) \
53 if (file.f_op->lseek) { \
54 if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
55 goto close_coredump; \
56 } else file.f_pos = (offset)
57
58
59
60
61
62
63
64
65
66
67 int core_dump(long signr, struct pt_regs * regs)
68 {
69 struct inode * inode = NULL;
70 struct file file;
71 unsigned short fs;
72 int has_dumped = 0;
73 register int dump_start, dump_size;
74 struct user dump;
75
76 if (!current->dumpable)
77 return 0;
78 current->dumpable = 0;
79
80 if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
81 return 0;
82 __asm__("mov %%fs,%0":"=r" (fs));
83 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
84 if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode,NULL)) {
85 inode = NULL;
86 goto end_coredump;
87 }
88 if (!S_ISREG(inode->i_mode))
89 goto end_coredump;
90 if (!inode->i_op || !inode->i_op->default_file_ops)
91 goto end_coredump;
92 file.f_mode = 3;
93 file.f_flags = 0;
94 file.f_count = 1;
95 file.f_inode = inode;
96 file.f_pos = 0;
97 file.f_reada = 0;
98 file.f_op = inode->i_op->default_file_ops;
99 if (file.f_op->open)
100 if (file.f_op->open(inode,&file))
101 goto end_coredump;
102 if (!file.f_op->write)
103 goto close_coredump;
104 has_dumped = 1;
105
106 dump.magic = CMAGIC;
107 dump.start_code = 0;
108 dump.start_stack = regs->esp & ~(PAGE_SIZE - 1);
109 dump.u_tsize = ((unsigned long) current->end_code) >> 12;
110 dump.u_dsize = ((unsigned long) (current->brk + (PAGE_SIZE-1))) >> 12;
111 dump.u_dsize -= dump.u_tsize;
112 dump.u_ssize = 0;
113 if (dump.start_stack < TASK_SIZE)
114 dump.u_ssize = ((unsigned long) (TASK_SIZE - dump.start_stack)) >> 12;
115
116
117 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
118 current->rlim[RLIMIT_CORE].rlim_cur)
119 dump.u_dsize = 0;
120
121 if ((dump.u_ssize+1) * PAGE_SIZE >
122 current->rlim[RLIMIT_CORE].rlim_cur)
123 dump.u_ssize = 0;
124 dump.u_comm = 0;
125 dump.u_ar0 = (struct pt_regs *)(((int)(&dump.regs)) -((int)(&dump)));
126 dump.signal = signr;
127 dump.regs = *regs;
128
129
130 if (hard_math) {
131 if ((dump.u_fpvalid = current->used_math) != 0) {
132 if (last_task_used_math == current)
133 __asm__("clts ; fnsave %0"::"m" (dump.i387));
134 else
135 memcpy(&dump.i387,¤t->tss.i387.hard,sizeof(dump.i387));
136 }
137 } else {
138
139
140 dump.u_fpvalid = 0;
141 }
142 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
143
144 DUMP_WRITE(&dump,sizeof(dump));
145
146 DUMP_WRITE(current->comm,16);
147
148 DUMP_SEEK(PAGE_SIZE);
149
150 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
151
152 if (dump.u_dsize != 0) {
153 dump_start = dump.u_tsize << 12;
154 dump_size = dump.u_dsize << 12;
155 DUMP_WRITE(dump_start,dump_size);
156 };
157
158 if (dump.u_ssize != 0) {
159 dump_start = dump.start_stack;
160 dump_size = dump.u_ssize << 12;
161 DUMP_WRITE(dump_start,dump_size);
162 };
163
164 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
165 DUMP_WRITE(current,sizeof(*current));
166 close_coredump:
167 if (file.f_op->release)
168 file.f_op->release(inode,&file);
169 end_coredump:
170 __asm__("mov %0,%%fs"::"r" (fs));
171 iput(inode);
172 return has_dumped;
173 }
174
175
176
177
178
179
180
181 int sys_uselib(const char * library)
182 {
183 #define libnum (current->numlibraries)
184 struct inode * inode;
185 struct buffer_head * bh;
186 struct exec ex;
187 unsigned long offset;
188 int error;
189
190 if (!library || get_limit(0x17) != TASK_SIZE)
191 return -EINVAL;
192 if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
193 return -EINVAL;
194 error = namei(library,&inode);
195 if (error)
196 return error;
197 if (!inode->i_sb || !S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
198 iput(inode);
199 return -EACCES;
200 }
201 if (!inode->i_op || !inode->i_op->bmap) {
202 iput(inode);
203 return -ENOEXEC;
204 }
205 if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
206 iput(inode);
207 return -EACCES;
208 }
209 if (!IS_RDONLY(inode)) {
210 inode->i_atime = CURRENT_TIME;
211 inode->i_dirt = 1;
212 }
213 ex = *(struct exec *) bh->b_data;
214 brelse(bh);
215 if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize ||
216 ex.a_drsize || ex.a_entry & 0xfff ||
217 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
218 iput(inode);
219 return -ENOEXEC;
220 }
221 current->libraries[libnum].library = inode;
222 current->libraries[libnum].start = ex.a_entry;
223 offset = (ex.a_data + ex.a_text + 0xfff) & 0xfffff000;
224 current->libraries[libnum].length = offset;
225 current->libraries[libnum].bss = ex.a_bss;
226 offset += ex.a_entry;
227 zeromap_page_range(offset, ex.a_bss, PAGE_COPY);
228 #if 0
229 printk("VFS: Loaded library %d at %08x, length %08x\n",
230 libnum,
231 current->libraries[libnum].start,
232 current->libraries[libnum].length);
233 #endif
234 libnum++;
235 return 0;
236 #undef libnum
237 }
238
239
240
241
242
243
244 static unsigned long * create_tables(char * p,int argc,int envc)
245 {
246 unsigned long *argv,*envp;
247 unsigned long * sp;
248
249 sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
250 sp -= envc+1;
251 envp = sp;
252 sp -= argc+1;
253 argv = sp;
254 put_fs_long((unsigned long)envp,--sp);
255 put_fs_long((unsigned long)argv,--sp);
256 put_fs_long((unsigned long)argc,--sp);
257 current->arg_start = (unsigned long) p;
258 while (argc-->0) {
259 put_fs_long((unsigned long) p,argv++);
260 while (get_fs_byte(p++)) ;
261 }
262 put_fs_long(0,argv);
263 current->arg_end = current->env_start = (unsigned long) p;
264 while (envc-->0) {
265 put_fs_long((unsigned long) p,envp++);
266 while (get_fs_byte(p++)) ;
267 }
268 put_fs_long(0,envp);
269 current->env_end = (unsigned long) p;
270 return sp;
271 }
272
273
274
275
276 static int count(char ** argv)
277 {
278 int i=0;
279 char ** tmp;
280
281 if ((tmp = argv) != 0)
282 while (get_fs_long((unsigned long *) (tmp++)))
283 i++;
284
285 return i;
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
306 unsigned long p, int from_kmem)
307 {
308 char *tmp, *pag = NULL;
309 int len, offset = 0;
310 unsigned long old_fs, new_fs;
311
312 if (!p)
313 return 0;
314 new_fs = get_ds();
315 old_fs = get_fs();
316 if (from_kmem==2)
317 set_fs(new_fs);
318 while (argc-- > 0) {
319 if (from_kmem == 1)
320 set_fs(new_fs);
321 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
322 panic("VFS: argc is wrong");
323 if (from_kmem == 1)
324 set_fs(old_fs);
325 len=0;
326 do {
327 len++;
328 } while (get_fs_byte(tmp++));
329 if (p < len) {
330 set_fs(old_fs);
331 return 0;
332 }
333 while (len) {
334 --p; --tmp; --len;
335 if (--offset < 0) {
336 offset = p % PAGE_SIZE;
337 if (from_kmem==2)
338 set_fs(old_fs);
339 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
340 !(pag = (char *) page[p/PAGE_SIZE] =
341 (unsigned long *) get_free_page(GFP_USER)))
342 return 0;
343 if (from_kmem==2)
344 set_fs(new_fs);
345
346 }
347 *(pag + offset) = get_fs_byte(tmp);
348 }
349 }
350 if (from_kmem==2)
351 set_fs(old_fs);
352 return p;
353 }
354
355 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
356 {
357 unsigned long code_limit,data_limit,code_base,data_base;
358 int i;
359
360 code_limit = TASK_SIZE;
361 data_limit = TASK_SIZE;
362 code_base = data_base = 0;
363 current->start_code = code_base;
364 set_base(current->ldt[1],code_base);
365 set_limit(current->ldt[1],code_limit);
366 set_base(current->ldt[2],data_base);
367 set_limit(current->ldt[2],data_limit);
368
369 __asm__("pushl $0x17\n\tpop %%fs"::);
370 data_base += data_limit;
371 for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
372 data_base -= PAGE_SIZE;
373 if (page[i])
374 put_dirty_page(current,page[i],data_base);
375 }
376 return data_limit;
377 }
378
379
380
381
382
383
384 static int read_exec(struct inode *inode, unsigned long offset,
385 char * addr, unsigned long count)
386 {
387 struct file file;
388 int result = -ENOEXEC;
389
390 if (!inode->i_op || !inode->i_op->default_file_ops)
391 goto end_readexec;
392 file.f_mode = 1;
393 file.f_flags = 0;
394 file.f_count = 1;
395 file.f_inode = inode;
396 file.f_pos = 0;
397 file.f_reada = 0;
398 file.f_op = inode->i_op->default_file_ops;
399 if (file.f_op->open)
400 if (file.f_op->open(inode,&file))
401 goto end_readexec;
402 if (!file.f_op || !file.f_op->read)
403 goto close_readexec;
404 if (file.f_op->lseek) {
405 if (file.f_op->lseek(inode,&file,offset,0) != offset)
406 goto close_readexec;
407 } else
408 file.f_pos = offset;
409 result = file.f_op->read(inode, &file, addr, count);
410 close_readexec:
411 if (file.f_op->release)
412 file.f_op->release(inode,&file);
413 end_readexec:
414 return result;
415 }
416
417
418
419
420
421
422
423 int do_execve(unsigned long * eip,long tmp,char * filename,
424 char ** argv, char ** envp)
425 {
426 struct inode * inode;
427 char buf[128];
428 unsigned long old_fs;
429 struct exec ex;
430 unsigned long page[MAX_ARG_PAGES];
431 int i,argc,envc;
432 int e_uid, e_gid;
433 int retval;
434 int sh_bang = 0;
435 unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
436 int ch;
437
438 if ((0xffff & eip[1]) != 0x000f)
439 panic("VFS: execve called from supervisor mode");
440 for (i=0 ; i<MAX_ARG_PAGES ; i++)
441 page[i]=0;
442 retval = namei(filename,&inode);
443 if (retval)
444 return retval;
445 argc = count(argv);
446 envc = count(envp);
447
448 restart_interp:
449 if (!S_ISREG(inode->i_mode)) {
450 retval = -EACCES;
451 goto exec_error2;
452 }
453 if (IS_NOEXEC(inode)) {
454 retval = -EPERM;
455 goto exec_error2;
456 }
457 if (!inode->i_sb) {
458 retval = -EACCES;
459 goto exec_error2;
460 }
461 i = inode->i_mode;
462 if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current->
463 euid) || ((i & S_ISGID) && !in_group_p(inode->i_gid))) &&
464 !suser()) {
465 retval = -EPERM;
466 goto exec_error2;
467 }
468
469 if (current->flags & PF_PTRACED) {
470 e_uid = current->euid;
471 e_gid = current->egid;
472 } else {
473 e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
474 e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
475 }
476 if (current->euid == inode->i_uid)
477 i >>= 6;
478 else if (in_group_p(inode->i_gid))
479 i >>= 3;
480 if (!(i & 1) &&
481 !((inode->i_mode & 0111) && suser())) {
482 retval = -EACCES;
483 goto exec_error2;
484 }
485 memset(buf,0,sizeof(buf));
486 old_fs = get_fs();
487 set_fs(get_ds());
488 retval = read_exec(inode,0,buf,128);
489 set_fs(old_fs);
490 if (retval < 0)
491 goto exec_error2;
492 ex = *((struct exec *) buf);
493 if ((buf[0] == '#') && (buf[1] == '!') && (!sh_bang)) {
494
495
496
497
498
499 char *cp, *interp, *i_name, *i_arg;
500
501 iput(inode);
502 buf[127] = '\0';
503 if ((cp = strchr(buf, '\n')) == NULL)
504 cp = buf+127;
505 *cp = '\0';
506 while (cp > buf) {
507 cp--;
508 if ((*cp == ' ') || (*cp == '\t'))
509 *cp = '\0';
510 else
511 break;
512 }
513 for (cp = buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
514 if (!cp || *cp == '\0') {
515 retval = -ENOEXEC;
516 goto exec_error1;
517 }
518 interp = i_name = cp;
519 i_arg = 0;
520 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
521 if (*cp == '/')
522 i_name = cp+1;
523 }
524 while ((*cp == ' ') || (*cp == '\t'))
525 *cp++ = '\0';
526 if (*cp)
527 i_arg = cp;
528
529
530
531
532 if (sh_bang++ == 0) {
533 p = copy_strings(envc, envp, page, p, 0);
534 p = copy_strings(--argc, argv+1, page, p, 0);
535 }
536
537
538
539
540
541
542
543
544 p = copy_strings(1, &filename, page, p, 1);
545 argc++;
546 if (i_arg) {
547 p = copy_strings(1, &i_arg, page, p, 2);
548 argc++;
549 }
550 p = copy_strings(1, &i_name, page, p, 2);
551 argc++;
552 if (!p) {
553 retval = -E2BIG;
554 goto exec_error1;
555 }
556
557
558
559
560
561 retval = open_namei(interp,0,0,&inode,NULL);
562 if (retval)
563 goto exec_error1;
564 goto restart_interp;
565 }
566 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
567 ex.a_trsize || ex.a_drsize ||
568 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
569 retval = -ENOEXEC;
570 goto exec_error2;
571 }
572 if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
573 printk("VFS: N_TXTOFF != BLOCK_SIZE. See a.out.h.");
574 retval = -ENOEXEC;
575 goto exec_error2;
576 }
577 if (!sh_bang) {
578 p = copy_strings(envc,envp,page,p,0);
579 p = copy_strings(argc,argv,page,p,0);
580 if (!p) {
581 retval = -E2BIG;
582 goto exec_error2;
583 }
584 }
585
586 current->dumpable = 1;
587 for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
588 if (ch == '/')
589 i = 0;
590 else
591 if (i < 15)
592 current->comm[i++] = ch;
593 current->comm[i] = '\0';
594 if (current->executable) {
595 iput(current->executable);
596 current->executable = NULL;
597 }
598 i = current->numlibraries;
599 while (i-- > 0) {
600 iput(current->libraries[i].library);
601 current->libraries[i].library = NULL;
602 }
603 if (e_uid != current->euid || e_gid != current->egid ||
604 !permission(inode,MAY_READ))
605 current->dumpable = 0;
606 current->numlibraries = 0;
607 current->signal = 0;
608 for (i=0 ; i<32 ; i++) {
609 current->sigaction[i].sa_mask = 0;
610 current->sigaction[i].sa_flags = 0;
611 if (current->sigaction[i].sa_handler != SIG_IGN)
612 current->sigaction[i].sa_handler = NULL;
613 }
614 for (i=0 ; i<NR_OPEN ; i++)
615 if (FD_ISSET(i,¤t->close_on_exec))
616 sys_close(i);
617 FD_ZERO(¤t->close_on_exec);
618 clear_page_tables(current);
619 if (last_task_used_math == current)
620 last_task_used_math = NULL;
621 current->used_math = 0;
622 p += change_ldt(ex.a_text,page);
623 p -= MAX_ARG_PAGES*PAGE_SIZE;
624 p = (unsigned long) create_tables((char *)p,argc,envc);
625 current->brk = ex.a_bss +
626 (current->end_data = ex.a_data +
627 (current->end_code = ex.a_text));
628 current->start_stack = p;
629 current->rss = (TASK_SIZE - p + PAGE_SIZE-1) / PAGE_SIZE;
630 current->suid = current->euid = e_uid;
631 current->sgid = current->egid = e_gid;
632 if (N_MAGIC(ex) == OMAGIC) {
633 read_exec(inode, 32, (char *) 0, ex.a_text+ex.a_data);
634 iput(inode);
635 } else if (!inode->i_op || !inode->i_op->bmap) {
636 read_exec(inode, 1024, (char *) 0, ex.a_text+ex.a_data);
637 iput(inode);
638 } else
639 current->executable = inode;
640 zeromap_page_range((ex.a_text + ex.a_data + 0xfff) & 0xfffff000,ex.a_bss, PAGE_COPY);
641 eip[0] = ex.a_entry;
642 eip[3] = p;
643 if (current->flags & PF_PTRACED)
644 send_sig(SIGTRAP, current, 0);
645 return 0;
646 exec_error2:
647 iput(inode);
648 exec_error1:
649 for (i=0 ; i<MAX_ARG_PAGES ; i++)
650 free_page(page[i]);
651 return(retval);
652 }