This source file includes following definitions.
- core_dump
- sys_uselib
- create_tables
- count
- copy_strings
- change_ldt
- read_omagic
- 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 DUMP_WRITE(&dump,sizeof(dump));
144 DUMP_SEEK(sizeof(dump));
145
146 DUMP_WRITE(current,sizeof(*current));
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 close_coredump:
164 if (file.f_op->release)
165 file.f_op->release(inode,&file);
166 end_coredump:
167 __asm__("mov %0,%%fs"::"r" (fs));
168 iput(inode);
169 return has_dumped;
170 }
171
172
173
174
175
176
177
178 int sys_uselib(const char * library)
179 {
180 #define libnum (current->numlibraries)
181 struct inode * inode;
182 struct buffer_head * bh;
183 struct exec ex;
184 int error;
185
186 if (!library || get_limit(0x17) != TASK_SIZE)
187 return -EINVAL;
188 if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
189 return -EINVAL;
190 error = namei(library,&inode);
191 if (error)
192 return error;
193 if (!inode->i_sb || !S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
194 iput(inode);
195 return -EACCES;
196 }
197 if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
198 iput(inode);
199 return -EACCES;
200 }
201 if (!IS_RDONLY(inode)) {
202 inode->i_atime = CURRENT_TIME;
203 inode->i_dirt = 1;
204 }
205 ex = *(struct exec *) bh->b_data;
206 brelse(bh);
207 if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
208 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
209 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
210 iput(inode);
211 return -ENOEXEC;
212 }
213 current->libraries[libnum].library = inode;
214 current->libraries[libnum].start = ex.a_entry;
215 current->libraries[libnum].length = (ex.a_data+ex.a_text+0xfff) & 0xfffff000;
216 current->libraries[libnum].bss = (ex.a_bss+0xfff) & 0xfffff000;
217 #if 0
218 printk("Loaded library %d at %08x, length %08x\n",
219 libnum,
220 current->libraries[libnum].start,
221 current->libraries[libnum].length);
222 #endif
223 libnum++;
224 return 0;
225 #undef libnum
226 }
227
228
229
230
231
232
233 static unsigned long * create_tables(char * p,int argc,int envc)
234 {
235 unsigned long *argv,*envp;
236 unsigned long * sp;
237
238 sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
239 sp -= envc+1;
240 envp = sp;
241 sp -= argc+1;
242 argv = sp;
243 put_fs_long((unsigned long)envp,--sp);
244 put_fs_long((unsigned long)argv,--sp);
245 put_fs_long((unsigned long)argc,--sp);
246 current->arg_start = (unsigned long) p;
247 while (argc-->0) {
248 put_fs_long((unsigned long) p,argv++);
249 while (get_fs_byte(p++)) ;
250 }
251 put_fs_long(0,argv);
252 current->arg_end = current->env_start = (unsigned long) p;
253 while (envc-->0) {
254 put_fs_long((unsigned long) p,envp++);
255 while (get_fs_byte(p++)) ;
256 }
257 put_fs_long(0,envp);
258 current->env_end = (unsigned long) p;
259 return sp;
260 }
261
262
263
264
265 static int count(char ** argv)
266 {
267 int i=0;
268 char ** tmp;
269
270 if ((tmp = argv) != 0)
271 while (get_fs_long((unsigned long *) (tmp++)))
272 i++;
273
274 return i;
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
295 unsigned long p, int from_kmem)
296 {
297 char *tmp, *pag = NULL;
298 int len, offset = 0;
299 unsigned long old_fs, new_fs;
300
301 if (!p)
302 return 0;
303 new_fs = get_ds();
304 old_fs = get_fs();
305 if (from_kmem==2)
306 set_fs(new_fs);
307 while (argc-- > 0) {
308 if (from_kmem == 1)
309 set_fs(new_fs);
310 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
311 panic("argc is wrong");
312 if (from_kmem == 1)
313 set_fs(old_fs);
314 len=0;
315 do {
316 len++;
317 } while (get_fs_byte(tmp++));
318 if (p < len) {
319 set_fs(old_fs);
320 return 0;
321 }
322 while (len) {
323 --p; --tmp; --len;
324 if (--offset < 0) {
325 offset = p % PAGE_SIZE;
326 if (from_kmem==2)
327 set_fs(old_fs);
328 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
329 !(pag = (char *) page[p/PAGE_SIZE] =
330 (unsigned long *) get_free_page(GFP_USER)))
331 return 0;
332 if (from_kmem==2)
333 set_fs(new_fs);
334
335 }
336 *(pag + offset) = get_fs_byte(tmp);
337 }
338 }
339 if (from_kmem==2)
340 set_fs(old_fs);
341 return p;
342 }
343
344 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
345 {
346 unsigned long code_limit,data_limit,code_base,data_base;
347 int i;
348
349 code_limit = TASK_SIZE;
350 data_limit = TASK_SIZE;
351 code_base = data_base = 0;
352 current->start_code = code_base;
353 set_base(current->ldt[1],code_base);
354 set_limit(current->ldt[1],code_limit);
355 set_base(current->ldt[2],data_base);
356 set_limit(current->ldt[2],data_limit);
357
358 __asm__("pushl $0x17\n\tpop %%fs"::);
359 data_base += data_limit;
360 for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
361 data_base -= PAGE_SIZE;
362 if (page[i])
363 put_dirty_page(current,page[i],data_base);
364 }
365 return data_limit;
366 }
367
368 static void read_omagic(struct inode *inode, int bytes)
369 {
370 struct buffer_head *bh;
371 int n, blkno, blk = 0;
372 char *dest = (char *) 0;
373 unsigned int block_size;
374
375 block_size = 1024;
376 if (inode->i_sb)
377 block_size = inode->i_sb->s_blocksize;
378 while (bytes > 0) {
379 if (!(blkno = bmap(inode, blk)))
380 sys_exit(-1);
381 if (!(bh = bread(inode->i_dev, blkno, block_size)))
382 sys_exit(-1);
383 n = (blk ? block_size : block_size - sizeof(struct exec));
384 if (bytes < n)
385 n = bytes;
386
387 memcpy_tofs(dest, (blk ? bh->b_data :
388 bh->b_data + sizeof(struct exec)), n);
389 brelse(bh);
390 ++blk;
391 dest += n;
392 bytes -= n;
393 }
394 iput(inode);
395 current->executable = NULL;
396 }
397
398
399
400
401
402
403
404 int do_execve(unsigned long * eip,long tmp,char * filename,
405 char ** argv, char ** envp)
406 {
407 struct inode * inode;
408 struct buffer_head * bh;
409 struct exec ex;
410 unsigned long page[MAX_ARG_PAGES];
411 int i,argc,envc;
412 int e_uid, e_gid;
413 int retval;
414 int sh_bang = 0;
415 unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
416 int ch;
417
418 if ((0xffff & eip[1]) != 0x000f)
419 panic("execve called from supervisor mode");
420 for (i=0 ; i<MAX_ARG_PAGES ; i++)
421 page[i]=0;
422 retval = namei(filename,&inode);
423 if (retval)
424 return retval;
425 argc = count(argv);
426 envc = count(envp);
427
428 restart_interp:
429 if (!S_ISREG(inode->i_mode)) {
430 retval = -EACCES;
431 goto exec_error2;
432 }
433 if (IS_NOEXEC(inode)) {
434 retval = -EPERM;
435 goto exec_error2;
436 }
437 if (!inode->i_sb) {
438 retval = -EACCES;
439 goto exec_error2;
440 }
441 i = inode->i_mode;
442 if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current->
443 euid) || ((i & S_ISGID) && inode->i_gid != current->egid)) &&
444 !suser()) {
445 retval = -EPERM;
446 goto exec_error2;
447 }
448
449 if (current->flags & PF_PTRACED) {
450 e_uid = current->euid;
451 e_gid = current->egid;
452 } else {
453 e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
454 e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
455 }
456 if (current->euid == inode->i_uid)
457 i >>= 6;
458 else if (in_group_p(inode->i_gid))
459 i >>= 3;
460 if (!(i & 1) &&
461 !((inode->i_mode & 0111) && suser())) {
462 retval = -EACCES;
463 goto exec_error2;
464 }
465 if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
466 retval = -EACCES;
467 goto exec_error2;
468 }
469 if (!IS_RDONLY(inode)) {
470 inode->i_atime = CURRENT_TIME;
471 inode->i_dirt = 1;
472 }
473 ex = *((struct exec *) bh->b_data);
474 if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
475
476
477
478
479
480 char buf[128], *cp, *interp, *i_name, *i_arg;
481 unsigned long old_fs;
482
483 strncpy(buf, bh->b_data+2, 127);
484 brelse(bh);
485 iput(inode);
486 buf[127] = '\0';
487 if ((cp = strchr(buf, '\n')) != NULL) {
488 *cp = '\0';
489 for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
490 }
491 if (!cp || *cp == '\0') {
492 retval = -ENOEXEC;
493 goto exec_error1;
494 }
495 interp = i_name = cp;
496 i_arg = 0;
497 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
498 if (*cp == '/')
499 i_name = cp+1;
500 }
501 if (*cp) {
502 *cp++ = '\0';
503 i_arg = cp;
504 }
505
506
507
508
509 if (sh_bang++ == 0) {
510 p = copy_strings(envc, envp, page, p, 0);
511 p = copy_strings(--argc, argv+1, page, p, 0);
512 }
513
514
515
516
517
518
519
520
521 p = copy_strings(1, &filename, page, p, 1);
522 argc++;
523 if (i_arg) {
524 p = copy_strings(1, &i_arg, page, p, 2);
525 argc++;
526 }
527 p = copy_strings(1, &i_name, page, p, 2);
528 argc++;
529 if (!p) {
530 retval = -ENOMEM;
531 goto exec_error1;
532 }
533
534
535
536 old_fs = get_fs();
537 set_fs(get_ds());
538 retval = namei(interp,&inode);
539 set_fs(old_fs);
540 if (retval)
541 goto exec_error1;
542 goto restart_interp;
543 }
544 brelse(bh);
545 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
546 ex.a_trsize || ex.a_drsize ||
547 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
548 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
549 retval = -ENOEXEC;
550 goto exec_error2;
551 }
552 if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
553 printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
554 retval = -ENOEXEC;
555 goto exec_error2;
556 }
557 if (!sh_bang) {
558 p = copy_strings(envc,envp,page,p,0);
559 p = copy_strings(argc,argv,page,p,0);
560 if (!p) {
561 retval = -ENOMEM;
562 goto exec_error2;
563 }
564 }
565
566 current->dumpable = 1;
567 for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
568 if (ch == '/')
569 i = 0;
570 else
571 if (i < 8)
572 current->comm[i++] = ch;
573 if (i < 8)
574 current->comm[i] = '\0';
575 if (current->executable)
576 iput(current->executable);
577 i = current->numlibraries;
578 while (i-- > 0) {
579 iput(current->libraries[i].library);
580 current->libraries[i].library = NULL;
581 }
582 if (e_uid != current->euid || e_gid != current->egid ||
583 !permission(inode,MAY_READ))
584 current->dumpable = 0;
585 current->numlibraries = 0;
586 current->executable = inode;
587 current->signal = 0;
588 for (i=0 ; i<32 ; i++) {
589 current->sigaction[i].sa_mask = 0;
590 current->sigaction[i].sa_flags = 0;
591 if (current->sigaction[i].sa_handler != SIG_IGN)
592 current->sigaction[i].sa_handler = NULL;
593 }
594 for (i=0 ; i<NR_OPEN ; i++)
595 if (FD_ISSET(i,¤t->close_on_exec))
596 sys_close(i);
597 FD_ZERO(¤t->close_on_exec);
598 clear_page_tables(current);
599 if (last_task_used_math == current)
600 last_task_used_math = NULL;
601 current->used_math = 0;
602 p += change_ldt(ex.a_text,page);
603 p -= MAX_ARG_PAGES*PAGE_SIZE;
604 p = (unsigned long) create_tables((char *)p,argc,envc);
605 current->brk = ex.a_bss +
606 (current->end_data = ex.a_data +
607 (current->end_code = ex.a_text));
608 current->start_stack = p;
609 current->rss = (TASK_SIZE - p + PAGE_SIZE-1) / PAGE_SIZE;
610 current->suid = current->euid = e_uid;
611 current->sgid = current->egid = e_gid;
612 if (N_MAGIC(ex) == OMAGIC)
613 read_omagic(inode, ex.a_text+ex.a_data);
614 eip[0] = ex.a_entry;
615 eip[3] = p;
616 if (current->flags & PF_PTRACED)
617 send_sig(SIGTRAP, current, 0);
618 return 0;
619 exec_error2:
620 iput(inode);
621 exec_error1:
622 for (i=0 ; i<MAX_ARG_PAGES ; i++)
623 free_page(page[i]);
624 return(retval);
625 }