sgx_file.c 20 KB

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