Add helper functions to do synchronous I/O to a file from inside the chrooted environment. This ensures that calls to kern_path() in the kernel resolves to paths that are relative to the nfsd root directory. Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> --- support/include/workqueue.h | 4 ++ support/misc/workqueue.c | 78 +++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/support/include/workqueue.h b/support/include/workqueue.h index 518be82f1b34..21b1ee6bc873 100644 --- a/support/include/workqueue.h +++ b/support/include/workqueue.h @@ -15,4 +15,8 @@ void xthread_work_run_sync(struct xthread_workqueue *wq, void xthread_workqueue_chroot(struct xthread_workqueue *wq, const char *path); +ssize_t xthread_read(struct xthread_workqueue *wq, + int fd, char *buf, size_t len); +ssize_t xthread_write(struct xthread_workqueue *wq, + int fd, const char *buf, size_t len); #endif diff --git a/support/misc/workqueue.c b/support/misc/workqueue.c index b8d03446f2c7..9d967cef6547 100644 --- a/support/misc/workqueue.c +++ b/support/misc/workqueue.c @@ -1,3 +1,4 @@ +#include <errno.h> #include <stdlib.h> #include <unistd.h> @@ -197,6 +198,72 @@ void xthread_workqueue_chroot(struct xthread_workqueue *wq, xthread_work_run_sync(wq, xthread_workqueue_do_chroot, (void *)path); } +struct xthread_read_data { + int fd; + char *buf; + size_t len; + ssize_t ret; + int err; +}; + +static void xthread_readfunc(void *data) +{ + struct xthread_read_data *d = data; + + d->ret = read(d->fd, d->buf, d->len); + if (d->ret < 0) + d->err = errno; +} + +ssize_t xthread_read(struct xthread_workqueue *wq, + int fd, char *buf, size_t len) +{ + struct xthread_read_data data = { + fd, + buf, + len, + 0, + 0 + }; + xthread_work_run_sync(wq, xthread_readfunc, &data); + if (data.ret < 0) + errno = data.err; + return data.ret; +} + +struct xthread_write_data { + int fd; + const char *buf; + size_t len; + ssize_t ret; + int err; +}; + +static void xthread_writefunc(void *data) +{ + struct xthread_write_data *d = data; + + d->ret = write(d->fd, d->buf, d->len); + if (d->ret < 0) + d->err = errno; +} + +ssize_t xthread_write(struct xthread_workqueue *wq, + int fd, const char *buf, size_t len) +{ + struct xthread_write_data data = { + fd, + buf, + len, + 0, + 0 + }; + xthread_work_run_sync(wq, xthread_writefunc, &data); + if (data.ret < 0) + errno = data.err; + return data.ret; +} + #else struct xthread_workqueue { @@ -225,4 +292,15 @@ void xthread_workqueue_chroot(struct xthread_workqueue *wq, xlog_err("Unable to run as chroot"); } +ssize_t xthread_read(struct xthread_workqueue *wq, + int fd, char *buf, size_t len) +{ + return read(fd, buf, len); +} + +ssize_t xthread_write(struct xthread_workqueue *wq, + int fd, const char *buf, size_t len) +{ + return write(fd, buf, len); +} #endif /* defined(HAVE_SCHED_H) && defined(HAVE_LIBPTHREAD) && defined(HAVE_UNSHARE) */ -- 2.21.0