qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 14/25] virtiofsd: prevent ".." escape in lo_do_readdir()


From: Dr. David Alan Gilbert (git)
Subject: [PATCH 14/25] virtiofsd: prevent ".." escape in lo_do_readdir()
Date: Thu, 24 Oct 2019 12:27:07 +0100

From: Stefan Hajnoczi <address@hidden>

Construct a fake dirent for the root directory's ".." entry.  This hides
the parent directory from the FUSE client.

Signed-off-by: Stefan Hajnoczi <address@hidden>
---
 contrib/virtiofsd/passthrough_ll.c | 36 ++++++++++++++++++------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/contrib/virtiofsd/passthrough_ll.c 
b/contrib/virtiofsd/passthrough_ll.c
index 7a61bf94fe..cb01e3f088 100644
--- a/contrib/virtiofsd/passthrough_ll.c
+++ b/contrib/virtiofsd/passthrough_ll.c
@@ -1087,18 +1087,24 @@ out_err:
 static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
                          off_t offset, struct fuse_file_info *fi, int plus)
 {
+       struct lo_data *lo = lo_data(req);
        struct lo_dirp *d;
+       struct lo_inode *dinode;
        char *buf = NULL;
        char *p;
        size_t rem = size;
-       int err = ENOMEM;
+       int err = EBADF;
 
-       (void) ino;
+       dinode = lo_inode(req, ino);
+       if (!dinode) {
+               goto error;
+       }
 
        d = lo_dirp(req, fi);
        if (!d)
                goto error;
 
+       err = ENOMEM;
        buf = calloc(1, size);
        if (!buf)
                goto error;
@@ -1128,15 +1134,21 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t 
ino, size_t size,
                }
                nextoff = d->entry->d_off;
                name = d->entry->d_name;
+
                fuse_ino_t entry_ino = 0;
+               struct fuse_entry_param e = (struct fuse_entry_param) {
+                       .attr.st_ino = d->entry->d_ino,
+                       .attr.st_mode = d->entry->d_type << 12,
+               };
+
+               /* Hide root's parent directory */
+               if (dinode == &lo->root && strcmp(name, "..") == 0) {
+                       e.attr.st_ino = lo->root.ino;
+                       e.attr.st_mode = DT_DIR << 12;
+               }
+
                if (plus) {
-                       struct fuse_entry_param e;
-                       if (is_dot_or_dotdot(name)) {
-                               e = (struct fuse_entry_param) {
-                                       .attr.st_ino = d->entry->d_ino,
-                                       .attr.st_mode = d->entry->d_type << 12,
-                               };
-                       } else {
+                       if (!is_dot_or_dotdot(name)) {
                                err = lo_do_lookup(req, ino, name, &e);
                                if (err)
                                        goto error;
@@ -1146,12 +1158,8 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t 
ino, size_t size,
                        entsize = fuse_add_direntry_plus(req, p, rem, name,
                                                         &e, nextoff);
                } else {
-                       struct stat st = {
-                               .st_ino = d->entry->d_ino,
-                               .st_mode = d->entry->d_type << 12,
-                       };
                        entsize = fuse_add_direntry(req, p, rem, name,
-                                                   &st, nextoff);
+                                                   &e.attr, nextoff);
                }
                if (entsize > rem) {
                        if (entry_ino != 0) 
-- 
2.23.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]