blob: 73a4cb20644cae34935d1a78dd40c9dbaeb7b4d5 [file] [log] [blame]
Andrew Geisslerc926e172021-05-07 16:11:35 -05001From 8afaaee976965b7fb90ec225a51d60f35c5f173c Mon Sep 17 00:00:00 2001
2From: Stefan Hajnoczi <stefanha@redhat.com>
3Date: Thu, 4 Feb 2021 15:02:06 +0000
4Subject: [PATCH] virtiofsd: extract lo_do_open() from lo_open()
5
6Both lo_open() and lo_create() have similar code to open a file. Extract
7a common lo_do_open() function from lo_open() that will be used by
8lo_create() in a later commit.
9
10Since lo_do_open() does not otherwise need fuse_req_t req, convert
11lo_add_fd_mapping() to use struct lo_data *lo instead.
12
13Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14Message-Id: <20210204150208.367837-2-stefanha@redhat.com>
15Reviewed-by: Greg Kurz <groug@kaod.org>
16Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
17
18Upstream-Status: Backport
19[https://github.com/qemu/qemu/commit/8afaaee976965b7fb90ec225a51d60f35c5f173c]
20
21CVE: CVE-2020-35517
22
23Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
24Signed-off-by: Khairul Rohaizzat Jamaluddin <khairul.rohaizzat.jamaluddin@intel.com>
25---
26 tools/virtiofsd/passthrough_ll.c | 73 +++++++++++++++++++++++++---------------
27 1 file changed, 46 insertions(+), 27 deletions(-)
28
29diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
30index 5fb36d9..f14fa51 100644
31--- a/tools/virtiofsd/passthrough_ll.c
32+++ b/tools/virtiofsd/passthrough_ll.c
33@@ -459,17 +459,17 @@ static void lo_map_remove(struct lo_map *map, size_t key)
34 }
35
36 /* Assumes lo->mutex is held */
37-static ssize_t lo_add_fd_mapping(fuse_req_t req, int fd)
38+static ssize_t lo_add_fd_mapping(struct lo_data *lo, int fd)
39 {
40 struct lo_map_elem *elem;
41
42- elem = lo_map_alloc_elem(&lo_data(req)->fd_map);
43+ elem = lo_map_alloc_elem(&lo->fd_map);
44 if (!elem) {
45 return -1;
46 }
47
48 elem->fd = fd;
49- return elem - lo_data(req)->fd_map.elems;
50+ return elem - lo->fd_map.elems;
51 }
52
53 /* Assumes lo->mutex is held */
54@@ -1651,6 +1651,38 @@ static void update_open_flags(int writeback, int allow_direct_io,
55 }
56 }
57
58+static int lo_do_open(struct lo_data *lo, struct lo_inode *inode,
59+ struct fuse_file_info *fi)
60+{
61+ char buf[64];
62+ ssize_t fh;
63+ int fd;
64+
65+ update_open_flags(lo->writeback, lo->allow_direct_io, fi);
66+
67+ sprintf(buf, "%i", inode->fd);
68+ fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
69+ if (fd == -1) {
70+ return errno;
71+ }
72+
73+ pthread_mutex_lock(&lo->mutex);
74+ fh = lo_add_fd_mapping(lo, fd);
75+ pthread_mutex_unlock(&lo->mutex);
76+ if (fh == -1) {
77+ close(fd);
78+ return ENOMEM;
79+ }
80+
81+ fi->fh = fh;
82+ if (lo->cache == CACHE_NONE) {
83+ fi->direct_io = 1;
84+ } else if (lo->cache == CACHE_ALWAYS) {
85+ fi->keep_cache = 1;
86+ }
87+ return 0;
88+}
89+
90 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
91 mode_t mode, struct fuse_file_info *fi)
92 {
93@@ -1691,7 +1723,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
94 ssize_t fh;
95
96 pthread_mutex_lock(&lo->mutex);
97- fh = lo_add_fd_mapping(req, fd);
98+ fh = lo_add_fd_mapping(lo, fd);
99 pthread_mutex_unlock(&lo->mutex);
100 if (fh == -1) {
101 close(fd);
102@@ -1892,38 +1924,25 @@ static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
103
104 static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
105 {
106- int fd;
107- ssize_t fh;
108- char buf[64];
109 struct lo_data *lo = lo_data(req);
110+ struct lo_inode *inode = lo_inode(req, ino);
111+ int err;
112
113 fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino,
114 fi->flags);
115
116- update_open_flags(lo->writeback, lo->allow_direct_io, fi);
117-
118- sprintf(buf, "%i", lo_fd(req, ino));
119- fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
120- if (fd == -1) {
121- return (void)fuse_reply_err(req, errno);
122- }
123-
124- pthread_mutex_lock(&lo->mutex);
125- fh = lo_add_fd_mapping(req, fd);
126- pthread_mutex_unlock(&lo->mutex);
127- if (fh == -1) {
128- close(fd);
129- fuse_reply_err(req, ENOMEM);
130+ if (!inode) {
131+ fuse_reply_err(req, EBADF);
132 return;
133 }
134
135- fi->fh = fh;
136- if (lo->cache == CACHE_NONE) {
137- fi->direct_io = 1;
138- } else if (lo->cache == CACHE_ALWAYS) {
139- fi->keep_cache = 1;
140+ err = lo_do_open(lo, inode, fi);
141+ lo_inode_put(lo, &inode);
142+ if (err) {
143+ fuse_reply_err(req, err);
144+ } else {
145+ fuse_reply_open(req, fi);
146 }
147- fuse_reply_open(req, fi);
148 }
149
150 static void lo_release(fuse_req_t req, fuse_ino_t ino,
151--
1521.8.3.1
153