Changed API to check internet privilege
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / r2r_checker.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <stdio.h>
20 #include <sys/mman.h>
21 #include <sys/stat.h>
22
23 #include <pal.h>
24 #include <pal_endian.h>
25 #include <ntimage.h>
26
27 #include <inc/corhdr.h>
28 #include <inc/readytorun.h>
29
30 #include <log.h>
31 #include <r2r_checker.h>
32
33 static inline UINT AlignUp(UINT value, UINT alignment)
34 {
35         return (value + alignment - 1) & ~(alignment - 1);
36 }
37
38 static inline UINT64 AlignUp(UINT64 value, UINT alignment)
39 {
40         return (value + alignment - 1)& ~(UINT64)(alignment - 1);
41 }
42
43 static IMAGE_NT_HEADERS* getNTHeaders(void* pAddr)
44 {
45         IMAGE_DOS_HEADER* pDOS = (IMAGE_DOS_HEADER*)pAddr;
46         if (pDOS->e_magic != VAL16(IMAGE_DOS_SIGNATURE)) return NULL;
47
48         return (IMAGE_NT_HEADERS*)((ULONG_PTR)pAddr + VAL32(pDOS->e_lfanew));
49 }
50
51 static IMAGE_DATA_DIRECTORY* getCorDirectoryEntry(IMAGE_NT_HEADERS* pNTHeaders)
52 {
53         IMAGE_DATA_DIRECTORY* pDir = NULL;
54         if (pNTHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
55                 pDir = (IMAGE_DATA_DIRECTORY*)((ULONG_PTR)(pNTHeaders)
56                                 + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory)
57                                 + IMAGE_DIRECTORY_ENTRY_COMHEADER * sizeof(IMAGE_DATA_DIRECTORY));
58         } else if (pNTHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
59                 pDir = (IMAGE_DATA_DIRECTORY*)((ULONG_PTR)(pNTHeaders)
60                                 + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory)
61                                 + IMAGE_DIRECTORY_ENTRY_COMHEADER * sizeof(IMAGE_DATA_DIRECTORY));
62         } else {
63                 _SERR("Invalid Optional Header Magic Number: 0x%x", VAL16(pNTHeaders->OptionalHeader.Magic));
64         }
65
66         return pDir;
67 }
68
69 static IMAGE_SECTION_HEADER* findFirstSection(IMAGE_NT_HEADERS* pNTHeaders)
70 {
71         return (IMAGE_SECTION_HEADER*)(
72                         (ULONG_PTR)(pNTHeaders) +
73                         offsetof(IMAGE_NT_HEADERS, OptionalHeader) +
74                         VAL16(pNTHeaders->FileHeader.SizeOfOptionalHeader));
75 }
76
77 static IMAGE_SECTION_HEADER* getSection(IMAGE_NT_HEADERS* pNTHeaders, UINT rva) {
78         IMAGE_SECTION_HEADER* section = (IMAGE_SECTION_HEADER*)(findFirstSection(pNTHeaders));
79         IMAGE_SECTION_HEADER* sectionEnd = section + VAL16(pNTHeaders->FileHeader.NumberOfSections);
80         while (section < sectionEnd) {
81                 if (rva < (VAL32(section->VirtualAddress)
82                                         + AlignUp((UINT)VAL32(section->Misc.VirtualSize), (UINT)VAL32(pNTHeaders->OptionalHeader.SectionAlignment)))) {
83                         if (rva < VAL32(section->VirtualAddress)) {
84                                 return NULL;
85                         } else {
86                                 return section;
87                         }
88                 }
89                 section++;
90         }
91
92         return NULL;
93 }
94
95 static ULONG_PTR getDirectoryData(void* pBaseAddr, IMAGE_NT_HEADERS* pNTHeaders, IMAGE_DATA_DIRECTORY* pDir) {
96         UINT rva = pDir->VirtualAddress;
97         if (rva == 0) {
98                 return 0;
99         }
100
101         IMAGE_SECTION_HEADER* section = getSection(pNTHeaders, rva);
102         if (!section) {
103                 return 0;
104         }
105
106         return (ULONG_PTR)pBaseAddr + rva - VAL32(section->VirtualAddress) + VAL32(section->PointerToRawData);
107 }
108
109 static bool hasValidR2RHeader(void* pAddr)
110 {
111         IMAGE_NT_HEADERS* pNTHeaders = getNTHeaders(pAddr);
112         if (!pNTHeaders) {
113                 _SERR("Invalid NT Header");
114                 return false;
115         }
116
117         IMAGE_DATA_DIRECTORY* pCorDir = getCorDirectoryEntry(pNTHeaders);
118         if (!pCorDir) {
119                 _SERR("Invalid Cor Data Directory");
120                 return false;
121         }
122
123         IMAGE_COR20_HEADER* pCor = (IMAGE_COR20_HEADER*)getDirectoryData(pAddr, pNTHeaders, pCorDir);
124         if (!pCor) {
125                 _SERR("Invalid Cor Header");
126                 return false;
127         }
128
129         IMAGE_DATA_DIRECTORY* pR2RDir = &pCor->ManagedNativeHeader;
130         if (VAL32(pR2RDir->Size) >= sizeof(READYTORUN_HEADER)) {
131                 READYTORUN_HEADER* pR2RHeader = (READYTORUN_HEADER*)getDirectoryData(pAddr, pNTHeaders, pR2RDir);
132                 if (!pR2RHeader) {
133                         return false;
134                 }
135
136                 if (pR2RHeader->Signature != VAL16(READYTORUN_SIGNATURE)) {
137                         return false;
138                 }
139                 return true;
140         }
141         return false;
142 }
143
144 bool isR2RImage(std::string fileName)
145 {
146         int fd;
147         struct stat sb;
148         if ((fd = open(fileName.c_str(), O_RDONLY)) == -1) {
149                 _SERR("File Not Found: %s", fileName.c_str());
150                 return false;
151         }
152
153         if (fstat(fd, &sb) == -1) {
154                 close(fd);
155                 return false;
156         }
157
158         void* pAddr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
159         if (pAddr == MAP_FAILED) {
160                 _SERR("Fail to Map File: %s", fileName.c_str());
161                 close(fd);
162                 return false;
163         }
164
165         bool ret = hasValidR2RHeader(pAddr);
166
167         munmap(pAddr, sb.st_size);
168         close(fd);
169         return ret;
170 }
171
172 unsigned int getSizeOfImage(std::string fileName)
173 {
174         int fd;
175         struct stat sb;
176         if ((fd = open(fileName.c_str(), O_RDONLY)) == -1) {
177                 _SERR("File Not Found: %s", fileName.c_str());
178                 return 0;
179         }
180
181         if (fstat(fd, &sb) == -1) {
182                 close(fd);
183                 return 0;
184         }
185
186         void* pAddr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
187         if (pAddr == MAP_FAILED) {
188                 _SERR("Fail to Map File: %s", fileName.c_str());
189                 close(fd);
190                 return 0;
191         }
192
193         IMAGE_NT_HEADERS* pNTHeaders = getNTHeaders(pAddr);
194         if (!pNTHeaders) {
195                 _SERR("Invalid NT Header");
196                 munmap(pAddr, sb.st_size);
197                 close(fd);
198                 return 0;
199         }
200
201         // typedef unsigned int ULONG;
202         unsigned int ret = pNTHeaders->OptionalHeader.SizeOfImage;
203
204         munmap(pAddr, sb.st_size);
205         close(fd);
206         return ret;
207 }