/* Copyright (C) 2019 Intel Corporation
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
/*
* shim_eventfd.c
*
* Implementation of system calls "eventfd" and "eventfd2". Since eventfd emulation currently relies
* on the host, these system calls are disallowed by default due to security concerns. To use them,
* they must be explicitly allowed through the "sys.allow_insecure_eventfd" manifest key.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int create_eventfd(PAL_HANDLE* efd, unsigned count, int flags) {
if (!root_config) {
/* eventfd must be explicitly allowed in manifest; error out if no manifest found */
return -ENOSYS;
}
char eventfd_cfg[2];
ssize_t len =
get_config(root_config, "sys.allow_insecure_eventfd", eventfd_cfg, sizeof(eventfd_cfg));
if (len != 1 || eventfd_cfg[0] != '1') {
/* eventfd is not explicitly allowed in manifest */
return -ENOSYS;
}
PAL_HANDLE hdl = NULL;
int pal_flags = 0;
pal_flags |= flags & EFD_NONBLOCK ? PAL_OPTION_NONBLOCK : 0;
pal_flags |= flags & EFD_CLOEXEC ? PAL_OPTION_CLOEXEC : 0;
pal_flags |= flags & EFD_SEMAPHORE ? PAL_OPTION_EFD_SEMAPHORE : 0;
/* eventfd() requires count (aka initval) but PAL's DkStreamOpen() doesn't have such an
* argument. Using create arg as a work-around (note: initval is uint32 but create is int32). */
if (!(hdl = DkStreamOpen(URI_PREFIX_EVENTFD, 0, 0, count, pal_flags))) {
debug("eventfd open failure\n");
return -PAL_ERRNO;
}
*efd = hdl;
return 0;
}
int shim_do_eventfd2(unsigned int count, int flags) {
int ret = 0;
struct shim_handle* hdl = get_new_handle();
if (!hdl) {
ret = -ENOMEM;
goto out;
}
hdl->type = TYPE_EVENTFD;
set_handle_fs(hdl, &eventfd_builtin_fs);
hdl->flags = O_RDWR;
hdl->acc_mode = MAY_READ | MAY_WRITE;
if ((ret = create_eventfd(&hdl->pal_handle, count, flags)) < 0)
goto out;
flags = flags & EFD_CLOEXEC ? FD_CLOEXEC : 0;
/* get_new_handle() above increments hdl's refcount. Followed by another increment inside
* set_new_fd_handle. So we need to put_handle() afterwards. */
int vfd = set_new_fd_handle(hdl, flags, NULL);
ret = vfd;
out:
if (hdl)
put_handle(hdl);
return ret;
}
int shim_do_eventfd(unsigned int count) {
return shim_do_eventfd2(count, 0);
}