shim_pipe.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /* Copyright (C) 2014 Stony Brook University
  2. This file is part of Graphene Library OS.
  3. Graphene Library OS is free software: you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public License
  5. as published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. Graphene Library OS is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /*
  14. * shim_pipe.c
  15. *
  16. * Implementation of system call "pipe", "pipe2" and "socketpair".
  17. */
  18. #include <asm/fcntl.h>
  19. #include <errno.h>
  20. #include <pal.h>
  21. #include <pal_error.h>
  22. #include <shim_fs.h>
  23. #include <shim_handle.h>
  24. #include <shim_internal.h>
  25. #include <shim_table.h>
  26. #include <shim_utils.h>
  27. int create_pipes(IDTYPE* pipeid, PAL_HANDLE* srv, PAL_HANDLE* cli, struct shim_qstr* qstr,
  28. int flags) {
  29. PAL_HANDLE hdl0 = NULL, hdl1 = NULL, hdl2 = NULL;
  30. int ret = 0;
  31. char uri[PIPE_URI_SIZE];
  32. if ((ret = create_pipe(pipeid, uri, PIPE_URI_SIZE, &hdl0, qstr,
  33. /*use_vmid_for_name=*/false)) < 0) {
  34. debug("pipe creation failure\n");
  35. return ret;
  36. }
  37. if (!(hdl2 = DkStreamOpen(uri, 0, 0, 0, flags & O_NONBLOCK))) {
  38. ret = -PAL_ERRNO;
  39. debug("pipe connection failure\n");
  40. goto err;
  41. }
  42. if (!(hdl1 = DkStreamWaitForClient(hdl0))) {
  43. ret = -PAL_ERRNO;
  44. debug("pipe acception failure\n");
  45. goto err;
  46. }
  47. DkStreamDelete(hdl0, 0);
  48. DkObjectClose(hdl0);
  49. *srv = hdl1;
  50. *cli = hdl2;
  51. return 0;
  52. err:
  53. if (hdl1)
  54. DkObjectClose(hdl1);
  55. if (hdl2)
  56. DkObjectClose(hdl2);
  57. DkStreamDelete(hdl0, 0);
  58. DkObjectClose(hdl0);
  59. return ret;
  60. }
  61. int shim_do_pipe2(int* filedes, int flags) {
  62. if (!filedes || test_user_memory(filedes, 2 * sizeof(int), true))
  63. return -EFAULT;
  64. int ret = 0;
  65. struct shim_handle* hdl1 = get_new_handle();
  66. struct shim_handle* hdl2 = get_new_handle();
  67. if (!hdl1 || !hdl2) {
  68. ret = -ENOMEM;
  69. goto out;
  70. }
  71. hdl1->type = TYPE_PIPE;
  72. set_handle_fs(hdl1, &pipe_builtin_fs);
  73. hdl1->flags = O_RDONLY;
  74. hdl1->acc_mode = MAY_READ;
  75. hdl2->type = TYPE_PIPE;
  76. set_handle_fs(hdl2, &pipe_builtin_fs);
  77. hdl2->flags = O_WRONLY;
  78. hdl2->acc_mode = MAY_WRITE;
  79. if ((ret = create_pipes(&hdl1->info.pipe.pipeid, &hdl1->pal_handle, &hdl2->pal_handle,
  80. &hdl1->uri, flags)) < 0)
  81. goto out;
  82. qstrcopy(&hdl2->uri, &hdl2->uri);
  83. flags = flags & O_CLOEXEC ? FD_CLOEXEC : 0;
  84. int vfd1 = set_new_fd_handle(hdl1, flags, NULL);
  85. int vfd2 = set_new_fd_handle(hdl2, flags, NULL);
  86. if (vfd1 < 0 || vfd2 < 0) {
  87. if (vfd1 >= 0) {
  88. struct shim_handle* tmp = detach_fd_handle(vfd1, NULL, NULL);
  89. if (tmp)
  90. put_handle(tmp);
  91. }
  92. if (vfd2 >= 0) {
  93. struct shim_handle* tmp = detach_fd_handle(vfd2, NULL, NULL);
  94. if (tmp)
  95. put_handle(tmp);
  96. }
  97. goto out;
  98. }
  99. filedes[0] = vfd1;
  100. filedes[1] = vfd2;
  101. out:
  102. if (hdl1)
  103. put_handle(hdl1);
  104. if (hdl2)
  105. put_handle(hdl2);
  106. return ret;
  107. }
  108. int shim_do_pipe(int* filedes) {
  109. return shim_do_pipe2(filedes, 0);
  110. }
  111. int shim_do_socketpair(int domain, int type, int protocol, int* sv) {
  112. if (domain != AF_UNIX)
  113. return -EAFNOSUPPORT;
  114. if (type != SOCK_STREAM)
  115. return -EPROTONOSUPPORT;
  116. if (!sv || test_user_memory(sv, 2 * sizeof(int), true))
  117. return -EFAULT;
  118. int ret = 0;
  119. struct shim_handle* hdl1 = get_new_handle();
  120. struct shim_handle* hdl2 = get_new_handle();
  121. if (!hdl1 || !hdl2) {
  122. ret = -ENOMEM;
  123. goto out;
  124. }
  125. struct shim_sock_handle* sock1 = &hdl1->info.sock;
  126. struct shim_sock_handle* sock2 = &hdl2->info.sock;
  127. hdl1->type = TYPE_SOCK;
  128. set_handle_fs(hdl1, &socket_builtin_fs);
  129. hdl1->flags = O_RDONLY;
  130. hdl1->acc_mode = MAY_READ | MAY_WRITE;
  131. sock1->domain = domain;
  132. sock1->sock_type = type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
  133. sock1->protocol = protocol;
  134. sock1->sock_state = SOCK_ACCEPTED;
  135. hdl2->type = TYPE_SOCK;
  136. set_handle_fs(hdl2, &socket_builtin_fs);
  137. hdl1->flags = O_WRONLY;
  138. hdl2->acc_mode = MAY_READ | MAY_WRITE;
  139. sock2->domain = domain;
  140. sock2->sock_type = type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
  141. sock2->protocol = protocol;
  142. sock2->sock_state = SOCK_CONNECTED;
  143. if ((ret = create_pipes(&sock1->addr.un.pipeid, &hdl1->pal_handle, &hdl2->pal_handle,
  144. &hdl1->uri, type & SOCK_NONBLOCK ? O_NONBLOCK : 0)) < 0)
  145. goto out;
  146. sock2->addr.un.pipeid = sock1->addr.un.pipeid;
  147. qstrcopy(&hdl2->uri, &hdl1->uri);
  148. int flags = type & SOCK_CLOEXEC ? FD_CLOEXEC : 0;
  149. int vfd1 = set_new_fd_handle(hdl1, flags, NULL);
  150. int vfd2 = set_new_fd_handle(hdl2, flags, NULL);
  151. if (vfd1 < 0 || vfd2 < 0) {
  152. if (vfd1 >= 0) {
  153. struct shim_handle* tmp = detach_fd_handle(vfd1, NULL, NULL);
  154. if (tmp)
  155. put_handle(tmp);
  156. }
  157. if (vfd2 >= 0) {
  158. struct shim_handle* tmp = detach_fd_handle(vfd2, NULL, NULL);
  159. if (tmp)
  160. put_handle(tmp);
  161. }
  162. goto out;
  163. }
  164. sv[0] = vfd1;
  165. sv[1] = vfd2;
  166. out:
  167. if (hdl1)
  168. put_handle(hdl1);
  169. if (hdl2)
  170. put_handle(hdl2);
  171. return ret;
  172. }