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

