From c9b823f82528777de5b1cf00c65f5291e99929bf Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sun, 10 Jan 2016 19:44:29 +0200 Subject: [PATCH] lkl tools: check if host calls are initialized The host calls may not be initialized from the constructor calls if another constructor calls one of the hooked functions. Manually check for that to avoid this issue. Reported-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/lib/hijack/hijack.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/lkl/lib/hijack/hijack.c b/tools/lkl/lib/hijack/hijack.c index 6884134422dec9..ca3951d5d85189 100644 --- a/tools/lkl/lib/hijack/hijack.c +++ b/tools/lkl/lib/hijack/hijack.c @@ -68,6 +68,8 @@ static host_call host_calls[__lkl__NR_syscalls]; { \ long p[6] = {p1, p2, p3, p4, p5, p6 }; \ \ + if (!host_calls[__lkl__NR_##name]) \ + host_calls[__lkl__NR_##name] = resolve_sym(#name); \ if (!is_lklfd(p1)) \ return host_calls[__lkl__NR_##name](p1, p2, p3, \ p4, p5, p6); \ @@ -96,6 +98,9 @@ static host_call host_calls[__lkl__NR_syscalls]; asm(".global " #name); \ asm(".set " #name "," #name "_hook"); \ +#define CHECK_HOST_CALL(name) \ + if (!host_##name) \ + host_##name = resolve_sym(#name) static int lkl_call(int nr, int args, ...) { @@ -136,6 +141,7 @@ HOST_CALL(setsockopt); int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { + CHECK_HOST_CALL(setsockopt); if (!is_lklfd(fd)) return host_setsockopt(fd, level, optname, optval, optlen); return lkl_call(__lkl__NR_setsockopt, 5, fd, lkl_solevel_xlate(level), @@ -145,6 +151,7 @@ int setsockopt(int fd, int level, int optname, const void *optval, HOST_CALL(getsockopt); int getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) { + CHECK_HOST_CALL(getsockopt); if (!is_lklfd(fd)) return host_setsockopt(fd, level, optname, optval, optlen); return lkl_call(__lkl__NR_getsockopt, 5, fd, lkl_solevel_xlate(level), @@ -154,6 +161,7 @@ int getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) HOST_CALL(socket); int socket(int domain, int type, int protocol) { + CHECK_HOST_CALL(socket); if (domain == AF_UNIX) return host_socket(domain, type, protocol); @@ -170,6 +178,8 @@ int ioctl(int fd, unsigned long req, ...) arg = va_arg(vl, long); va_end(vl); + CHECK_HOST_CALL(ioctl); + if (!is_lklfd(fd)) return host_ioctl(fd, req, arg); return lkl_call(__lkl__NR_fcntl, 3, fd, lkl_ioctl_req_xlate(req), arg); @@ -186,6 +196,8 @@ int fcntl(int fd, int cmd, ...) arg = va_arg(vl, long); va_end(vl); + CHECK_HOST_CALL(fcntl); + if (!is_lklfd(fd)) return host_fcntl(fd, cmd, arg); return lkl_call(__lkl__NR_fcntl, 3, fd, lkl_fcntl_cmd_xlate(cmd), arg); @@ -196,6 +208,8 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) { unsigned int i, lklfds = 0, hostfds = 0; + CHECK_HOST_CALL(poll); + for (i = 0; i < nfds; i++) { if (is_lklfd(fds[i].fd)) lklfds = 1; @@ -221,6 +235,8 @@ int select(int nfds, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) { int fd, hostfds = 0, lklfds = 0; + CHECK_HOST_CALL(select); + for (fd = 0; fd < nfds; fd++) { if (r != 0 && FD_ISSET(fd, r)) { if (is_lklfd(fd)) @@ -257,10 +273,11 @@ HOOK_CALL(epoll_create) HOST_CALL(epoll_ctl); int epoll_ctl(int epollfd, int op, int fd, struct epoll_event *event) { + CHECK_HOST_CALL(epoll_ctl); + if (is_lklfd(epollfd) != is_lklfd(fd)) return lkl_set_errno(LKL_EOPNOTSUPP); - if (!is_lklfd(epollfd)) return host_epoll_ctl(epollfd, op, fd, event);