OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * NaCl service run-time, non-platform specific system call helper routines. | 8 * NaCl service run-time, non-platform specific system call helper routines. |
9 */ | 9 */ |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
11 #include <sys/stat.h> | 11 #include <sys/stat.h> |
12 | 12 |
13 #include <errno.h> | 13 #include <errno.h> |
14 #include <stdio.h> | 14 #include <stdio.h> |
| 15 #include <string.h> |
15 | 16 |
16 #include "native_client/src/include/build_config.h" | 17 #include "native_client/src/include/build_config.h" |
17 | 18 |
18 #if NACL_WINDOWS | 19 #if NACL_WINDOWS |
19 #include <windows.h> | 20 #include <windows.h> |
20 #endif | 21 #endif |
21 | 22 |
22 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h" | 23 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h" |
23 | 24 |
24 #include "native_client/src/include/nacl_macros.h" | 25 #include "native_client/src/include/nacl_macros.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 return 0; | 85 return 0; |
85 } | 86 } |
86 | 87 |
87 int NaClAclBypassChecks = 0; | 88 int NaClAclBypassChecks = 0; |
88 | 89 |
89 void NaClInsecurelyBypassAllAclChecks(void) { | 90 void NaClInsecurelyBypassAllAclChecks(void) { |
90 NaClLog(LOG_WARNING, "BYPASSING ALL ACL CHECKS\n"); | 91 NaClLog(LOG_WARNING, "BYPASSING ALL ACL CHECKS\n"); |
91 NaClAclBypassChecks = 1; | 92 NaClAclBypassChecks = 1; |
92 } | 93 } |
93 | 94 |
| 95 char *NaClRootDir = NULL; |
| 96 size_t NaClRootDirLen = 0; |
| 97 |
| 98 #if NACL_WINDOWS |
| 99 int NaClMountRootDir(char *root) { |
| 100 return 0; |
| 101 } |
| 102 |
| 103 int NaClSanitizePathLexically(char *path) { |
| 104 /* |
| 105 * TODO(jtolds): this could totally be made to work with Windows, but I'm |
| 106 * unclear what the path separator and drive letter requirements are at this |
| 107 * level. |
| 108 */ |
| 109 return 0; |
| 110 } |
| 111 #elif NACL_LINUX || NACL_OSX |
| 112 int NaClMountRootDir(char *root) { |
| 113 NaClRootDir = strdup(root); |
| 114 if (!NaClSanitizePathLexically(NaClRootDir)) { |
| 115 goto fail; |
| 116 } |
| 117 NaClRootDirLen = strlen(NaClRootDir); |
| 118 if (NaClRootDirLen <= 0) { |
| 119 goto fail; |
| 120 } |
| 121 while (NaClRootDirLen > 0 && NaClRootDir[NaClRootDirLen-1] == '/') { |
| 122 NaClRootDir[--NaClRootDirLen] = '\0'; |
| 123 } |
| 124 return 1; |
| 125 fail: |
| 126 free(NaClRootDir); |
| 127 NaClRootDir = NULL; |
| 128 return 0; |
| 129 } |
| 130 |
| 131 int NaClSanitizePathLexically(char *path) { |
| 132 size_t last_path_sep = 0, prev_sep = 0, next_char = 0; |
| 133 size_t path_len = strlen(path); |
| 134 |
| 135 /* |
| 136 * Overall strategy: |
| 137 * We're going to keep track of the last path separator we saw. Each time |
| 138 * we see a new path separator, we'll mark off the last path element, then |
| 139 * decide what to do with it. We'll either: |
| 140 * * decide the path element was empty (a double slash) and slide everything |
| 141 * back a byte. |
| 142 * * decide the path element was '.' and slide everything back two bytes. |
| 143 * * decide the path element is '..' and it's immediately after the root, so |
| 144 * we'll slide everything back three bytes |
| 145 * * decide the path element is '..' and it's not after the root, so we'll |
| 146 * go find the previous path separator and slide everything back to it. |
| 147 * * decide the path element is fine and continue with the new path |
| 148 * separator. |
| 149 * |
| 150 * This strategy avoids mallocs. |
| 151 */ |
| 152 |
| 153 /* |
| 154 * This algorithm assumes that there is always at least space for |
| 155 * "/\0", and the path is absolute, so make sure strlen(path) >= 1 and the |
| 156 * path starts with '/'. |
| 157 */ |
| 158 if (path_len <= 0 || path[0] != '/') { |
| 159 return 0; |
| 160 } |
| 161 |
| 162 /* |
| 163 * For the purposes of this algorithm, '/' and '\0' are both path separators. |
| 164 * last_path_sep refers to the index of the last path separator (either one |
| 165 * of the above two bytes) that we've seen so far. |
| 166 * |
| 167 * We'll loop as long as the last path separator isn't the null byte and do |
| 168 * some cleanup after. |
| 169 */ |
| 170 while (path[last_path_sep] != '\0') { |
| 171 |
| 172 /* |
| 173 * Let's find the full next path element. |
| 174 */ |
| 175 next_char = last_path_sep + 1; |
| 176 while (path[next_char] != '/' && path[next_char] != '\0') { |
| 177 next_char++; |
| 178 } |
| 179 |
| 180 /* Check if the path element was empty (double-separator case) */ |
| 181 if (next_char == last_path_sep + 1) { |
| 182 if (path[next_char] == '\0') { |
| 183 /* |
| 184 * Special '/\0' end case, allow a double separator when the second one |
| 185 * is a null byte. This allows us to sanitize paths with or without |
| 186 * trailing slashes. |
| 187 */ |
| 188 last_path_sep = next_char; |
| 189 continue; |
| 190 } |
| 191 /* Normal double-separator case. Just slide everything back one. */ |
| 192 memmove(path + last_path_sep, path + last_path_sep + 1, |
| 193 (path_len + 1) - (last_path_sep + 1)); |
| 194 path_len -= 1; |
| 195 continue; |
| 196 } |
| 197 |
| 198 /* Check if the last path element was "." */ |
| 199 if (next_char == last_path_sep + 2 && path[last_path_sep + 1] == '.') { |
| 200 /* Slide everything back two */ |
| 201 memmove(path + last_path_sep, path + last_path_sep + 2, |
| 202 (path_len + 1) - (last_path_sep + 2)); |
| 203 path_len -= 2; |
| 204 continue; |
| 205 } |
| 206 |
| 207 /* Check if the last path element was ".." */ |
| 208 if (next_char == last_path_sep + 3 && path[last_path_sep + 1] == '.' && |
| 209 path[last_path_sep + 2] == '.') { |
| 210 if (last_path_sep == 0) { |
| 211 /* '..' after root case, just slide everything back three. */ |
| 212 memmove(path + last_path_sep, path + last_path_sep + 3, |
| 213 (path_len + 1) - (last_path_sep + 3)); |
| 214 path_len -= 3; |
| 215 continue; |
| 216 } |
| 217 /* |
| 218 * Normal '..' case. Go find the previous path separator and then slide |
| 219 * everything back to it. |
| 220 */ |
| 221 prev_sep = last_path_sep - 1; |
| 222 while (path[prev_sep] != '/') { |
| 223 prev_sep--; |
| 224 } |
| 225 memmove(path + prev_sep, path + last_path_sep + 3, |
| 226 (path_len + 1) - (last_path_sep + 3)); |
| 227 path_len -= (last_path_sep + 3 - prev_sep); |
| 228 last_path_sep = prev_sep; |
| 229 continue; |
| 230 } |
| 231 |
| 232 /* Default path element case. */ |
| 233 last_path_sep = next_char; |
| 234 } |
| 235 |
| 236 /* |
| 237 * Cleanup scenario: whenever we slide something back, we overwrite the |
| 238 * last path separator. For example, in the "/a/.\0" case, we slide |
| 239 * everything starting at byte 4 back over byte 3, so the result is "/a\0". |
| 240 * In the case of a full path "/.\0", the end result ends up being "\0", so |
| 241 * we need to fix up root paths like this specially. |
| 242 * N.B.: we know we have enough space in the buffer for this. |
| 243 */ |
| 244 if (last_path_sep == 0) { |
| 245 path[0] = '/'; |
| 246 path[1] = '\0'; |
| 247 } |
| 248 |
| 249 return 1; |
| 250 } |
| 251 |
| 252 #else |
| 253 #error Unsupported platform |
| 254 #endif |
| 255 |
| 256 int NaClFileAccessEnabled(void) { |
| 257 return NaClAclBypassChecks || (NaClRootDir != NULL); |
| 258 } |
| 259 |
94 int NaClHighResolutionTimerEnabled(void) { | 260 int NaClHighResolutionTimerEnabled(void) { |
95 return NaClAclBypassChecks; | 261 return NaClAclBypassChecks; |
96 } | 262 } |
97 | 263 |
98 int32_t NaClSysGetpid(struct NaClAppThread *natp) { | 264 int32_t NaClSysGetpid(struct NaClAppThread *natp) { |
99 int32_t pid; | 265 int32_t pid; |
100 UNREFERENCED_PARAMETER(natp); | 266 UNREFERENCED_PARAMETER(natp); |
101 | 267 |
102 if (NaClAclBypassChecks) { | 268 if (NaClAclBypassChecks) { |
103 pid = GETPID(); | 269 pid = GETPID(); |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 #else | 864 #else |
699 #error Unsupported platform | 865 #error Unsupported platform |
700 #endif | 866 #endif |
701 break; | 867 break; |
702 } | 868 } |
703 case NACL_ABI__SC_PAGESIZE: { | 869 case NACL_ABI__SC_PAGESIZE: { |
704 result_value = 1 << 16; /* always 64k pages */ | 870 result_value = 1 << 16; /* always 64k pages */ |
705 break; | 871 break; |
706 } | 872 } |
707 case NACL_ABI__SC_NACL_FILE_ACCESS_ENABLED: { | 873 case NACL_ABI__SC_NACL_FILE_ACCESS_ENABLED: { |
708 result_value = NaClAclBypassChecks; | 874 result_value = NaClFileAccessEnabled(); |
709 break; | 875 break; |
710 } | 876 } |
711 case NACL_ABI__SC_NACL_LIST_MAPPINGS_ENABLED: { | 877 case NACL_ABI__SC_NACL_LIST_MAPPINGS_ENABLED: { |
712 result_value = nap->enable_list_mappings; | 878 result_value = nap->enable_list_mappings; |
713 break; | 879 break; |
714 } | 880 } |
715 case NACL_ABI__SC_NACL_PNACL_MODE: { | 881 case NACL_ABI__SC_NACL_PNACL_MODE: { |
716 result_value = nap->pnacl_mode; | 882 result_value = nap->pnacl_mode; |
717 break; | 883 break; |
718 } | 884 } |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 return NaClSysClockGetCommon(natp, clk_id, (uintptr_t) tsp, | 1173 return NaClSysClockGetCommon(natp, clk_id, (uintptr_t) tsp, |
1008 NaClClockGetRes, 1); | 1174 NaClClockGetRes, 1); |
1009 } | 1175 } |
1010 | 1176 |
1011 int32_t NaClSysClockGetTime(struct NaClAppThread *natp, | 1177 int32_t NaClSysClockGetTime(struct NaClAppThread *natp, |
1012 int clk_id, | 1178 int clk_id, |
1013 uint32_t tsp) { | 1179 uint32_t tsp) { |
1014 return NaClSysClockGetCommon(natp, clk_id, (uintptr_t) tsp, | 1180 return NaClSysClockGetCommon(natp, clk_id, (uintptr_t) tsp, |
1015 NaClClockGetTime, 0); | 1181 NaClClockGetTime, 0); |
1016 } | 1182 } |
OLD | NEW |