This source file includes following definitions.
- rpl_stpcpy
- check_interpreter
- write_open_command
- write_load_command
- process_interpreter_1
- process_interpreter
- process_program_header
- insert_args
- format_pid
- exec_0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <errno.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <stdlib.h>
29
30 #include <sys/ptrace.h>
31 #include <sys/param.h>
32 #include <sys/mman.h>
33
34 #include "exec.h"
35
36 #if defined __mips__ && !defined MIPS_NABI
37 #include "mipsfpu.h"
38 #endif
39
40
41
42
43
44
45 #if !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY
46
47
48
49
50 static char *
51 rpl_stpcpy (char *dest, const char *src)
52 {
53 register char *d;
54 register const char *s;
55
56 d = dest;
57 s = src;
58
59 do
60 *d++ = *s;
61 while (*s++ != '\0');
62
63 return d - 1;
64 }
65
66 #define stpcpy rpl_stpcpy
67 #endif
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 static const char *
97 check_interpreter (const char *name, int fd, const char **extra)
98 {
99 static char buffer[PATH_MAX], *start;
100 char first[2], *end, *ws;
101 ssize_t rc;
102
103
104 rc = read (fd, &first, 2);
105
106 if (rc != 2)
107 goto fail;
108
109 if (first[0] != '#' || first[1] != '!')
110 goto nomatch;
111
112 rc = read (fd, buffer, PATH_MAX);
113
114 if (rc < 0)
115 goto fail;
116
117
118 start = buffer;
119 while (*start && ((unsigned char) *start) < 128 && isspace (*start))
120 ++start;
121
122
123 end = memchr (start, '\n', rc);
124
125 if (!end)
126 goto fail;
127
128
129
130 *end = '\0';
131
132
133 ws = strchr (start, ' ');
134
135
136
137 if (!ws)
138 {
139 if (lseek (fd, 0, SEEK_SET))
140 goto fail;
141
142 return start;
143 }
144
145
146
147 *ws = '\0';
148
149 if (lseek (fd, 0, SEEK_SET))
150 goto fail;
151
152 *extra = ws + 1;
153 return start;
154
155 nomatch:
156
157 if (lseek (fd, 0, SEEK_SET))
158 goto fail;
159
160 return name;
161
162 fail:
163 errno = ENOEXEC;
164 return NULL;
165 }
166
167
168 static char loader_area[65536];
169
170
171 static int loader_area_used;
172
173
174
175
176
177
178 struct exec_open_command
179 {
180
181 USER_WORD command;
182
183
184
185 };
186
187 struct exec_map_command
188 {
189
190 USER_WORD command;
191
192
193 USER_WORD vm_address;
194
195
196 USER_WORD file_offset;
197
198
199 USER_WORD protection;
200
201
202 USER_WORD length;
203
204
205 USER_WORD flags;
206
207
208 USER_WORD clear;
209 };
210
211 struct exec_jump_command
212 {
213
214 USER_WORD command;
215
216
217 USER_WORD entry;
218
219
220 USER_WORD at_entry;
221
222
223 USER_WORD at_phent;
224
225
226 USER_WORD at_phnum;
227
228
229 USER_WORD at_phdr;
230
231
232 USER_WORD at_base;
233
234 #if defined __mips__ && !defined MIPS_NABI
235
236 USER_WORD fpu_mode;
237 #endif
238 };
239
240
241
242
243
244
245
246 static int
247 write_open_command (const char *name, bool alternate)
248 {
249 struct exec_open_command command;
250 size_t size;
251
252
253
254
255 command.command = alternate ? 16 : 0;
256 if (sizeof loader_area - loader_area_used < sizeof command)
257 return 1;
258 memcpy (loader_area + loader_area_used, &command, sizeof command);
259 loader_area_used += sizeof command;
260
261
262 size = strlen (name) + 1;
263
264
265 size = ((size + (sizeof (USER_WORD) - 1))
266 & ~(sizeof (USER_WORD) - 1));
267
268 if (sizeof loader_area - loader_area_used < size)
269 return 1;
270
271
272
273 strncpy (loader_area + loader_area_used, name, size);
274
275
276 loader_area_used += size;
277 return 0;
278 }
279
280
281
282
283
284
285
286
287 static int
288 write_load_command (program_header *header, bool use_alternate,
289 USER_WORD offset)
290 {
291 struct exec_map_command command;
292 struct exec_map_command command1;
293 USER_WORD start, end;
294 bool need_command1;
295 static long pagesize;
296
297
298
299
300
301
302
303 #ifndef PAGE_MASK
304
305
306 #ifdef HAVE_GETPAGESIZE
307 if (!pagesize)
308 pagesize = getpagesize ();
309 #else
310 if (!pagesize)
311 pagesize = sysconf (_SC_PAGESIZE);
312
313 #define PAGE_MASK (~(pagesize - 1))
314 #define PAGE_SIZE (pagesize)
315 #endif
316 #endif
317
318 start = header->p_vaddr & PAGE_MASK;
319 end = ((header->p_vaddr + header->p_filesz
320 + PAGE_SIZE)
321 & PAGE_MASK);
322
323 command.command = use_alternate ? 17 : 1;
324 command.vm_address = start;
325 command.file_offset = header->p_offset & PAGE_MASK;
326 command.protection = 0;
327 command.length = end - start;
328 command.clear = 0;
329 command.flags = MAP_PRIVATE | MAP_FIXED;
330
331
332
333 if (header->p_flags & 4)
334 command.protection |= PROT_READ;
335
336 if (header->p_flags & 2)
337 command.protection |= PROT_WRITE;
338
339 if (header->p_flags & 1)
340 command.protection |= PROT_EXEC;
341
342
343
344 need_command1 = false;
345
346 if (header->p_memsz > header->p_filesz)
347 {
348
349
350 command.clear = end - header->p_vaddr - header->p_filesz;
351 start = end;
352 end = header->p_vaddr + header->p_memsz + PAGE_SIZE;
353 end &= PAGE_MASK;
354
355 if (end > start)
356 {
357 command1.command = 4;
358 command1.vm_address = start;
359 command1.file_offset = 0;
360 command1.length = end - start;
361 command1.clear = 0;
362 command1.protection = command.protection;
363 command1.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
364 need_command1 = true;
365 }
366 }
367
368
369
370 if (offset)
371 {
372 if (need_command1)
373 command1.vm_address += offset;
374
375 command.vm_address += offset;
376 }
377
378
379
380 if (sizeof loader_area - loader_area_used < sizeof command)
381 return 1;
382
383 memcpy (loader_area + loader_area_used, &command,
384 sizeof command);
385 loader_area_used += sizeof command;
386
387 if (!need_command1)
388 return 0;
389
390 if (sizeof loader_area - loader_area_used < sizeof command1)
391 return 1;
392
393 memcpy (loader_area + loader_area_used, &command1,
394 sizeof command1);
395 loader_area_used += sizeof command1;
396
397 return 0;
398 }
399
400 #if defined __mips__ && !defined MIPS_NABI
401
402
403 static struct mips_elf_abi_flags exec_abi, interpreter_abi;
404
405
406 static elf_header exec_interpreter_header;
407
408
409 static elf_header *interpreter_header;
410
411
412
413 static struct mips_elf_abi_flags *exec_abiflags;
414
415
416
417 static struct mips_elf_abi_flags *interpreter_abiflags;
418
419 #endif
420
421
422
423
424
425
426
427
428
429
430
431 static int
432 process_interpreter_1 (const char *name, int fd,
433 program_header *header,
434 elf_header *elf_header)
435 {
436 int rc;
437 #if defined __mips__ && !defined MIPS_NABI
438 ssize_t rc1;
439 #endif
440
441 switch (header->p_type)
442 {
443 default:
444 rc = 0;
445 break;
446
447 case 1:
448
449
450
451 if (elf_header->e_type == 3)
452 rc = write_load_command (header, true,
453 INTERPRETER_BASE);
454 else
455 rc = write_load_command (header, true, 0);
456
457 break;
458
459 #if defined __mips__ && !defined MIPS_NABI
460 case 0x70000003:
461
462 rc1 = pread (fd, &interpreter_abi, sizeof interpreter_abi,
463 header->p_offset);
464
465 if (rc1 != sizeof interpreter_abi)
466 return 1;
467
468 interpreter_abiflags = &interpreter_abi;
469 rc = 0;
470 #endif
471 }
472
473 return rc;
474 }
475
476
477
478
479
480
481
482 static int
483 process_interpreter (int fd, program_header *prog_header,
484 USER_WORD *entry)
485 {
486 char buffer[PATH_MAX + 1];
487 int rc, size, i;
488 elf_header header;
489 program_header program;
490
491
492 size = MIN (prog_header->p_filesz, PATH_MAX);
493 rc = pread (fd, buffer, size, prog_header->p_offset);
494 if (rc < size)
495 return 1;
496
497
498 buffer[size] = '\0';
499
500
501
502
503 if (access (buffer, X_OK))
504 return 1;
505
506
507
508
509
510
511
512 fd = open (buffer, O_RDONLY);
513
514 if (fd < 0)
515 return 1;
516
517 rc = read (fd, &header, sizeof header);
518
519 if (rc < sizeof header)
520 goto fail;
521
522 #if defined __mips__ && !defined MIPS_NABI
523
524
525 exec_interpreter_header = header;
526 interpreter_header = &exec_interpreter_header;
527 #endif
528
529
530
531 if (header.e_ident[0] != 0x7f
532 || header.e_ident[1] != 'E'
533 || header.e_ident[2] != 'L'
534 || header.e_ident[3] != 'F')
535 goto fail;
536
537
538 #ifdef EXEC_64
539 if (header.e_ident[4] != 2)
540 goto fail;
541 #else
542 if (header.e_ident[4] != 1)
543 goto fail;
544 #endif
545
546
547 #ifndef WORDS_BIGENDIAN
548 if (header.e_ident[5] != 1)
549 goto fail;
550 #else
551 if (header.e_ident[5] != 2)
552 goto fail;
553 #endif
554
555
556 if (header.e_type != 2 && header.e_type != 3)
557 goto fail;
558
559
560 if (header.e_phnum > 0xffff
561 || (header.e_phentsize
562 != sizeof (program_header)))
563 goto fail;
564
565 if (write_open_command (buffer, true))
566 goto fail;
567
568 for (i = 0; i < header.e_phnum; ++i)
569 {
570 rc = read (fd, &program, sizeof program);
571 if (rc < sizeof program)
572 goto fail;
573
574 if (process_interpreter_1 (buffer, fd, &program,
575 &header))
576 goto fail;
577 }
578
579 if (header.e_type == 3)
580 *entry = header.e_entry + INTERPRETER_BASE;
581 else
582 *entry = header.e_entry;
583
584 close (fd);
585 return 0;
586
587 fail:
588 close (fd);
589 return 1;
590 }
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606 static int
607 process_program_header (const char *name, int fd,
608 program_header *header,
609 elf_header *elf_header,
610 USER_WORD *entry,
611 USER_WORD *offset)
612 {
613 int rc;
614 #if defined __mips__ && !defined MIPS_NABI
615 ssize_t rc1;
616 #endif
617
618 switch (header->p_type)
619 {
620 default:
621 rc = 0;
622 break;
623
624 case 1:
625
626
627
628 if (elf_header->e_type == 3)
629 {
630 rc = write_load_command (header, false,
631 EXECUTABLE_BASE);
632
633 if (!rc && offset && *offset == (USER_WORD) -1)
634 *offset = EXECUTABLE_BASE + header->p_vaddr;
635 }
636 else
637 {
638 rc = write_load_command (header, false, 0);
639
640 if (!rc && offset && *offset == (USER_WORD) -1)
641 *offset = header->p_vaddr;
642 }
643
644 break;
645
646 case 3:
647
648
649 rc = process_interpreter (fd, header, entry);
650 break;
651
652 case 1685382481:
653
654 rc = 0;
655 break;
656
657 #if defined __mips__ && !defined MIPS_NABI
658 case 0x70000003:
659
660 rc1 = pread (fd, &exec_abi, sizeof exec_abi,
661 header->p_offset);
662
663 if (rc1 != sizeof exec_abi)
664 return 1;
665
666 exec_abiflags = &exec_abi;
667 rc = 0;
668 #endif
669 }
670
671 return rc;
672 }
673
674
675
676
677
678
679
680
681 static int
682 insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
683 const char *arg1, const char *arg2, const char *arg3)
684 {
685 USER_WORD argv, argc, word, new;
686 USER_WORD new1, new2, new3, i;
687 size_t text_size, effective_size;
688 USER_REGS_STRUCT original;
689
690
691 argv = regs->SYSCALL_ARG1_REG;
692
693
694 argc = 0;
695 while (true)
696 {
697
698
699
700
701
702 errno = 0;
703 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
704 (void *) argv, NULL);
705 argv += sizeof (USER_WORD);
706
707 if (errno)
708 return 1;
709
710 if (!word)
711 break;
712
713 ++argc;
714 };
715
716
717
718
719 text_size = (strlen (arg1) + 1
720 + (arg2 ? strlen (arg2) + 1 : 0)
721 + strlen (arg3) + 1);
722
723
724 text_size += sizeof (USER_WORD) - 1;
725 text_size &= ~(sizeof (USER_WORD) - 1);
726
727
728
729
730 effective_size = sizeof word * (MAX (1, argc) + 2) + text_size;
731
732 if (arg2)
733 effective_size += sizeof word;
734
735
736
737
738 memcpy (&original, regs, sizeof *regs);
739 new = user_alloca (tracee, &original, regs,
740 effective_size);
741
742 if (!new)
743 goto fail;
744
745
746
747 new3 = new + text_size;
748
749
750
751 new1 = new + strlen (arg1) + 1;
752 new2 = new1 + (arg2 ? strlen (arg2) + 1 : 0);
753
754 if (user_copy (tracee, (const unsigned char *) arg1,
755 new, new1 - new))
756 goto fail;
757
758 if (arg2 && user_copy (tracee, (const unsigned char *) arg2,
759 new1, new2 - new1))
760 goto fail;
761
762
763
764 if (user_copy (tracee, (const unsigned char *) arg3,
765 new2, new3 - new2))
766 goto fail;
767
768
769
770
771 if (ptrace (PTRACE_POKETEXT, tracee->pid,
772 (void *) new3, (void *) new))
773 goto fail;
774
775 new3 += sizeof new3;
776
777 if (arg2 && ptrace (PTRACE_POKETEXT, tracee->pid,
778 (void *) new3, (void *) new1))
779 goto fail;
780 else if (arg2)
781 new3 += sizeof new3;
782
783
784
785 if (ptrace (PTRACE_POKETEXT, tracee->pid, (void *) new3,
786 (void *) new2))
787 goto fail;
788
789 new3 += sizeof new3;
790
791
792
793 argv = regs->SYSCALL_ARG1_REG;
794
795 if (argc)
796 {
797
798 argc += 1;
799
800
801
802 for (i = 1; i < argc; ++i)
803 {
804
805 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
806 (void *) (argv + i * sizeof argv), NULL);
807
808
809
810 if (ptrace (PTRACE_POKETEXT, tracee->pid,
811 (void *) new3, (void *) word))
812 goto fail;
813
814 new3 += sizeof new3;
815 }
816 }
817 else
818 {
819
820
821 if (ptrace (PTRACE_POKETEXT, tracee->pid,
822 (void *) new3, (void *) 0))
823 goto fail;
824
825 new3 += sizeof new3;
826 }
827
828
829 assert (new3 == new + effective_size);
830
831
832 assert (!(new3 & (sizeof new3 - 2)));
833
834
835
836
837 regs->SYSCALL_ARG1_REG = new + text_size;
838
839 #ifdef __aarch64__
840 if (aarch64_set_regs (tracee->pid, regs, false))
841 goto fail;
842 #else
843 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs))
844 goto fail;
845 #endif
846
847
848
849 return 0;
850
851 fail:
852
853 #ifdef __aarch64__
854 aarch64_set_regs (tracee->pid, &original, false);
855 #else
856 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &original);
857 #endif
858 errno = ENOMEM;
859 return 1;
860 }
861
862
863
864
865
866
867
868 static char *
869 format_pid (char *in, unsigned int pid)
870 {
871 unsigned int digits[32], *fill;
872
873 fill = digits;
874
875 for (; pid != 0; pid = pid / 10)
876 *fill++ = pid % 10;
877
878
879
880 if (fill == digits)
881 *fill++ = 0;
882
883 while (fill != digits)
884 {
885 --fill;
886 *in++ = '0' + *fill;
887 }
888
889 *in = '\0';
890 return in;
891 }
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911 char *
912 exec_0 (char *name, struct exec_tracee *tracee,
913 size_t *size, USER_REGS_STRUCT *regs)
914 {
915 int fd, rc, i;
916 elf_header header;
917 const char *interpreter_name, *extra;
918 program_header program;
919 USER_WORD entry, program_entry, offset;
920 USER_WORD header_offset;
921 struct exec_jump_command jump;
922 #if defined __mips__ && !defined MIPS_NABI
923 int fpu_mode;
924 #endif
925 char buffer[80], buffer1[PATH_MAX + 80], *rewrite;
926 ssize_t link_size;
927 size_t remaining;
928
929
930
931
932 if (!strcmp (name, "/proc/self/exe") && tracee->exec_file)
933 {
934 strncpy (name, tracee->exec_file, PATH_MAX - 1);
935 name[PATH_MAX] = '\0';
936 }
937 else
938 {
939
940
941
942
943 if (name[0] && name[0] != '/')
944 {
945
946 memset (buffer, 0, sizeof buffer);
947 memset (buffer1, 0, sizeof buffer1);
948
949
950 rewrite = stpcpy (buffer, "/proc/");
951 rewrite = format_pid (rewrite, tracee->pid);
952 strcpy (rewrite, "/cwd");
953
954
955
956 link_size = readlink (buffer, buffer1,
957 PATH_MAX + 1);
958
959 if (link_size < 0)
960 return NULL;
961
962
963
964 if (link_size > PATH_MAX)
965 {
966
967 errno = ENAMETOOLONG;
968 return NULL;
969 }
970
971
972
973 if (!link_size || buffer1[link_size - 1] != '/')
974 buffer1[link_size] = '/', link_size++;
975
976 rewrite = buffer1 + link_size;
977 remaining = buffer1 + sizeof buffer1 - rewrite - 1;
978 memcpy (rewrite, name, strnlen (name, remaining));
979
980
981 #ifndef REENTRANT
982 strcpy (name, buffer1);
983 #endif
984 }
985 }
986
987
988
989 if (access (name, X_OK))
990 return NULL;
991
992 fd = open (name, O_RDONLY);
993 if (fd < 0)
994 return NULL;
995
996
997
998 extra = NULL;
999 interpreter_name = check_interpreter (name, fd, &extra);
1000 if (!interpreter_name)
1001 goto fail;
1002
1003
1004 if (interpreter_name != name)
1005 {
1006 close (fd);
1007 fd = open (interpreter_name, O_RDONLY);
1008 if (fd < 0)
1009 return NULL;
1010
1011
1012
1013
1014 if (insert_args (tracee, regs, interpreter_name,
1015 extra, name))
1016 goto fail1;
1017 }
1018
1019 rc = read (fd, &header, sizeof header);
1020
1021 if (rc < sizeof header)
1022 goto fail1;
1023
1024
1025
1026 if (header.e_ident[0] != 0x7f
1027 || header.e_ident[1] != 'E'
1028 || header.e_ident[2] != 'L'
1029 || header.e_ident[3] != 'F')
1030 goto fail1;
1031
1032
1033 #ifdef EXEC_64
1034 if (header.e_ident[4] != 2)
1035 goto fail1;
1036 #else
1037 if (header.e_ident[4] != 1)
1038 goto fail1;
1039 #endif
1040
1041
1042 #ifndef WORDS_BIGENDIAN
1043 if (header.e_ident[5] != 1)
1044 goto fail1;
1045 #else
1046 if (header.e_ident[5] != 2)
1047 goto fail1;
1048 #endif
1049
1050
1051 if (header.e_type != 2 && header.e_type != 3)
1052 goto fail1;
1053
1054
1055 if (header.e_phnum > 0xffff
1056 || (header.e_phentsize
1057 != sizeof (program_header)))
1058 goto fail1;
1059
1060
1061 rc = lseek (fd, header.e_phoff, SEEK_SET);
1062 if (rc < 0)
1063 goto fail1;
1064 loader_area_used = 0;
1065
1066
1067 if (write_open_command (interpreter_name, false))
1068 goto fail1;
1069
1070
1071
1072 if (header.e_type == 3)
1073 offset = EXECUTABLE_BASE;
1074 else
1075 offset = 0;
1076
1077
1078
1079
1080 entry = header.e_entry + offset;
1081 program_entry = header.e_entry;
1082
1083 #if defined __mips__ && !defined MIPS_NABI
1084
1085 exec_abiflags = NULL;
1086 interpreter_abiflags = NULL;
1087 interpreter_header = NULL;
1088 #endif
1089
1090
1091
1092 header_offset = -1;
1093
1094 for (i = 0; i < header.e_phnum; ++i)
1095 {
1096 rc = read (fd, &program, sizeof program);
1097 if (rc < sizeof program)
1098 goto fail1;
1099
1100 if (process_program_header (interpreter_name, fd,
1101 &program, &header,
1102 &entry, &header_offset))
1103 goto fail1;
1104 }
1105
1106
1107
1108 jump.command = 3;
1109 jump.entry = entry;
1110
1111
1112
1113 jump.at_entry = program_entry + offset;
1114 jump.at_phent = header.e_phentsize;
1115 jump.at_phnum = header.e_phnum;
1116 jump.at_base = (entry == header.e_entry + offset
1117 ? EXECUTABLE_BASE
1118 : INTERPRETER_BASE);
1119
1120 #if defined __mips__ && !defined MIPS_NABI
1121
1122
1123 if (determine_fpu_mode (&header, interpreter_header,
1124 &fpu_mode, exec_abiflags,
1125 interpreter_abiflags))
1126
1127 goto fail;
1128
1129
1130
1131
1132 if (fpu_mode == FP_FR0 && !cpu_supports_fr0_p ())
1133 fpu_mode = FP_FRE;
1134
1135 jump.fpu_mode = fpu_mode;
1136 #endif
1137
1138
1139
1140
1141 if (header_offset == (USER_WORD) -1)
1142 header_offset = 0;
1143
1144 jump.at_phdr = header.e_phoff + header_offset;
1145
1146 if (sizeof loader_area - loader_area_used < sizeof jump)
1147 goto fail1;
1148
1149 memcpy (loader_area + loader_area_used, &jump,
1150 sizeof jump);
1151 loader_area_used += sizeof jump;
1152
1153
1154
1155
1156 close (fd);
1157 *size = loader_area_used;
1158
1159
1160 assert (!(loader_area_used & (sizeof (USER_WORD) - 1)));
1161 return loader_area;
1162
1163 fail1:
1164 errno = ENOEXEC;
1165 fail:
1166 close (fd);
1167 return NULL;
1168 }