Skip to content

Commit

Permalink
Merge pull request ssrg-vt#2 from tv-deusen/dup2
Browse files Browse the repository at this point in the history
dup2 implementation
  • Loading branch information
olivierpierre authored Oct 23, 2019
2 parents 5aa546e + d28c588 commit a92c859
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 1 deletion.
8 changes: 8 additions & 0 deletions arch/x86/kernel/isrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,14 @@ void syscall_handler(struct state *s)
break;
#endif /* DISABLE_SYS_MADVISE */

#ifndef DISABLE_SYS_DUP2
case 33:
/* dup2 */
s->rax = sys_dup2(s->rdi, s->rsi);
break;
#endif /* DISABLE_SYS_DUP2 */


#ifndef DISABLE_SYS_NANOSLEEP
case 35:
/* nanosleep */
Expand Down
7 changes: 7 additions & 0 deletions include/hermit/minifs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,12 @@ int minifs_write(int fd, const void *buf, size_t count);
uint64_t minifs_lseek(int fd, uint64_t offset, int whence);
int minifs_mkdir(const char *pathname, mode_t mode);
int minifs_rmdir(const char *pathname);
/**
* MiniFS implementation of dup2.
* Attempts to follow Linux convention of
* error handling with regards to
* bad file descriptors.
*/
int minifs_dup2(int oldfd, int newfd);

#endif /* MINI_FS_H */
1 change: 1 addition & 0 deletions include/hermit/stddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ extern uint64_t tux_start_address;
#define UHYVE_PORT_FDATASYNC 0x527
#define UHYVE_PORT_SYNCFS 0x528
#define UHYVE_PORT_GETDENTS 0x529
#define UHYVE_PORT_DUP2 0x530

// Networkports
#define UHYVE_PORT_NETINFO 0x505
Expand Down
1 change: 1 addition & 0 deletions include/hermit/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ int sys_syncfs(int fd);
long sys_set_tid_address(int *tidptr);
int sys_getdents(unsigned int fd, struct linux_dirent *dirp,
unsigned int count);
int sys_dup2(int oldfd, int newfd);

struct ucontext;
typedef struct ucontext ucontext_t;
Expand Down
19 changes: 19 additions & 0 deletions kernel/minifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#define SEEK_CUR 1
#define SEEK_END 2

#define IS_OPEN(fd) (fds && (fds[fd].f != NULL))

typedef struct s_file {
char *name;
uint64_t size;
Expand Down Expand Up @@ -262,6 +264,23 @@ int meminfo_read(int fd, void *buf, uint64_t len) {
return len;
}

int minifs_dup2(int oldfd, int newfd) {

if (!IS_OPEN(oldfd) || newfd > MAX_FDS) {
return -EBADF;
}

if (IS_OPEN(newfd) && !minifs_close(newfd)) {
LOG_ERROR("minifs_dup2: failed to close open file with fd: %d\n",
newfd);
return -1;
}

fds[newfd].f = fds[oldfd].f;
fds[newfd].offset = fds[oldfd].offset;

return 0;
}

int meminfo_write(int fd, const void *buf, uint64_t len) {
return len;
Expand Down
41 changes: 41 additions & 0 deletions kernel/syscalls/dup2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <hermit/syscall.h>
#include <hermit/logging.h>
#include <hermit/errno.h>
#include <asm/uhyve.h>
#include <asm/page.h>
#include <hermit/minifs.h>

extern int hermit_dup2(int oldfd, int newfd);

typedef struct {
int oldfd;
int newfd;
int ret;
} __attribute__ ((packed)) uhyve_dup2_t;


int sys_dup2(int oldfd, int newfd)
{
if (unlikely(newfd == oldfd))
return newfd;

#ifndef NO_NET
if ((oldfd & LWIP_FD_BIT) || (newfd & LWIP_FD_BIT)) {
LOG_ERROR("dup2: sockets not supported\n");
return -ENOSYS;
}
#endif

if (likely(is_uhyve())) {

if (minifs_enabled)
return minifs_dup2(oldfd, newfd);

uhyve_dup2_t uhyve_args = {oldfd, newfd, -1};
uhyve_send(UHYVE_PORT_DUP2, (unsigned)virt_to_phys((size_t)&uhyve_args));
return uhyve_args.ret;
}

LOG_ERROR("dup2: not supported with qemu isle\n");
return -ENOSYS;
}
2 changes: 2 additions & 0 deletions kernel/syscalls/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ int sys_fcntl(int fd, unsigned int cmd, unsigned long arg) {
}

switch(cmd) {
case F_GETFL:
case F_GETFD:
case F_SETFD:
u_arg.fd = fd;
u_arg.cmd = cmd;
Expand Down
9 changes: 8 additions & 1 deletion tools/uhyve-syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ typedef enum {
UHYVE_PORT_FSYNC = 0x526,
UHYVE_PORT_FDATASYNC = 0x527,
UHYVE_PORT_SYNCFS = 0x528,
UHYVE_PORT_GETDENTS = 0x529
UHYVE_PORT_GETDENTS = 0x529,
UHYVE_PORT_DUP2 = 0X530
} uhyve_syscall_t;

typedef struct {
Expand Down Expand Up @@ -195,4 +196,10 @@ typedef struct {
int ret;
} __attribute__((packed)) uhyve_getdeents_t;

typedef struct {
int oldfd;
int newfd;
int ret;
} __attribute__ ((packed)) uhyve_dup2_t;

#endif // UHYVE_SYSCALLS_H
8 changes: 8 additions & 0 deletions tools/uhyve.c
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,14 @@ static int vcpu_loop(void)
break;
}

case UHYVE_PORT_DUP2: {
unsigned data = *((unsigned*)((size_t)run+run->io.data_offset));
uhyve_dup2_t *arg = (uhyve_dup2_t *)(guest_mem + data);

arg->ret = dup2(arg->oldfd, arg->newfd);
break;
}


default:
err(1, "KVM: unhandled KVM_EXIT_IO at port 0x%x, direction %d\n", run->io.port, run->io.direction);
Expand Down

0 comments on commit a92c859

Please sign in to comment.