shim_eventfd.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Copyright (C) 2019 Intel Corporation
  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_eventfd.c
  15. *
  16. * Implementation of system calls "eventfd" and "eventfd2". Since eventfd emulation currently relies
  17. * on the host, these system calls are disallowed by default due to security concerns. To use them,
  18. * they must be explicitly allowed through the "sys.allow_insecure_eventfd" manifest key.
  19. */
  20. #include <asm/fcntl.h>
  21. #include <sys/eventfd.h>
  22. #include <pal.h>
  23. #include <pal_error.h>
  24. #include <shim_fs.h>
  25. #include <shim_handle.h>
  26. #include <shim_internal.h>
  27. #include <shim_table.h>
  28. #include <shim_utils.h>
  29. static int create_eventfd(PAL_HANDLE* efd, unsigned count, int flags) {
  30. if (!root_config) {
  31. /* eventfd must be explicitly allowed in manifest; error out if no manifest found */
  32. return -ENOSYS;
  33. }
  34. char eventfd_cfg[2];
  35. ssize_t len =
  36. get_config(root_config, "sys.allow_insecure_eventfd", eventfd_cfg, sizeof(eventfd_cfg));
  37. if (len != 1 || eventfd_cfg[0] != '1') {
  38. /* eventfd is not explicitly allowed in manifest */
  39. return -ENOSYS;
  40. }
  41. PAL_HANDLE hdl = NULL;
  42. int pal_flags = 0;
  43. pal_flags |= flags & EFD_NONBLOCK ? PAL_OPTION_NONBLOCK : 0;
  44. pal_flags |= flags & EFD_CLOEXEC ? PAL_OPTION_CLOEXEC : 0;
  45. pal_flags |= flags & EFD_SEMAPHORE ? PAL_OPTION_EFD_SEMAPHORE : 0;
  46. /* eventfd() requires count (aka initval) but PAL's DkStreamOpen() doesn't have such an
  47. * argument. Using create arg as a work-around (note: initval is uint32 but create is int32). */
  48. if (!(hdl = DkStreamOpen(URI_PREFIX_EVENTFD, 0, 0, count, pal_flags))) {
  49. debug("eventfd open failure\n");
  50. return -PAL_ERRNO;
  51. }
  52. *efd = hdl;
  53. return 0;
  54. }
  55. int shim_do_eventfd2(unsigned int count, int flags) {
  56. int ret = 0;
  57. struct shim_handle* hdl = get_new_handle();
  58. if (!hdl) {
  59. ret = -ENOMEM;
  60. goto out;
  61. }
  62. hdl->type = TYPE_EVENTFD;
  63. set_handle_fs(hdl, &eventfd_builtin_fs);
  64. hdl->flags = O_RDWR;
  65. hdl->acc_mode = MAY_READ | MAY_WRITE;
  66. if ((ret = create_eventfd(&hdl->pal_handle, count, flags)) < 0)
  67. goto out;
  68. flags = flags & EFD_CLOEXEC ? FD_CLOEXEC : 0;
  69. /* get_new_handle() above increments hdl's refcount. Followed by another increment inside
  70. * set_new_fd_handle. So we need to put_handle() afterwards. */
  71. int vfd = set_new_fd_handle(hdl, flags, NULL);
  72. ret = vfd;
  73. out:
  74. if (hdl)
  75. put_handle(hdl);
  76. return ret;
  77. }
  78. int shim_do_eventfd(unsigned int count) {
  79. return shim_do_eventfd2(count, 0);
  80. }