Add helper functions to do synchronous I/O to a nfsd filesystem pseudofile from inside the chrooted environment. This ensures that calls to kern_path() in knfsd resolves to paths that are relative to the nfsd root directory. Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> --- support/include/nfsd_path.h | 3 ++ support/misc/nfsd_path.c | 84 +++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h index db9b41a179ad..f4a7f0a4337f 100644 --- a/support/include/nfsd_path.h +++ b/support/include/nfsd_path.h @@ -13,4 +13,7 @@ char * nfsd_path_prepend_dir(const char *dir, const char *pathname); int nfsd_path_stat(const char *pathname, struct stat *statbuf); int nfsd_path_lstat(const char *pathname, struct stat *statbuf); +ssize_t nfsd_path_read(int fd, char *buf, size_t len); +ssize_t nfsd_path_write(int fd, const char *buf, size_t len); + #endif diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c index fe2c011b1521..55bca9bdf4bd 100644 --- a/support/misc/nfsd_path.c +++ b/support/misc/nfsd_path.c @@ -166,3 +166,87 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf) return xlstat(pathname, statbuf); return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf); } + +struct nfsd_read_data { + int fd; + char *buf; + size_t len; + ssize_t ret; + int err; +}; + +static void +nfsd_readfunc(void *data) +{ + struct nfsd_read_data *d = data; + + d->ret = read(d->fd, d->buf, d->len); + if (d->ret < 0) + d->err = errno; +} + +static ssize_t +nfsd_run_read(struct xthread_workqueue *wq, int fd, char *buf, size_t len) +{ + struct nfsd_read_data data = { + fd, + buf, + len, + 0, + 0 + }; + xthread_work_run_sync(wq, nfsd_readfunc, &data); + if (data.ret < 0) + errno = data.err; + return data.ret; +} + +ssize_t +nfsd_path_read(int fd, char *buf, size_t len) +{ + if (!nfsd_wq) + return read(fd, buf, len); + return nfsd_run_read(nfsd_wq, fd, buf, len); +} + +struct nfsd_write_data { + int fd; + const char *buf; + size_t len; + ssize_t ret; + int err; +}; + +static void +nfsd_writefunc(void *data) +{ + struct nfsd_write_data *d = data; + + d->ret = write(d->fd, d->buf, d->len); + if (d->ret < 0) + d->err = errno; +} + +static ssize_t +nfsd_run_write(struct xthread_workqueue *wq, int fd, const char *buf, size_t len) +{ + struct nfsd_write_data data = { + fd, + buf, + len, + 0, + 0 + }; + xthread_work_run_sync(wq, nfsd_writefunc, &data); + if (data.ret < 0) + errno = data.err; + return data.ret; +} + +ssize_t +nfsd_path_write(int fd, const char *buf, size_t len) +{ + if (!nfsd_wq) + return write(fd, buf, len); + return nfsd_run_write(nfsd_wq, fd, buf, len); +} -- 2.21.0