enclave_ocalls.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. /*
  2. * This is for enclave to make ocalls to untrusted runtime.
  3. */
  4. #include "pal_linux.h"
  5. #include "pal_internal.h"
  6. #include "pal_debug.h"
  7. #include "enclave_ocalls.h"
  8. #include "ocall_types.h"
  9. #include "ecall_types.h"
  10. #include <api.h>
  11. #include <asm/errno.h>
  12. noreturn void ocall_exit(int exitcode, int is_exitgroup)
  13. {
  14. ms_ocall_exit_t * ms;
  15. ms = sgx_alloc_on_ustack(sizeof(*ms));
  16. ms->ms_exitcode = exitcode;
  17. ms->ms_is_exitgroup = is_exitgroup;
  18. // There are two reasons for this loop:
  19. // 1. Ocalls can be interuppted.
  20. // 2. We can't trust the outside to actually exit, so we need to ensure
  21. // that we never return even when the outside tries to trick us.
  22. while (true) {
  23. sgx_ocall(OCALL_EXIT, ms);
  24. }
  25. }
  26. int ocall_print_string (const char * str, unsigned int length)
  27. {
  28. int retval = 0;
  29. ms_ocall_print_string_t * ms;
  30. ms = sgx_alloc_on_ustack(sizeof(*ms));
  31. if (!ms) {
  32. sgx_reset_ustack();
  33. return -EPERM;
  34. }
  35. if (!str || length <= 0) {
  36. sgx_reset_ustack();
  37. return -EPERM;
  38. }
  39. ms->ms_length = length;
  40. ms->ms_str = sgx_copy_to_ustack(str, length);
  41. if (!ms->ms_str) {
  42. sgx_reset_ustack();
  43. return -EPERM;
  44. }
  45. retval = sgx_ocall(OCALL_PRINT_STRING, ms);
  46. sgx_reset_ustack();
  47. return retval;
  48. }
  49. int ocall_alloc_untrusted (uint64_t size, void ** mem)
  50. {
  51. int retval = 0;
  52. ms_ocall_alloc_untrusted_t * ms;
  53. ms = sgx_alloc_on_ustack(sizeof(*ms));
  54. if (!ms) {
  55. sgx_reset_ustack();
  56. return -EPERM;
  57. }
  58. ms->ms_size = size;
  59. retval = sgx_ocall(OCALL_ALLOC_UNTRUSTED, ms);
  60. if (!retval) {
  61. if (!sgx_copy_ptr_to_enclave(mem, ms->ms_mem, size)) {
  62. sgx_reset_ustack();
  63. return -EPERM;
  64. }
  65. }
  66. sgx_reset_ustack();
  67. return retval;
  68. }
  69. int ocall_map_untrusted (int fd, uint64_t offset,
  70. uint64_t size, unsigned short prot,
  71. void ** mem)
  72. {
  73. int retval = 0;
  74. ms_ocall_map_untrusted_t * ms;
  75. ms = sgx_alloc_on_ustack(sizeof(*ms));
  76. if (!ms) {
  77. sgx_reset_ustack();
  78. return -EPERM;
  79. }
  80. ms->ms_fd = fd;
  81. ms->ms_offset = offset;
  82. ms->ms_size = size;
  83. ms->ms_prot = prot;
  84. retval = sgx_ocall(OCALL_MAP_UNTRUSTED, ms);
  85. if (!retval) {
  86. if (!sgx_copy_ptr_to_enclave(mem, ms->ms_mem, size)) {
  87. sgx_reset_ustack();
  88. return -EPERM;
  89. }
  90. }
  91. sgx_reset_ustack();
  92. return retval;
  93. }
  94. int ocall_unmap_untrusted (const void * mem, uint64_t size)
  95. {
  96. int retval = 0;
  97. ms_ocall_unmap_untrusted_t * ms;
  98. if (!sgx_is_completely_outside_enclave(mem, size)) {
  99. sgx_reset_ustack();
  100. return -EINVAL;
  101. }
  102. ms = sgx_alloc_on_ustack(sizeof(*ms));
  103. if (!ms) {
  104. sgx_reset_ustack();
  105. return -EPERM;
  106. }
  107. ms->ms_mem = mem;
  108. ms->ms_size = size;
  109. retval = sgx_ocall(OCALL_UNMAP_UNTRUSTED, ms);
  110. sgx_reset_ustack();
  111. return retval;
  112. }
  113. int ocall_cpuid (unsigned int leaf, unsigned int subleaf,
  114. unsigned int values[4])
  115. {
  116. int retval = 0;
  117. ms_ocall_cpuid_t * ms;
  118. ms = sgx_alloc_on_ustack(sizeof(*ms));
  119. if (!ms) {
  120. sgx_reset_ustack();
  121. return -EPERM;
  122. }
  123. ms->ms_leaf = leaf;
  124. ms->ms_subleaf = subleaf;
  125. retval = sgx_ocall(OCALL_CPUID, ms);
  126. if (!retval) {
  127. values[0] = ms->ms_values[0];
  128. values[1] = ms->ms_values[1];
  129. values[2] = ms->ms_values[2];
  130. values[3] = ms->ms_values[3];
  131. }
  132. sgx_reset_ustack();
  133. return retval;
  134. }
  135. int ocall_open (const char * pathname, int flags, unsigned short mode)
  136. {
  137. int retval = 0;
  138. int len = pathname ? strlen(pathname) + 1 : 0;
  139. ms_ocall_open_t * ms;
  140. ms = sgx_alloc_on_ustack(sizeof(*ms));
  141. if (!ms) {
  142. sgx_reset_ustack();
  143. return -EPERM;
  144. }
  145. ms->ms_flags = flags;
  146. ms->ms_mode = mode;
  147. ms->ms_pathname = sgx_copy_to_ustack(pathname, len);
  148. if (!ms->ms_pathname) {
  149. sgx_reset_ustack();
  150. return -EPERM;
  151. }
  152. retval = sgx_ocall(OCALL_OPEN, ms);
  153. sgx_reset_ustack();
  154. return retval;
  155. }
  156. int ocall_close (int fd)
  157. {
  158. int retval = 0;
  159. ms_ocall_close_t *ms;
  160. ms = sgx_alloc_on_ustack(sizeof(*ms));
  161. if (!ms) {
  162. sgx_reset_ustack();
  163. return -EPERM;
  164. }
  165. ms->ms_fd = fd;
  166. retval = sgx_ocall(OCALL_CLOSE, ms);
  167. sgx_reset_ustack();
  168. return retval;
  169. }
  170. int ocall_read (int fd, void * buf, unsigned int count)
  171. {
  172. int retval = 0;
  173. void * obuf = NULL;
  174. ms_ocall_read_t * ms;
  175. if (count > PRESET_PAGESIZE) {
  176. retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
  177. if (IS_ERR(retval))
  178. return retval;
  179. }
  180. ms = sgx_alloc_on_ustack(sizeof(*ms));
  181. if (!ms) {
  182. retval = -EPERM;
  183. goto out;
  184. }
  185. ms->ms_fd = fd;
  186. ms->ms_count = count;
  187. if (obuf)
  188. ms->ms_buf = obuf;
  189. else
  190. ms->ms_buf = sgx_alloc_on_ustack(count);
  191. if (!ms->ms_buf) {
  192. retval = -EPERM;
  193. goto out;
  194. }
  195. retval = sgx_ocall(OCALL_READ, ms);
  196. if (retval > 0) {
  197. if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) {
  198. retval = -EPERM;
  199. goto out;
  200. }
  201. }
  202. out:
  203. sgx_reset_ustack();
  204. if (obuf)
  205. ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
  206. return retval;
  207. }
  208. int ocall_write (int fd, const void * buf, unsigned int count)
  209. {
  210. int retval = 0;
  211. void * obuf = NULL;
  212. ms_ocall_write_t * ms;
  213. if (count > PRESET_PAGESIZE) {
  214. retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
  215. if (IS_ERR(retval))
  216. return retval;
  217. }
  218. ms = sgx_alloc_on_ustack(sizeof(*ms));
  219. if (!ms) {
  220. retval = -EPERM;
  221. goto out;
  222. }
  223. ms->ms_fd = fd;
  224. ms->ms_count = count;
  225. if (obuf) {
  226. ms->ms_buf = obuf;
  227. memcpy(obuf, buf, count);
  228. } else {
  229. ms->ms_buf = sgx_copy_to_ustack(buf, count);
  230. }
  231. if (!ms->ms_buf) {
  232. retval = -EPERM;
  233. goto out;
  234. }
  235. retval = sgx_ocall(OCALL_WRITE, ms);
  236. out:
  237. sgx_reset_ustack();
  238. if (obuf)
  239. ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
  240. return retval;
  241. }
  242. int ocall_fstat (int fd, struct stat * buf)
  243. {
  244. int retval = 0;
  245. ms_ocall_fstat_t * ms;
  246. ms = sgx_alloc_on_ustack(sizeof(*ms));
  247. if (!ms) {
  248. sgx_reset_ustack();
  249. return -EPERM;
  250. }
  251. ms->ms_fd = fd;
  252. retval = sgx_ocall(OCALL_FSTAT, ms);
  253. if (!retval)
  254. memcpy(buf, &ms->ms_stat, sizeof(struct stat));
  255. sgx_reset_ustack();
  256. return retval;
  257. }
  258. int ocall_fionread (int fd)
  259. {
  260. int retval = 0;
  261. ms_ocall_fionread_t * ms;
  262. ms = sgx_alloc_on_ustack(sizeof(*ms));
  263. if (!ms) {
  264. sgx_reset_ustack();
  265. return -EPERM;
  266. }
  267. ms->ms_fd = fd;
  268. retval = sgx_ocall(OCALL_FIONREAD, ms);
  269. sgx_reset_ustack();
  270. return retval;
  271. }
  272. int ocall_fsetnonblock (int fd, int nonblocking)
  273. {
  274. int retval = 0;
  275. ms_ocall_fsetnonblock_t * ms;
  276. ms = sgx_alloc_on_ustack(sizeof(*ms));
  277. if (!ms) {
  278. sgx_reset_ustack();
  279. return -EPERM;
  280. }
  281. ms->ms_fd = fd;
  282. ms->ms_nonblocking = nonblocking;
  283. retval = sgx_ocall(OCALL_FSETNONBLOCK, ms);
  284. sgx_reset_ustack();
  285. return retval;
  286. }
  287. int ocall_fchmod (int fd, unsigned short mode)
  288. {
  289. int retval = 0;
  290. ms_ocall_fchmod_t * ms;
  291. ms = sgx_alloc_on_ustack(sizeof(*ms));
  292. if (!ms) {
  293. sgx_reset_ustack();
  294. return -EPERM;
  295. }
  296. ms->ms_fd = fd;
  297. ms->ms_mode = mode;
  298. retval = sgx_ocall(OCALL_FCHMOD, ms);
  299. sgx_reset_ustack();
  300. return retval;
  301. }
  302. int ocall_fsync (int fd)
  303. {
  304. int retval = 0;
  305. ms_ocall_fsync_t * ms;
  306. ms = sgx_alloc_on_ustack(sizeof(*ms));
  307. if (!ms) {
  308. sgx_reset_ustack();
  309. return -EPERM;
  310. }
  311. ms->ms_fd = fd;
  312. retval = sgx_ocall(OCALL_FSYNC, ms);
  313. sgx_reset_ustack();
  314. return retval;
  315. }
  316. int ocall_ftruncate (int fd, uint64_t length)
  317. {
  318. int retval = 0;
  319. ms_ocall_ftruncate_t * ms;
  320. ms = sgx_alloc_on_ustack(sizeof(*ms));
  321. if (!ms) {
  322. sgx_reset_ustack();
  323. return -EPERM;
  324. }
  325. ms->ms_fd = fd;
  326. ms->ms_length = length;
  327. retval = sgx_ocall(OCALL_FTRUNCATE, ms);
  328. sgx_reset_ustack();
  329. return retval;
  330. }
  331. int ocall_mkdir (const char * pathname, unsigned short mode)
  332. {
  333. int retval = 0;
  334. int len = pathname ? strlen(pathname) + 1 : 0;
  335. ms_ocall_mkdir_t * ms;
  336. ms = sgx_alloc_on_ustack(sizeof(*ms));
  337. if (!ms) {
  338. sgx_reset_ustack();
  339. return -EPERM;
  340. }
  341. ms->ms_mode = mode;
  342. ms->ms_pathname = sgx_copy_to_ustack(pathname, len);
  343. if (!ms->ms_pathname) {
  344. sgx_reset_ustack();
  345. return -EPERM;
  346. }
  347. retval = sgx_ocall(OCALL_MKDIR, ms);
  348. sgx_reset_ustack();
  349. return retval;
  350. }
  351. int ocall_getdents (int fd, struct linux_dirent64 * dirp, unsigned int size)
  352. {
  353. int retval = 0;
  354. ms_ocall_getdents_t * ms;
  355. ms = sgx_alloc_on_ustack(sizeof(*ms));
  356. if (!ms) {
  357. sgx_reset_ustack();
  358. return -EPERM;
  359. }
  360. ms->ms_fd = fd;
  361. ms->ms_size = size;
  362. ms->ms_dirp = sgx_alloc_on_ustack(size);
  363. if (!ms->ms_dirp) {
  364. sgx_reset_ustack();
  365. return -EPERM;
  366. }
  367. retval = sgx_ocall(OCALL_GETDENTS, ms);
  368. if (retval > 0) {
  369. if (!sgx_copy_to_enclave(dirp, size, ms->ms_dirp, retval)) {
  370. sgx_reset_ustack();
  371. return -EPERM;
  372. }
  373. }
  374. sgx_reset_ustack();
  375. return retval;
  376. }
  377. int ocall_wake_thread (void * tcs)
  378. {
  379. return sgx_ocall(OCALL_WAKE_THREAD, tcs);
  380. }
  381. int ocall_create_process (const char * uri,
  382. int nargs, const char ** args,
  383. int procfds[3],
  384. unsigned int * pid)
  385. {
  386. int retval = 0;
  387. int ulen = uri ? strlen(uri) + 1 : 0;
  388. ms_ocall_create_process_t * ms;
  389. ms = sgx_alloc_on_ustack(sizeof(*ms) + nargs * sizeof(char *));
  390. if (!ms) {
  391. sgx_reset_ustack();
  392. return -EPERM;
  393. }
  394. ms->ms_uri = uri ? sgx_copy_to_ustack(uri, ulen) : NULL;
  395. if (uri && !ms->ms_uri) {
  396. sgx_reset_ustack();
  397. return -EPERM;
  398. }
  399. ms->ms_nargs = nargs;
  400. for (int i = 0 ; i < nargs ; i++) {
  401. int len = args[i] ? strlen(args[i]) + 1 : 0;
  402. ms->ms_args[i] = args[i] ? sgx_copy_to_ustack(args[i], len) : NULL;
  403. if (args[i] && !ms->ms_args[i]) {
  404. sgx_reset_ustack();
  405. return -EPERM;
  406. }
  407. }
  408. retval = sgx_ocall(OCALL_CREATE_PROCESS, ms);
  409. if (!retval) {
  410. if (pid)
  411. *pid = ms->ms_pid;
  412. procfds[0] = ms->ms_proc_fds[0];
  413. procfds[1] = ms->ms_proc_fds[1];
  414. procfds[2] = ms->ms_proc_fds[2];
  415. }
  416. sgx_reset_ustack();
  417. return retval;
  418. }
  419. int ocall_futex(int* futex, int op, int val, int64_t timeout_us) {
  420. int retval = 0;
  421. ms_ocall_futex_t * ms;
  422. if (!sgx_is_completely_outside_enclave(futex, sizeof(int))) {
  423. sgx_reset_ustack();
  424. return -EINVAL;
  425. }
  426. ms = sgx_alloc_on_ustack(sizeof(*ms));
  427. if (!ms) {
  428. sgx_reset_ustack();
  429. return -EPERM;
  430. }
  431. ms->ms_futex = futex;
  432. ms->ms_op = op;
  433. ms->ms_val = val;
  434. ms->ms_timeout_us = timeout_us;
  435. retval = sgx_ocall(OCALL_FUTEX, ms);
  436. sgx_reset_ustack();
  437. return retval;
  438. }
  439. int ocall_socketpair (int domain, int type, int protocol,
  440. int sockfds[2])
  441. {
  442. int retval = 0;
  443. ms_ocall_socketpair_t * ms;
  444. ms = sgx_alloc_on_ustack(sizeof(*ms));
  445. if (!ms) {
  446. sgx_reset_ustack();
  447. return -EPERM;
  448. }
  449. ms->ms_domain = domain;
  450. ms->ms_type = type;
  451. ms->ms_protocol = protocol;
  452. retval = sgx_ocall(OCALL_SOCKETPAIR, ms);
  453. if (!retval) {
  454. sockfds[0] = ms->ms_sockfds[0];
  455. sockfds[1] = ms->ms_sockfds[1];
  456. }
  457. sgx_reset_ustack();
  458. return retval;
  459. }
  460. int ocall_sock_listen (int domain, int type, int protocol,
  461. struct sockaddr * addr, unsigned int * addrlen,
  462. struct sockopt * sockopt)
  463. {
  464. int retval = 0;
  465. unsigned int copied;
  466. unsigned int len = addrlen ? *addrlen : 0;
  467. ms_ocall_sock_listen_t * ms;
  468. ms = sgx_alloc_on_ustack(sizeof(*ms));
  469. if (!ms) {
  470. sgx_reset_ustack();
  471. return -EPERM;
  472. }
  473. ms->ms_domain = domain;
  474. ms->ms_type = type;
  475. ms->ms_protocol = protocol;
  476. ms->ms_addrlen = len;
  477. ms->ms_addr = (addr && len) ? sgx_copy_to_ustack(addr, len) : NULL;
  478. if (addr && len && !ms->ms_addr) {
  479. sgx_reset_ustack();
  480. return -EPERM;
  481. }
  482. retval = sgx_ocall(OCALL_SOCK_LISTEN, ms);
  483. if (retval >= 0) {
  484. if (addr && len) {
  485. copied = sgx_copy_to_enclave(addr, len, ms->ms_addr, ms->ms_addrlen);
  486. if (!copied) {
  487. sgx_reset_ustack();
  488. return -EPERM;
  489. }
  490. *addrlen = copied;
  491. }
  492. if (sockopt) {
  493. *sockopt = ms->ms_sockopt;
  494. }
  495. }
  496. sgx_reset_ustack();
  497. return retval;
  498. }
  499. int ocall_sock_accept (int sockfd, struct sockaddr * addr,
  500. unsigned int * addrlen, struct sockopt * sockopt)
  501. {
  502. int retval = 0;
  503. unsigned int copied;
  504. unsigned int len = addrlen ? *addrlen : 0;
  505. ms_ocall_sock_accept_t * ms;
  506. ms = sgx_alloc_on_ustack(sizeof(*ms));
  507. if (!ms) {
  508. sgx_reset_ustack();
  509. return -EPERM;
  510. }
  511. ms->ms_sockfd = sockfd;
  512. ms->ms_addrlen = len;
  513. ms->ms_addr = (addr && len) ? sgx_copy_to_ustack(addr, len) : NULL;
  514. if (addr && len && !ms->ms_addr) {
  515. sgx_reset_ustack();
  516. return -EPERM;
  517. }
  518. retval = sgx_ocall(OCALL_SOCK_ACCEPT, ms);
  519. if (retval >= 0) {
  520. if (addr && len) {
  521. copied = sgx_copy_to_enclave(addr, len, ms->ms_addr, ms->ms_addrlen);
  522. if (!copied) {
  523. sgx_reset_ustack();
  524. return -EPERM;
  525. }
  526. *addrlen = copied;
  527. }
  528. if (sockopt) {
  529. *sockopt = ms->ms_sockopt;
  530. }
  531. }
  532. sgx_reset_ustack();
  533. return retval;
  534. }
  535. int ocall_sock_connect (int domain, int type, int protocol,
  536. const struct sockaddr * addr,
  537. unsigned int addrlen,
  538. struct sockaddr * bind_addr,
  539. unsigned int * bind_addrlen, struct sockopt * sockopt)
  540. {
  541. int retval = 0;
  542. unsigned int copied;
  543. unsigned int bind_len = bind_addrlen ? *bind_addrlen : 0;
  544. ms_ocall_sock_connect_t * ms;
  545. ms = sgx_alloc_on_ustack(sizeof(*ms));
  546. if (!ms) {
  547. sgx_reset_ustack();
  548. return -EPERM;
  549. }
  550. ms->ms_domain = domain;
  551. ms->ms_type = type;
  552. ms->ms_protocol = protocol;
  553. ms->ms_addrlen = addrlen;
  554. ms->ms_bind_addrlen = bind_len;
  555. ms->ms_addr = addr ? sgx_copy_to_ustack(addr, addrlen) : NULL;
  556. ms->ms_bind_addr = bind_addr ? sgx_copy_to_ustack(bind_addr, bind_len) : NULL;
  557. if ((addr && !ms->ms_addr) || (bind_addr && !ms->ms_bind_addr)) {
  558. sgx_reset_ustack();
  559. return -EPERM;
  560. }
  561. retval = sgx_ocall(OCALL_SOCK_CONNECT, ms);
  562. if (retval >= 0) {
  563. if (bind_addr && bind_len) {
  564. copied = sgx_copy_to_enclave(bind_addr, bind_len, ms->ms_bind_addr, ms->ms_bind_addrlen);
  565. if (!copied) {
  566. sgx_reset_ustack();
  567. return -EPERM;
  568. }
  569. *bind_addrlen = copied;
  570. }
  571. if (sockopt) {
  572. *sockopt = ms->ms_sockopt;
  573. }
  574. }
  575. sgx_reset_ustack();
  576. return retval;
  577. }
  578. int ocall_sock_recv (int sockfd, void * buf, unsigned int count,
  579. struct sockaddr * addr, unsigned int * addrlen)
  580. {
  581. int retval = 0;
  582. void * obuf = NULL;
  583. unsigned int copied;
  584. unsigned int len = addrlen ? *addrlen : 0;
  585. ms_ocall_sock_recv_t * ms;
  586. if ((count + len) > PRESET_PAGESIZE) {
  587. retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
  588. if (IS_ERR(retval))
  589. return retval;
  590. }
  591. ms = sgx_alloc_on_ustack(sizeof(*ms));
  592. if (!ms) {
  593. retval = -EPERM;
  594. goto out;
  595. }
  596. ms->ms_sockfd = sockfd;
  597. ms->ms_count = count;
  598. ms->ms_addrlen = len;
  599. ms->ms_addr = addr ? sgx_alloc_on_ustack(len) : NULL;
  600. if (obuf)
  601. ms->ms_buf = obuf;
  602. else
  603. ms->ms_buf = sgx_alloc_on_ustack(count);
  604. if (!ms->ms_buf || (addr && !ms->ms_addr)) {
  605. retval = -EPERM;
  606. goto out;
  607. }
  608. retval = sgx_ocall(OCALL_SOCK_RECV, ms);
  609. if (retval >= 0) {
  610. if (addr && len) {
  611. copied = sgx_copy_to_enclave(addr, len, ms->ms_addr, ms->ms_addrlen);
  612. if (!copied) {
  613. retval = -EPERM;
  614. goto out;
  615. }
  616. *addrlen = copied;
  617. }
  618. if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) {
  619. retval = -EPERM;
  620. goto out;
  621. }
  622. }
  623. out:
  624. sgx_reset_ustack();
  625. if (obuf)
  626. ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
  627. return retval;
  628. }
  629. int ocall_sock_send (int sockfd, const void * buf, unsigned int count,
  630. const struct sockaddr * addr, unsigned int addrlen)
  631. {
  632. int retval = 0;
  633. void * obuf = NULL;
  634. ms_ocall_sock_send_t * ms;
  635. if ((count + addrlen) > PRESET_PAGESIZE) {
  636. retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
  637. if (IS_ERR(retval))
  638. return retval;
  639. }
  640. ms = sgx_alloc_on_ustack(sizeof(*ms));
  641. if (!ms) {
  642. retval = -EPERM;
  643. goto out;
  644. }
  645. ms->ms_sockfd = sockfd;
  646. ms->ms_count = count;
  647. ms->ms_addrlen = addrlen;
  648. ms->ms_addr = addr ? sgx_copy_to_ustack(addr, addrlen) : NULL;
  649. if (obuf) {
  650. ms->ms_buf = obuf;
  651. memcpy(obuf, buf, count);
  652. } else {
  653. ms->ms_buf = sgx_copy_to_ustack(buf, count);
  654. }
  655. if (!ms->ms_buf || (addr && !ms->ms_addr)) {
  656. retval = -EPERM;
  657. goto out;
  658. }
  659. retval = sgx_ocall(OCALL_SOCK_SEND, ms);
  660. out:
  661. sgx_reset_ustack();
  662. if (obuf)
  663. ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
  664. return retval;
  665. }
  666. int ocall_sock_recv_fd (int sockfd, void * buf, unsigned int count,
  667. unsigned int * fds, unsigned int * nfds)
  668. {
  669. int retval = 0;
  670. unsigned int copied;
  671. unsigned int max_nfds_bytes = (*nfds) * sizeof(int);
  672. ms_ocall_sock_recv_fd_t * ms;
  673. ms = sgx_alloc_on_ustack(sizeof(*ms));
  674. if (!ms) {
  675. sgx_reset_ustack();
  676. return -EPERM;
  677. }
  678. ms->ms_sockfd = sockfd;
  679. ms->ms_count = count;
  680. ms->ms_nfds = *nfds;
  681. ms->ms_buf = sgx_alloc_on_ustack(count);
  682. ms->ms_fds = sgx_alloc_on_ustack(max_nfds_bytes);
  683. if (!ms->ms_buf || !ms->ms_fds) {
  684. sgx_reset_ustack();
  685. return -EPERM;
  686. }
  687. retval = sgx_ocall(OCALL_SOCK_RECV_FD, ms);
  688. if (retval >= 0) {
  689. if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) {
  690. sgx_reset_ustack();
  691. return -EPERM;
  692. }
  693. copied = sgx_copy_to_enclave(fds, max_nfds_bytes, ms->ms_fds, ms->ms_nfds * sizeof(int));
  694. if (!copied) {
  695. sgx_reset_ustack();
  696. return -EPERM;
  697. }
  698. *nfds = copied / sizeof(int);
  699. }
  700. sgx_reset_ustack();
  701. return retval;
  702. }
  703. int ocall_sock_send_fd (int sockfd, const void * buf, unsigned int count,
  704. const unsigned int * fds, unsigned int nfds)
  705. {
  706. int retval = 0;
  707. ms_ocall_sock_send_fd_t * ms;
  708. ms = sgx_alloc_on_ustack(sizeof(*ms));
  709. if (!ms) {
  710. sgx_reset_ustack();
  711. return -EPERM;
  712. }
  713. ms->ms_sockfd = sockfd;
  714. ms->ms_count = count;
  715. ms->ms_nfds = nfds;
  716. ms->ms_buf = sgx_copy_to_ustack(buf, count);
  717. ms->ms_fds = sgx_copy_to_ustack(fds, nfds * sizeof(int));
  718. if (!ms->ms_buf || !ms->ms_fds) {
  719. sgx_reset_ustack();
  720. return -EPERM;
  721. }
  722. retval = sgx_ocall(OCALL_SOCK_SEND_FD, ms);
  723. sgx_reset_ustack();
  724. return retval;
  725. }
  726. int ocall_sock_setopt (int sockfd, int level, int optname,
  727. const void * optval, unsigned int optlen)
  728. {
  729. int retval = 0;
  730. ms_ocall_sock_setopt_t * ms;
  731. ms = sgx_alloc_on_ustack(sizeof(*ms));
  732. if (!ms) {
  733. sgx_reset_ustack();
  734. return -EPERM;
  735. }
  736. ms->ms_sockfd = sockfd;
  737. ms->ms_level = level;
  738. ms->ms_optname = optname;
  739. ms->ms_optlen = 0;
  740. ms->ms_optval = NULL;
  741. if (optval && optlen > 0) {
  742. ms->ms_optlen = optlen;
  743. ms->ms_optval = sgx_copy_to_ustack(optval, optlen);
  744. if (!ms->ms_optval) {
  745. sgx_reset_ustack();
  746. return -EPERM;
  747. }
  748. }
  749. retval = sgx_ocall(OCALL_SOCK_SETOPT, ms);
  750. sgx_reset_ustack();
  751. return retval;
  752. }
  753. int ocall_sock_shutdown (int sockfd, int how)
  754. {
  755. int retval = 0;
  756. ms_ocall_sock_shutdown_t * ms;
  757. ms = sgx_alloc_on_ustack(sizeof(*ms));
  758. if (!ms) {
  759. sgx_reset_ustack();
  760. return -EPERM;
  761. }
  762. ms->ms_sockfd = sockfd;
  763. ms->ms_how = how;
  764. retval = sgx_ocall(OCALL_SOCK_SHUTDOWN, ms);
  765. sgx_reset_ustack();
  766. return retval;
  767. }
  768. int ocall_gettime (unsigned long * microsec)
  769. {
  770. int retval = 0;
  771. ms_ocall_gettime_t * ms;
  772. ms = sgx_alloc_on_ustack(sizeof(*ms));
  773. if (!ms) {
  774. sgx_reset_ustack();
  775. return -EPERM;
  776. }
  777. do {
  778. retval = sgx_ocall(OCALL_GETTIME, ms);
  779. } while(retval == -EINTR);
  780. if (!retval)
  781. *microsec = ms->ms_microsec;
  782. sgx_reset_ustack();
  783. return retval;
  784. }
  785. int ocall_sleep (unsigned long * microsec)
  786. {
  787. int retval = 0;
  788. ms_ocall_sleep_t * ms;
  789. ms = sgx_alloc_on_ustack(sizeof(*ms));
  790. if (!ms) {
  791. sgx_reset_ustack();
  792. return -EPERM;
  793. }
  794. ms->ms_microsec = microsec ? *microsec : 0;
  795. retval = sgx_ocall(OCALL_SLEEP, ms);
  796. if (microsec) {
  797. if (!retval)
  798. *microsec = 0;
  799. else if (retval == -EINTR)
  800. *microsec = ms->ms_microsec;
  801. }
  802. sgx_reset_ustack();
  803. return retval;
  804. }
  805. int ocall_poll(struct pollfd* fds, int nfds, int64_t timeout_us) {
  806. int retval = 0;
  807. unsigned int nfds_bytes = nfds * sizeof(struct pollfd);
  808. ms_ocall_poll_t * ms;
  809. ms = sgx_alloc_on_ustack(sizeof(*ms));
  810. if (!ms) {
  811. sgx_reset_ustack();
  812. return -EPERM;
  813. }
  814. ms->ms_nfds = nfds;
  815. ms->ms_timeout_us = timeout_us;
  816. ms->ms_fds = sgx_copy_to_ustack(fds, nfds_bytes);
  817. if (!ms->ms_fds) {
  818. sgx_reset_ustack();
  819. return -EPERM;
  820. }
  821. retval = sgx_ocall(OCALL_POLL, ms);
  822. if (retval >= 0) {
  823. if (!sgx_copy_to_enclave(fds, nfds_bytes, ms->ms_fds, nfds_bytes)) {
  824. sgx_reset_ustack();
  825. return -EPERM;
  826. }
  827. }
  828. sgx_reset_ustack();
  829. return retval;
  830. }
  831. int ocall_rename (const char * oldpath, const char * newpath)
  832. {
  833. int retval = 0;
  834. int oldlen = oldpath ? strlen(oldpath) + 1 : 0;
  835. int newlen = newpath ? strlen(newpath) + 1 : 0;
  836. ms_ocall_rename_t * ms;
  837. ms = sgx_alloc_on_ustack(sizeof(*ms));
  838. if (!ms) {
  839. sgx_reset_ustack();
  840. return -EPERM;
  841. }
  842. ms->ms_oldpath = sgx_copy_to_ustack(oldpath, oldlen);
  843. ms->ms_newpath = sgx_copy_to_ustack(newpath, newlen);
  844. if (!ms->ms_oldpath || !ms->ms_newpath) {
  845. sgx_reset_ustack();
  846. return -EPERM;
  847. }
  848. retval = sgx_ocall(OCALL_RENAME, ms);
  849. sgx_reset_ustack();
  850. return retval;
  851. }
  852. int ocall_delete (const char * pathname)
  853. {
  854. int retval = 0;
  855. int len = pathname ? strlen(pathname) + 1 : 0;
  856. ms_ocall_delete_t * ms;
  857. ms = sgx_alloc_on_ustack(sizeof(*ms));
  858. if (!ms) {
  859. sgx_reset_ustack();
  860. return -EPERM;
  861. }
  862. ms->ms_pathname = sgx_copy_to_ustack(pathname, len);
  863. if (!ms->ms_pathname) {
  864. sgx_reset_ustack();
  865. return -EPERM;
  866. }
  867. retval = sgx_ocall(OCALL_DELETE, ms);
  868. sgx_reset_ustack();
  869. return retval;
  870. }
  871. int ocall_load_debug(const char * command)
  872. {
  873. int retval = 0;
  874. int len = strlen(command) + 1;
  875. const char * ms = sgx_copy_to_ustack(command, len);
  876. if (!ms) {
  877. sgx_reset_ustack();
  878. return -EPERM;
  879. }
  880. retval = sgx_ocall(OCALL_LOAD_DEBUG, (void *) ms);
  881. sgx_reset_ustack();
  882. return retval;
  883. }