summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/qemu/qemu
diff options
context:
space:
mode:
authorKhairul Rohaizzat Jamaluddin <khairul.rohaizzat.jamaluddin@intel.com>2021-04-07 05:42:35 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-04-18 11:37:24 +0100
commitb50e51b1c848e0162e693e986be59c15e5e57e5c (patch)
tree480fa560f39d79da4dcfa0c510c8d00686c3b6b6 /meta/recipes-devtools/qemu/qemu
parent84a6d97670d6ec0589b2591b4a660b3b069e21cb (diff)
downloadpoky-b50e51b1c848e0162e693e986be59c15e5e57e5c.tar.gz
qemu: Fix CVE-2020-35517
CVE: CVE-2020-35517 (From OE-Core rev: 51376edb13eed748395ebe1e56081c092565be9b) Signed-off-by: Khairul Rohaizzat Jamaluddin <khairul.rohaizzat.jamaluddin@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/qemu/qemu')
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2020-35517_1.patch153
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2020-35517_2.patch117
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2020-35517_3.patch303
3 files changed, 573 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_1.patch b/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_1.patch
new file mode 100644
index 0000000000..73a4cb2064
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_1.patch
@@ -0,0 +1,153 @@
1From 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
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_2.patch b/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_2.patch
new file mode 100644
index 0000000000..bf11bdb6f8
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_2.patch
@@ -0,0 +1,117 @@
1From 22d2ece71e533310da31f2857ebc4a00d91968b3 Mon Sep 17 00:00:00 2001
2From: Stefan Hajnoczi <stefanha@redhat.com>
3Date: Thu, 4 Feb 2021 15:02:07 +0000
4Subject: [PATCH] virtiofsd: optionally return inode pointer from
5 lo_do_lookup()
6
7lo_do_lookup() finds an existing inode or allocates a new one. It
8increments nlookup so that the inode stays alive until the client
9releases it.
10
11Existing callers don't need the struct lo_inode so the function doesn't
12return it. Extend the function to optionally return the inode. The next
13commit will need it.
14
15Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16Reviewed-by: Greg Kurz <groug@kaod.org>
17Message-Id: <20210204150208.367837-3-stefanha@redhat.com>
18Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
19
20Upstream-Status: Backport
21[https://github.com/qemu/qemu/commit/22d2ece71e533310da31f2857ebc4a00d91968b3]
22
23CVE: CVE-2020-35517
24
25Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
26Signed-off-by: Khairul Rohaizzat Jamaluddin <khairul.rohaizzat.jamaluddin@intel.com>
27---
28 tools/virtiofsd/passthrough_ll.c | 29 +++++++++++++++++++++--------
29 1 file changed, 21 insertions(+), 8 deletions(-)
30
31diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
32index f14fa51..aa35fc6 100644
33--- a/tools/virtiofsd/passthrough_ll.c
34+++ b/tools/virtiofsd/passthrough_ll.c
35@@ -831,11 +831,13 @@ static int do_statx(struct lo_data *lo, int dirfd, const char *pathname,
36 }
37
38 /*
39- * Increments nlookup and caller must release refcount using
40- * lo_inode_put(&parent).
41+ * Increments nlookup on the inode on success. unref_inode_lolocked() must be
42+ * called eventually to decrement nlookup again. If inodep is non-NULL, the
43+ * inode pointer is stored and the caller must call lo_inode_put().
44 */
45 static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
46- struct fuse_entry_param *e)
47+ struct fuse_entry_param *e,
48+ struct lo_inode **inodep)
49 {
50 int newfd;
51 int res;
52@@ -845,6 +847,10 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
53 struct lo_inode *inode = NULL;
54 struct lo_inode *dir = lo_inode(req, parent);
55
56+ if (inodep) {
57+ *inodep = NULL;
58+ }
59+
60 /*
61 * name_to_handle_at() and open_by_handle_at() can reach here with fuse
62 * mount point in guest, but we don't have its inode info in the
63@@ -913,7 +919,14 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
64 pthread_mutex_unlock(&lo->mutex);
65 }
66 e->ino = inode->fuse_ino;
67- lo_inode_put(lo, &inode);
68+
69+ /* Transfer ownership of inode pointer to caller or drop it */
70+ if (inodep) {
71+ *inodep = inode;
72+ } else {
73+ lo_inode_put(lo, &inode);
74+ }
75+
76 lo_inode_put(lo, &dir);
77
78 fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", (unsigned long long)parent,
79@@ -948,7 +961,7 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
80 return;
81 }
82
83- err = lo_do_lookup(req, parent, name, &e);
84+ err = lo_do_lookup(req, parent, name, &e, NULL);
85 if (err) {
86 fuse_reply_err(req, err);
87 } else {
88@@ -1056,7 +1069,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
89 goto out;
90 }
91
92- saverr = lo_do_lookup(req, parent, name, &e);
93+ saverr = lo_do_lookup(req, parent, name, &e, NULL);
94 if (saverr) {
95 goto out;
96 }
97@@ -1534,7 +1547,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
98
99 if (plus) {
100 if (!is_dot_or_dotdot(name)) {
101- err = lo_do_lookup(req, ino, name, &e);
102+ err = lo_do_lookup(req, ino, name, &e, NULL);
103 if (err) {
104 goto error;
105 }
106@@ -1732,7 +1745,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
107 }
108
109 fi->fh = fh;
110- err = lo_do_lookup(req, parent, name, &e);
111+ err = lo_do_lookup(req, parent, name, &e, NULL);
112 }
113 if (lo->cache == CACHE_NONE) {
114 fi->direct_io = 1;
115--
1161.8.3.1
117
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_3.patch b/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_3.patch
new file mode 100644
index 0000000000..f348f3f2bd
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2020-35517_3.patch
@@ -0,0 +1,303 @@
1From a3fdbbc7f271bff7d53d0501b29d910ece0b3789 Mon Sep 17 00:00:00 2001
2From: Stefan Hajnoczi <stefanha@redhat.com>
3Date: Thu, 4 Feb 2021 15:02:08 +0000
4Subject: [PATCH] virtiofsd: prevent opening of special files (CVE-2020-35517)
5
6A well-behaved FUSE client does not attempt to open special files with
7FUSE_OPEN because they are handled on the client side (e.g. device nodes
8are handled by client-side device drivers).
9
10The check to prevent virtiofsd from opening special files is missing in
11a few cases, most notably FUSE_OPEN. A malicious client can cause
12virtiofsd to open a device node, potentially allowing the guest to
13escape. This can be exploited by a modified guest device driver. It is
14not exploitable from guest userspace since the guest kernel will handle
15special files inside the guest instead of sending FUSE requests.
16
17This patch fixes this issue by introducing the lo_inode_open() function
18to check the file type before opening it. This is a short-term solution
19because it does not prevent a compromised virtiofsd process from opening
20device nodes on the host.
21
22Restructure lo_create() to try O_CREAT | O_EXCL first. Note that O_CREAT
23| O_EXCL does not follow symlinks, so O_NOFOLLOW masking is not
24necessary here. If the file exists and the user did not specify O_EXCL,
25open it via lo_do_open().
26
27Reported-by: Alex Xu <alex@alxu.ca>
28Fixes: CVE-2020-35517
29Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
30Reviewed-by: Vivek Goyal <vgoyal@redhat.com>
31Reviewed-by: Greg Kurz <groug@kaod.org>
32Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
33Message-Id: <20210204150208.367837-4-stefanha@redhat.com>
34Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
35
36Upstream-Status: Backport
37[https://github.com/qemu/qemu/commit/a3fdbbc7f271bff7d53d0501b29d910ece0b3789]
38
39CVE: CVE-2020-35517
40
41Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
42Signed-off-by: Khairul Rohaizzat Jamaluddin <khairul.rohaizzat.jamaluddin@intel.com>
43---
44 tools/virtiofsd/passthrough_ll.c | 144 ++++++++++++++++++++-----------
45 1 file changed, 92 insertions(+), 52 deletions(-)
46
47diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
48index aa35fc6ba5a5..147b59338a18 100644
49--- a/tools/virtiofsd/passthrough_ll.c
50+++ b/tools/virtiofsd/passthrough_ll.c
51@@ -555,6 +555,38 @@ static int lo_fd(fuse_req_t req, fuse_ino_t ino)
52 return fd;
53 }
54
55+/*
56+ * Open a file descriptor for an inode. Returns -EBADF if the inode is not a
57+ * regular file or a directory.
58+ *
59+ * Use this helper function instead of raw openat(2) to prevent security issues
60+ * when a malicious client opens special files such as block device nodes.
61+ * Symlink inodes are also rejected since symlinks must already have been
62+ * traversed on the client side.
63+ */
64+static int lo_inode_open(struct lo_data *lo, struct lo_inode *inode,
65+ int open_flags)
66+{
67+ g_autofree char *fd_str = g_strdup_printf("%d", inode->fd);
68+ int fd;
69+
70+ if (!S_ISREG(inode->filetype) && !S_ISDIR(inode->filetype)) {
71+ return -EBADF;
72+ }
73+
74+ /*
75+ * The file is a symlink so O_NOFOLLOW must be ignored. We checked earlier
76+ * that the inode is not a special file but if an external process races
77+ * with us then symlinks are traversed here. It is not possible to escape
78+ * the shared directory since it is mounted as "/" though.
79+ */
80+ fd = openat(lo->proc_self_fd, fd_str, open_flags & ~O_NOFOLLOW);
81+ if (fd < 0) {
82+ return -errno;
83+ }
84+ return fd;
85+}
86+
87 static void lo_init(void *userdata, struct fuse_conn_info *conn)
88 {
89 struct lo_data *lo = (struct lo_data *)userdata;
90@@ -684,9 +716,9 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
91 if (fi) {
92 truncfd = fd;
93 } else {
94- sprintf(procname, "%i", ifd);
95- truncfd = openat(lo->proc_self_fd, procname, O_RDWR);
96+ truncfd = lo_inode_open(lo, inode, O_RDWR);
97 if (truncfd < 0) {
98+ errno = -truncfd;
99 goto out_err;
100 }
101 }
102@@ -848,7 +880,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
103 struct lo_inode *dir = lo_inode(req, parent);
104
105 if (inodep) {
106- *inodep = NULL;
107+ *inodep = NULL; /* in case there is an error */
108 }
109
110 /*
111@@ -1664,19 +1696,26 @@ static void update_open_flags(int writeback, int allow_direct_io,
112 }
113 }
114
115+/*
116+ * Open a regular file, set up an fd mapping, and fill out the struct
117+ * fuse_file_info for it. If existing_fd is not negative, use that fd instead
118+ * opening a new one. Takes ownership of existing_fd.
119+ *
120+ * Returns 0 on success or a positive errno.
121+ */
122 static int lo_do_open(struct lo_data *lo, struct lo_inode *inode,
123- struct fuse_file_info *fi)
124+ int existing_fd, struct fuse_file_info *fi)
125 {
126- char buf[64];
127 ssize_t fh;
128- int fd;
129+ int fd = existing_fd;
130
131 update_open_flags(lo->writeback, lo->allow_direct_io, fi);
132
133- sprintf(buf, "%i", inode->fd);
134- fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
135- if (fd == -1) {
136- return errno;
137+ if (fd < 0) {
138+ fd = lo_inode_open(lo, inode, fi->flags);
139+ if (fd < 0) {
140+ return -fd;
141+ }
142 }
143
144 pthread_mutex_lock(&lo->mutex);
145@@ -1699,9 +1738,10 @@ static int lo_do_open(struct lo_data *lo, struct lo_inode *inode,
146 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
147 mode_t mode, struct fuse_file_info *fi)
148 {
149- int fd;
150+ int fd = -1;
151 struct lo_data *lo = lo_data(req);
152 struct lo_inode *parent_inode;
153+ struct lo_inode *inode = NULL;
154 struct fuse_entry_param e;
155 int err;
156 struct lo_cred old = {};
157@@ -1727,36 +1767,38 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
158
159 update_open_flags(lo->writeback, lo->allow_direct_io, fi);
160
161- fd = openat(parent_inode->fd, name, (fi->flags | O_CREAT) & ~O_NOFOLLOW,
162- mode);
163+ /* Try to create a new file but don't open existing files */
164+ fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
165 err = fd == -1 ? errno : 0;
166- lo_restore_cred(&old);
167
168- if (!err) {
169- ssize_t fh;
170+ lo_restore_cred(&old);
171
172- pthread_mutex_lock(&lo->mutex);
173- fh = lo_add_fd_mapping(lo, fd);
174- pthread_mutex_unlock(&lo->mutex);
175- if (fh == -1) {
176- close(fd);
177- err = ENOMEM;
178- goto out;
179- }
180+ /* Ignore the error if file exists and O_EXCL was not given */
181+ if (err && (err != EEXIST || (fi->flags & O_EXCL))) {
182+ goto out;
183+ }
184
185- fi->fh = fh;
186- err = lo_do_lookup(req, parent, name, &e, NULL);
187+ err = lo_do_lookup(req, parent, name, &e, &inode);
188+ if (err) {
189+ goto out;
190 }
191- if (lo->cache == CACHE_NONE) {
192- fi->direct_io = 1;
193- } else if (lo->cache == CACHE_ALWAYS) {
194- fi->keep_cache = 1;
195+
196+ err = lo_do_open(lo, inode, fd, fi);
197+ fd = -1; /* lo_do_open() takes ownership of fd */
198+ if (err) {
199+ /* Undo lo_do_lookup() nlookup ref */
200+ unref_inode_lolocked(lo, inode, 1);
201 }
202
203 out:
204+ lo_inode_put(lo, &inode);
205 lo_inode_put(lo, &parent_inode);
206
207 if (err) {
208+ if (fd >= 0) {
209+ close(fd);
210+ }
211+
212 fuse_reply_err(req, err);
213 } else {
214 fuse_reply_create(req, &e, fi);
215@@ -1770,7 +1812,6 @@ static struct lo_inode_plock *lookup_create_plock_ctx(struct lo_data *lo,
216 pid_t pid, int *err)
217 {
218 struct lo_inode_plock *plock;
219- char procname[64];
220 int fd;
221
222 plock =
223@@ -1787,12 +1828,10 @@ static struct lo_inode_plock *lookup_create_plock_ctx(struct lo_data *lo,
224 }
225
226 /* Open another instance of file which can be used for ofd locks. */
227- sprintf(procname, "%i", inode->fd);
228-
229 /* TODO: What if file is not writable? */
230- fd = openat(lo->proc_self_fd, procname, O_RDWR);
231- if (fd == -1) {
232- *err = errno;
233+ fd = lo_inode_open(lo, inode, O_RDWR);
234+ if (fd < 0) {
235+ *err = -fd;
236 free(plock);
237 return NULL;
238 }
239@@ -1949,7 +1988,7 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
240 return;
241 }
242
243- err = lo_do_open(lo, inode, fi);
244+ err = lo_do_open(lo, inode, -1, fi);
245 lo_inode_put(lo, &inode);
246 if (err) {
247 fuse_reply_err(req, err);
248@@ -2014,39 +2053,40 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
249 static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
250 struct fuse_file_info *fi)
251 {
252+ struct lo_inode *inode = lo_inode(req, ino);
253+ struct lo_data *lo = lo_data(req);
254 int res;
255 int fd;
256- char *buf;
257
258 fuse_log(FUSE_LOG_DEBUG, "lo_fsync(ino=%" PRIu64 ", fi=0x%p)\n", ino,
259 (void *)fi);
260
261- if (!fi) {
262- struct lo_data *lo = lo_data(req);
263-
264- res = asprintf(&buf, "%i", lo_fd(req, ino));
265- if (res == -1) {
266- return (void)fuse_reply_err(req, errno);
267- }
268+ if (!inode) {
269+ fuse_reply_err(req, EBADF);
270+ return;
271+ }
272
273- fd = openat(lo->proc_self_fd, buf, O_RDWR);
274- free(buf);
275- if (fd == -1) {
276- return (void)fuse_reply_err(req, errno);
277+ if (!fi) {
278+ fd = lo_inode_open(lo, inode, O_RDWR);
279+ if (fd < 0) {
280+ res = -fd;
281+ goto out;
282 }
283 } else {
284 fd = lo_fi_fd(req, fi);
285 }
286
287 if (datasync) {
288- res = fdatasync(fd);
289+ res = fdatasync(fd) == -1 ? errno : 0;
290 } else {
291- res = fsync(fd);
292+ res = fsync(fd) == -1 ? errno : 0;
293 }
294 if (!fi) {
295 close(fd);
296 }
297- fuse_reply_err(req, res == -1 ? errno : 0);
298+out:
299+ lo_inode_put(lo, &inode);
300+ fuse_reply_err(req, res);
301 }
302
303 static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset,