897 lines
28 KiB
Diff
897 lines
28 KiB
Diff
From 2052c2d81abe204e557b7b7d15be623caf26d7f7 Mon Sep 17 00:00:00 2001
|
|
From: yangxin <245051644@qq.com>
|
|
Date: Fri, 10 Feb 2023 16:37:27 +0800
|
|
Subject: [PATCH 1/5] Add whitelist of qtfs.
|
|
|
|
Signed-off-by: yangxin <245051644@qq.com>
|
|
---
|
|
qtfs/comm.h | 31 ++++
|
|
qtfs/misc.c | 2 -
|
|
qtfs/qtfs/Makefile | 2 +-
|
|
qtfs/qtfs/qtfs-mod.h | 1 -
|
|
qtfs/qtfs/sb.c | 17 +-
|
|
qtfs/qtfs/syscall.c | 3 +-
|
|
qtfs/qtfs_server/Makefile | 4 +-
|
|
qtfs/qtfs_server/fsops.c | 145 ++++++++++++++----
|
|
qtfs/qtfs_server/qtfs-server.c | 35 ++++-
|
|
qtfs/qtfs_server/qtfs-server.h | 1 +
|
|
qtfs/qtfs_server/user_engine.c | 51 +++++-
|
|
qtfs/req.h | 36 ++---
|
|
.../whitelist/libvirt/qtfs_whitelist | 35 +++++
|
|
13 files changed, 286 insertions(+), 77 deletions(-)
|
|
create mode 100644 usecases/transparent-offload/whitelist/libvirt/qtfs_whitelist
|
|
|
|
diff --git a/qtfs/comm.h b/qtfs/comm.h
|
|
index d639c19..901552c 100644
|
|
--- a/qtfs/comm.h
|
|
+++ b/qtfs/comm.h
|
|
@@ -13,6 +13,7 @@ enum {
|
|
_QTFS_IOCTL_EXIT,
|
|
|
|
_QTFS_IOCTL_ALLINFO,
|
|
+ _QTFS_IOCTL_WHITELIST,
|
|
_QTFS_IOCTL_CLEARALL,
|
|
|
|
_QTFS_IOCTL_LOG_LEVEL,
|
|
@@ -26,6 +27,7 @@ enum {
|
|
#define QTFS_IOCTL_EPOLL_THREAD_RUN _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_EPOLL_THREAD_RUN)
|
|
#define QTFS_IOCTL_EXIT _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_EXIT)
|
|
#define QTFS_IOCTL_ALLINFO _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_ALLINFO)
|
|
+#define QTFS_IOCTL_WHITELIST _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_WHITELIST)
|
|
#define QTFS_IOCTL_CLEARALL _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_CLEARALL)
|
|
#define QTFS_IOCTL_LOGLEVEL _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_LOG_LEVEL)
|
|
#define QTFS_IOCTL_EPOLL_SUPPORT _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_EPOLL_SUPPORT)
|
|
@@ -42,6 +44,35 @@ struct qtfs_server_userp_s {
|
|
void *userp2;
|
|
};
|
|
|
|
+
|
|
+enum {
|
|
+ QTFS_WHITELIST_OPEN,
|
|
+ QTFS_WHITELIST_WRITE,
|
|
+ QTFS_WHITELIST_READ,
|
|
+ QTFS_WHITELIST_READDIR,
|
|
+ QTFS_WHITELIST_MKDIR,
|
|
+ QTFS_WHITELIST_RMDIR,
|
|
+ QTFS_WHITELIST_CREATE,
|
|
+ QTFS_WHITELIST_UNLINK,
|
|
+ QTFS_WHITELIST_RENAME,
|
|
+ QTFS_WHITELIST_SETATTR,
|
|
+ QTFS_WHITELIST_SETXATTR,
|
|
+ QTFS_WHITELIST_MOUNT,
|
|
+ QTFS_WHITELIST_MAX,
|
|
+};
|
|
+
|
|
+
|
|
+struct wl_item {
|
|
+ int len;
|
|
+ char path[4096];
|
|
+};
|
|
+
|
|
+struct whitelist {
|
|
+ int len;
|
|
+ int type;
|
|
+ struct wl_item wl[0];
|
|
+};
|
|
+
|
|
struct qtfs_thread_init_s {
|
|
int thread_nums;
|
|
struct qtfs_server_userp_s *userp;
|
|
diff --git a/qtfs/misc.c b/qtfs/misc.c
|
|
index 90c8d36..98222bd 100644
|
|
--- a/qtfs/misc.c
|
|
+++ b/qtfs/misc.c
|
|
@@ -61,7 +61,6 @@ void qtfs_req_size(void)
|
|
qtfs_diag_info->req_size[QTFS_REQ_MOUNT] = sizeof(struct qtreq_mount);
|
|
qtfs_diag_info->req_size[QTFS_REQ_OPEN] = sizeof(struct qtreq_open);
|
|
qtfs_diag_info->req_size[QTFS_REQ_CLOSE] = sizeof(struct qtreq_close);
|
|
- qtfs_diag_info->req_size[QTFS_REQ_READ] = sizeof(struct qtreq_read);
|
|
qtfs_diag_info->req_size[QTFS_REQ_READITER] = sizeof(struct qtreq_readiter);
|
|
qtfs_diag_info->req_size[QTFS_REQ_WRITE] = sizeof(struct qtreq_write);
|
|
qtfs_diag_info->req_size[QTFS_REQ_LOOKUP] = sizeof(struct qtreq_lookup);
|
|
@@ -92,7 +91,6 @@ void qtfs_req_size(void)
|
|
qtfs_diag_info->rsp_size[QTFS_REQ_MOUNT] = sizeof(struct qtrsp_mount);
|
|
qtfs_diag_info->rsp_size[QTFS_REQ_OPEN] = sizeof(struct qtrsp_open);
|
|
qtfs_diag_info->rsp_size[QTFS_REQ_CLOSE] = sizeof(struct qtrsp_close);
|
|
- qtfs_diag_info->rsp_size[QTFS_REQ_READ] = sizeof(struct qtrsp_read);
|
|
qtfs_diag_info->rsp_size[QTFS_REQ_READITER] = sizeof(struct qtrsp_readiter);
|
|
qtfs_diag_info->rsp_size[QTFS_REQ_WRITE] = sizeof(struct qtrsp_write);
|
|
qtfs_diag_info->rsp_size[QTFS_REQ_LOOKUP] = sizeof(struct qtrsp_lookup);
|
|
diff --git a/qtfs/qtfs/Makefile b/qtfs/qtfs/Makefile
|
|
index f3c6014..f03ec52 100644
|
|
--- a/qtfs/qtfs/Makefile
|
|
+++ b/qtfs/qtfs/Makefile
|
|
@@ -11,4 +11,4 @@ qtfs:
|
|
|
|
clean:
|
|
make -C $(KBUILD) M=$(PWD) clean
|
|
- rm -rf ../*.o
|
|
+ rm -rf ../*.o ../.*.o.cmd
|
|
diff --git a/qtfs/qtfs/qtfs-mod.h b/qtfs/qtfs/qtfs-mod.h
|
|
index 5a30868..6ba7a4d 100644
|
|
--- a/qtfs/qtfs/qtfs-mod.h
|
|
+++ b/qtfs/qtfs/qtfs-mod.h
|
|
@@ -35,7 +35,6 @@ extern struct kmem_cache *qtfs_inode_priv_cache;
|
|
|
|
struct private_data {
|
|
int fd;
|
|
- unsigned long long file;
|
|
};
|
|
|
|
struct qtfs_inode_priv {
|
|
diff --git a/qtfs/qtfs/sb.c b/qtfs/qtfs/sb.c
|
|
index 06ce402..9374cfb 100644
|
|
--- a/qtfs/qtfs/sb.c
|
|
+++ b/qtfs/qtfs/sb.c
|
|
@@ -196,7 +196,6 @@ int qtfs_open(struct inode *inode, struct file *file)
|
|
return err;
|
|
}
|
|
qtfs_info("qtfs open:%s success, f_mode:%o flag:%x, fd:%d", req->path, file->f_mode, file->f_flags, rsp->fd);
|
|
- data->file = rsp->file;
|
|
data->fd = rsp->fd;
|
|
WARN_ON(file->private_data);
|
|
file->private_data = data;
|
|
@@ -287,9 +286,9 @@ ssize_t qtfs_readiter(struct kiocb *kio, struct iov_iter *iov)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- req->file = private->file;
|
|
- if (req->file <= 0) {
|
|
- qtfs_err("qtfs_readiter: invalid file(0x%llx)", req->file);
|
|
+ req->fd = private->fd;
|
|
+ if (req->fd <= 0) {
|
|
+ qtfs_err("qtfs_readiter: invalid file(0x%llx)", req->fd);
|
|
qtfs_conn_put_param(pvar);
|
|
return -EINVAL;
|
|
}
|
|
@@ -359,9 +358,9 @@ ssize_t qtfs_writeiter(struct kiocb *kio, struct iov_iter *iov)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- req->d.file = private->file;
|
|
- if (req->d.file < 0) {
|
|
- qtfs_err("qtfs_write: invalid file(0x%llx)", req->d.file);
|
|
+ req->d.fd = private->fd;
|
|
+ if (req->d.fd < 0) {
|
|
+ qtfs_err("qtfs_write: invalid file(0x%llx)", req->d.fd);
|
|
qtfs_conn_put_param(pvar);
|
|
return -EINVAL;
|
|
}
|
|
@@ -617,7 +616,7 @@ qtfsfifo_poll(struct file *filp, poll_table *wait)
|
|
|
|
p = &priv->readq.head;
|
|
|
|
- if (IS_ERR((void *)fpriv->file) || (void *)fpriv->file == NULL) {
|
|
+ if (fpriv->fd < 0) {
|
|
qtfs_err("fifo poll priv file invalid.");
|
|
return 0;
|
|
}
|
|
@@ -627,7 +626,7 @@ qtfsfifo_poll(struct file *filp, poll_table *wait)
|
|
return 0;
|
|
}
|
|
req = qtfs_sock_msg_buf(pvar, QTFS_SEND);
|
|
- req->file = fpriv->file;
|
|
+ req->fd = fpriv->fd;
|
|
rsp = qtfs_remote_run(pvar, QTFS_REQ_FIFOPOLL, sizeof(struct qtreq_poll));
|
|
if (IS_ERR(rsp) || rsp == NULL) {
|
|
qtfs_conn_put_param(pvar);
|
|
diff --git a/qtfs/qtfs/syscall.c b/qtfs/qtfs/syscall.c
|
|
index 85cfbbe..2912f48 100644
|
|
--- a/qtfs/qtfs/syscall.c
|
|
+++ b/qtfs/qtfs/syscall.c
|
|
@@ -110,7 +110,6 @@ static void do_epoll_ctl_remote(int op, struct epoll_event __user *event, struct
|
|
}
|
|
req = qtfs_sock_msg_buf(pvar, QTFS_SEND);
|
|
req->fd = priv->fd;
|
|
- req->file = priv->file;
|
|
req->op = op;
|
|
if (ep_op_has_event(op) && copy_from_user(&tmp, event, sizeof(struct epoll_event))) {
|
|
qtfs_err("qtfs do epoll ctl remote copy from user failed.");
|
|
@@ -131,7 +130,7 @@ static void do_epoll_ctl_remote(int op, struct epoll_event __user *event, struct
|
|
} else {
|
|
qtinfo_cntinc(QTINF_EPOLL_DELFDS);
|
|
}
|
|
- qtfs_info("qtfs do epoll ctl remote success, fd:%d file:%lx.", req->fd, (unsigned long)req->file);
|
|
+ qtfs_info("qtfs do epoll ctl remote success, fd:%d.", req->fd);
|
|
qtfs_conn_put_param(pvar);
|
|
return;
|
|
}
|
|
diff --git a/qtfs/qtfs_server/Makefile b/qtfs/qtfs_server/Makefile
|
|
index c1c5ef6..9c6bcd5 100644
|
|
--- a/qtfs/qtfs_server/Makefile
|
|
+++ b/qtfs/qtfs_server/Makefile
|
|
@@ -10,9 +10,9 @@ qtfs_server:
|
|
make -C $(KBUILD) M=$(PWD) modules
|
|
|
|
engine:
|
|
- gcc -O2 -o engine user_engine.c -lpthread -I../ -DQTFS_SERVER
|
|
+ gcc -O2 -o engine user_engine.c -lpthread -lglib-2.0 -I../ -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -DQTFS_SERVER
|
|
|
|
clean:
|
|
make -C $(KBUILD) M=$(PWD) clean
|
|
rm -rf engine
|
|
- rm -rf ../*.o
|
|
+ rm -rf ../*.o ../.*.o.cmd
|
|
diff --git a/qtfs/qtfs_server/fsops.c b/qtfs/qtfs_server/fsops.c
|
|
index 48ec7ab..d00db6d 100644
|
|
--- a/qtfs/qtfs_server/fsops.c
|
|
+++ b/qtfs/qtfs_server/fsops.c
|
|
@@ -23,6 +23,21 @@
|
|
#define RSP(arg) (arg->out)
|
|
#define USERP(arg) (arg->userp)
|
|
|
|
+bool in_white_list(char *path, int type)
|
|
+{
|
|
+ if (!whitelist[type]) {
|
|
+ return true;
|
|
+ }
|
|
+ int i, in_wl = -1;
|
|
+ for (i = 0; i < whitelist[type]->len; i++) {
|
|
+ if (!strncmp(path, whitelist[type]->wl[i].path, whitelist[type]->wl[i].len)){
|
|
+ in_wl = i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ return in_wl != -1;
|
|
+}
|
|
+
|
|
static inline void qtfs_inode_info_fill(struct inode_info *ii, struct inode *inode)
|
|
{
|
|
ii->mode = inode->i_mode;
|
|
@@ -55,7 +70,6 @@ static int handle_ioctl(struct qtserver_arg *arg)
|
|
struct qtreq_ioctl *req = (struct qtreq_ioctl *)REQ(arg);
|
|
struct qtrsp_ioctl *rsp = (struct qtrsp_ioctl *)RSP(arg);
|
|
struct qtfs_server_userp_s *userp = (struct qtfs_server_userp_s *)USERP(arg);
|
|
-
|
|
file = filp_open(req->path, O_RDONLY, 0);
|
|
if (err_ptr(file)) {
|
|
qtfs_err("handle ioctl error, path:<%s> failed.\n", req->path);
|
|
@@ -188,9 +202,13 @@ static int handle_statfs(struct qtserver_arg *arg)
|
|
static int handle_mount(struct qtserver_arg *arg)
|
|
{
|
|
struct path path;
|
|
- int ret;
|
|
+ int ret, i, in_wl = -1;
|
|
struct qtreq_mount *req = (struct qtreq_mount *)REQ(arg);
|
|
struct qtrsp_mount *rsp = (struct qtrsp_mount *)RSP(arg);
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_MOUNT)) {
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ return sizeof(rsp->ret);
|
|
+ }
|
|
|
|
ret = kern_path(req->path, LOOKUP_DIRECTORY, &path);
|
|
if (ret) {
|
|
@@ -208,11 +226,15 @@ int handle_open(struct qtserver_arg *arg)
|
|
{
|
|
int fd;
|
|
int ret;
|
|
- struct fd f;
|
|
- struct file *file = NULL;
|
|
struct qtreq_open *req = (struct qtreq_open *)REQ(arg);
|
|
struct qtrsp_open *rsp = (struct qtrsp_open *)RSP(arg);
|
|
struct qtfs_server_userp_s *userp = (struct qtfs_server_userp_s *)USERP(arg);
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_OPEN)) {
|
|
+ qtfs_err("handle open path:%s not permited", req->path);
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ rsp->fd = -EACCES;
|
|
+ return sizeof(struct qtrsp_open);
|
|
+ }
|
|
|
|
ret = copy_to_user(userp->userp, req->path, strlen(req->path)+1);
|
|
if (ret) {
|
|
@@ -235,26 +257,11 @@ int handle_open(struct qtserver_arg *arg)
|
|
}
|
|
rsp->ret = QTFS_ERR;
|
|
rsp->fd = fd;
|
|
- rsp->file = 0;
|
|
return sizeof(struct qtrsp_open);
|
|
}
|
|
|
|
- f = fdget(fd);
|
|
- file = f.file;
|
|
- if (err_ptr(file)) {
|
|
- rsp->ret = QTFS_ERR;
|
|
- rsp->fd = PTR_ERR(file);
|
|
- // must close_fd(fd)?
|
|
- WARN_ON(1);
|
|
- qtfs_err("handle open get file pointer of <<%s>> error, fd:%d file err:%d.", req->path, fd, rsp->fd);
|
|
- // XXX: fileclose here?
|
|
- } else {
|
|
- rsp->ret = QTFS_OK;
|
|
- rsp->file = (__u64)file;
|
|
- rsp->fd = fd;
|
|
- }
|
|
- qtfs_info("handle open file :%s fd:%d filep:%lx.", req->path, fd, (unsigned long)rsp->file);
|
|
- fdput(f);
|
|
+ rsp->ret = QTFS_OK;
|
|
+ rsp->fd = fd;
|
|
return sizeof(struct qtrsp_open);
|
|
}
|
|
|
|
@@ -279,18 +286,30 @@ int handle_close(struct qtserver_arg *arg)
|
|
static int handle_readiter(struct qtserver_arg *arg)
|
|
{
|
|
struct file *file = NULL;
|
|
+ char *pathbuf, *fullname;
|
|
struct qtreq_readiter *req = (struct qtreq_readiter *)REQ(arg);
|
|
struct qtrsp_readiter *rsp = (struct qtrsp_readiter *)RSP(arg);
|
|
struct qtfs_server_userp_s *userp = (struct qtfs_server_userp_s *)USERP(arg);
|
|
size_t maxlen = (req->len >= sizeof(rsp->readbuf)) ? (sizeof(rsp->readbuf) - 1) : req->len;
|
|
|
|
- file = (struct file *)req->file;
|
|
+ file = fget(req->fd);
|
|
+ pathbuf = __getname();
|
|
+ fullname = file_path(file, pathbuf, PATH_MAX);
|
|
+ if (!in_white_list(fullname, QTFS_WHITELIST_READ)) {
|
|
+ qtfs_err("%s not in whitelist.\n", fullname);
|
|
+ __putname(pathbuf);
|
|
+ rsp->d.ret = QTFS_ERR;
|
|
+ rsp->d.len = 0;
|
|
+ rsp->d.errno = -ENOENT;
|
|
+ goto end;
|
|
+ }
|
|
+ __putname(pathbuf);
|
|
if (err_ptr(file)) {
|
|
qtfs_err("handle readiter error, open failed, file:%p.\n", file);
|
|
rsp->d.ret = QTFS_ERR;
|
|
rsp->d.len = 0;
|
|
rsp->d.errno = -ENOENT;
|
|
- return sizeof(struct qtrsp_readiter) - sizeof(rsp->readbuf) + rsp->d.len;
|
|
+ goto end;
|
|
}
|
|
if (file->f_op->read) {
|
|
int idx = 0;
|
|
@@ -326,23 +345,35 @@ static int handle_readiter(struct qtserver_arg *arg)
|
|
|
|
qtfs_info("handle readiter file:<%s>, len:%lu, rsplen:%ld, pos:%lld, ret:%d errno:%d.\n",
|
|
file->f_path.dentry->d_iname, req->len, rsp->d.len, req->pos, rsp->d.ret, rsp->d.errno);
|
|
+end:
|
|
+ fput(file);
|
|
return sizeof(struct qtrsp_readiter) - sizeof(rsp->readbuf) + rsp->d.len;
|
|
}
|
|
|
|
static int handle_write(struct qtserver_arg *arg)
|
|
{
|
|
struct file *file = NULL;
|
|
+ char *pathbuf, *fullname;
|
|
struct qtreq_write *req = (struct qtreq_write *)REQ(arg);
|
|
struct qtrsp_write *rsp = (struct qtrsp_write *)RSP(arg);
|
|
struct qtfs_server_userp_s *userp = (struct qtfs_server_userp_s *)USERP(arg);
|
|
int idx = 0, leftlen = 0, ret = 0, len = 0;
|
|
|
|
- file = (struct file *)req->d.file;
|
|
+ file = fget(req->d.fd);
|
|
+ pathbuf = __getname();
|
|
+ fullname = file_path(file, pathbuf, PATH_MAX);
|
|
+ if (!in_white_list(fullname, QTFS_WHITELIST_WRITE)) {
|
|
+ kfree(pathbuf);
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ rsp->len = 0;
|
|
+ goto end;
|
|
+ }
|
|
+ __putname(pathbuf);
|
|
if (err_ptr(file)) {
|
|
qtfs_err("qtfs handle write error, filp:<%p> open failed.\n", file);
|
|
rsp->ret = QTFS_ERR;
|
|
rsp->len = 0;
|
|
- return sizeof(struct qtrsp_write);
|
|
+ goto end;
|
|
}
|
|
|
|
file->f_mode = req->d.mode;
|
|
@@ -372,6 +403,8 @@ static int handle_write(struct qtserver_arg *arg)
|
|
rsp->ret = (rsp->len <= 0) ? QTFS_ERR : QTFS_OK;
|
|
qtfs_info("handle write file<%s> %s, write len:%ld pos:%lld mode:%o flags:%x.", file->f_path.dentry->d_iname,
|
|
(rsp->ret == QTFS_ERR) ? "failed" : "succeded", rsp->len, req->d.pos, file->f_mode, file->f_flags);
|
|
+end:
|
|
+ fput(file);
|
|
return sizeof(struct qtrsp_write);
|
|
}
|
|
|
|
@@ -438,6 +471,12 @@ static int handle_readdir(struct qtserver_arg *arg)
|
|
.dir = (struct qtfs_dirent64 *)rsp->dirent,
|
|
.vldcnt = 0,
|
|
};
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_READDIR)) {
|
|
+ rsp->d.ret = QTFS_ERR;
|
|
+ rsp->d.vldcnt = 0;
|
|
+ return sizeof(struct qtrsp_readdir) - sizeof(rsp->dirent);
|
|
+ }
|
|
file = filp_open(req->path, O_RDONLY|O_NONBLOCK|O_DIRECTORY, 0);
|
|
if (err_ptr(file)) {
|
|
qtfs_err("handle readdir error, filp:<%s> open failed.\n", req->path);
|
|
@@ -466,7 +505,11 @@ static int handle_mkdir(struct qtserver_arg *arg)
|
|
struct inode *inode;
|
|
struct path path;
|
|
int ret;
|
|
-
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_MKDIR)) {
|
|
+ rsp->errno = -EFAULT;
|
|
+ goto err;
|
|
+ }
|
|
if (copy_to_user(userp->userp, req->path, strlen(req->path) + 1)) {
|
|
qtfs_err("handle mkdir copy to userp failed.\n");
|
|
rsp->errno = -EFAULT;
|
|
@@ -499,7 +542,11 @@ static int handle_rmdir(struct qtserver_arg *arg)
|
|
struct qtreq_rmdir *req = (struct qtreq_rmdir *)REQ(arg);
|
|
struct qtrsp_rmdir *rsp = (struct qtrsp_rmdir *)RSP(arg);
|
|
struct qtfs_server_userp_s *userp = (struct qtfs_server_userp_s *)USERP(arg);
|
|
-
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_RMDIR)) {
|
|
+ rsp->errno = -EFAULT;
|
|
+ goto err;
|
|
+ }
|
|
if (copy_to_user(userp->userp, req->path, strlen(req->path) + 1)) {
|
|
qtfs_err("handle rmdir copy to userp failed.\n");
|
|
rsp->errno = -EFAULT;
|
|
@@ -558,6 +605,12 @@ static int handle_setattr(struct qtserver_arg *arg)
|
|
struct inode *inode = NULL;
|
|
struct path path;
|
|
int ret;
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_SETATTR)) {
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ rsp->errno = -ENOENT;
|
|
+ return sizeof(struct qtrsp_setattr);
|
|
+ }
|
|
|
|
ret = kern_path(req->path, 0, &path);
|
|
if (ret) {
|
|
@@ -610,6 +663,12 @@ int handle_icreate(struct qtserver_arg *arg)
|
|
struct inode *inode;
|
|
struct qtreq_icreate *req = (struct qtreq_icreate *)REQ(arg);
|
|
struct qtrsp_icreate *rsp = (struct qtrsp_icreate *)RSP(arg);
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_CREATE)) {
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ rsp->errno = -ENOENT;
|
|
+ return sizeof(struct qtrsp_icreate);
|
|
+ }
|
|
|
|
file = filp_open(req->path, O_CREAT, req->mode);
|
|
if (err_ptr(file)) {
|
|
@@ -635,6 +694,12 @@ static int handle_mknod(struct qtserver_arg *arg)
|
|
struct path path;
|
|
int error;
|
|
unsigned int flags = LOOKUP_DIRECTORY;
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_CREATE)) {
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ rsp->errno = -ENOENT;
|
|
+ return sizeof(struct qtrsp_mknod);
|
|
+ }
|
|
|
|
retry:
|
|
dent = kern_path_create(AT_FDCWD, req->path, &path, flags);
|
|
@@ -668,6 +733,11 @@ int handle_unlink(struct qtserver_arg *arg)
|
|
{
|
|
struct qtreq_unlink *req = (struct qtreq_unlink *)REQ(arg);
|
|
struct qtrsp_unlink *rsp = (struct qtrsp_unlink *)RSP(arg);
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_UNLINK)) {
|
|
+ rsp->errno = -ENOENT;
|
|
+ return sizeof(struct qtrsp_unlink);
|
|
+ }
|
|
|
|
rsp->errno = qtfs_kern_syms.do_unlinkat(AT_FDCWD, qtfs_kern_syms.getname_kernel(req->path));
|
|
if (rsp->errno < 0) {
|
|
@@ -770,7 +840,11 @@ int handle_rename(struct qtserver_arg *arg)
|
|
struct qtreq_rename *req = (struct qtreq_rename *)REQ(arg);
|
|
struct qtrsp_rename *rsp = (struct qtrsp_rename *)RSP(arg);
|
|
struct qtfs_server_userp_s *userp = (struct qtfs_server_userp_s *)USERP(arg);
|
|
-
|
|
+
|
|
+ if (!in_white_list(req->path, QTFS_WHITELIST_RENAME)) {
|
|
+ rsp->errno = -ENOENT;
|
|
+ goto err_handle;
|
|
+ }
|
|
if (copy_to_user(userp->userp, req->path, strlen(req->path) + 1) ||
|
|
copy_to_user(userp->userp2, &req->path[req->d.oldlen], strlen(&req->path[req->d.oldlen]) + 1)) {
|
|
qtfs_err("handle rename copy to userp failed.\n");
|
|
@@ -831,6 +905,12 @@ int handle_xattrset(struct qtserver_arg *arg)
|
|
struct path path;
|
|
int ret = 0;
|
|
|
|
+ if (!in_white_list(req->buf, QTFS_WHITELIST_SETXATTR)) {
|
|
+ rsp->errno = -ENOENT;
|
|
+ rsp->ret = QTFS_ERR;
|
|
+ goto err_handle;
|
|
+ }
|
|
+
|
|
ret = kern_path(req->buf, 0, &path);
|
|
if (ret) {
|
|
qtfs_err("handle xattrset path error, file:%s.\n", req->buf);
|
|
@@ -997,7 +1077,7 @@ int handle_fifopoll(struct qtserver_arg *arg)
|
|
struct poll_wqueues table;
|
|
poll_table *pt;
|
|
|
|
- filp = (struct file *)req->file;
|
|
+ filp = fget(req->fd);
|
|
inode = filp->f_inode;
|
|
if (!S_ISFIFO(inode->i_mode)) {
|
|
msleep(1);
|
|
@@ -1011,6 +1091,7 @@ int handle_fifopoll(struct qtserver_arg *arg)
|
|
if (pipe == NULL) {
|
|
qtfs_err("file :%s pipe data is NULL.", filp->f_path.dentry->d_iname);
|
|
rsp->ret = QTFS_ERR;
|
|
+ fput(filp);
|
|
return sizeof(struct qtrsp_poll);
|
|
}
|
|
head = READ_ONCE(pipe->head);
|
|
@@ -1035,6 +1116,7 @@ end:
|
|
|
|
qtfs_info("handle fifo poll f_mode:%o: %s get poll mask 0x%x poll:%lx\n",
|
|
filp->f_mode, filp->f_path.dentry->d_iname, rsp->mask, (unsigned long)filp->f_op->poll);
|
|
+ fput(filp);
|
|
return sizeof(struct qtrsp_poll);
|
|
}
|
|
|
|
@@ -1055,8 +1137,8 @@ int handle_epollctl(struct qtserver_arg *arg)
|
|
}
|
|
qtinfo_cntinc((req->op == EPOLL_CTL_ADD) ? QTINF_EPOLL_ADDFDS : QTINF_EPOLL_DELFDS);
|
|
rsp->ret = QTFS_OK;
|
|
- qtfs_info("handle do epoll ctl success, fd:%d file:%lx op:%x data:%lx poll_t:%x.",
|
|
- req->fd, (unsigned long)req->file, req->op, req->event.data, (unsigned)req->event.events);
|
|
+ qtfs_info("handle do epoll ctl success, fd:%d op:%x data:%lx poll_t:%x.",
|
|
+ req->fd, req->op, req->event.data, (unsigned)req->event.events);
|
|
|
|
return sizeof(struct qtrsp_epollctl);
|
|
}
|
|
@@ -1197,3 +1279,4 @@ int qtfs_sock_server_run(struct qtfs_sock_var_s *pvar)
|
|
qtfs_sock_msg_clear(pvar);
|
|
return (ret < 0) ? QTERROR : QTOK;
|
|
}
|
|
+
|
|
diff --git a/qtfs/qtfs_server/qtfs-server.c b/qtfs/qtfs_server/qtfs-server.c
|
|
index bcd60b7..b0b8ab0 100644
|
|
--- a/qtfs/qtfs_server/qtfs-server.c
|
|
+++ b/qtfs/qtfs_server/qtfs-server.c
|
|
@@ -28,6 +28,8 @@ struct qtfs_server_epoll_s qtfs_epoll = {
|
|
.events = NULL,
|
|
};
|
|
|
|
+struct whitelist* whitelist[QTFS_WHITELIST_MAX];
|
|
+
|
|
long qtfs_server_epoll_thread(struct qtfs_sock_var_s *pvar)
|
|
{
|
|
int n;
|
|
@@ -140,9 +142,10 @@ long qtfs_server_epoll_init(void)
|
|
|
|
long qtfs_server_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
{
|
|
- int i;
|
|
+ int i, len;
|
|
long ret = 0;
|
|
struct qtfs_sock_var_s *pvar;
|
|
+ struct whitelist *tmp;
|
|
struct qtfs_thread_init_s init_userp;
|
|
switch (cmd) {
|
|
case QTFS_IOCTL_THREAD_INIT:
|
|
@@ -216,6 +219,26 @@ long qtfs_server_misc_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
|
case QTFS_IOCTL_LOGLEVEL:
|
|
ret = qtfs_misc_ioctl(file, cmd, arg);
|
|
break;
|
|
+ case QTFS_IOCTL_WHITELIST:
|
|
+ if (copy_from_user(&len, (void __user *)arg, sizeof(int))) {
|
|
+ qtfs_err("qtfs ioctl white init copy from user failed.");
|
|
+ return QTERROR;
|
|
+ }
|
|
+ tmp = (struct whitelist *)kmalloc(sizeof(struct whitelist) + sizeof(struct wl_item) * len, GFP_KERNEL);
|
|
+
|
|
+ if (copy_from_user(tmp, (void __user *)arg, sizeof(struct whitelist) + sizeof(struct wl_item) * len)) {
|
|
+ qtfs_err("qtfs ioctl white init copy from user failed.");
|
|
+ return QTERROR;
|
|
+ }
|
|
+
|
|
+ if (whitelist[tmp->type] != NULL) {
|
|
+ kfree(whitelist[tmp->type]);
|
|
+ }
|
|
+ whitelist[tmp->type] = tmp;
|
|
+ for (i = 0; i < whitelist[tmp->type]->len; i++) {
|
|
+ qtfs_err("init %d list:%d %s", tmp->type, i, whitelist[tmp->type]->wl[i].path);
|
|
+ }
|
|
+ break;
|
|
default:
|
|
qtfs_err("qtfs misc ioctl unknown cmd:%u.", cmd);
|
|
break;
|
|
@@ -226,7 +249,11 @@ long qtfs_server_misc_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
|
|
|
static int __init qtfs_server_init(void)
|
|
{
|
|
+ int i;
|
|
qtfs_log_init(qtfs_log_level);
|
|
+ for (i = 0; i < QTFS_WHITELIST_MAX; i++) {
|
|
+ whitelist[i] = NULL;
|
|
+ }
|
|
qtfs_diag_info = (struct qtinfo *)kmalloc(sizeof(struct qtinfo), GFP_KERNEL);
|
|
if (qtfs_diag_info == NULL)
|
|
qtfs_err("kmalloc qtfs diag info failed.");
|
|
@@ -246,6 +273,7 @@ static int __init qtfs_server_init(void)
|
|
|
|
static void __exit qtfs_server_exit(void)
|
|
{
|
|
+ int i;
|
|
qtfs_mod_exiting = true;
|
|
qtfs_server_thread_run = 0;
|
|
|
|
@@ -269,6 +297,11 @@ static void __exit qtfs_server_exit(void)
|
|
kfree(qtfs_userps);
|
|
qtfs_userps = NULL;
|
|
}
|
|
+ for (i = 0; i < QTFS_WHITELIST_MAX; i++) {
|
|
+ if (whitelist[i] != NULL) {
|
|
+ kfree(whitelist[i]);
|
|
+ }
|
|
+ }
|
|
qtfs_misc_destroy();
|
|
qtfs_info("qtfs server exit done.\n");
|
|
return;
|
|
diff --git a/qtfs/qtfs_server/qtfs-server.h b/qtfs/qtfs_server/qtfs-server.h
|
|
index 8bcadf6..d10742a 100644
|
|
--- a/qtfs/qtfs_server/qtfs-server.h
|
|
+++ b/qtfs/qtfs_server/qtfs-server.h
|
|
@@ -4,6 +4,7 @@
|
|
extern int qtfs_server_thread_run;
|
|
extern struct qtfs_server_epoll_s qtfs_epoll;
|
|
extern int qtfs_mod_exiting;
|
|
+extern struct whitelist* whitelist[QTFS_WHITELIST_MAX];
|
|
|
|
struct qtserver_arg {
|
|
char *data;
|
|
diff --git a/qtfs/qtfs_server/user_engine.c b/qtfs/qtfs_server/user_engine.c
|
|
index a062b63..547935c 100644
|
|
--- a/qtfs/qtfs_server/user_engine.c
|
|
+++ b/qtfs/qtfs_server/user_engine.c
|
|
@@ -9,11 +9,14 @@
|
|
#include <string.h>
|
|
#include <pthread.h>
|
|
#include <signal.h>
|
|
+#include <glib.h>
|
|
|
|
#include <sys/epoll.h>
|
|
|
|
#include "comm.h"
|
|
|
|
+char wl_type_str[QTFS_WHITELIST_MAX][10] = {"Open", "Write", "Read", "Readdir", "Mkdir", "Rmdir", "Create", "Unlink", "Rename", "Setattr", "Setxattr", "Mount"};
|
|
+
|
|
#define engine_out(info, ...) \
|
|
do {\
|
|
printf("[Engine::%s:%3d]"info"\n", __func__, __LINE__, ##__VA_ARGS__);\
|
|
@@ -29,6 +32,10 @@
|
|
printf("[ERROR:Engine::%s:%3d]"info"\n", __func__, __LINE__, ##__VA_ARGS__);\
|
|
} while (0);
|
|
|
|
+#define WHITELIST_FILE "/etc/qtfs/whitelist"
|
|
+
|
|
+struct whitelist *whitelist[QTFS_WHITELIST_MAX];
|
|
+
|
|
struct engine_arg {
|
|
int psize;
|
|
int fd;
|
|
@@ -171,6 +178,46 @@ int qtfs_epoll_init(int fd)
|
|
return epfd;
|
|
}
|
|
|
|
+static int qtfs_whitelist_transfer(int fd, GKeyFile *config, int type)
|
|
+{
|
|
+ int64_t i, len;
|
|
+ char **items = g_key_file_get_string_list(config,wl_type_str[type],"Path",&len,NULL);
|
|
+ if (len == 0) {
|
|
+ engine_out("Can't find whitelist item %s", wl_type_str[type]);
|
|
+ return 0;
|
|
+ }
|
|
+ whitelist[type] = (struct whitelist *)malloc(sizeof(struct whitelist) + sizeof(struct wl_item) * len);
|
|
+ g_print("%s:\n", wl_type_str[type]);
|
|
+ whitelist[type]->len = len;
|
|
+ whitelist[type]->type = type;
|
|
+ for(i = 0; i < len;i++){
|
|
+ printf("%s\n", items[i]);
|
|
+ whitelist[type]->wl[i].len = strlen(items[i]);
|
|
+ strcpy(whitelist[type]->wl[i].path, items[i]);
|
|
+ }
|
|
+ int ret = ioctl(fd, QTFS_IOCTL_WHITELIST, whitelist[type]);
|
|
+ free(items);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int qtfs_whitelist_init(int fd)
|
|
+{
|
|
+ int ret, i;
|
|
+ GKeyFile *config = g_key_file_new();
|
|
+ g_key_file_load_from_file(config, WHITELIST_FILE, G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
|
|
+ for (i = 0; i < QTFS_WHITELIST_MAX; i++) {
|
|
+ ret = qtfs_whitelist_transfer(fd, config, i);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ g_key_file_free(config);
|
|
+ for (i = 0; i < QTFS_WHITELIST_MAX; i++) {
|
|
+ free(whitelist[i]);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc != 3) {
|
|
@@ -192,6 +239,9 @@ int main(int argc, char *argv[])
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
+ if (qtfs_whitelist_init(fd)) {
|
|
+ goto end;
|
|
+ }
|
|
|
|
umask(0);
|
|
|
|
@@ -212,7 +262,6 @@ int main(int argc, char *argv[])
|
|
engine_out("qtfs engine userp init failed.");
|
|
goto end;
|
|
}
|
|
-
|
|
struct engine_arg arg[QTFS_MAX_THREADS];
|
|
for (int i = 0; i < thread_nums; i++) {
|
|
arg[i].psize = psize;
|
|
diff --git a/qtfs/req.h b/qtfs/req.h
|
|
index 0208667..3bcfa77 100644
|
|
--- a/qtfs/req.h
|
|
+++ b/qtfs/req.h
|
|
@@ -12,29 +12,29 @@ enum qtreq_type {
|
|
QTFS_REQ_OPEN,
|
|
QTFS_REQ_CLOSE,
|
|
QTFS_REQ_READ,
|
|
- QTFS_REQ_READITER, //5
|
|
+ QTFS_REQ_READITER, // 5
|
|
QTFS_REQ_WRITE,
|
|
QTFS_REQ_LOOKUP,
|
|
QTFS_REQ_READDIR,
|
|
QTFS_REQ_MKDIR,
|
|
- QTFS_REQ_RMDIR, //10
|
|
+ QTFS_REQ_RMDIR, // 10
|
|
QTFS_REQ_GETATTR,
|
|
QTFS_REQ_SETATTR,
|
|
QTFS_REQ_ICREATE,
|
|
QTFS_REQ_MKNOD,
|
|
- QTFS_REQ_UNLINK, //15
|
|
+ QTFS_REQ_UNLINK, // 15
|
|
QTFS_REQ_SYMLINK,
|
|
QTFS_REQ_LINK,
|
|
QTFS_REQ_GETLINK,
|
|
QTFS_REQ_READLINK,
|
|
- QTFS_REQ_RENAME, //20
|
|
+ QTFS_REQ_RENAME, // 20
|
|
|
|
QTFS_REQ_XATTRLIST,
|
|
QTFS_REQ_XATTRGET,
|
|
QTFS_REQ_XATTRSET,
|
|
|
|
QTFS_REQ_SYSMOUNT,
|
|
- QTFS_REQ_SYSUMOUNT, //25
|
|
+ QTFS_REQ_SYSUMOUNT, // 25
|
|
QTFS_REQ_FIFOPOLL,
|
|
|
|
QTFS_REQ_STATFS,
|
|
@@ -117,11 +117,11 @@ static inline void qtfs_nbytes_print(unsigned char *buf, int bytes)
|
|
#define QTFS_SEND_SIZE(stru, tailstr) sizeof(stru) - sizeof(tailstr) + strlen(tailstr) + 1
|
|
|
|
struct qtreq {
|
|
- unsigned int type; // operation type
|
|
+ unsigned int type; // operation type
|
|
unsigned int err;
|
|
unsigned long seq_num; // check code
|
|
size_t len;
|
|
- char data[QTFS_REQ_MAX_LEN]; // operation's private data
|
|
+ char data[QTFS_REQ_MAX_LEN]; // operation's private data
|
|
};
|
|
|
|
#define QTFS_MSG_LEN sizeof(struct qtreq)
|
|
@@ -169,7 +169,6 @@ struct qtreq_open {
|
|
};
|
|
|
|
struct qtrsp_open {
|
|
- __u64 file;
|
|
int fd;
|
|
int ret;
|
|
};
|
|
@@ -182,25 +181,10 @@ struct qtrsp_close {
|
|
int ret;
|
|
};
|
|
|
|
-struct qtreq_read {
|
|
- size_t len;
|
|
- long long pos;
|
|
- __u64 file;
|
|
-};
|
|
-
|
|
-struct qtrsp_read {
|
|
- struct qtrsp_read_len {
|
|
- int ret;
|
|
- ssize_t len;
|
|
- int errno;
|
|
- } d;
|
|
- char readbuf[QTFS_TAIL_LEN(struct qtrsp_read_len)];
|
|
-};
|
|
-
|
|
struct qtreq_readiter {
|
|
size_t len;
|
|
long long pos;
|
|
- __u64 file;
|
|
+ int fd;
|
|
};
|
|
|
|
struct qtrsp_readiter {
|
|
@@ -216,7 +200,7 @@ struct qtreq_write {
|
|
struct qtreq_write_len {
|
|
int buflen;
|
|
long long pos;
|
|
- __u64 file;
|
|
+ int fd;
|
|
long long flags;
|
|
long long mode;
|
|
} d;
|
|
@@ -505,7 +489,6 @@ struct qtrsp_sysumount {
|
|
|
|
struct qtreq_poll {
|
|
int fd;
|
|
- __u64 file;
|
|
int qproc;
|
|
};
|
|
|
|
@@ -516,7 +499,6 @@ struct qtrsp_poll {
|
|
|
|
|
|
struct qtreq_epollctl {
|
|
- __u64 file;
|
|
int fd;
|
|
int op;
|
|
struct qtreq_epoll_event event;
|
|
diff --git a/usecases/transparent-offload/whitelist/libvirt/qtfs_whitelist b/usecases/transparent-offload/whitelist/libvirt/qtfs_whitelist
|
|
new file mode 100644
|
|
index 0000000..d6e14ae
|
|
--- /dev/null
|
|
+++ b/usecases/transparent-offload/whitelist/libvirt/qtfs_whitelist
|
|
@@ -0,0 +1,35 @@
|
|
+[Open]
|
|
+Path=/proc/sys/kernel/sched_autogroup_enabled;/proc/sys/vm;/sys/bus/pci;/sys/devices/pic;/sys/devices/system/node;/sys/kernel/mm;/sys/fs/cgroup;/home/VMs;/sys/fs/cgroup;/var/lib/libvirt/qemu;/sys/devices/system/cpu/online;/sys/module/kvm;/proc;/sys
|
|
+
|
|
+[Write]
|
|
+Path=/proc/sys/kernel/sched_autogroup_enabled;/proc/sys/vm;/sys/bus/pci;/sys/devices/pic;/sys/devices/system/node;/sys/kernel/mm;/sys/fs/cgroup;/home/VMs;/sys/fs/cgroup;/var/lib/libvirt/qemu
|
|
+
|
|
+[Readiter]
|
|
+Path=/sys/module/kvm;/proc;/home/VMs;/sys/kernel/mm/transparent_hugepage;/sys/devices/system/cpu/online;/sys/devices/system/node;/sys/devices;/sys/firmware;/var/lib/libvirt/qemu;/sys/fs/cgroup
|
|
+
|
|
+[Readdir]
|
|
+Path=/proc;/sys/bus;/sys/kernel/iommu_groups;/sys/kernel/mm/hugepages;/sys/class;/sys/bus;/sys/class;/sys/devices/system;/var/lib/libvirt;/sys/fs/cgroup;/root/test;/sys/devices/system/node;/dev/pts;/home/VMs
|
|
+
|
|
+[Mkdir]
|
|
+Path=/var/lib/libvirt/qemu;/home/VMs;/sys/fs/cgroup
|
|
+
|
|
+[Rmdir]
|
|
+Path=/var/lib/libvirt/qemu;/home/VMs;/sys/fs/cgroup
|
|
+
|
|
+[Create]
|
|
+Path=/var/lib/libvirt/qemu;/home/VMs;/sys/fs/cgroup
|
|
+
|
|
+[Unlink]
|
|
+Path=/var/lib/libvirt/qemu;/home/VMs;/sys/fs/cgroup
|
|
+
|
|
+[Rename]
|
|
+Path=/var/lib/libvirt/qemu;/home/VMs;/sys/fs/cgroup
|
|
+
|
|
+[Setattr]
|
|
+Path=/sys/bus/pci/drivers/pcieport/unbind;/sys/bus/pci/drivers_probe;/sys/devices/pci0000:00/0000:00:08.0/driver_override;/root/test;/var/lib/libvirt/qemu;/sys/fs/cgroup;/home/VMs
|
|
+
|
|
+[Setxattr]
|
|
+Path=/sys/bus/pci/drivers/pcieport/unbind;/sys/bus/pci/drivers_probe;/sys/devices/pci0000:00/0000:00:08.0/driver_override;/root/test;/var/lib/libvirt/qemu;/sys/fs/cgroup;/home/VMs
|
|
+
|
|
+[Mount]
|
|
+Path=/home/VMs;/var/lib/libvirt;/proc;/sys;/dev/pts;/dev/vfio
|
|
\ No newline at end of file
|
|
--
|
|
2.33.0
|
|
|