db_streams.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * db_stream.c
  17. *
  18. * This file contains APIs to open, read, write and get attribute of
  19. * streams.
  20. */
  21. #include "pal_defs.h"
  22. #include "pal_linux_defs.h"
  23. #include "pal.h"
  24. #include "pal_internal.h"
  25. #include "pal_linux.h"
  26. #include "pal_debug.h"
  27. #include "pal_error.h"
  28. #include "api.h"
  29. #include <linux/types.h>
  30. typedef __kernel_pid_t pid_t;
  31. #include <linux/stat.h>
  32. #include <linux/msg.h>
  33. #include <linux/socket.h>
  34. #include <linux/wait.h>
  35. #include <asm/stat.h>
  36. #include <asm/socket.h>
  37. #include <asm/poll.h>
  38. #include <sys/signal.h>
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <asm-errno.h>
  42. void _DkPrintConsole (const void * buf, int size)
  43. {
  44. INLINE_SYSCALL(write, 3, 2, buf, size);
  45. }
  46. bool stataccess (struct stat * stat, int acc)
  47. {
  48. mode_t mode = stat->st_mode;
  49. if (pal_linux_config.uid && pal_linux_config.uid == stat->st_uid) {
  50. mode >>= 6;
  51. goto out;
  52. }
  53. if (pal_linux_config.gid && pal_linux_config.gid == stat->st_gid) {
  54. mode >>= 3;
  55. goto out;
  56. }
  57. if (!pal_linux_config.uid)
  58. mode >>= 6;
  59. out:
  60. return (mode & acc);
  61. }
  62. /* _DkStreamUnmap for internal use. Unmap stream at certain memory address.
  63. The memory is unmapped as a whole.*/
  64. int _DkStreamUnmap (void * addr, size_t size)
  65. {
  66. /* Just let the kernel tell us if the mapping isn't good. */
  67. int ret = INLINE_SYSCALL(munmap, 2, addr, size);
  68. if (IS_ERR(ret))
  69. return -PAL_ERROR_DENIED;
  70. return 0;
  71. }
  72. // Header for DkSendHandle and DkRecvHandle
  73. struct hdl_header {
  74. int type, body_size, nfds;
  75. };
  76. /* _DkSendHandle for internal use. Send a Pal Handle over the given
  77. process handle. Return 1 if success else return negative error code */
  78. int _DkSendHandle (PAL_HANDLE hdl, PAL_HANDLE cargo)
  79. {
  80. // Variables to store information for the message
  81. char * msg_buf[2] = { NULL, NULL };
  82. int msg_len[2] = { 0, 0 };
  83. int msg_nfds = 0, fds[2];
  84. struct hdl_header hdl_hdr;
  85. // ~ Check connection PAL_HANDLE - is of process type for sending handle
  86. // else fail
  87. if(__PAL_GET_TYPE(hdl) != pal_type_process)
  88. return -PAL_ERROR_BADHANDLE;
  89. // ~ Check cargo PAL_HANDLE - is allowed to be sent (White List checking
  90. // of cargo type)
  91. // ~ Also, Initialize common parameter formessage passing
  92. // Channel between parent and child
  93. switch(__PAL_GET_TYPE(cargo)) {
  94. case pal_type_file:
  95. msg_nfds = 1;
  96. fds[0] = cargo->file.fd;
  97. msg_len[0] = strlen(cargo->file.realpath) + 1;
  98. msg_buf[0] = (char *) cargo->file.realpath;
  99. break;
  100. case pal_type_pipe:
  101. case pal_type_pipesrv:
  102. case pal_type_pipecli:
  103. msg_nfds = 1;
  104. fds[0] = cargo->pipe.fd;
  105. break;
  106. case pal_type_pipeprv:
  107. msg_nfds = 2;
  108. fds[0] = cargo->pipeprv.fds[0];
  109. fds[1] = cargo->pipeprv.fds[1];
  110. break;
  111. case pal_type_dev:
  112. if (cargo->dev.fd_in != PAL_IDX_POISON)
  113. fds[msg_nfds++] = cargo->dev.fd_in;
  114. if (cargo->dev.fd_out != PAL_IDX_POISON)
  115. fds[msg_nfds++] = cargo->dev.fd_out;
  116. if (cargo->dev.realpath) {
  117. msg_len[0] = strlen(cargo->dev.realpath) + 1;
  118. msg_buf[0] = (char *) cargo->dev.realpath;
  119. }
  120. break;
  121. case pal_type_dir:
  122. msg_nfds = 1;
  123. fds[0] = cargo->dir.fd;
  124. if (cargo->dir.realpath) {
  125. msg_len[0] = strlen(cargo->dir.realpath) + 1;
  126. msg_buf[0] = (char *) cargo->dir.realpath;
  127. }
  128. break;
  129. case pal_type_tcp:
  130. case pal_type_tcpsrv:
  131. case pal_type_udp:
  132. case pal_type_udpsrv:
  133. #define addr_size(addr) \
  134. ({ int _size = 0; \
  135. switch (((struct sockaddr *) addr)->sa_family) { \
  136. case AF_INET: \
  137. _size = sizeof(struct sockaddr_in); break; \
  138. case AF_INET6: \
  139. _size = sizeof(struct sockaddr_in6); break; \
  140. default: break; \
  141. } _size; \
  142. })
  143. msg_nfds = 1;
  144. fds[0] = cargo->sock.fd;
  145. int nmsg = 0;
  146. if (cargo->sock.bind) {
  147. msg_len[nmsg] = addr_size(cargo->sock.bind);
  148. msg_buf[nmsg] = cargo->sock.bind;
  149. nmsg++;
  150. }
  151. if (cargo->sock.conn) {
  152. msg_len[nmsg] = addr_size(cargo->sock.conn);
  153. msg_buf[nmsg] = cargo->sock.conn;
  154. nmsg++;
  155. }
  156. break;
  157. case pal_type_gipc:
  158. msg_nfds = 1;
  159. fds[0] = cargo->gipc.fd;
  160. break;
  161. default:
  162. return -PAL_ERROR_INVAL;
  163. }
  164. // ~ Initialize common parameter formessage passing
  165. // Channel between parent and child
  166. int ch = hdl->process.cargo;
  167. // Initialize header information
  168. // Common information for all the PAL_HANDLEs
  169. hdl_hdr.type = __PAL_GET_TYPE(cargo);
  170. hdl_hdr.body_size = msg_len[0] + msg_len[1];
  171. hdl_hdr.nfds = msg_nfds;
  172. // Declare variables required for sending the message
  173. struct msghdr hdr; // message header
  174. struct cmsghdr * chdr; //control message header
  175. struct iovec iov[3]; // IO Vector
  176. iov[0].iov_base = &hdl_hdr;
  177. iov[0].iov_len = sizeof(struct hdl_header);
  178. hdr.msg_name = NULL;
  179. hdr.msg_namelen = 0;
  180. hdr.msg_iov = iov;
  181. hdr.msg_iovlen = 1;
  182. hdr.msg_control = NULL;
  183. hdr.msg_controllen = 0;
  184. hdr.msg_flags = 0;
  185. int ret = INLINE_SYSCALL(sendmsg, 3, ch, &hdr, MSG_NOSIGNAL);
  186. // Unlock is error
  187. if (IS_ERR(ret))
  188. return -PAL_ERROR_DENIED;
  189. /* Message Body Composition:
  190. IOVEC[0]: PAL_HANDLE
  191. IOVEC[1..n]: Additional handle member follow
  192. Control Message: file descriptors */
  193. // Control message buffer with added space for 2 fds (ie. max size
  194. // that it will have)
  195. char cbuf[sizeof(struct cmsghdr) + 2 * sizeof(int)];
  196. // Initialize iovec[0] with struct PAL_HANDLE
  197. iov[0].iov_base = cargo;
  198. iov[0].iov_len = sizeof(union pal_handle);
  199. // Initialize iovec[1] for additional element with message buffer
  200. iov[1].iov_base = msg_len[0] ? msg_buf[0] : NULL;
  201. iov[1].iov_len = msg_len[0] ? : 0;
  202. // Initialize iovec[2] for additional element with message buffer
  203. iov[2].iov_base = msg_len[1] ? msg_buf[0] : NULL;
  204. iov[2].iov_len = msg_len[1] ? : 0;
  205. hdr.msg_iov = iov;
  206. hdr.msg_iovlen = msg_len[0] ? (msg_len[1] ? 3 : 2) : 1;
  207. hdr.msg_control = cbuf; // Control Message Buffer
  208. hdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * msg_nfds;
  209. // Fill control message infomation for the file descriptors
  210. // Check hdr.msg_controllen >= sizeof(struct cmsghdr) to point to
  211. // cbuf, which is redundant based on the above code as we have
  212. // statically allocated memory.
  213. // or (struct cmsghdr*) cbuf
  214. chdr = CMSG_FIRSTHDR(&hdr); // Pointer to msg_control
  215. chdr->cmsg_level = SOL_SOCKET; // Originating Protocol
  216. chdr->cmsg_type = SCM_RIGHTS; // Protocol Specific Type
  217. // Length of control message = sizeof(struct cmsghdr) + nfds
  218. chdr->cmsg_len = CMSG_LEN(sizeof(int) * msg_nfds);
  219. // Copy the fds below control header
  220. memcpy(CMSG_DATA(chdr), fds, sizeof(int) * msg_nfds);
  221. // Also, Update main header with control message length (duplicate)
  222. hdr.msg_controllen = chdr->cmsg_len;
  223. // Send message
  224. ret = INLINE_SYSCALL(sendmsg, 3, ch, &hdr, 0);
  225. return IS_ERR(ret) ? -PAL_ERROR_DENIED : 0;
  226. }
  227. /* _DkRecvHandle for internal use. Receive and return a PAL_HANDLE over the
  228. given PAL_HANDLE else return negative value. */
  229. int _DkReceiveHandle(PAL_HANDLE hdl, PAL_HANDLE cargo)
  230. {
  231. struct hdl_header hdl_hdr;
  232. // ~ Check connection PAL_HANDLE - is of process type for sending handle
  233. // else fail
  234. if (__PAL_GET_TYPE(hdl) != pal_type_process)
  235. return -PAL_ERROR_BADHANDLE;
  236. // ~ Initialize common parameter for message passing
  237. // Channel between parent and child
  238. int ch = hdl->process.cargo;
  239. struct msghdr hdr;
  240. struct iovec iov[2];
  241. iov[0].iov_base = &hdl_hdr;
  242. iov[0].iov_len = sizeof(struct hdl_header);
  243. hdr.msg_name = NULL;
  244. hdr.msg_namelen = 0;
  245. hdr.msg_iov = iov;
  246. hdr.msg_iovlen = 1;
  247. hdr.msg_control = NULL;
  248. hdr.msg_controllen = 0;
  249. hdr.msg_flags = 0;
  250. int ret = INLINE_SYSCALL(recvmsg, 3, ch, &hdr, 0);
  251. if (IS_ERR(ret) || ret < sizeof(struct hdl_header)) {
  252. if (!IS_ERR(ret))
  253. return -PAL_ERROR_TRYAGAIN;
  254. if (ERRNO(ret) != EINTR && ERRNO(ret) != ERESTART)
  255. return -ERRNO(ret);
  256. }
  257. // initialize variables to get body
  258. int msg_len = hdl_hdr.body_size, msg_nfds = hdl_hdr.nfds;
  259. void * msg_buf = msg_len ? malloc(msg_len) : NULL;
  260. // make in stack
  261. int * fds = __alloca(sizeof(int) * msg_nfds);
  262. // receive PAL_HANDLE contents in the body
  263. char cbuf[sizeof(struct cmsghdr) + 2 * sizeof(int)];
  264. // initialize iovec[0] with struct PAL_HANDLE
  265. iov[0].iov_base = cargo;
  266. iov[0].iov_len = sizeof(union pal_handle);
  267. // initialize iovec[1] for additional element with message buffer
  268. iov[1].iov_base = msg_buf;
  269. iov[1].iov_len = msg_len;
  270. // clear body memory
  271. memset(&hdr, 0, sizeof(struct msghdr));
  272. // set message header values
  273. hdr.msg_iov = iov;
  274. hdr.msg_iovlen = msg_len ? 2 : 1;
  275. hdr.msg_control = cbuf;
  276. hdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) *
  277. msg_nfds;
  278. ret = INLINE_SYSCALL(recvmsg, 3, ch, &hdr, 0);
  279. if (!IS_ERR(ret)) {
  280. struct cmsghdr * chdr = CMSG_FIRSTHDR(&hdr);
  281. if (chdr &&
  282. chdr->cmsg_type == SCM_RIGHTS) {
  283. msg_nfds = (hdr.msg_controllen - sizeof(struct cmsghdr)) /
  284. sizeof(int);
  285. memcpy(fds, CMSG_DATA(chdr), sizeof(int) * msg_nfds);
  286. } else {
  287. msg_nfds = 0;
  288. }
  289. }
  290. // if error was returned
  291. if (IS_ERR(ret) && ERRNO(ret) != EINTR && ERRNO(ret) != ERESTART)
  292. return -ERRNO(ret);
  293. // recreate PAL_HANDLE based on type
  294. switch(hdl_hdr.type) {
  295. case pal_type_file: {
  296. if (msg_nfds < 1)
  297. return -PAL_ERROR_BADHANDLE;
  298. cargo->file.fd = fds[0];
  299. cargo->file.realpath = remalloc(msg_buf, msg_len);
  300. break;
  301. }
  302. case pal_type_pipe:
  303. case pal_type_pipesrv:
  304. case pal_type_pipecli:
  305. if (msg_nfds < 1)
  306. return -PAL_ERROR_BADHANDLE;
  307. cargo->pipe.fd = fds[0];
  308. break;
  309. case pal_type_pipeprv:
  310. if (msg_nfds < 2)
  311. return -PAL_ERROR_BADHANDLE;
  312. cargo->pipeprv.fds[0] = fds[0];
  313. cargo->pipeprv.fds[1] = fds[1];
  314. break;
  315. case pal_type_dev: {
  316. int i = 0;
  317. if (cargo->dev.fd_in != PAL_IDX_POISON) {
  318. if (msg_nfds < 1)
  319. return -PAL_ERROR_BADHANDLE;
  320. cargo->dev.fd_in = fds[i++];
  321. msg_nfds--;
  322. }
  323. if (cargo->dev.fd_out != PAL_IDX_POISON) {
  324. if (msg_nfds < 1)
  325. return -PAL_ERROR_BADHANDLE;
  326. cargo->dev.fd_out = fds[i++];
  327. msg_nfds--;
  328. }
  329. cargo->file.realpath = remalloc(msg_buf, msg_len);;
  330. break;
  331. }
  332. case pal_type_dir: {
  333. if (msg_nfds < 1)
  334. return -PAL_ERROR_BADHANDLE;
  335. cargo->dir.fd = fds[0];
  336. cargo->dir.realpath = remalloc(msg_buf, msg_len);
  337. break;
  338. }
  339. case pal_type_tcp:
  340. case pal_type_tcpsrv:
  341. case pal_type_udp: {
  342. void * addr = msg_buf;
  343. if (cargo->sock.bind) {
  344. int len = addr_size(addr);
  345. if (addr + len > msg_buf + msg_len)
  346. return -PAL_ERROR_OVERFLOW;
  347. cargo->sock.bind = remalloc(addr, len);
  348. addr += len;
  349. }
  350. if (cargo->sock.conn) {
  351. int len = addr_size(addr);
  352. if (addr + len > msg_buf + msg_len)
  353. return -PAL_ERROR_OVERFLOW;
  354. cargo->sock.conn = remalloc(addr, len);
  355. addr += len;
  356. }
  357. }
  358. case pal_type_udpsrv:
  359. if (msg_nfds < 1)
  360. return -PAL_ERROR_BADHANDLE;
  361. cargo->sock.fd = fds[0];
  362. break;
  363. case pal_type_gipc:
  364. if (msg_nfds < 1)
  365. return -PAL_ERROR_BADHANDLE;
  366. cargo->gipc.fd = fds[0];
  367. break;
  368. default :
  369. return -PAL_ERROR_BADHANDLE;
  370. }
  371. return 0;
  372. }