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