Gentoo Archives: gentoo-commits

From: Aric Belsito <lluixhi@×××××.com>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/musl:master commit in: app-emulation/qemu/, app-emulation/qemu/files/
Date: Thu, 27 Jul 2017 17:59:44
Message-Id: 1501178341.9212f510625a88c624d5d8d9456842091ee93305.lluixhi@gentoo
1 commit: 9212f510625a88c624d5d8d9456842091ee93305
2 Author: Aric Belsito <lluixhi <AT> gmail <DOT> com>
3 AuthorDate: Thu Jul 27 17:59:01 2017 +0000
4 Commit: Aric Belsito <lluixhi <AT> gmail <DOT> com>
5 CommitDate: Thu Jul 27 17:59:01 2017 +0000
6 URL: https://gitweb.gentoo.org/proj/musl.git/commit/?id=9212f510
7
8 app-emulation/qemu: restore patch
9
10 deleted the wrong one..
11
12 app-emulation/qemu/Manifest | 2 +-
13 .../qemu/files/qemu-2.9.0-CVE-2017-7493.patch | 174 ++++++
14 .../qemu/files/qemu-2.9.0-CVE-2017-7539.patch | 601 ---------------------
15 3 files changed, 175 insertions(+), 602 deletions(-)
16
17 diff --git a/app-emulation/qemu/Manifest b/app-emulation/qemu/Manifest
18 index e4a3f79..e3f4bd2 100644
19 --- a/app-emulation/qemu/Manifest
20 +++ b/app-emulation/qemu/Manifest
21 @@ -9,7 +9,7 @@ AUX qemu-2.9.0-CVE-2017-10664.patch 1613 SHA256 5941cc41f0c02b185be3f6ba450f155d
22 AUX qemu-2.9.0-CVE-2017-10806.patch 1450 SHA256 ef884e2ed3adb618273af1d036ed0c7e3a09599e3d042080bb4b5014c6bc54d7 SHA512 38fea2c1a2a5a224585a07a028a8c4cfc1bec4d943e85c13e01228062bf306a502b0948270863b226bc974832e3af18158904fbfc08ccdf1f72f06e7830780d5 WHIRLPOOL f02fb957016af684dc894f93ec0b7dcca3febb8d37882aae1e17d2aca9948e200a013ae467cb54c5555e76c73f124a37c95fde189a4492d88322802d8160310c
23 AUX qemu-2.9.0-CVE-2017-11334.patch 1362 SHA256 bc2f3a50ad174e5453d0e4d1e14e9723b316e2339dc25ff31e27060ee13242bb SHA512 422296269ec29b3313c984947ac48b7179ce8e169131624d316589a621778f846b883e76cdfba50c62dc63ab5fede0ad0292704c1ca1cc9e1e7b3b01a153b8c8 WHIRLPOOL 504cf6b2ebfb11bf1471f920d101df28df59f1a585eac31ac278a366f2b769386bc7d100aa8386b3f8f45d5f5f700aa6625be3192eb4f1f3b77e69c6684cf74f
24 AUX qemu-2.9.0-CVE-2017-11434.patch 912 SHA256 e8be3cb9261f8735ff2a50fb8b79ccfea85456c7a2e5a5702fcc5339463dc05a SHA512 db95d9459b9669e0981195fe15f16c4e74d5f00c03e1ce5e33541e005260e77fa114b1b3f30bc06d80b723a6361b704fb58709b25773c168c8aa8f5f96580ac9 WHIRLPOOL c68e25024ab3c1d01e5b53d0a7b1591110b96d78079bc940ec28da2e2770dac6b1f9bbaaeb97c88ea0e1b46db886f7035d81bde582750e560d136916ecdab8a2
25 -AUX qemu-2.9.0-CVE-2017-7539.patch 22018 SHA256 523d41e08a2aab888e3e63b4dda6a19e535fe6fba2bf08b6ead06498ca923f29 SHA512 5c81488aeae78307bee551a3a037f3b9cf55971a17c5df17f89f31224bdfa0a5e79141341314546256bffe542b781ad25151c54340a63c766086a578e5465825 WHIRLPOOL 085fc7e7d40c803a3caf15cdee77ce553b385919678ecf4bbcc3f532af5e482ca804a167af43e4f393da93aed88285690d84a3054c7f0df61d603d0046029dbc
26 +AUX qemu-2.9.0-CVE-2017-7493.patch 5656 SHA256 77462d39e811e58d3761523a6c580485bdfca0e74adbd10cf24c254e0ece262a SHA512 2b01f2878c98e77997b645ba80e69b5db398ef1e8f2b66344818d3c9af35dd66d49041ef9ee8aa152bf3e94970b4db282cf53909cb13b2532bc0a104251b2e81 WHIRLPOOL 23c788c5a78e126a61bd277e9fa1511cc71b8fbdc83a5bf319c5fc424219cbcceefad737844e45c11a76e047f8a49853d0a85b267f24f7b23bb7276d0edf0451
27 AUX qemu-2.9.0-CVE-2017-8112.patch 696 SHA256 a4dcc2a94749a5c20ef38d4c7ce13cd1ffe46017c77eea29ced0bec5c232e6aa SHA512 840f5270332729e0149a4705bae5fcc16e9503a995d6bfa5033904a544add337ca8ccb1d2a36bb57cc198f6354f5253403f1c4f04cbd18c08b4e1a9d6af9e07f WHIRLPOOL 1ba4e75fdd0c767254c85754612da9e8ff9ba2e7ea0811f723844bec190946805cd59db83f347a3dea4296d2b58d2df4a8d99a492335ba818824348bcebdd556
28 AUX qemu-2.9.0-CVE-2017-8309.patch 595 SHA256 8231747fe4d9c97392fe44b117caccd07d320313dc27fad17ac658122113ced9 SHA512 4415c36acb4f0594de7fe0de2b669d03d6b54ae44eb7f1f285c36223a02cca887b57db27a43ab1cc2e7e193ee5bce2748f9d2056aa925e0cc8f2133e67168a74 WHIRLPOOL af4c5e9763a0e114e554a1c8be99ea79da0b634fdc9d87922c7713187f1f904bfcce103648d549bbb190e92443664dbb9bd7592d8137f2337be0f4b22d1f9bd1
29 AUX qemu-2.9.0-CVE-2017-8379.patch 2736 SHA256 f2f8910c8e1ce9fc9804f4fbbe978fee20ccbfccc5efe49f42cdaafa63c511ce SHA512 79e32f75d98ca4a92a5069b65c5b9cff16064255ed4d161e4e292b97373742c25d5ddc12dfffa627197fdb5e0808108b30d0182a9c060cd181723bd90c618d15 WHIRLPOOL 545c00189da3b252c80bb35c6b6d3368a02b36b06f2866838ddd9ebb9ccf2b608ae278ee192b6b3aef2966736afe9bcdd646c80c228ec5daef76b92bd2721bd5
30
31 diff --git a/app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7493.patch b/app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7493.patch
32 new file mode 100644
33 index 0000000..346e771
34 --- /dev/null
35 +++ b/app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7493.patch
36 @@ -0,0 +1,174 @@
37 +From 7a95434e0ca8a037fd8aa1a2e2461f92585eb77b Mon Sep 17 00:00:00 2001
38 +From: Greg Kurz <groug@××××.org>
39 +Date: Fri, 5 May 2017 14:48:08 +0200
40 +Subject: [PATCH] 9pfs: local: forbid client access to metadata (CVE-2017-7493)
41 +
42 +When using the mapped-file security mode, we shouldn't let the client mess
43 +with the metadata. The current code already tries to hide the metadata dir
44 +from the client by skipping it in local_readdir(). But the client can still
45 +access or modify it through several other operations. This can be used to
46 +escalate privileges in the guest.
47 +
48 +Affected backend operations are:
49 +- local_mknod()
50 +- local_mkdir()
51 +- local_open2()
52 +- local_symlink()
53 +- local_link()
54 +- local_unlinkat()
55 +- local_renameat()
56 +- local_rename()
57 +- local_name_to_path()
58 +
59 +Other operations are safe because they are only passed a fid path, which
60 +is computed internally in local_name_to_path().
61 +
62 +This patch converts all the functions listed above to fail and return
63 +EINVAL when being passed the name of the metadata dir. This may look
64 +like a poor choice for errno, but there's no such thing as an illegal
65 +path name on Linux and I could not think of anything better.
66 +
67 +This fixes CVE-2017-7493.
68 +
69 +Reported-by: Leo Gaspard <leo@×××××××.io>
70 +Signed-off-by: Greg Kurz <groug@××××.org>
71 +Reviewed-by: Eric Blake <eblake@××××××.com>
72 +---
73 + hw/9pfs/9p-local.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
74 + 1 file changed, 56 insertions(+), 2 deletions(-)
75 +
76 +diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
77 +index f3ebca4f7a..a2486566af 100644
78 +--- a/hw/9pfs/9p-local.c
79 ++++ b/hw/9pfs/9p-local.c
80 +@@ -452,6 +452,11 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
81 + return telldir(fs->dir.stream);
82 + }
83 +
84 ++static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name)
85 ++{
86 ++ return !strcmp(name, VIRTFS_META_DIR);
87 ++}
88 ++
89 + static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
90 + {
91 + struct dirent *entry;
92 +@@ -465,8 +470,8 @@ again:
93 + if (ctx->export_flags & V9FS_SM_MAPPED) {
94 + entry->d_type = DT_UNKNOWN;
95 + } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
96 +- if (!strcmp(entry->d_name, VIRTFS_META_DIR)) {
97 +- /* skp the meta data directory */
98 ++ if (local_is_mapped_file_metadata(ctx, entry->d_name)) {
99 ++ /* skip the meta data directory */
100 + goto again;
101 + }
102 + entry->d_type = DT_UNKNOWN;
103 +@@ -559,6 +564,12 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
104 + int err = -1;
105 + int dirfd;
106 +
107 ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
108 ++ local_is_mapped_file_metadata(fs_ctx, name)) {
109 ++ errno = EINVAL;
110 ++ return -1;
111 ++ }
112 ++
113 + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
114 + if (dirfd == -1) {
115 + return -1;
116 +@@ -605,6 +616,12 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
117 + int err = -1;
118 + int dirfd;
119 +
120 ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
121 ++ local_is_mapped_file_metadata(fs_ctx, name)) {
122 ++ errno = EINVAL;
123 ++ return -1;
124 ++ }
125 ++
126 + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
127 + if (dirfd == -1) {
128 + return -1;
129 +@@ -694,6 +711,12 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
130 + int err = -1;
131 + int dirfd;
132 +
133 ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
134 ++ local_is_mapped_file_metadata(fs_ctx, name)) {
135 ++ errno = EINVAL;
136 ++ return -1;
137 ++ }
138 ++
139 + /*
140 + * Mark all the open to not follow symlinks
141 + */
142 +@@ -752,6 +775,12 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
143 + int err = -1;
144 + int dirfd;
145 +
146 ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
147 ++ local_is_mapped_file_metadata(fs_ctx, name)) {
148 ++ errno = EINVAL;
149 ++ return -1;
150 ++ }
151 ++
152 + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
153 + if (dirfd == -1) {
154 + return -1;
155 +@@ -826,6 +855,12 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
156 + int ret = -1;
157 + int odirfd, ndirfd;
158 +
159 ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
160 ++ local_is_mapped_file_metadata(ctx, name)) {
161 ++ errno = EINVAL;
162 ++ return -1;
163 ++ }
164 ++
165 + odirfd = local_opendir_nofollow(ctx, odirpath);
166 + if (odirfd == -1) {
167 + goto out;
168 +@@ -1096,6 +1131,12 @@ static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
169 + static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
170 + const char *name, V9fsPath *target)
171 + {
172 ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
173 ++ local_is_mapped_file_metadata(ctx, name)) {
174 ++ errno = EINVAL;
175 ++ return -1;
176 ++ }
177 ++
178 + if (dir_path) {
179 + v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
180 + } else if (strcmp(name, "/")) {
181 +@@ -1116,6 +1157,13 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir,
182 + int ret;
183 + int odirfd, ndirfd;
184 +
185 ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
186 ++ (local_is_mapped_file_metadata(ctx, old_name) ||
187 ++ local_is_mapped_file_metadata(ctx, new_name))) {
188 ++ errno = EINVAL;
189 ++ return -1;
190 ++ }
191 ++
192 + odirfd = local_opendir_nofollow(ctx, olddir->data);
193 + if (odirfd == -1) {
194 + return -1;
195 +@@ -1206,6 +1254,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
196 + int ret;
197 + int dirfd;
198 +
199 ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
200 ++ local_is_mapped_file_metadata(ctx, name)) {
201 ++ errno = EINVAL;
202 ++ return -1;
203 ++ }
204 ++
205 + dirfd = local_opendir_nofollow(ctx, dir->data);
206 + if (dirfd == -1) {
207 + return -1;
208 +--
209 +2.13.0
210 +
211
212 diff --git a/app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7539.patch b/app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7539.patch
213 deleted file mode 100644
214 index 3af1697..0000000
215 --- a/app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7539.patch
216 +++ /dev/null
217 @@ -1,601 +0,0 @@
218 -From 2b0bbc4f8809c972bad134bc1a2570dbb01dea0b Mon Sep 17 00:00:00 2001
219 -From: Vladimir Sementsov-Ogievskiy <vsementsov@×××××××××.com>
220 -Date: Fri, 2 Jun 2017 18:01:41 +0300
221 -Subject: [PATCH] nbd/server: get rid of nbd_negotiate_read and friends
222 -
223 -Functions nbd_negotiate_{read,write,drop_sync} were introduced in
224 -1a6245a5b, when nbd_rwv (was nbd_wr_sync) was working through
225 -qemu_co_sendv_recvv (the path is nbd_wr_sync -> qemu_co_{recv/send} ->
226 -qemu_co_send_recv -> qemu_co_sendv_recvv), which just yields, without
227 -setting any handlers. But starting from ff82911cd nbd_rwv (was
228 -nbd_wr_syncv) works through qio_channel_yield() which sets handlers, so
229 -watchers are redundant in nbd_negotiate_{read,write,drop_sync}, then,
230 -let's just use nbd_{read,write,drop} functions.
231 -
232 -Functions nbd_{read,write,drop} has errp parameter, which is unused in
233 -this patch. This will be fixed later.
234 -
235 -Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@×××××××××.com>
236 -Reviewed-by: Eric Blake <eblake@××××××.com>
237 -Message-Id: <20170602150150.258222-4-vsementsov@×××××××××.com>
238 -Signed-off-by: Paolo Bonzini <pbonzini@××××××.com>
239 ----
240 - nbd/server.c | 107 ++++++++++++-----------------------------------------------
241 - 1 file changed, 22 insertions(+), 85 deletions(-)
242 -
243 -diff --git a/nbd/client.c b/nbd/client.c
244 -index a58fb02..6b74a62 100644
245 ---- a/nbd/client.c
246 -+++ b/nbd/client.c
247 -@@ -86,9 +86,9 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
248 -
249 - */
250 -
251 --/* Discard length bytes from channel. Return -errno on failure, or
252 -- * the amount of bytes consumed. */
253 --static ssize_t drop_sync(QIOChannel *ioc, size_t size)
254 -+/* Discard length bytes from channel. Return -errno on failure and 0 on
255 -+ * success*/
256 -+static int drop_sync(QIOChannel *ioc, size_t size)
257 - {
258 - ssize_t ret = 0;
259 - char small[1024];
260 -@@ -96,14 +96,13 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size)
261 -
262 - buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
263 - while (size > 0) {
264 -- ssize_t count = read_sync(ioc, buffer, MIN(65536, size));
265 -+ ssize_t count = MIN(65536, size);
266 -+ ret = read_sync(ioc, buffer, MIN(65536, size));
267 -
268 -- if (count <= 0) {
269 -+ if (ret < 0) {
270 - goto cleanup;
271 - }
272 -- assert(count <= size);
273 - size -= count;
274 -- ret += count;
275 - }
276 -
277 - cleanup:
278 -@@ -136,12 +135,12 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t opt,
279 - stl_be_p(&req.option, opt);
280 - stl_be_p(&req.length, len);
281 -
282 -- if (write_sync(ioc, &req, sizeof(req)) != sizeof(req)) {
283 -+ if (write_sync(ioc, &req, sizeof(req)) < 0) {
284 - error_setg(errp, "Failed to send option request header");
285 - return -1;
286 - }
287 -
288 -- if (len && write_sync(ioc, (char *) data, len) != len) {
289 -+ if (len && write_sync(ioc, (char *) data, len) < 0) {
290 - error_setg(errp, "Failed to send option request data");
291 - return -1;
292 - }
293 -@@ -170,7 +169,7 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt,
294 - nbd_opt_reply *reply, Error **errp)
295 - {
296 - QEMU_BUILD_BUG_ON(sizeof(*reply) != 20);
297 -- if (read_sync(ioc, reply, sizeof(*reply)) != sizeof(*reply)) {
298 -+ if (read_sync(ioc, reply, sizeof(*reply)) < 0) {
299 - error_setg(errp, "failed to read option reply");
300 - nbd_send_opt_abort(ioc);
301 - return -1;
302 -@@ -219,7 +218,7 @@ static int nbd_handle_reply_err(QIOChannel *ioc, nbd_opt_reply *reply,
303 - goto cleanup;
304 - }
305 - msg = g_malloc(reply->length + 1);
306 -- if (read_sync(ioc, msg, reply->length) != reply->length) {
307 -+ if (read_sync(ioc, msg, reply->length) < 0) {
308 - error_setg(errp, "failed to read option error message");
309 - goto cleanup;
310 - }
311 -@@ -321,7 +320,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
312 - nbd_send_opt_abort(ioc);
313 - return -1;
314 - }
315 -- if (read_sync(ioc, &namelen, sizeof(namelen)) != sizeof(namelen)) {
316 -+ if (read_sync(ioc, &namelen, sizeof(namelen)) < 0) {
317 - error_setg(errp, "failed to read option name length");
318 - nbd_send_opt_abort(ioc);
319 - return -1;
320 -@@ -334,7 +333,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
321 - return -1;
322 - }
323 - if (namelen != strlen(want)) {
324 -- if (drop_sync(ioc, len) != len) {
325 -+ if (drop_sync(ioc, len) < 0) {
326 - error_setg(errp, "failed to skip export name with wrong length");
327 - nbd_send_opt_abort(ioc);
328 - return -1;
329 -@@ -343,14 +342,14 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
330 - }
331 -
332 - assert(namelen < sizeof(name));
333 -- if (read_sync(ioc, name, namelen) != namelen) {
334 -+ if (read_sync(ioc, name, namelen) < 0) {
335 - error_setg(errp, "failed to read export name");
336 - nbd_send_opt_abort(ioc);
337 - return -1;
338 - }
339 - name[namelen] = '\0';
340 - len -= namelen;
341 -- if (drop_sync(ioc, len) != len) {
342 -+ if (drop_sync(ioc, len) < 0) {
343 - error_setg(errp, "failed to read export description");
344 - nbd_send_opt_abort(ioc);
345 - return -1;
346 -@@ -477,7 +476,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
347 - goto fail;
348 - }
349 -
350 -- if (read_sync(ioc, buf, 8) != 8) {
351 -+ if (read_sync(ioc, buf, 8) < 0) {
352 - error_setg(errp, "Failed to read data");
353 - goto fail;
354 - }
355 -@@ -503,7 +502,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
356 - goto fail;
357 - }
358 -
359 -- if (read_sync(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
360 -+ if (read_sync(ioc, &magic, sizeof(magic)) < 0) {
361 - error_setg(errp, "Failed to read magic");
362 - goto fail;
363 - }
364 -@@ -515,8 +514,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
365 - uint16_t globalflags;
366 - bool fixedNewStyle = false;
367 -
368 -- if (read_sync(ioc, &globalflags, sizeof(globalflags)) !=
369 -- sizeof(globalflags)) {
370 -+ if (read_sync(ioc, &globalflags, sizeof(globalflags)) < 0) {
371 - error_setg(errp, "Failed to read server flags");
372 - goto fail;
373 - }
374 -@@ -534,8 +532,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
375 - }
376 - /* client requested flags */
377 - clientflags = cpu_to_be32(clientflags);
378 -- if (write_sync(ioc, &clientflags, sizeof(clientflags)) !=
379 -- sizeof(clientflags)) {
380 -+ if (write_sync(ioc, &clientflags, sizeof(clientflags)) < 0) {
381 - error_setg(errp, "Failed to send clientflags field");
382 - goto fail;
383 - }
384 -@@ -573,13 +570,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
385 - }
386 -
387 - /* Read the response */
388 -- if (read_sync(ioc, &s, sizeof(s)) != sizeof(s)) {
389 -+ if (read_sync(ioc, &s, sizeof(s)) < 0) {
390 - error_setg(errp, "Failed to read export length");
391 - goto fail;
392 - }
393 - *size = be64_to_cpu(s);
394 -
395 -- if (read_sync(ioc, flags, sizeof(*flags)) != sizeof(*flags)) {
396 -+ if (read_sync(ioc, flags, sizeof(*flags)) < 0) {
397 - error_setg(errp, "Failed to read export flags");
398 - goto fail;
399 - }
400 -@@ -596,14 +593,14 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
401 - goto fail;
402 - }
403 -
404 -- if (read_sync(ioc, &s, sizeof(s)) != sizeof(s)) {
405 -+ if (read_sync(ioc, &s, sizeof(s)) < 0) {
406 - error_setg(errp, "Failed to read export length");
407 - goto fail;
408 - }
409 - *size = be64_to_cpu(s);
410 - TRACE("Size is %" PRIu64, *size);
411 -
412 -- if (read_sync(ioc, &oldflags, sizeof(oldflags)) != sizeof(oldflags)) {
413 -+ if (read_sync(ioc, &oldflags, sizeof(oldflags)) < 0) {
414 - error_setg(errp, "Failed to read export flags");
415 - goto fail;
416 - }
417 -@@ -619,7 +616,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
418 - }
419 -
420 - TRACE("Size is %" PRIu64 ", export flags %" PRIx16, *size, *flags);
421 -- if (zeroes && drop_sync(ioc, 124) != 124) {
422 -+ if (zeroes && drop_sync(ioc, 124) < 0) {
423 - error_setg(errp, "Failed to read reserved block");
424 - goto fail;
425 - }
426 -@@ -744,7 +741,6 @@ int nbd_disconnect(int fd)
427 - ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request)
428 - {
429 - uint8_t buf[NBD_REQUEST_SIZE];
430 -- ssize_t ret;
431 -
432 - TRACE("Sending request to server: "
433 - "{ .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64
434 -@@ -759,16 +755,7 @@ ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request)
435 - stq_be_p(buf + 16, request->from);
436 - stl_be_p(buf + 24, request->len);
437 -
438 -- ret = write_sync(ioc, buf, sizeof(buf));
439 -- if (ret < 0) {
440 -- return ret;
441 -- }
442 --
443 -- if (ret != sizeof(buf)) {
444 -- LOG("writing to socket failed");
445 -- return -EINVAL;
446 -- }
447 -- return 0;
448 -+ return write_sync(ioc, buf, sizeof(buf));
449 - }
450 -
451 - ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply)
452 -@@ -777,7 +764,7 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply)
453 - uint32_t magic;
454 - ssize_t ret;
455 -
456 -- ret = read_sync(ioc, buf, sizeof(buf));
457 -+ ret = read_sync_eof(ioc, buf, sizeof(buf));
458 - if (ret <= 0) {
459 - return ret;
460 - }
461 -diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
462 -index f43d990..e6bbc7c 100644
463 ---- a/nbd/nbd-internal.h
464 -+++ b/nbd/nbd-internal.h
465 -@@ -94,7 +94,13 @@
466 - #define NBD_ENOSPC 28
467 - #define NBD_ESHUTDOWN 108
468 -
469 --static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size)
470 -+/* read_sync_eof
471 -+ * Tries to read @size bytes from @ioc. Returns number of bytes actually read.
472 -+ * May return a value >= 0 and < size only on EOF, i.e. when iteratively called
473 -+ * qio_channel_readv() returns 0. So, there are no needs to call read_sync_eof
474 -+ * iteratively.
475 -+ */
476 -+static inline ssize_t read_sync_eof(QIOChannel *ioc, void *buffer, size_t size)
477 - {
478 - struct iovec iov = { .iov_base = buffer, .iov_len = size };
479 - /* Sockets are kept in blocking mode in the negotiation phase. After
480 -@@ -105,12 +111,32 @@ static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size)
481 - return nbd_wr_syncv(ioc, &iov, 1, size, true);
482 - }
483 -
484 --static inline ssize_t write_sync(QIOChannel *ioc, const void *buffer,
485 -- size_t size)
486 -+/* read_sync
487 -+ * Reads @size bytes from @ioc. Returns 0 on success.
488 -+ */
489 -+static inline int read_sync(QIOChannel *ioc, void *buffer, size_t size)
490 -+{
491 -+ ssize_t ret = read_sync_eof(ioc, buffer, size);
492 -+
493 -+ if (ret >= 0 && ret != size) {
494 -+ ret = -EINVAL;
495 -+ }
496 -+
497 -+ return ret < 0 ? ret : 0;
498 -+}
499 -+
500 -+/* write_sync
501 -+ * Writes @size bytes to @ioc. Returns 0 on success.
502 -+ */
503 -+static inline int write_sync(QIOChannel *ioc, const void *buffer, size_t size)
504 - {
505 - struct iovec iov = { .iov_base = (void *) buffer, .iov_len = size };
506 -
507 -- return nbd_wr_syncv(ioc, &iov, 1, size, false);
508 -+ ssize_t ret = nbd_wr_syncv(ioc, &iov, 1, size, false);
509 -+
510 -+ assert(ret < 0 || ret == size);
511 -+
512 -+ return ret < 0 ? ret : 0;
513 - }
514 -
515 - struct NBDTLSHandshakeData {
516 -diff --git a/nbd/server.c b/nbd/server.c
517 -index 924a1fe..a1f106b 100644
518 ---- a/nbd/server.c
519 -+++ b/nbd/server.c
520 -@@ -104,69 +104,6 @@ struct NBDClient {
521 -
522 - static void nbd_client_receive_next_request(NBDClient *client);
523 -
524 --static gboolean nbd_negotiate_continue(QIOChannel *ioc,
525 -- GIOCondition condition,
526 -- void *opaque)
527 --{
528 -- qemu_coroutine_enter(opaque);
529 -- return TRUE;
530 --}
531 --
532 --static ssize_t nbd_negotiate_read(QIOChannel *ioc, void *buffer, size_t size)
533 --{
534 -- ssize_t ret;
535 -- guint watch;
536 --
537 -- assert(qemu_in_coroutine());
538 -- /* Negotiation are always in main loop. */
539 -- watch = qio_channel_add_watch(ioc,
540 -- G_IO_IN,
541 -- nbd_negotiate_continue,
542 -- qemu_coroutine_self(),
543 -- NULL);
544 -- ret = read_sync(ioc, buffer, size);
545 -- g_source_remove(watch);
546 -- return ret;
547 --
548 --}
549 --
550 --static ssize_t nbd_negotiate_write(QIOChannel *ioc, const void *buffer,
551 -- size_t size)
552 --{
553 -- ssize_t ret;
554 -- guint watch;
555 --
556 -- assert(qemu_in_coroutine());
557 -- /* Negotiation are always in main loop. */
558 -- watch = qio_channel_add_watch(ioc,
559 -- G_IO_OUT,
560 -- nbd_negotiate_continue,
561 -- qemu_coroutine_self(),
562 -- NULL);
563 -- ret = write_sync(ioc, buffer, size);
564 -- g_source_remove(watch);
565 -- return ret;
566 --}
567 --
568 --static ssize_t nbd_negotiate_drop_sync(QIOChannel *ioc, size_t size)
569 --{
570 -- ssize_t ret, dropped = size;
571 -- uint8_t *buffer = g_malloc(MIN(65536, size));
572 --
573 -- while (size > 0) {
574 -- ret = nbd_negotiate_read(ioc, buffer, MIN(65536, size));
575 -- if (ret < 0) {
576 -- g_free(buffer);
577 -- return ret;
578 -- }
579 --
580 -- assert(ret <= size);
581 -- size -= ret;
582 -- }
583 --
584 -- g_free(buffer);
585 -- return dropped;
586 --}
587 -
588 - /* Basic flow for negotiation
589 -
590 -@@ -206,22 +143,22 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
591 - type, opt, len);
592 -
593 - magic = cpu_to_be64(NBD_REP_MAGIC);
594 -- if (nbd_negotiate_write(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
595 -+ if (nbd_write(ioc, &magic, sizeof(magic), NULL) < 0) {
596 - LOG("write failed (rep magic)");
597 - return -EINVAL;
598 - }
599 - opt = cpu_to_be32(opt);
600 -- if (nbd_negotiate_write(ioc, &opt, sizeof(opt)) != sizeof(opt)) {
601 -+ if (nbd_write(ioc, &opt, sizeof(opt), NULL) < 0) {
602 - LOG("write failed (rep opt)");
603 - return -EINVAL;
604 - }
605 - type = cpu_to_be32(type);
606 -- if (nbd_negotiate_write(ioc, &type, sizeof(type)) != sizeof(type)) {
607 -+ if (nbd_write(ioc, &type, sizeof(type), NULL) < 0) {
608 - LOG("write failed (rep type)");
609 - return -EINVAL;
610 - }
611 - len = cpu_to_be32(len);
612 -- if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
613 -+ if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
614 - LOG("write failed (rep data length)");
615 - return -EINVAL;
616 - }
617 -@@ -256,7 +193,7 @@ nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
618 - if (ret < 0) {
619 - goto out;
620 - }
621 -- if (nbd_negotiate_write(ioc, msg, len) != len) {
622 -+ if (nbd_write(ioc, msg, len, NULL) < 0) {
623 - LOG("write failed (error message)");
624 - ret = -EIO;
625 - } else {
626 -@@ -287,15 +224,15 @@ static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp)
627 - }
628 -
629 - len = cpu_to_be32(name_len);
630 -- if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
631 -+ if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
632 - LOG("write failed (name length)");
633 - return -EINVAL;
634 - }
635 -- if (nbd_negotiate_write(ioc, name, name_len) != name_len) {
636 -+ if (nbd_write(ioc, name, name_len, NULL) < 0) {
637 - LOG("write failed (name buffer)");
638 - return -EINVAL;
639 - }
640 -- if (nbd_negotiate_write(ioc, desc, desc_len) != desc_len) {
641 -+ if (nbd_write(ioc, desc, desc_len, NULL) < 0) {
642 - LOG("write failed (description buffer)");
643 - return -EINVAL;
644 - }
645 -@@ -309,7 +246,7 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length)
646 - NBDExport *exp;
647 -
648 - if (length) {
649 -- if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
650 -+ if (nbd_drop(client->ioc, length, NULL) < 0) {
651 - return -EIO;
652 - }
653 - return nbd_negotiate_send_rep_err(client->ioc,
654 -@@ -340,7 +277,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
655 - LOG("Bad length received");
656 - goto fail;
657 - }
658 -- if (nbd_negotiate_read(client->ioc, name, length) != length) {
659 -+ if (nbd_read(client->ioc, name, length, NULL) < 0) {
660 - LOG("read failed");
661 - goto fail;
662 - }
663 -@@ -373,7 +310,7 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
664 - TRACE("Setting up TLS");
665 - ioc = client->ioc;
666 - if (length) {
667 -- if (nbd_negotiate_drop_sync(ioc, length) != length) {
668 -+ if (nbd_drop(ioc, length, NULL) < 0) {
669 - return NULL;
670 - }
671 - nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS,
672 -@@ -437,8 +374,7 @@ static int nbd_negotiate_options(NBDClient *client)
673 - ... Rest of request
674 - */
675 -
676 -- if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) !=
677 -- sizeof(flags)) {
678 -+ if (nbd_read(client->ioc, &flags, sizeof(flags), NULL) < 0) {
679 - LOG("read failed");
680 - return -EIO;
681 - }
682 -@@ -464,8 +400,7 @@ static int nbd_negotiate_options(NBDClient *client)
683 - uint32_t clientflags, length;
684 - uint64_t magic;
685 -
686 -- if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=
687 -- sizeof(magic)) {
688 -+ if (nbd_read(client->ioc, &magic, sizeof(magic), NULL) < 0) {
689 - LOG("read failed");
690 - return -EINVAL;
691 - }
692 -@@ -475,15 +410,15 @@ static int nbd_negotiate_options(NBDClient *client)
693 - return -EINVAL;
694 - }
695 -
696 -- if (nbd_negotiate_read(client->ioc, &clientflags,
697 -- sizeof(clientflags)) != sizeof(clientflags)) {
698 -+ if (nbd_read(client->ioc, &clientflags,
699 -+ sizeof(clientflags), NULL) < 0)
700 -+ {
701 - LOG("read failed");
702 - return -EINVAL;
703 - }
704 - clientflags = be32_to_cpu(clientflags);
705 -
706 -- if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=
707 -- sizeof(length)) {
708 -+ if (nbd_read(client->ioc, &length, sizeof(length), NULL) < 0) {
709 - LOG("read failed");
710 - return -EINVAL;
711 - }
712 -@@ -513,7 +448,7 @@ static int nbd_negotiate_options(NBDClient *client)
713 - return -EINVAL;
714 -
715 - default:
716 -- if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
717 -+ if (nbd_drop(client->ioc, length, NULL) < 0) {
718 - return -EIO;
719 - }
720 - ret = nbd_negotiate_send_rep_err(client->ioc,
721 -@@ -551,7 +486,7 @@ static int nbd_negotiate_options(NBDClient *client)
722 - return nbd_negotiate_handle_export_name(client, length);
723 -
724 - case NBD_OPT_STARTTLS:
725 -- if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
726 -+ if (nbd_drop(client->ioc, length, NULL) < 0) {
727 - return -EIO;
728 - }
729 - if (client->tlscreds) {
730 -@@ -570,7 +505,7 @@ static int nbd_negotiate_options(NBDClient *client)
731 - }
732 - break;
733 - default:
734 -- if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
735 -+ if (nbd_drop(client->ioc, length, NULL) < 0) {
736 - return -EIO;
737 - }
738 - ret = nbd_negotiate_send_rep_err(client->ioc,
739 -@@ -659,12 +594,12 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
740 - TRACE("TLS cannot be enabled with oldstyle protocol");
741 - goto fail;
742 - }
743 -- if (nbd_negotiate_write(client->ioc, buf, sizeof(buf)) != sizeof(buf)) {
744 -+ if (nbd_write(client->ioc, buf, sizeof(buf), NULL) < 0) {
745 - LOG("write failed");
746 - goto fail;
747 - }
748 - } else {
749 -- if (nbd_negotiate_write(client->ioc, buf, 18) != 18) {
750 -+ if (nbd_write(client->ioc, buf, 18, NULL) < 0) {
751 - LOG("write failed");
752 - goto fail;
753 - }
754 -@@ -679,7 +614,7 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
755 - stq_be_p(buf + 18, client->exp->size);
756 - stw_be_p(buf + 26, client->exp->nbdflags | myflags);
757 - len = client->no_zeroes ? 10 : sizeof(buf) - 18;
758 -- if (nbd_negotiate_write(client->ioc, buf + 18, len) != len) {
759 -+ if (nbd_write(client->ioc, buf + 18, len, NULL) < 0) {
760 - LOG("write failed");
761 - goto fail;
762 - }
763 -@@ -702,11 +637,6 @@ static ssize_t nbd_receive_request(QIOChannel *ioc, NBDRequest *request)
764 - return ret;
765 - }
766 -
767 -- if (ret != sizeof(buf)) {
768 -- LOG("read failed");
769 -- return -EINVAL;
770 -- }
771 --
772 - /* Request
773 - [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
774 - [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
775 -@@ -737,7 +667,6 @@ static ssize_t nbd_receive_request(QIOChannel *ioc, NBDRequest *request)
776 - static ssize_t nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
777 - {
778 - uint8_t buf[NBD_REPLY_SIZE];
779 -- ssize_t ret;
780 -
781 - reply->error = system_errno_to_nbd_errno(reply->error);
782 -
783 -@@ -754,16 +683,7 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
784 - stl_be_p(buf + 4, reply->error);
785 - stq_be_p(buf + 8, reply->handle);
786 -
787 -- ret = write_sync(ioc, buf, sizeof(buf));
788 -- if (ret < 0) {
789 -- return ret;
790 -- }
791 --
792 -- if (ret != sizeof(buf)) {
793 -- LOG("writing to socket failed");
794 -- return -EINVAL;
795 -- }
796 -- return 0;
797 -+ return write_sync(ioc, buf, sizeof(buf));
798 - }
799 -
800 - #define MAX_NBD_REQUESTS 16
801 -@@ -1067,7 +987,7 @@ static ssize_t nbd_co_send_reply(NBDRequestData *req, NBDReply *reply,
802 - rc = nbd_send_reply(client->ioc, reply);
803 - if (rc >= 0) {
804 - ret = write_sync(client->ioc, req->data, len);
805 -- if (ret != len) {
806 -+ if (ret < 0) {
807 - rc = -EIO;
808 - }
809 - }
810 -@@ -1141,7 +1061,7 @@ static ssize_t nbd_co_receive_request(NBDRequestData *req,
811 - if (request->type == NBD_CMD_WRITE) {
812 - TRACE("Reading %" PRIu32 " byte(s)", request->len);
813 -
814 -- if (read_sync(client->ioc, req->data, request->len) != request->len) {
815 -+ if (read_sync(client->ioc, req->data, request->len) < 0) {
816 - LOG("reading from socket failed");
817 - rc = -EIO;
818 - goto out;