sgx_file.c 22 KB

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