sgx_file.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "platform_api_vmcore.h"
  6. #include "sgx_error.h"
  7. #include "sgx_file.h"
  8. #if WASM_ENABLE_SGX_IPFS != 0
  9. #include "sgx_ipfs.h"
  10. #endif
  11. #ifndef SGX_DISABLE_WASI
  12. #define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__)
  13. #define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__)
  14. /** fd **/
  15. int
  16. ocall_open(int *p_fd, const char *pathname, int flags, bool has_mode,
  17. unsigned mode);
  18. int
  19. ocall_openat(int *p_fd, int dirfd, const char *pathname, int flags,
  20. bool has_mode, unsigned mode);
  21. int
  22. ocall_read(ssize_t *p_ret, int fd, void *buf, size_t read_size);
  23. int
  24. ocall_close(int *p_ret, int fd);
  25. int
  26. ocall_lseek(off_t *p_ret, int fd, off_t offset, int whence);
  27. int
  28. ocall_ftruncate(int *p_ret, int fd, off_t length);
  29. int
  30. ocall_fsync(int *p_ret, int fd);
  31. int
  32. ocall_fdatasync(int *p_ret, int fd);
  33. int
  34. ocall_isatty(int *p_ret, int fd);
  35. /** fd end **/
  36. /** DIR **/
  37. int
  38. ocall_fdopendir(int fd, void **p_dirp);
  39. int
  40. ocall_readdir(void **p_dirent, void *dirp);
  41. int
  42. ocall_rewinddir(void *dirp);
  43. int
  44. ocall_seekdir(void *dirp, long loc);
  45. int
  46. ocall_telldir(long *p_dir, void *dirp);
  47. int
  48. ocall_closedir(int *p_ret, void *dirp);
  49. /** DIR end **/
  50. /** stat **/
  51. int
  52. ocall_stat(int *p_ret, const char *pathname, void *buf, unsigned int buf_len);
  53. int
  54. ocall_fstat(int *p_ret, int fd, void *buf, unsigned int buf_len);
  55. int
  56. ocall_fstatat(int *p_ret, int dirfd, const char *pathname, void *buf,
  57. unsigned int buf_len, int flags);
  58. /** stat end **/
  59. /** link **/
  60. int
  61. ocall_mkdirat(int *p_ret, int dirfd, const char *pathname, unsigned mode);
  62. int
  63. ocall_link(int *p_ret, const char *oldpath, const char *newpath);
  64. int
  65. ocall_linkat(int *p_ret, int olddirfd, const char *oldpath, int newdirfd,
  66. const char *newpath, int flags);
  67. int
  68. ocall_unlinkat(int *p_ret, int dirfd, const char *pathname, int flags);
  69. int
  70. ocall_readlink(ssize_t *p_ret, const char *pathname, char *buf, size_t bufsiz);
  71. int
  72. ocall_readlinkat(ssize_t *p_ret, int dirfd, const char *pathname, char *buf,
  73. size_t bufsiz);
  74. int
  75. ocall_renameat(int *p_ret, int olddirfd, const char *oldpath, int newdirfd,
  76. const char *newpath);
  77. int
  78. ocall_symlinkat(int *p_ret, const char *target, int newdirfd,
  79. const char *linkpath);
  80. /** link end **/
  81. /** control **/
  82. int
  83. ocall_ioctl(int *p_ret, int fd, unsigned long request, void *arg,
  84. unsigned int arg_len);
  85. int
  86. ocall_fcntl(int *p_ret, int fd, int cmd);
  87. int
  88. ocall_fcntl_long(int *p_ret, int fd, int cmd, long arg);
  89. /** control end **/
  90. /** **/
  91. int
  92. ocall_realpath(int *p_ret, const char *path, char *buf, unsigned int buf_len);
  93. int
  94. ocall_posix_fallocate(int *p_ret, int fd, off_t offset, off_t len);
  95. int
  96. ocall_poll(int *p_ret, void *fds, unsigned nfds, int timeout,
  97. unsigned int fds_len);
  98. int
  99. ocall_getopt(int *p_ret, int argc, char *argv_buf, unsigned int argv_buf_len,
  100. const char *optstring);
  101. int
  102. ocall_sched_yield(int *p_ret);
  103. /** struct iovec **/
  104. ssize_t
  105. ocall_readv(ssize_t *p_ret, int fd, char *iov_buf, unsigned int buf_size,
  106. int iovcnt, bool has_offset, off_t offset);
  107. ssize_t
  108. ocall_writev(ssize_t *p_ret, int fd, char *iov_buf, unsigned int buf_size,
  109. int iovcnt, bool has_offset, off_t offset);
  110. /** iovec end **/
  111. int
  112. ocall_get_errno(int *p_ret);
  113. int
  114. open(const char *pathname, int flags, ...)
  115. {
  116. int fd;
  117. bool has_mode = false;
  118. mode_t mode = 0;
  119. if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
  120. va_list ap;
  121. va_start(ap, flags);
  122. mode = va_arg(ap, mode_t);
  123. va_end(ap);
  124. has_mode = true;
  125. }
  126. if (SGX_SUCCESS != ocall_open(&fd, pathname, flags, has_mode, mode)) {
  127. TRACE_OCALL_FAIL();
  128. return -1;
  129. }
  130. if (fd >= 0 && (flags & O_CLOEXEC))
  131. fcntl(fd, F_SETFD, FD_CLOEXEC);
  132. if (fd == -1)
  133. errno = get_errno();
  134. return fd;
  135. }
  136. int
  137. openat(int dirfd, const char *pathname, int flags, ...)
  138. {
  139. int fd;
  140. bool has_mode = false;
  141. mode_t mode = 0;
  142. if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
  143. va_list ap;
  144. va_start(ap, flags);
  145. mode = va_arg(ap, mode_t);
  146. va_end(ap);
  147. has_mode = true;
  148. }
  149. if (SGX_SUCCESS
  150. != ocall_openat(&fd, dirfd, pathname, flags, has_mode, mode)) {
  151. TRACE_OCALL_FAIL();
  152. return -1;
  153. }
  154. if (fd >= 0 && (flags & O_CLOEXEC))
  155. fcntl(fd, F_SETFD, FD_CLOEXEC);
  156. if (fd == -1)
  157. errno = get_errno();
  158. #if WASM_ENABLE_SGX_IPFS != 0
  159. struct stat sb;
  160. int ret = fstatat(dirfd, pathname, &sb, 0);
  161. if (ret < 0) {
  162. if (ocall_close(&ret, fd) != SGX_SUCCESS) {
  163. TRACE_OCALL_FAIL();
  164. }
  165. return -1;
  166. }
  167. // Ony files are managed by SGX IPFS
  168. if (S_ISREG(sb.st_mode)) {
  169. // When WAMR uses Intel SGX IPFS to enabled, it opens a second
  170. // file descriptor to interact with the secure file.
  171. // The first file descriptor opened earlier is used to interact
  172. // with the metadata of the file (e.g., time, flags, etc.).
  173. void *file_ptr = ipfs_fopen(fd, flags);
  174. if (file_ptr == NULL) {
  175. if (ocall_close(&ret, fd) != SGX_SUCCESS) {
  176. TRACE_OCALL_FAIL();
  177. }
  178. return -1;
  179. }
  180. }
  181. #endif
  182. return fd;
  183. }
  184. int
  185. close(int fd)
  186. {
  187. int ret;
  188. #if WASM_ENABLE_SGX_IPFS != 0
  189. // Close the IPFS file pointer in addition of the file descriptor
  190. ret = ipfs_close(fd);
  191. if (ret == -1)
  192. errno = get_errno();
  193. #endif
  194. if (ocall_close(&ret, fd) != SGX_SUCCESS) {
  195. TRACE_OCALL_FAIL();
  196. return -1;
  197. }
  198. if (ret == -1)
  199. errno = get_errno();
  200. return ret;
  201. }
  202. ssize_t
  203. read(int fd, void *buf, size_t size)
  204. {
  205. ssize_t ret;
  206. int size_read_max = 2048, size_read, total_size_read = 0, count, i;
  207. char *p = buf;
  208. if (buf == NULL) {
  209. TRACE_FUNC();
  210. return -1;
  211. }
  212. count = (size + size_read_max - 1) / size_read_max;
  213. for (i = 0; i < count; i++) {
  214. size_read = (i < count - 1) ? size_read_max : size - size_read_max * i;
  215. if (ocall_read(&ret, fd, p, size_read) != SGX_SUCCESS) {
  216. TRACE_OCALL_FAIL();
  217. return -1;
  218. }
  219. if (ret == -1) {
  220. /* read failed */
  221. errno = get_errno();
  222. return -1;
  223. }
  224. p += ret;
  225. total_size_read += ret;
  226. if (ret < size_read)
  227. /* end of file */
  228. break;
  229. }
  230. return total_size_read;
  231. }
  232. DIR *
  233. fdopendir(int fd)
  234. {
  235. DIR *result = NULL;
  236. result = (DIR *)BH_MALLOC(sizeof(DIR));
  237. if (!result)
  238. return NULL;
  239. if (ocall_fdopendir(fd, (void **)result) != SGX_SUCCESS) {
  240. TRACE_OCALL_FAIL();
  241. BH_FREE(result);
  242. return NULL;
  243. }
  244. if ((void *)*result == NULL) { /* opendir failed */
  245. TRACE_FUNC();
  246. BH_FREE(result);
  247. errno = get_errno();
  248. return NULL;
  249. }
  250. return result;
  251. }
  252. struct dirent *
  253. readdir(DIR *dirp)
  254. {
  255. struct dirent *result;
  256. if (dirp == NULL)
  257. return NULL;
  258. if (ocall_readdir((void **)&result, (void *)*dirp) != SGX_SUCCESS) {
  259. TRACE_OCALL_FAIL();
  260. return NULL;
  261. }
  262. if (!result)
  263. errno = get_errno();
  264. return result;
  265. }
  266. void
  267. rewinddir(DIR *dirp)
  268. {
  269. if (ocall_rewinddir((void *)*dirp) != SGX_SUCCESS) {
  270. TRACE_OCALL_FAIL();
  271. }
  272. }
  273. void
  274. seekdir(DIR *dirp, long loc)
  275. {
  276. if (ocall_seekdir((void *)*dirp, loc) != SGX_SUCCESS) {
  277. TRACE_OCALL_FAIL();
  278. }
  279. }
  280. long
  281. telldir(DIR *dirp)
  282. {
  283. long ret;
  284. if (ocall_telldir(&ret, (void *)*dirp) != SGX_SUCCESS) {
  285. TRACE_OCALL_FAIL();
  286. return -1;
  287. }
  288. if (ret == -1)
  289. errno = get_errno();
  290. return ret;
  291. }
  292. int
  293. closedir(DIR *dirp)
  294. {
  295. int ret;
  296. if (ocall_closedir(&ret, (void *)*dirp) != SGX_SUCCESS) {
  297. TRACE_OCALL_FAIL();
  298. return -1;
  299. }
  300. BH_FREE(dirp);
  301. if (ret == -1)
  302. errno = get_errno();
  303. return ret;
  304. }
  305. static ssize_t
  306. readv_internal(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
  307. off_t offset)
  308. {
  309. ssize_t ret, size_left;
  310. struct iovec *iov1;
  311. int i;
  312. char *p;
  313. uint64 total_size = sizeof(struct iovec) * (uint64)iovcnt;
  314. if (iov == NULL || iovcnt < 1)
  315. return -1;
  316. for (i = 0; i < iovcnt; i++) {
  317. total_size += iov[i].iov_len;
  318. }
  319. if (total_size >= UINT32_MAX)
  320. return -1;
  321. #if WASM_ENABLE_SGX_IPFS != 0
  322. if (fd > 2) {
  323. return ipfs_read(fd, iov, iovcnt, has_offset, offset);
  324. }
  325. #endif
  326. iov1 = BH_MALLOC((uint32)total_size);
  327. if (iov1 == NULL)
  328. return -1;
  329. memset(iov1, 0, (uint32)total_size);
  330. p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
  331. for (i = 0; i < iovcnt; i++) {
  332. iov1[i].iov_len = iov[i].iov_len;
  333. iov1[i].iov_base = p;
  334. p += iov[i].iov_len;
  335. }
  336. if (ocall_readv(&ret, fd, (char *)iov1, (uint32)total_size, iovcnt,
  337. has_offset, offset)
  338. != SGX_SUCCESS) {
  339. TRACE_OCALL_FAIL();
  340. BH_FREE(iov1);
  341. return -1;
  342. }
  343. p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
  344. size_left = ret;
  345. for (i = 0; i < iovcnt; i++) {
  346. if (size_left > iov[i].iov_len) {
  347. memcpy(iov[i].iov_base, (uintptr_t)p + (char *)iov1,
  348. iov[i].iov_len);
  349. p += iov[i].iov_len;
  350. size_left -= iov[i].iov_len;
  351. }
  352. else {
  353. memcpy(iov[i].iov_base, (uintptr_t)p + (char *)iov1, size_left);
  354. break;
  355. }
  356. }
  357. BH_FREE(iov1);
  358. if (ret == -1)
  359. errno = get_errno();
  360. return ret;
  361. }
  362. static ssize_t
  363. writev_internal(int fd, const struct iovec *iov, int iovcnt, bool has_offset,
  364. off_t offset)
  365. {
  366. ssize_t ret;
  367. struct iovec *iov1;
  368. int i;
  369. char *p;
  370. uint64 total_size = sizeof(struct iovec) * (uint64)iovcnt;
  371. if (iov == NULL || iovcnt < 1)
  372. return -1;
  373. for (i = 0; i < iovcnt; i++) {
  374. total_size += iov[i].iov_len;
  375. }
  376. if (total_size >= UINT32_MAX)
  377. return -1;
  378. #if WASM_ENABLE_SGX_IPFS != 0
  379. if (fd > 2) {
  380. return ipfs_write(fd, iov, iovcnt, has_offset, offset);
  381. }
  382. #endif
  383. iov1 = BH_MALLOC((uint32)total_size);
  384. if (iov1 == NULL)
  385. return -1;
  386. memset(iov1, 0, (uint32)total_size);
  387. p = (char *)(uintptr_t)(sizeof(struct iovec) * iovcnt);
  388. for (i = 0; i < iovcnt; i++) {
  389. iov1[i].iov_len = iov[i].iov_len;
  390. iov1[i].iov_base = p;
  391. memcpy((uintptr_t)p + (char *)iov1, iov[i].iov_base, iov[i].iov_len);
  392. p += iov[i].iov_len;
  393. }
  394. if (ocall_writev(&ret, fd, (char *)iov1, (uint32)total_size, iovcnt,
  395. has_offset, offset)
  396. != SGX_SUCCESS) {
  397. TRACE_OCALL_FAIL();
  398. BH_FREE(iov1);
  399. return -1;
  400. }
  401. BH_FREE(iov1);
  402. if (ret == -1)
  403. errno = get_errno();
  404. return ret;
  405. }
  406. ssize_t
  407. readv(int fd, const struct iovec *iov, int iovcnt)
  408. {
  409. return readv_internal(fd, iov, iovcnt, false, 0);
  410. }
  411. ssize_t
  412. writev(int fd, const struct iovec *iov, int iovcnt)
  413. {
  414. return writev_internal(fd, iov, iovcnt, false, 0);
  415. }
  416. ssize_t
  417. preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
  418. {
  419. return readv_internal(fd, iov, iovcnt, true, offset);
  420. }
  421. ssize_t
  422. pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
  423. {
  424. return writev_internal(fd, iov, iovcnt, true, offset);
  425. }
  426. off_t
  427. lseek(int fd, off_t offset, int whence)
  428. {
  429. off_t ret;
  430. #if WASM_ENABLE_SGX_IPFS != 0
  431. ret = ipfs_lseek(fd, offset, whence);
  432. #else
  433. if (ocall_lseek(&ret, fd, (long)offset, whence) != SGX_SUCCESS) {
  434. TRACE_OCALL_FAIL();
  435. return -1;
  436. }
  437. if (ret == -1)
  438. errno = get_errno();
  439. #endif
  440. return ret;
  441. }
  442. int
  443. ftruncate(int fd, off_t length)
  444. {
  445. int ret;
  446. #if WASM_ENABLE_SGX_IPFS != 0
  447. ret = ipfs_ftruncate(fd, length);
  448. #else
  449. if (ocall_ftruncate(&ret, fd, length) != SGX_SUCCESS) {
  450. TRACE_OCALL_FAIL();
  451. return -1;
  452. }
  453. if (ret == -1)
  454. errno = get_errno();
  455. #endif
  456. return ret;
  457. }
  458. int
  459. stat(const char *pathname, struct stat *statbuf)
  460. {
  461. int ret;
  462. if (statbuf == NULL)
  463. return -1;
  464. if (ocall_stat(&ret, pathname, (void *)statbuf, sizeof(struct stat))
  465. != SGX_SUCCESS) {
  466. TRACE_OCALL_FAIL();
  467. return -1;
  468. }
  469. if (ret == -1)
  470. errno = get_errno();
  471. return ret;
  472. }
  473. int
  474. fstat(int fd, struct stat *statbuf)
  475. {
  476. int ret;
  477. if (statbuf == NULL)
  478. return -1;
  479. if (ocall_fstat(&ret, fd, (void *)statbuf, sizeof(struct stat))
  480. != SGX_SUCCESS) {
  481. TRACE_OCALL_FAIL();
  482. return -1;
  483. }
  484. if (ret == -1)
  485. errno = get_errno();
  486. return ret;
  487. }
  488. int
  489. fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags)
  490. {
  491. int ret;
  492. if (statbuf == NULL)
  493. return -1;
  494. if (ocall_fstatat(&ret, dirfd, pathname, (void *)statbuf,
  495. sizeof(struct stat), flags)
  496. != SGX_SUCCESS) {
  497. TRACE_OCALL_FAIL();
  498. return -1;
  499. }
  500. if (ret == -1)
  501. errno = get_errno();
  502. return ret;
  503. }
  504. int
  505. fsync(int fd)
  506. {
  507. int ret;
  508. #if WASM_ENABLE_SGX_IPFS != 0
  509. ret = ipfs_fflush(fd);
  510. #else
  511. if (ocall_fsync(&ret, fd) != SGX_SUCCESS) {
  512. TRACE_OCALL_FAIL();
  513. return -1;
  514. }
  515. if (ret == -1)
  516. errno = get_errno();
  517. #endif
  518. return ret;
  519. }
  520. int
  521. fdatasync(int fd)
  522. {
  523. int ret;
  524. #if WASM_ENABLE_SGX_IPFS != 0
  525. ret = ipfs_fflush(fd);
  526. #else
  527. if (ocall_fdatasync(&ret, fd) != SGX_SUCCESS) {
  528. TRACE_OCALL_FAIL();
  529. return -1;
  530. }
  531. if (ret == -1)
  532. errno = get_errno();
  533. #endif
  534. return ret;
  535. }
  536. int
  537. mkdirat(int dirfd, const char *pathname, mode_t mode)
  538. {
  539. int ret;
  540. if (ocall_mkdirat(&ret, dirfd, pathname, mode) != SGX_SUCCESS) {
  541. TRACE_OCALL_FAIL();
  542. return -1;
  543. }
  544. if (ret == -1)
  545. errno = get_errno();
  546. return ret;
  547. }
  548. int
  549. link(const char *oldpath, const char *newpath)
  550. {
  551. int ret;
  552. if (ocall_link(&ret, oldpath, newpath) != SGX_SUCCESS) {
  553. TRACE_OCALL_FAIL();
  554. return -1;
  555. }
  556. if (ret == -1)
  557. errno = get_errno();
  558. return ret;
  559. }
  560. int
  561. linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
  562. int flags)
  563. {
  564. int ret;
  565. if (ocall_linkat(&ret, olddirfd, oldpath, newdirfd, newpath, flags)
  566. != SGX_SUCCESS) {
  567. TRACE_OCALL_FAIL();
  568. return -1;
  569. }
  570. if (ret == -1)
  571. errno = get_errno();
  572. return ret;
  573. }
  574. int
  575. unlinkat(int dirfd, const char *pathname, int flags)
  576. {
  577. int ret;
  578. if (ocall_unlinkat(&ret, dirfd, pathname, flags) != SGX_SUCCESS) {
  579. TRACE_OCALL_FAIL();
  580. return -1;
  581. }
  582. if (ret == -1)
  583. errno = get_errno();
  584. return ret;
  585. }
  586. ssize_t
  587. readlink(const char *pathname, char *buf, size_t bufsiz)
  588. {
  589. ssize_t ret;
  590. if (buf == NULL)
  591. return -1;
  592. if (ocall_readlink(&ret, pathname, buf, bufsiz) != SGX_SUCCESS) {
  593. TRACE_OCALL_FAIL();
  594. return -1;
  595. }
  596. if (ret == -1)
  597. errno = get_errno();
  598. return ret;
  599. }
  600. ssize_t
  601. readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
  602. {
  603. ssize_t ret;
  604. if (buf == NULL)
  605. return -1;
  606. if (ocall_readlinkat(&ret, dirfd, pathname, buf, bufsiz) != SGX_SUCCESS) {
  607. TRACE_OCALL_FAIL();
  608. return -1;
  609. }
  610. if (ret == -1)
  611. errno = get_errno();
  612. return ret;
  613. }
  614. int
  615. symlinkat(const char *target, int newdirfd, const char *linkpath)
  616. {
  617. int ret;
  618. if (ocall_symlinkat(&ret, target, newdirfd, linkpath) != SGX_SUCCESS) {
  619. TRACE_OCALL_FAIL();
  620. return -1;
  621. }
  622. if (ret == -1)
  623. errno = get_errno();
  624. return ret;
  625. }
  626. int
  627. renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)
  628. {
  629. int ret;
  630. if (ocall_renameat(&ret, olddirfd, oldpath, newdirfd, newpath)
  631. != SGX_SUCCESS) {
  632. TRACE_OCALL_FAIL();
  633. return -1;
  634. }
  635. if (ret == -1)
  636. errno = get_errno();
  637. return ret;
  638. }
  639. int
  640. ioctl(int fd, unsigned long request, ...)
  641. {
  642. int ret;
  643. va_list args;
  644. switch (request) {
  645. case FIONREAD:
  646. va_start(args, request);
  647. int *arg = (int *)va_arg(args, int *);
  648. if (ocall_ioctl(&ret, fd, request, arg, sizeof(*arg))
  649. != SGX_SUCCESS) {
  650. TRACE_OCALL_FAIL();
  651. va_end(args);
  652. return -1;
  653. }
  654. va_end(args);
  655. break;
  656. default:
  657. os_printf("ioctl failed: unknown request", request);
  658. return -1;
  659. }
  660. if (ret == -1)
  661. errno = get_errno();
  662. return ret;
  663. }
  664. int
  665. fcntl(int fd, int cmd, ... /* arg */)
  666. {
  667. int ret;
  668. va_list args;
  669. switch (cmd) {
  670. case F_GETFD:
  671. case F_GETFL:
  672. if (ocall_fcntl(&ret, fd, cmd) != SGX_SUCCESS) {
  673. TRACE_OCALL_FAIL();
  674. return -1;
  675. }
  676. break;
  677. case F_DUPFD:
  678. case F_SETFD:
  679. case F_SETFL:
  680. va_start(args, cmd);
  681. long arg_1 = (long)va_arg(args, long);
  682. if (ocall_fcntl_long(&ret, fd, cmd, arg_1) != SGX_SUCCESS) {
  683. TRACE_OCALL_FAIL();
  684. va_end(args);
  685. return -1;
  686. }
  687. va_end(args);
  688. break;
  689. default:
  690. os_printf("fcntl failed: unknown cmd %d.\n", cmd);
  691. return -1;
  692. }
  693. if (ret == -1)
  694. errno = get_errno();
  695. return ret;
  696. }
  697. int
  698. isatty(int fd)
  699. {
  700. int ret;
  701. if (ocall_isatty(&ret, fd) != SGX_SUCCESS) {
  702. TRACE_OCALL_FAIL();
  703. return -1;
  704. }
  705. if (ret == 0)
  706. errno = get_errno();
  707. return ret;
  708. }
  709. char *
  710. realpath(const char *path, char *resolved_path)
  711. {
  712. int ret;
  713. char buf[PATH_MAX] = { 0 };
  714. if (ocall_realpath(&ret, path, buf, PATH_MAX) != SGX_SUCCESS) {
  715. TRACE_OCALL_FAIL();
  716. return (char *)NULL;
  717. }
  718. if (ret != 0)
  719. return (char *)NULL;
  720. if (resolved_path) {
  721. strcpy(resolved_path, buf);
  722. }
  723. else {
  724. resolved_path = BH_MALLOC(strlen(buf) + 1);
  725. if (resolved_path == NULL)
  726. return NULL;
  727. strcpy(resolved_path, buf);
  728. }
  729. return resolved_path;
  730. }
  731. int
  732. posix_fallocate(int fd, off_t offset, off_t len)
  733. {
  734. int ret;
  735. #if WASM_ENABLE_SGX_IPFS != 0
  736. ret = ipfs_posix_fallocate(fd, offset, len);
  737. #else
  738. if (ocall_posix_fallocate(&ret, fd, offset, len) != SGX_SUCCESS) {
  739. TRACE_OCALL_FAIL();
  740. return -1;
  741. }
  742. #endif
  743. return ret;
  744. }
  745. int
  746. poll(struct pollfd *fds, nfds_t nfds, int timeout)
  747. {
  748. int ret;
  749. if (fds == NULL)
  750. return -1;
  751. if (ocall_poll(&ret, fds, nfds, timeout, sizeof(*fds) * nfds)
  752. != SGX_SUCCESS) {
  753. TRACE_OCALL_FAIL();
  754. return -1;
  755. }
  756. if (ret == -1)
  757. errno = get_errno();
  758. return ret;
  759. }
  760. int
  761. getopt(int argc, char *const argv[], const char *optstring)
  762. {
  763. int ret;
  764. char **argv1;
  765. char *p;
  766. int i;
  767. uint64 total_size = sizeof(char *) * (uint64)argc;
  768. for (i = 0; i < argc; i++) {
  769. total_size += strlen(argv[i]) + 1;
  770. }
  771. if (total_size >= UINT32_MAX)
  772. return -1;
  773. argv1 = BH_MALLOC((uint32)total_size);
  774. if (argv1 == NULL)
  775. return -1;
  776. p = (char *)(uintptr_t)(sizeof(char *) * argc);
  777. for (i = 0; i < argc; i++) {
  778. argv1[i] = p;
  779. strcpy((char *)argv1 + (uintptr_t)p, argv[i]);
  780. p += ((uintptr_t)strlen(argv[i]) + 1);
  781. }
  782. if (ocall_getopt(&ret, argc, (char *)argv1, total_size, optstring)
  783. != SGX_SUCCESS) {
  784. TRACE_OCALL_FAIL();
  785. BH_FREE(argv1);
  786. return -1;
  787. }
  788. BH_FREE(argv1);
  789. if (ret == -1)
  790. errno = get_errno();
  791. return ret;
  792. }
  793. int
  794. sched_yield(void)
  795. {
  796. int ret;
  797. if (ocall_sched_yield(&ret) != SGX_SUCCESS) {
  798. TRACE_OCALL_FAIL();
  799. return -1;
  800. }
  801. if (ret == -1)
  802. errno = get_errno();
  803. return ret;
  804. }
  805. ssize_t
  806. getrandom(void *buf, size_t buflen, unsigned int flags)
  807. {
  808. sgx_status_t ret;
  809. if (!buf || buflen > INT32_MAX || flags != 0) {
  810. errno = EINVAL;
  811. return -1;
  812. }
  813. ret = sgx_read_rand(buf, buflen);
  814. if (ret != SGX_SUCCESS) {
  815. errno = EFAULT;
  816. return -1;
  817. }
  818. return (ssize_t)buflen;
  819. }
  820. #define RDRAND_RETRIES 3
  821. static int
  822. rdrand64_step(uint64 *seed)
  823. {
  824. uint8 ok;
  825. __asm__ volatile("rdseed %0; setc %1" : "=r"(*seed), "=qm"(ok));
  826. return (int)ok;
  827. }
  828. static int
  829. rdrand64_retry(uint64 *rand, uint32 retries)
  830. {
  831. uint32 count = 0;
  832. while (count++ <= retries) {
  833. if (rdrand64_step(rand)) {
  834. return -1;
  835. }
  836. }
  837. return 0;
  838. }
  839. static uint32
  840. rdrand_get_bytes(uint8 *dest, uint32 n)
  841. {
  842. uint8 *head_start = dest, *tail_start = NULL;
  843. uint64 *block_start;
  844. uint32 count, ltail, lhead, lblock;
  845. uint64 i, temp_rand;
  846. /* Get the address of the first 64-bit aligned block in the
  847. destination buffer. */
  848. if (((uintptr_t)head_start & (uintptr_t)7) == 0) {
  849. /* already 8-byte aligned */
  850. block_start = (uint64 *)head_start;
  851. lhead = 0;
  852. lblock = n & ~7;
  853. }
  854. else {
  855. /* next 8-byte aligned */
  856. block_start = (uint64 *)(((uintptr_t)head_start + 7) & ~(uintptr_t)7);
  857. lhead = (uint32)((uintptr_t)block_start - (uintptr_t)head_start);
  858. lblock = (n - lhead) & ~7;
  859. }
  860. /* Compute the number of 64-bit blocks and the remaining number
  861. of bytes (the tail) */
  862. ltail = n - lblock - lhead;
  863. if (ltail > 0) {
  864. tail_start = (uint8 *)block_start + lblock;
  865. }
  866. /* Populate the starting, mis-aligned section (the head) */
  867. if (lhead > 0) {
  868. if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
  869. return 0;
  870. }
  871. memcpy(head_start, &temp_rand, lhead);
  872. }
  873. /* Populate the central, aligned blocks */
  874. count = lblock / 8;
  875. for (i = 0; i < count; i++, block_start++) {
  876. if (!rdrand64_retry(block_start, RDRAND_RETRIES)) {
  877. return i * 8 + lhead;
  878. }
  879. }
  880. /* Populate the tail */
  881. if (ltail > 0) {
  882. if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
  883. return count * 8 + lhead;
  884. }
  885. memcpy(tail_start, &temp_rand, ltail);
  886. }
  887. return n;
  888. }
  889. int
  890. getentropy(void *buffer, size_t length)
  891. {
  892. uint32 size;
  893. if (!buffer || length > INT32_MAX) {
  894. errno = EINVAL;
  895. return -1;
  896. }
  897. if (length == 0) {
  898. return 0;
  899. }
  900. size = rdrand_get_bytes(buffer, (uint32)length);
  901. if (size != length) {
  902. errno = EFAULT;
  903. return -1;
  904. }
  905. return 0;
  906. }
  907. int
  908. get_errno(void)
  909. {
  910. int ret;
  911. if (ocall_get_errno(&ret) != SGX_SUCCESS) {
  912. TRACE_OCALL_FAIL();
  913. return -1;
  914. }
  915. return ret;
  916. }
  917. #endif