1
The following changes since commit 411ad78115ebeb3411cf4b7622784b93dfabe259:
1
The following changes since commit 812b835fb4d23dd108b2f9802158472d50b73579:
2
2
3
Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2017-12-15-1' into staging (2017-12-17 15:27:41 +0000)
3
Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2019-05-07' into staging (2019-05-09 16:31:12 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://github.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 996922de45299878cdc4c15b72b19edf2bc618a4:
9
for you to fetch changes up to e84125761f78919fe63616d9888ea45e72dc956f:
10
10
11
block/curl: fix minor memory leaks (2017-12-18 15:44:39 -0500)
11
docs: add Security chapter to the documentation (2019-05-10 10:53:52 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Blockjob and protocol patches
14
Pull request
15
15
----------------------------------------------------------------
16
----------------------------------------------------------------
16
17
17
Jeff Cody (4):
18
Andrey Shinkevich (1):
18
block/sheepdog: remove spurious NULL check
19
block/io.c: fix for the allocation failure
19
block/sheepdog: code beautification
20
block/curl: check error return of curl_global_init()
21
block/curl: fix minor memory leaks
22
20
23
John Snow (1):
21
Jules Irenge (3):
24
blockjob: kick jobs on set-speed
22
util/readline: add a space to fix errors by checkpatch tool
23
util: readline: replace tab indent by four spaces to fix checkpatch
24
errors
25
util/readline: Add braces to fix checkpatch errors
25
26
26
Vladimir Sementsov-Ogievskiy (5):
27
Nikita Alekseev (1):
27
hbitmap: add next_zero function
28
block: Add coroutine_fn to bdrv_check_co_entry
28
backup: move from done_bitmap to copy_bitmap
29
backup: init copy_bitmap from sync_bitmap for incremental
30
backup: simplify non-dirty bits progress processing
31
backup: use copy_bitmap in incremental backup
32
29
33
block/backup.c | 116 +++++++++++++++++-------------
30
Paolo Bonzini (1):
34
block/curl.c | 24 +++++--
31
aio-posix: ensure poll mode is left when aio_notify is called
35
block/dirty-bitmap.c | 5 ++
32
36
block/sheepdog.c | 166 +++++++++++++++++++++----------------------
33
Stefan Hajnoczi (2):
37
blockjob.c | 30 +++++++-
34
docs: add Secure Coding Practices to developer docs
38
include/block/dirty-bitmap.h | 1 +
35
docs: add Security chapter to the documentation
39
include/qemu/hbitmap.h | 8 +++
36
40
tests/test-hbitmap.c | 61 ++++++++++++++++
37
Makefile | 2 +-
41
util/hbitmap.c | 39 ++++++++++
38
block.c | 2 +-
42
9 files changed, 309 insertions(+), 141 deletions(-)
39
block/io.c | 2 +-
40
util/aio-posix.c | 12 +-
41
util/readline.c | 174 ++++++++++++++-----------
42
docs/devel/index.rst | 1 +
43
docs/devel/secure-coding-practices.rst | 106 +++++++++++++++
44
docs/security.texi | 131 +++++++++++++++++++
45
qemu-doc.texi | 3 +
46
9 files changed, 347 insertions(+), 86 deletions(-)
47
create mode 100644 docs/devel/secure-coding-practices.rst
48
create mode 100644 docs/security.texi
43
49
44
--
50
--
45
2.9.5
51
2.21.0
46
52
47
53
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
The function searches for next zero bit.
4
Also add interface for BdrvDirtyBitmap and unit test.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20171012135313.227864-2-vsementsov@virtuozzo.com
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
10
---
11
block/dirty-bitmap.c | 5 ++++
12
include/block/dirty-bitmap.h | 1 +
13
include/qemu/hbitmap.h | 8 ++++++
14
tests/test-hbitmap.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
15
util/hbitmap.c | 39 ++++++++++++++++++++++++++++
16
5 files changed, 114 insertions(+)
17
18
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/dirty-bitmap.c
21
+++ b/block/dirty-bitmap.c
22
@@ -XXX,XX +XXX,XX @@ char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
23
{
24
return hbitmap_sha256(bitmap->bitmap, errp);
25
}
26
+
27
+int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
28
+{
29
+ return hbitmap_next_zero(bitmap->bitmap, offset);
30
+}
31
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/block/dirty-bitmap.h
34
+++ b/include/block/dirty-bitmap.h
35
@@ -XXX,XX +XXX,XX @@ bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
36
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
37
BdrvDirtyBitmap *bitmap);
38
char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp);
39
+int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t start);
40
41
#endif
42
diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/qemu/hbitmap.h
45
+++ b/include/qemu/hbitmap.h
46
@@ -XXX,XX +XXX,XX @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first);
47
*/
48
unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi);
49
50
+/* hbitmap_next_zero:
51
+ * @hb: The HBitmap to operate on
52
+ * @start: The bit to start from.
53
+ *
54
+ * Find next not dirty bit.
55
+ */
56
+int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start);
57
+
58
/* hbitmap_create_meta:
59
* Create a "meta" hbitmap to track dirtiness of the bits in this HBitmap.
60
* The caller owns the created bitmap and must call hbitmap_free_meta(hb) to
61
diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/tests/test-hbitmap.c
64
+++ b/tests/test-hbitmap.c
65
@@ -XXX,XX +XXX,XX @@ static void test_hbitmap_iter_and_reset(TestHBitmapData *data,
66
hbitmap_iter_next(&hbi);
67
}
68
69
+static void test_hbitmap_next_zero_check(TestHBitmapData *data, int64_t start)
70
+{
71
+ int64_t ret1 = hbitmap_next_zero(data->hb, start);
72
+ int64_t ret2 = start;
73
+ for ( ; ret2 < data->size && hbitmap_get(data->hb, ret2); ret2++) {
74
+ ;
75
+ }
76
+ if (ret2 == data->size) {
77
+ ret2 = -1;
78
+ }
79
+
80
+ g_assert_cmpint(ret1, ==, ret2);
81
+}
82
+
83
+static void test_hbitmap_next_zero_do(TestHBitmapData *data, int granularity)
84
+{
85
+ hbitmap_test_init(data, L3, granularity);
86
+ test_hbitmap_next_zero_check(data, 0);
87
+ test_hbitmap_next_zero_check(data, L3 - 1);
88
+
89
+ hbitmap_set(data->hb, L2, 1);
90
+ test_hbitmap_next_zero_check(data, 0);
91
+ test_hbitmap_next_zero_check(data, L2 - 1);
92
+ test_hbitmap_next_zero_check(data, L2);
93
+ test_hbitmap_next_zero_check(data, L2 + 1);
94
+
95
+ hbitmap_set(data->hb, L2 + 5, L1);
96
+ test_hbitmap_next_zero_check(data, 0);
97
+ test_hbitmap_next_zero_check(data, L2 + 1);
98
+ test_hbitmap_next_zero_check(data, L2 + 2);
99
+ test_hbitmap_next_zero_check(data, L2 + 5);
100
+ test_hbitmap_next_zero_check(data, L2 + L1 - 1);
101
+ test_hbitmap_next_zero_check(data, L2 + L1);
102
+
103
+ hbitmap_set(data->hb, L2 * 2, L3 - L2 * 2);
104
+ test_hbitmap_next_zero_check(data, L2 * 2 - L1);
105
+ test_hbitmap_next_zero_check(data, L2 * 2 - 2);
106
+ test_hbitmap_next_zero_check(data, L2 * 2 - 1);
107
+ test_hbitmap_next_zero_check(data, L2 * 2);
108
+ test_hbitmap_next_zero_check(data, L3 - 1);
109
+
110
+ hbitmap_set(data->hb, 0, L3);
111
+ test_hbitmap_next_zero_check(data, 0);
112
+}
113
+
114
+static void test_hbitmap_next_zero_0(TestHBitmapData *data, const void *unused)
115
+{
116
+ test_hbitmap_next_zero_do(data, 0);
117
+}
118
+
119
+static void test_hbitmap_next_zero_4(TestHBitmapData *data, const void *unused)
120
+{
121
+ test_hbitmap_next_zero_do(data, 4);
122
+}
123
+
124
int main(int argc, char **argv)
125
{
126
g_test_init(&argc, &argv, NULL);
127
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
128
129
hbitmap_test_add("/hbitmap/iter/iter_and_reset",
130
test_hbitmap_iter_and_reset);
131
+
132
+ hbitmap_test_add("/hbitmap/next_zero/next_zero_0",
133
+ test_hbitmap_next_zero_0);
134
+ hbitmap_test_add("/hbitmap/next_zero/next_zero_4",
135
+ test_hbitmap_next_zero_4);
136
+
137
g_test_run();
138
139
return 0;
140
diff --git a/util/hbitmap.c b/util/hbitmap.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/util/hbitmap.c
143
+++ b/util/hbitmap.c
144
@@ -XXX,XX +XXX,XX @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first)
145
}
146
}
147
148
+int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start)
149
+{
150
+ size_t pos = (start >> hb->granularity) >> BITS_PER_LEVEL;
151
+ unsigned long *last_lev = hb->levels[HBITMAP_LEVELS - 1];
152
+ uint64_t sz = hb->sizes[HBITMAP_LEVELS - 1];
153
+ unsigned long cur = last_lev[pos];
154
+ unsigned start_bit_offset =
155
+ (start >> hb->granularity) & (BITS_PER_LONG - 1);
156
+ int64_t res;
157
+
158
+ cur |= (1UL << start_bit_offset) - 1;
159
+ assert((start >> hb->granularity) < hb->size);
160
+
161
+ if (cur == (unsigned long)-1) {
162
+ do {
163
+ pos++;
164
+ } while (pos < sz && last_lev[pos] == (unsigned long)-1);
165
+
166
+ if (pos >= sz) {
167
+ return -1;
168
+ }
169
+
170
+ cur = last_lev[pos];
171
+ }
172
+
173
+ res = (pos << BITS_PER_LEVEL) + ctol(cur);
174
+ if (res >= hb->size) {
175
+ return -1;
176
+ }
177
+
178
+ res = res << hb->granularity;
179
+ if (res < start) {
180
+ assert(((start - res) >> hb->granularity) == 0);
181
+ return start;
182
+ }
183
+
184
+ return res;
185
+}
186
+
187
bool hbitmap_empty(const HBitmap *hb)
188
{
189
return hb->count == 0;
190
--
191
2.9.5
192
193
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Use HBitmap copy_bitmap instead of done_bitmap. This is needed to
4
improve incremental backup in following patches and to unify backup
5
loop for full/incremental modes in future patches.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Message-id: 20171012135313.227864-3-vsementsov@virtuozzo.com
12
Signed-off-by: Jeff Cody <jcody@redhat.com>
13
---
14
block/backup.c | 23 ++++++++++++++---------
15
1 file changed, 14 insertions(+), 9 deletions(-)
16
17
diff --git a/block/backup.c b/block/backup.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/backup.c
20
+++ b/block/backup.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
22
BlockdevOnError on_target_error;
23
CoRwlock flush_rwlock;
24
uint64_t bytes_read;
25
- unsigned long *done_bitmap;
26
int64_t cluster_size;
27
bool compress;
28
NotifierWithReturn before_write;
29
QLIST_HEAD(, CowRequest) inflight_reqs;
30
+
31
+ HBitmap *copy_bitmap;
32
} BackupBlockJob;
33
34
/* See if in-flight requests overlap and wait for them to complete */
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
36
cow_request_begin(&cow_request, job, start, end);
37
38
for (; start < end; start += job->cluster_size) {
39
- if (test_bit(start / job->cluster_size, job->done_bitmap)) {
40
+ if (!hbitmap_get(job->copy_bitmap, start / job->cluster_size)) {
41
trace_backup_do_cow_skip(job, start);
42
continue; /* already copied */
43
}
44
+ hbitmap_reset(job->copy_bitmap, start / job->cluster_size, 1);
45
46
trace_backup_do_cow_process(job, start);
47
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
49
if (error_is_read) {
50
*error_is_read = true;
51
}
52
+ hbitmap_set(job->copy_bitmap, start / job->cluster_size, 1);
53
goto out;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
57
if (error_is_read) {
58
*error_is_read = false;
59
}
60
+ hbitmap_set(job->copy_bitmap, start / job->cluster_size, 1);
61
goto out;
62
}
63
64
- set_bit(start / job->cluster_size, job->done_bitmap);
65
-
66
/* Publish progress, guest I/O counts as progress too. Note that the
67
* offset field is an opaque progress value, it is not a disk offset.
68
*/
69
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
70
}
71
72
len = DIV_ROUND_UP(backup_job->common.len, backup_job->cluster_size);
73
- bitmap_zero(backup_job->done_bitmap, len);
74
+ hbitmap_set(backup_job->copy_bitmap, 0, len);
75
}
76
77
void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
78
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
79
BackupBlockJob *job = opaque;
80
BackupCompleteData *data;
81
BlockDriverState *bs = blk_bs(job->common.blk);
82
- int64_t offset;
83
+ int64_t offset, nb_clusters;
84
int ret = 0;
85
86
QLIST_INIT(&job->inflight_reqs);
87
qemu_co_rwlock_init(&job->flush_rwlock);
88
89
- job->done_bitmap = bitmap_new(DIV_ROUND_UP(job->common.len,
90
- job->cluster_size));
91
+ nb_clusters = DIV_ROUND_UP(job->common.len, job->cluster_size);
92
+ job->copy_bitmap = hbitmap_alloc(nb_clusters, 0);
93
+ hbitmap_set(job->copy_bitmap, 0, nb_clusters);
94
95
job->before_write.notify = backup_before_write_notify;
96
bdrv_add_before_write_notifier(bs, &job->before_write);
97
98
if (job->sync_mode == MIRROR_SYNC_MODE_NONE) {
99
+ /* All bits are set in copy_bitmap to allow any cluster to be copied.
100
+ * This does not actually require them to be copied. */
101
while (!block_job_is_cancelled(&job->common)) {
102
/* Yield until the job is cancelled. We just let our before_write
103
* notify callback service CoW requests. */
104
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
105
/* wait until pending backup_do_cow() calls have completed */
106
qemu_co_rwlock_wrlock(&job->flush_rwlock);
107
qemu_co_rwlock_unlock(&job->flush_rwlock);
108
- g_free(job->done_bitmap);
109
+ hbitmap_free(job->copy_bitmap);
110
111
data = g_malloc(sizeof(*data));
112
data->ret = ret;
113
--
114
2.9.5
115
116
diff view generated by jsdifflib
1
Signed-off-by: Jeff Cody <jcody@redhat.com>
1
From: Jules Irenge <jbi.octave@gmail.com>
2
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
2
3
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
util/readline: add a space to fix errors reported by checkpatch.pl tool
4
"ERROR: space required before the open parenthesis"
5
"ERROR: space required after that ..."
6
within "util/redline.c" file
7
8
Signed-off-by: Jules Irenge <jbi.octave@gmail.com>
9
Reviewed-by: Thomas Huth <thuth@redhat.com>
10
Message-id: 20190401024406.10819-2-jbi.octave@gmail.com
11
Message-Id: <20190401024406.10819-2-jbi.octave@gmail.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
---
13
---
5
block/curl.c | 6 ++++++
14
util/readline.c | 34 +++++++++++++++++-----------------
6
1 file changed, 6 insertions(+)
15
1 file changed, 17 insertions(+), 17 deletions(-)
7
16
8
diff --git a/block/curl.c b/block/curl.c
17
diff --git a/util/readline.c b/util/readline.c
9
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
10
--- a/block/curl.c
19
--- a/util/readline.c
11
+++ b/block/curl.c
20
+++ b/util/readline.c
12
@@ -XXX,XX +XXX,XX @@ out_noclean:
21
@@ -XXX,XX +XXX,XX @@ static void readline_update(ReadLineState *rs)
13
qemu_mutex_destroy(&s->mutex);
22
14
g_free(s->cookie);
23
if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
15
g_free(s->url);
24
memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
16
+ g_free(s->username);
25
- for(i = 0; i < rs->last_cmd_buf_index; i++) {
17
+ g_free(s->proxyusername);
26
+ for (i = 0; i < rs->last_cmd_buf_index; i++) {
18
+ g_free(s->proxypassword);
27
rs->printf_func(rs->opaque, "\033[D");
19
qemu_opts_del(opts);
28
}
20
return -EINVAL;
29
rs->cmd_buf[rs->cmd_buf_size] = '\0';
21
}
30
if (rs->read_password) {
22
@@ -XXX,XX +XXX,XX @@ static void curl_close(BlockDriverState *bs)
31
len = strlen(rs->cmd_buf);
23
32
- for(i = 0; i < len; i++)
24
g_free(s->cookie);
33
+ for (i = 0; i < len; i++)
25
g_free(s->url);
34
rs->printf_func(rs->opaque, "*");
26
+ g_free(s->username);
35
} else {
27
+ g_free(s->proxyusername);
36
rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
28
+ g_free(s->proxypassword);
37
@@ -XXX,XX +XXX,XX @@ static void readline_update(ReadLineState *rs)
29
}
38
if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
30
39
delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
31
static int64_t curl_getlength(BlockDriverState *bs)
40
if (delta > 0) {
41
- for(i = 0;i < delta; i++) {
42
+ for (i = 0; i < delta; i++) {
43
rs->printf_func(rs->opaque, "\033[C");
44
}
45
} else {
46
delta = -delta;
47
- for(i = 0;i < delta; i++) {
48
+ for (i = 0; i < delta; i++) {
49
rs->printf_func(rs->opaque, "\033[D");
50
}
51
}
52
@@ -XXX,XX +XXX,XX @@ static void readline_completion(ReadLineState *rs)
53
return;
54
if (rs->nb_completions == 1) {
55
len = strlen(rs->completions[0]);
56
- for(i = rs->completion_index; i < len; i++) {
57
+ for (i = rs->completion_index; i < len; i++) {
58
readline_insert_char(rs, rs->completions[0][i]);
59
}
60
/* extra space for next argument. XXX: make it more generic */
61
@@ -XXX,XX +XXX,XX @@ static void readline_completion(ReadLineState *rs)
62
completion_comp);
63
rs->printf_func(rs->opaque, "\n");
64
max_width = 0;
65
- max_prefix = 0;    
66
- for(i = 0; i < rs->nb_completions; i++) {
67
+ max_prefix = 0;
68
+ for (i = 0; i < rs->nb_completions; i++) {
69
len = strlen(rs->completions[i]);
70
- if (i==0) {
71
+ if (i == 0) {
72
max_prefix = len;
73
} else {
74
if (len < max_prefix)
75
max_prefix = len;
76
- for(j=0; j<max_prefix; j++) {
77
+ for (j = 0; j < max_prefix; j++) {
78
if (rs->completions[i][j] != rs->completions[0][j])
79
max_prefix = j;
80
}
81
@@ -XXX,XX +XXX,XX @@ static void readline_completion(ReadLineState *rs)
82
if (len > max_width)
83
max_width = len;
84
}
85
- if (max_prefix > 0)
86
- for(i = rs->completion_index; i < max_prefix; i++) {
87
+ if (max_prefix > 0)
88
+ for (i = rs->completion_index; i < max_prefix; i++) {
89
readline_insert_char(rs, rs->completions[0][i]);
90
}
91
max_width += 2;
92
@@ -XXX,XX +XXX,XX @@ static void readline_completion(ReadLineState *rs)
93
max_width = 80;
94
nb_cols = 80 / max_width;
95
j = 0;
96
- for(i = 0; i < rs->nb_completions; i++) {
97
+ for (i = 0; i < rs->nb_completions; i++) {
98
rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
99
if (++j == nb_cols || i == (rs->nb_completions - 1)) {
100
rs->printf_func(rs->opaque, "\n");
101
@@ -XXX,XX +XXX,XX @@ static void readline_clear_screen(ReadLineState *rs)
102
/* return true if command handled */
103
void readline_handle_byte(ReadLineState *rs, int ch)
104
{
105
- switch(rs->esc_state) {
106
+ switch (rs->esc_state) {
107
case IS_NORM:
108
- switch(ch) {
109
+ switch (ch) {
110
case 1:
111
readline_bol(rs);
112
break;
113
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
114
}
115
break;
116
case IS_CSI:
117
- switch(ch) {
118
+ switch (ch) {
119
    case 'A':
120
    case 'F':
121
     readline_up_char(rs);
122
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
123
rs->esc_param = rs->esc_param * 10 + (ch - '0');
124
goto the_end;
125
case '~':
126
- switch(rs->esc_param) {
127
+ switch (rs->esc_param) {
128
case 1:
129
readline_bol(rs);
130
break;
131
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
132
the_end:
133
break;
134
case IS_SS3:
135
- switch(ch) {
136
+ switch (ch) {
137
case 'F':
138
readline_eol(rs);
139
break;
32
--
140
--
33
2.9.5
141
2.21.0
34
142
35
143
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Jules Irenge <jbi.octave@gmail.com>
2
2
3
If users set an unreasonably low speed (like one byte per second), the
3
Replace tab indent by four spaces to fix errors issued by checkpatch.pl tool
4
calculated delay may exceed many hours. While we like to punish users
4
"ERROR: code indent should never use tabs" within "util/readline.c" file.
5
for asking for stupid things, we do also like to allow users to correct
6
their wicked ways.
7
5
8
When a user provides a new speed, kick the job to allow it to recalculate
6
Signed-off-by: Jules Irenge <jbi.octave@gmail.com>
9
its delay.
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Message-id: 20190401024406.10819-3-jbi.octave@gmail.com
9
Message-Id: <20190401024406.10819-3-jbi.octave@gmail.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
util/readline.c | 98 ++++++++++++++++++++++++-------------------------
13
1 file changed, 49 insertions(+), 49 deletions(-)
10
14
11
Signed-off-by: John Snow <jsnow@redhat.com>
15
diff --git a/util/readline.c b/util/readline.c
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 20171213204611.26276-1-jsnow@redhat.com
14
Signed-off-by: Jeff Cody <jcody@redhat.com>
15
---
16
blockjob.c | 30 +++++++++++++++++++++++++++++-
17
1 file changed, 29 insertions(+), 1 deletion(-)
18
19
diff --git a/blockjob.c b/blockjob.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/blockjob.c
17
--- a/util/readline.c
22
+++ b/blockjob.c
18
+++ b/util/readline.c
23
@@ -XXX,XX +XXX,XX @@ static void __attribute__((__constructor__)) block_job_init(void)
19
@@ -XXX,XX +XXX,XX @@ static void readline_up_char(ReadLineState *rs)
24
20
int idx;
25
static void block_job_event_cancelled(BlockJob *job);
21
26
static void block_job_event_completed(BlockJob *job, const char *msg);
22
if (rs->hist_entry == 0)
27
+static void block_job_enter_cond(BlockJob *job, bool(*fn)(BlockJob *job));
23
-    return;
28
24
+ return;
29
/* Transactional group of block jobs */
25
if (rs->hist_entry == -1) {
30
struct BlockJobTxn {
26
-    /* Find latest entry */
31
@@ -XXX,XX +XXX,XX @@ static void block_job_completed_txn_success(BlockJob *job)
27
-    for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
28
-     if (rs->history[idx] == NULL)
29
-        break;
30
-    }
31
-    rs->hist_entry = idx;
32
+ /* Find latest entry */
33
+ for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
34
+ if (rs->history[idx] == NULL)
35
+ break;
36
+ }
37
+ rs->hist_entry = idx;
38
}
39
rs->hist_entry--;
40
if (rs->hist_entry >= 0) {
41
-    pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
42
+ pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
43
rs->history[rs->hist_entry]);
44
-    rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
45
+ rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
32
}
46
}
33
}
47
}
34
48
35
+/* Assumes the block_job_mutex is held */
49
@@ -XXX,XX +XXX,XX @@ static void readline_down_char(ReadLineState *rs)
36
+static bool block_job_timer_pending(BlockJob *job)
50
return;
37
+{
51
if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
38
+ return timer_pending(&job->sleep_timer);
52
rs->history[++rs->hist_entry] != NULL) {
39
+}
53
-    pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
40
+
54
+ pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
41
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
55
rs->history[rs->hist_entry]);
42
{
56
} else {
43
Error *local_err = NULL;
57
rs->cmd_buf[0] = 0;
44
+ int64_t old_speed = job->speed;
58
-    rs->hist_entry = -1;
45
59
+ rs->hist_entry = -1;
46
if (!job->driver->set_speed) {
47
error_setg(errp, QERR_UNSUPPORTED);
48
@@ -XXX,XX +XXX,XX @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
49
}
60
}
50
61
rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
51
job->speed = speed;
62
}
52
+ if (speed <= old_speed) {
63
@@ -XXX,XX +XXX,XX @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
64
int idx;
65
66
if (cmdline[0] == '\0')
67
-    return;
53
+ return;
68
+ return;
54
+ }
69
new_entry = NULL;
55
+
70
if (rs->hist_entry != -1) {
56
+ /* kick only if a timer is pending */
71
-    /* We were editing an existing history entry: replace it */
57
+ block_job_enter_cond(job, block_job_timer_pending);
72
-    hist_entry = rs->history[rs->hist_entry];
58
}
73
-    idx = rs->hist_entry;
59
74
-    if (strcmp(hist_entry, cmdline) == 0) {
60
void block_job_complete(BlockJob *job, Error **errp)
75
-     goto same_entry;
61
@@ -XXX,XX +XXX,XX @@ void block_job_resume_all(void)
76
-    }
77
+ /* We were editing an existing history entry: replace it */
78
+ hist_entry = rs->history[rs->hist_entry];
79
+ idx = rs->hist_entry;
80
+ if (strcmp(hist_entry, cmdline) == 0) {
81
+ goto same_entry;
82
+ }
62
}
83
}
63
}
84
/* Search cmdline in history buffers */
64
85
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
65
-void block_job_enter(BlockJob *job)
86
-    hist_entry = rs->history[idx];
66
+/*
87
-    if (hist_entry == NULL)
67
+ * Conditionally enter a block_job pending a call to fn() while
88
-     break;
68
+ * under the block_job_lock critical section.
89
-    if (strcmp(hist_entry, cmdline) == 0) {
69
+ */
90
-    same_entry:
70
+static void block_job_enter_cond(BlockJob *job, bool(*fn)(BlockJob *job))
91
-     new_entry = hist_entry;
71
{
92
-     /* Put this entry at the end of history */
72
if (!block_job_started(job)) {
93
-     memmove(&rs->history[idx], &rs->history[idx + 1],
73
return;
94
-         (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
74
@@ -XXX,XX +XXX,XX @@ void block_job_enter(BlockJob *job)
95
-     rs->history[READLINE_MAX_CMDS - 1] = NULL;
75
return;
96
-     for (; idx < READLINE_MAX_CMDS; idx++) {
97
-        if (rs->history[idx] == NULL)
98
-         break;
99
-     }
100
-     break;
101
-    }
102
+ hist_entry = rs->history[idx];
103
+ if (hist_entry == NULL)
104
+ break;
105
+ if (strcmp(hist_entry, cmdline) == 0) {
106
+ same_entry:
107
+ new_entry = hist_entry;
108
+ /* Put this entry at the end of history */
109
+ memmove(&rs->history[idx], &rs->history[idx + 1],
110
+ (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
111
+ rs->history[READLINE_MAX_CMDS - 1] = NULL;
112
+ for (; idx < READLINE_MAX_CMDS; idx++) {
113
+ if (rs->history[idx] == NULL)
114
+ break;
115
+ }
116
+ break;
117
+ }
76
}
118
}
77
119
if (idx == READLINE_MAX_CMDS) {
78
+ if (fn && !fn(job)) {
120
-    /* Need to get one free slot */
79
+ block_job_unlock();
121
+ /* Need to get one free slot */
80
+ return;
122
g_free(rs->history[0]);
81
+ }
123
-    memmove(rs->history, &rs->history[1],
82
+
124
-     (READLINE_MAX_CMDS - 1) * sizeof(char *));
83
assert(!job->deferred_to_main_loop);
125
-    rs->history[READLINE_MAX_CMDS - 1] = NULL;
84
timer_del(&job->sleep_timer);
126
-    idx = READLINE_MAX_CMDS - 1;
85
job->busy = true;
127
+ memmove(rs->history, &rs->history[1],
86
@@ -XXX,XX +XXX,XX @@ void block_job_enter(BlockJob *job)
128
+ (READLINE_MAX_CMDS - 1) * sizeof(char *));
87
aio_co_wake(job->co);
129
+ rs->history[READLINE_MAX_CMDS - 1] = NULL;
88
}
130
+ idx = READLINE_MAX_CMDS - 1;
89
131
}
90
+void block_job_enter(BlockJob *job)
132
if (new_entry == NULL)
91
+{
133
new_entry = g_strdup(cmdline);
92
+ block_job_enter_cond(job, NULL);
134
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
93
+}
135
case 8:
94
+
136
readline_backspace(rs);
95
bool block_job_is_cancelled(BlockJob *job)
137
break;
96
{
138
-    case 155:
97
return job->cancelled;
139
+ case 155:
140
rs->esc_state = IS_CSI;
141
-     break;
142
+ break;
143
default:
144
if (ch >= 32) {
145
readline_insert_char(rs, ch);
146
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
147
break;
148
case IS_CSI:
149
switch (ch) {
150
-    case 'A':
151
-    case 'F':
152
-     readline_up_char(rs);
153
-     break;
154
-    case 'B':
155
-    case 'E':
156
-     readline_down_char(rs);
157
-     break;
158
+ case 'A':
159
+ case 'F':
160
+ readline_up_char(rs);
161
+ break;
162
+ case 'B':
163
+ case 'E':
164
+ readline_down_char(rs);
165
+ break;
166
case 'D':
167
readline_backward_char(rs);
168
break;
98
--
169
--
99
2.9.5
170
2.21.0
100
171
101
172
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Jules Irenge <jbi.octave@gmail.com>
2
2
3
We can use copy_bitmap instead of sync_bitmap. copy_bitmap is
3
Add braces to fix errors issued by checkpatch.pl tool
4
initialized from sync_bitmap and it is more informative: we will not try
4
"ERROR: braces {} are necessary for all arms of this statement"
5
to process data, that is already in progress (by write notifier).
5
Within "util/readline.c" file
6
Message-Id: <20190330112142.14082-1-jbi.octave@gmail.com>
6
7
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Jeff Cody <jcody@redhat.com>
11
Message-id: 20171012135313.227864-6-vsementsov@virtuozzo.com
12
Signed-off-by: Jeff Cody <jcody@redhat.com>
13
---
9
---
14
block/backup.c | 55 +++++++++++++++++--------------------------------------
10
util/readline.c | 50 ++++++++++++++++++++++++++++++++-----------------
15
1 file changed, 17 insertions(+), 38 deletions(-)
11
1 file changed, 33 insertions(+), 17 deletions(-)
16
12
17
diff --git a/block/backup.c b/block/backup.c
13
diff --git a/util/readline.c b/util/readline.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/block/backup.c
15
--- a/util/readline.c
20
+++ b/block/backup.c
16
+++ b/util/readline.c
21
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job)
17
@@ -XXX,XX +XXX,XX @@ static void readline_update(ReadLineState *rs)
22
18
rs->cmd_buf[rs->cmd_buf_size] = '\0';
23
static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
19
if (rs->read_password) {
20
len = strlen(rs->cmd_buf);
21
- for (i = 0; i < len; i++)
22
+ for (i = 0; i < len; i++) {
23
rs->printf_func(rs->opaque, "*");
24
+ }
25
} else {
26
rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
27
}
28
@@ -XXX,XX +XXX,XX @@ static void readline_up_char(ReadLineState *rs)
24
{
29
{
25
+ int ret;
30
int idx;
26
bool error_is_read;
31
27
- int ret = 0;
32
- if (rs->hist_entry == 0)
28
- int clusters_per_iter;
33
+ if (rs->hist_entry == 0) {
29
- uint32_t granularity;
34
return;
30
- int64_t offset;
35
+ }
31
int64_t cluster;
36
if (rs->hist_entry == -1) {
32
- int64_t end;
37
/* Find latest entry */
33
- BdrvDirtyBitmapIter *dbi;
38
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
34
+ HBitmapIter hbi;
39
- if (rs->history[idx] == NULL)
35
40
+ if (rs->history[idx] == NULL) {
36
- granularity = bdrv_dirty_bitmap_granularity(job->sync_bitmap);
41
break;
37
- clusters_per_iter = MAX((granularity / job->cluster_size), 1);
38
- dbi = bdrv_dirty_iter_new(job->sync_bitmap);
39
-
40
- /* Find the next dirty sector(s) */
41
- while ((offset = bdrv_dirty_iter_next(dbi)) >= 0) {
42
- cluster = offset / job->cluster_size;
43
-
44
- for (end = cluster + clusters_per_iter; cluster < end; cluster++) {
45
- do {
46
- if (yield_and_check(job)) {
47
- goto out;
48
- }
49
- ret = backup_do_cow(job, cluster * job->cluster_size,
50
- job->cluster_size, &error_is_read,
51
- false);
52
- if ((ret < 0) &&
53
- backup_error_action(job, error_is_read, -ret) ==
54
- BLOCK_ERROR_ACTION_REPORT) {
55
- goto out;
56
- }
57
- } while (ret < 0);
58
- }
59
-
60
- /* If the bitmap granularity is smaller than the backup granularity,
61
- * we need to advance the iterator pointer to the next cluster. */
62
- if (granularity < job->cluster_size) {
63
- bdrv_set_dirty_iter(dbi, cluster * job->cluster_size);
64
- }
65
+ hbitmap_iter_init(&hbi, job->copy_bitmap, 0);
66
+ while ((cluster = hbitmap_iter_next(&hbi)) != -1) {
67
+ do {
68
+ if (yield_and_check(job)) {
69
+ return 0;
70
+ }
42
+ }
71
+ ret = backup_do_cow(job, cluster * job->cluster_size,
43
}
72
+ job->cluster_size, &error_is_read, false);
44
rs->hist_entry = idx;
73
+ if (ret < 0 && backup_error_action(job, error_is_read, -ret) ==
45
}
74
+ BLOCK_ERROR_ACTION_REPORT)
46
@@ -XXX,XX +XXX,XX @@ static void readline_up_char(ReadLineState *rs)
75
+ {
47
76
+ return ret;
48
static void readline_down_char(ReadLineState *rs)
49
{
50
- if (rs->hist_entry == -1)
51
+ if (rs->hist_entry == -1) {
52
return;
53
+ }
54
if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
55
rs->history[++rs->hist_entry] != NULL) {
56
pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
57
@@ -XXX,XX +XXX,XX @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
58
char *hist_entry, *new_entry;
59
int idx;
60
61
- if (cmdline[0] == '\0')
62
+ if (cmdline[0] == '\0') {
63
return;
64
+ }
65
new_entry = NULL;
66
if (rs->hist_entry != -1) {
67
/* We were editing an existing history entry: replace it */
68
@@ -XXX,XX +XXX,XX @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
69
/* Search cmdline in history buffers */
70
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
71
hist_entry = rs->history[idx];
72
- if (hist_entry == NULL)
73
+ if (hist_entry == NULL) {
74
break;
75
+ }
76
if (strcmp(hist_entry, cmdline) == 0) {
77
same_entry:
78
new_entry = hist_entry;
79
@@ -XXX,XX +XXX,XX @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
80
(READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
81
rs->history[READLINE_MAX_CMDS - 1] = NULL;
82
for (; idx < READLINE_MAX_CMDS; idx++) {
83
- if (rs->history[idx] == NULL)
84
+ if (rs->history[idx] == NULL) {
85
break;
86
+ }
87
}
88
break;
89
}
90
@@ -XXX,XX +XXX,XX @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
91
rs->history[READLINE_MAX_CMDS - 1] = NULL;
92
idx = READLINE_MAX_CMDS - 1;
93
}
94
- if (new_entry == NULL)
95
+ if (new_entry == NULL) {
96
new_entry = g_strdup(cmdline);
97
+ }
98
rs->history[idx] = new_entry;
99
rs->hist_entry = -1;
100
}
101
@@ -XXX,XX +XXX,XX @@ static void readline_completion(ReadLineState *rs)
102
g_free(cmdline);
103
104
/* no completion found */
105
- if (rs->nb_completions <= 0)
106
+ if (rs->nb_completions <= 0) {
107
return;
108
+ }
109
if (rs->nb_completions == 1) {
110
len = strlen(rs->completions[0]);
111
for (i = rs->completion_index; i < len; i++) {
112
readline_insert_char(rs, rs->completions[0][i]);
113
}
114
/* extra space for next argument. XXX: make it more generic */
115
- if (len > 0 && rs->completions[0][len - 1] != '/')
116
+ if (len > 0 && rs->completions[0][len - 1] != '/') {
117
readline_insert_char(rs, ' ');
118
+ }
119
} else {
120
qsort(rs->completions, rs->nb_completions, sizeof(char *),
121
completion_comp);
122
@@ -XXX,XX +XXX,XX @@ static void readline_completion(ReadLineState *rs)
123
if (i == 0) {
124
max_prefix = len;
125
} else {
126
- if (len < max_prefix)
127
+ if (len < max_prefix) {
128
max_prefix = len;
129
+ }
130
for (j = 0; j < max_prefix; j++) {
131
- if (rs->completions[i][j] != rs->completions[0][j])
132
+ if (rs->completions[i][j] != rs->completions[0][j]) {
133
max_prefix = j;
134
+ }
135
}
136
}
137
- if (len > max_width)
138
+ if (len > max_width) {
139
max_width = len;
77
+ }
140
+ }
78
+ } while (ret < 0);
141
}
79
}
142
if (max_prefix > 0)
80
143
for (i = rs->completion_index; i < max_prefix; i++) {
81
-out:
144
readline_insert_char(rs, rs->completions[0][i]);
82
- bdrv_dirty_iter_free(dbi);
145
}
83
- return ret;
146
max_width += 2;
84
+ return 0;
147
- if (max_width < 10)
148
+ if (max_width < 10) {
149
max_width = 10;
150
- else if (max_width > 80)
151
+ } else if (max_width > 80) {
152
max_width = 80;
153
+ }
154
nb_cols = 80 / max_width;
155
j = 0;
156
for (i = 0; i < rs->nb_completions; i++) {
157
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
158
case 10:
159
case 13:
160
rs->cmd_buf[rs->cmd_buf_size] = '\0';
161
- if (!rs->read_password)
162
+ if (!rs->read_password) {
163
readline_hist_add(rs, rs->cmd_buf);
164
+ }
165
rs->printf_func(rs->opaque, "\n");
166
rs->cmd_buf_index = 0;
167
rs->cmd_buf_size = 0;
168
@@ -XXX,XX +XXX,XX @@ void readline_restart(ReadLineState *rs)
169
170
const char *readline_get_history(ReadLineState *rs, unsigned int index)
171
{
172
- if (index >= READLINE_MAX_CMDS)
173
+ if (index >= READLINE_MAX_CMDS) {
174
return NULL;
175
+ }
176
return rs->history[index];
85
}
177
}
86
178
87
/* init copy_bitmap from sync_bitmap */
88
--
179
--
89
2.9.5
180
2.21.0
90
181
91
182
diff view generated by jsdifflib
1
'tag' is already checked in the lines immediately preceding this check,
1
From: Nikita Alekseev <n.alekseev2104@gmail.com>
2
and set to non-NULL if NULL. No need to check again, it hasn't changed.
3
2
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
bdrv_check_co_entry calls bdrv_co_check, which is a coroutine function.
5
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Thus, it also needs to be marked as a coroutine.
6
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
5
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
Signed-off-by: Nikita Alekseev <n.alekseev2104@gmail.com>
7
Message-id: 20190401093051.16488-1-n.alekseev2104@gmail.com
8
Message-Id: <20190401093051.16488-1-n.alekseev2104@gmail.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
10
---
9
block/sheepdog.c | 2 +-
11
block.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
11
13
12
diff --git a/block/sheepdog.c b/block/sheepdog.c
14
diff --git a/block.c b/block.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/block/sheepdog.c
16
--- a/block.c
15
+++ b/block/sheepdog.c
17
+++ b/block.c
16
@@ -XXX,XX +XXX,XX @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
18
@@ -XXX,XX +XXX,XX @@ typedef struct CheckCo {
17
if (!tag) {
19
int ret;
18
tag = "";
20
} CheckCo;
19
}
21
20
- if (tag && strlen(tag) >= SD_MAX_VDI_TAG_LEN) {
22
-static void bdrv_check_co_entry(void *opaque)
21
+ if (strlen(tag) >= SD_MAX_VDI_TAG_LEN) {
23
+static void coroutine_fn bdrv_check_co_entry(void *opaque)
22
error_setg(errp, "value of parameter 'tag' is too long");
24
{
23
ret = -EINVAL;
25
CheckCo *cco = opaque;
24
goto err_no_fd;
26
cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
25
--
27
--
26
2.9.5
28
2.21.0
27
29
28
30
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
2
3
Set fake progress for non-dirty clusters in copy_bitmap initialization,
3
On a file system used by the customer, fallocate() returns an error
4
to. It simplifies code and allows further refactoring.
4
if the block is not properly aligned. So, bdrv_co_pwrite_zeroes()
5
fails. We can handle that case the same way as it is done for the
6
unsupported cases, namely, call to bdrv_driver_pwritev() that writes
7
zeroes to an image for the unaligned chunk of the block.
5
8
6
This patch changes user's view of backup progress, but formally it
9
Suggested-by: Denis V. Lunev <den@openvz.org>
7
doesn't changed: progress hops are just moved to the beginning.
10
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Message-id: 1554474244-553661-1-git-send-email-andrey.shinkevich@virtuozzo.com
13
Message-Id: <1554474244-553661-1-git-send-email-andrey.shinkevich@virtuozzo.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
16
block/io.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
8
18
9
Actually it's just a point of view: when do we actually skip clusters?
19
diff --git a/block/io.c b/block/io.c
10
We can say in the very beginning, that we skip these clusters and do
11
not think about them later.
12
13
Of course, if go through disk sequentially, it's logical to say, that
14
we skip clusters between copied portions to the left and to the right
15
of them. But even now copying progress is not sequential because of
16
write notifiers. Future patches will introduce new backup architecture
17
which will do copying in several coroutines in parallel, so it will
18
make no sense to publish fake progress by parts in parallel with
19
other copying requests.
20
21
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
22
Reviewed-by: John Snow <jsnow@redhat.com>
23
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
24
Reviewed-by: Jeff Cody <jcody@redhat.com>
25
Message-id: 20171012135313.227864-5-vsementsov@virtuozzo.com
26
Signed-off-by: Jeff Cody <jcody@redhat.com>
27
---
28
block/backup.c | 18 +++---------------
29
1 file changed, 3 insertions(+), 15 deletions(-)
30
31
diff --git a/block/backup.c b/block/backup.c
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
33
--- a/block/backup.c
21
--- a/block/io.c
34
+++ b/block/backup.c
22
+++ b/block/io.c
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
23
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
36
int64_t offset;
24
assert(!bs->supported_zero_flags);
37
int64_t cluster;
38
int64_t end;
39
- int64_t last_cluster = -1;
40
BdrvDirtyBitmapIter *dbi;
41
42
granularity = bdrv_dirty_bitmap_granularity(job->sync_bitmap);
43
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
44
while ((offset = bdrv_dirty_iter_next(dbi)) >= 0) {
45
cluster = offset / job->cluster_size;
46
47
- /* Fake progress updates for any clusters we skipped */
48
- if (cluster != last_cluster + 1) {
49
- job->common.offset += ((cluster - last_cluster - 1) *
50
- job->cluster_size);
51
- }
52
-
53
for (end = cluster + clusters_per_iter; cluster < end; cluster++) {
54
do {
55
if (yield_and_check(job)) {
56
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
57
if (granularity < job->cluster_size) {
58
bdrv_set_dirty_iter(dbi, cluster * job->cluster_size);
59
}
25
}
60
-
26
61
- last_cluster = cluster - 1;
27
- if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) {
62
- }
28
+ if (ret < 0 && !(flags & BDRV_REQ_NO_FALLBACK)) {
63
-
29
/* Fall back to bounce buffer if write zeroes is unsupported */
64
- /* Play some final catchup with the progress meter */
30
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
65
- end = DIV_ROUND_UP(job->common.len, job->cluster_size);
66
- if (last_cluster + 1 < end) {
67
- job->common.offset += ((end - last_cluster - 1) * job->cluster_size);
68
}
69
70
out:
71
@@ -XXX,XX +XXX,XX @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job)
72
bdrv_set_dirty_iter(dbi, next_cluster * job->cluster_size);
73
}
74
75
+ job->common.offset = job->common.len -
76
+ hbitmap_count(job->copy_bitmap) * job->cluster_size;
77
+
78
bdrv_dirty_iter_free(dbi);
79
}
80
31
81
--
32
--
82
2.9.5
33
2.21.0
83
34
84
35
diff view generated by jsdifflib
1
If curl_global_init() fails, per the documentation no other curl
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
functions may be called, so make sure to check the return value.
3
2
4
Also, some minor changes to the initialization latch variable 'inited':
3
With aio=thread, adaptive polling makes latency worse rather than
4
better, because it delays the execution of the ThreadPool's
5
completion bottom half.
5
6
6
- Make it static in the file, for clarity
7
event_notifier_poll() does run while polling, detecting that
7
- Change the name for clarity
8
a bottom half was scheduled by a worker thread, but because
8
- Make it a bool
9
ctx->notifier is explicitly ignored in run_poll_handlers_once(),
10
scheduling the BH does not count as making progress and
11
run_poll_handlers() keeps running. Fix this by recomputing
12
the deadline after *timeout could have changed.
9
13
10
Signed-off-by: Jeff Cody <jcody@redhat.com>
14
With this change, ThreadPool still cannot participate in polling
11
Reviewed-by: Eric Blake <eblake@redhat.com>
15
but at least it does not suffer from extra latency.
12
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
16
13
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
17
Reported-by: Sergio Lopez <slp@redhat.com>
14
Signed-off-by: Jeff Cody <jcody@redhat.com>
18
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
19
Message-id: 20190409122823.12416-1-pbonzini@redhat.com
20
Cc: Stefan Hajnoczi <stefanha@gmail.com>
21
Cc: Kevin Wolf <kwolf@redhat.com>
22
Cc: qemu-block@nongnu.org
23
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24
Message-Id: <1553692145-86728-1-git-send-email-pbonzini@redhat.com>
25
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
26
Message-Id: <20190409122823.12416-1-pbonzini@redhat.com>
27
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
28
---
16
block/curl.c | 18 ++++++++++++------
29
util/aio-posix.c | 12 ++++++++----
17
1 file changed, 12 insertions(+), 6 deletions(-)
30
1 file changed, 8 insertions(+), 4 deletions(-)
18
31
19
diff --git a/block/curl.c b/block/curl.c
32
diff --git a/util/aio-posix.c b/util/aio-posix.c
20
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
21
--- a/block/curl.c
34
--- a/util/aio-posix.c
22
+++ b/block/curl.c
35
+++ b/util/aio-posix.c
23
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
36
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers_once(AioContext *ctx, int64_t *timeout)
24
37
if (!node->deleted && node->io_poll &&
25
struct BDRVCURLState;
38
aio_node_check(ctx, node->is_external) &&
26
39
node->io_poll(node->opaque)) {
27
+static bool libcurl_initialized;
40
+ /*
28
+
41
+ * Polling was successful, exit try_poll_mode immediately
29
typedef struct CURLAIOCB {
42
+ * to adjust the next polling time.
30
Coroutine *co;
43
+ */
31
QEMUIOVector *qiov;
44
*timeout = 0;
32
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
45
if (node->opaque != &ctx->notifier) {
33
double d;
46
progress = true;
34
const char *secretid;
47
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
35
const char *protocol_delimiter;
48
do {
36
+ int ret;
49
progress = run_poll_handlers_once(ctx, timeout);
37
50
elapsed_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time;
38
- static int inited = 0;
51
- } while (!progress && elapsed_time < max_ns
39
52
- && !atomic_read(&ctx->poll_disable_cnt));
40
if (flags & BDRV_O_RDWR) {
53
+ max_ns = qemu_soonest_timeout(*timeout, max_ns);
41
error_setg(errp, "curl block device does not support writes");
54
+ assert(!(max_ns && progress));
42
return -EROFS;
55
+ } while (elapsed_time < max_ns && !atomic_read(&ctx->poll_disable_cnt));
43
}
56
44
57
/* If time has passed with no successful polling, adjust *timeout to
45
+ if (!libcurl_initialized) {
58
* keep the same ending time.
46
+ ret = curl_global_init(CURL_GLOBAL_ALL);
59
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
47
+ if (ret) {
60
*/
48
+ error_setg(errp, "libcurl initialization failed with %d", ret);
61
static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
49
+ return -EIO;
62
{
50
+ }
63
- /* See qemu_soonest_timeout() uint64_t hack */
51
+ libcurl_initialized = true;
64
- int64_t max_ns = MIN((uint64_t)*timeout, (uint64_t)ctx->poll_ns);
52
+ }
65
+ int64_t max_ns = qemu_soonest_timeout(*timeout, ctx->poll_ns);
53
+
66
54
qemu_mutex_init(&s->mutex);
67
if (max_ns && !atomic_read(&ctx->poll_disable_cnt)) {
55
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
68
poll_set_started(ctx, true);
56
qemu_opts_absorb_qdict(opts, options, &local_err);
57
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
58
}
59
}
60
61
- if (!inited) {
62
- curl_global_init(CURL_GLOBAL_ALL);
63
- inited = 1;
64
- }
65
-
66
DPRINTF("CURL: Opening %s\n", file);
67
QSIMPLEQ_INIT(&s->free_state_waitq);
68
s->aio_context = bdrv_get_aio_context(bs);
69
--
69
--
70
2.9.5
70
2.21.0
71
71
72
72
diff view generated by jsdifflib
1
No functional changes, just whitespace manipulation.
1
At KVM Forum 2018 I gave a presentation on security in QEMU:
2
https://www.youtube.com/watch?v=YAdRf_hwxU8 (video)
3
https://vmsplice.net/~stefan/stefanha-kvm-forum-2018.pdf (slides)
2
4
3
Signed-off-by: Jeff Cody <jcody@redhat.com>
5
This patch adds a guide to secure coding practices. This document
4
Reviewed-by: Eric Blake <eblake@redhat.com>
6
covers things that developers should know about security in QEMU. It is
5
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
7
just a starting point that we can expand on later. I hope it will be
6
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
useful as a resource for new contributors and will save code reviewers
9
from explaining the same concepts many times.
10
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
16
Reviewed-by: Li Qiang <liq3ea@gmail.com>
17
Message-id: 20190509121820.16294-2-stefanha@redhat.com
18
Message-Id: <20190509121820.16294-2-stefanha@redhat.com>
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
20
---
8
block/sheepdog.c | 164 +++++++++++++++++++++++++++----------------------------
21
docs/devel/index.rst | 1 +
9
1 file changed, 82 insertions(+), 82 deletions(-)
22
docs/devel/secure-coding-practices.rst | 106 +++++++++++++++++++++++++
23
2 files changed, 107 insertions(+)
24
create mode 100644 docs/devel/secure-coding-practices.rst
10
25
11
diff --git a/block/sheepdog.c b/block/sheepdog.c
26
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
12
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
13
--- a/block/sheepdog.c
28
--- a/docs/devel/index.rst
14
+++ b/block/sheepdog.c
29
+++ b/docs/devel/index.rst
15
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVSheepdogReopenState {
30
@@ -XXX,XX +XXX,XX @@ Contents:
16
int cache_flags;
31
stable-process
17
} BDRVSheepdogReopenState;
32
testing
18
33
decodetree
19
-static const char * sd_strerror(int err)
34
+ secure-coding-practices
20
+static const char *sd_strerror(int err)
35
diff --git a/docs/devel/secure-coding-practices.rst b/docs/devel/secure-coding-practices.rst
21
{
36
new file mode 100644
22
int i;
37
index XXXXXXX..XXXXXXX
23
38
--- /dev/null
24
@@ -XXX,XX +XXX,XX @@ static QemuOptsList sd_create_opts = {
39
+++ b/docs/devel/secure-coding-practices.rst
25
};
40
@@ -XXX,XX +XXX,XX @@
26
41
+=======================
27
static BlockDriver bdrv_sheepdog = {
42
+Secure Coding Practices
28
- .format_name = "sheepdog",
43
+=======================
29
- .protocol_name = "sheepdog",
44
+This document covers topics that both developers and security researchers must
30
- .instance_size = sizeof(BDRVSheepdogState),
45
+be aware of so that they can develop safe code and audit existing code
31
- .bdrv_parse_filename = sd_parse_filename,
46
+properly.
32
- .bdrv_file_open = sd_open,
47
+
33
- .bdrv_reopen_prepare = sd_reopen_prepare,
48
+Reporting Security Bugs
34
- .bdrv_reopen_commit = sd_reopen_commit,
49
+-----------------------
35
- .bdrv_reopen_abort = sd_reopen_abort,
50
+For details on how to report security bugs or ask questions about potential
36
- .bdrv_close = sd_close,
51
+security bugs, see the `Security Process wiki page
37
- .bdrv_create = sd_create,
52
+<https://wiki.qemu.org/SecurityProcess>`_.
38
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
53
+
39
- .bdrv_getlength = sd_getlength,
54
+General Secure C Coding Practices
40
+ .format_name = "sheepdog",
55
+---------------------------------
41
+ .protocol_name = "sheepdog",
56
+Most CVEs (security bugs) reported against QEMU are not specific to
42
+ .instance_size = sizeof(BDRVSheepdogState),
57
+virtualization or emulation. They are simply C programming bugs. Therefore
43
+ .bdrv_parse_filename = sd_parse_filename,
58
+it's critical to be aware of common classes of security bugs.
44
+ .bdrv_file_open = sd_open,
59
+
45
+ .bdrv_reopen_prepare = sd_reopen_prepare,
60
+There is a wide selection of resources available covering secure C coding. For
46
+ .bdrv_reopen_commit = sd_reopen_commit,
61
+example, the `CERT C Coding Standard
47
+ .bdrv_reopen_abort = sd_reopen_abort,
62
+<https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard>`_
48
+ .bdrv_close = sd_close,
63
+covers the most important classes of security bugs.
49
+ .bdrv_create = sd_create,
64
+
50
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
65
+Instead of describing them in detail here, only the names of the most important
51
+ .bdrv_getlength = sd_getlength,
66
+classes of security bugs are mentioned:
52
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
67
+
53
- .bdrv_truncate = sd_truncate,
68
+* Buffer overflows
54
+ .bdrv_truncate = sd_truncate,
69
+* Use-after-free and double-free
55
70
+* Integer overflows
56
- .bdrv_co_readv = sd_co_readv,
71
+* Format string vulnerabilities
57
- .bdrv_co_writev = sd_co_writev,
72
+
58
- .bdrv_co_flush_to_disk = sd_co_flush_to_disk,
73
+Some of these classes of bugs can be detected by analyzers. Static analysis is
59
- .bdrv_co_pdiscard = sd_co_pdiscard,
74
+performed regularly by Coverity and the most obvious of these bugs are even
60
- .bdrv_co_get_block_status = sd_co_get_block_status,
75
+reported by compilers. Dynamic analysis is possible with valgrind, tsan, and
61
+ .bdrv_co_readv = sd_co_readv,
76
+asan.
62
+ .bdrv_co_writev = sd_co_writev,
77
+
63
+ .bdrv_co_flush_to_disk = sd_co_flush_to_disk,
78
+Input Validation
64
+ .bdrv_co_pdiscard = sd_co_pdiscard,
79
+----------------
65
+ .bdrv_co_get_block_status = sd_co_get_block_status,
80
+Inputs from the guest or external sources (e.g. network, files) cannot be
66
81
+trusted and may be invalid. Inputs must be checked before using them in a way
67
- .bdrv_snapshot_create = sd_snapshot_create,
82
+that could crash the program, expose host memory to the guest, or otherwise be
68
- .bdrv_snapshot_goto = sd_snapshot_goto,
83
+exploitable by an attacker.
69
- .bdrv_snapshot_delete = sd_snapshot_delete,
84
+
70
- .bdrv_snapshot_list = sd_snapshot_list,
85
+The most sensitive attack surface is device emulation. All hardware register
71
+ .bdrv_snapshot_create = sd_snapshot_create,
86
+accesses and data read from guest memory must be validated. A typical example
72
+ .bdrv_snapshot_goto = sd_snapshot_goto,
87
+is a device that contains multiple units that are selectable by the guest via
73
+ .bdrv_snapshot_delete = sd_snapshot_delete,
88
+an index register::
74
+ .bdrv_snapshot_list = sd_snapshot_list,
89
+
75
90
+ typedef struct {
76
- .bdrv_save_vmstate = sd_save_vmstate,
91
+ ProcessingUnit unit[2];
77
- .bdrv_load_vmstate = sd_load_vmstate,
92
+ ...
78
+ .bdrv_save_vmstate = sd_save_vmstate,
93
+ } MyDeviceState;
79
+ .bdrv_load_vmstate = sd_load_vmstate,
94
+
80
95
+ static void mydev_writel(void *opaque, uint32_t addr, uint32_t val)
81
- .bdrv_detach_aio_context = sd_detach_aio_context,
96
+ {
82
- .bdrv_attach_aio_context = sd_attach_aio_context,
97
+ MyDeviceState *mydev = opaque;
83
+ .bdrv_detach_aio_context = sd_detach_aio_context,
98
+ ProcessingUnit *unit;
84
+ .bdrv_attach_aio_context = sd_attach_aio_context,
99
+
85
100
+ switch (addr) {
86
- .create_opts = &sd_create_opts,
101
+ case MYDEV_SELECT_UNIT:
87
+ .create_opts = &sd_create_opts,
102
+ unit = &mydev->unit[val]; <-- this input wasn't validated!
88
};
103
+ ...
89
104
+ }
90
static BlockDriver bdrv_sheepdog_tcp = {
105
+ }
91
- .format_name = "sheepdog",
106
+
92
- .protocol_name = "sheepdog+tcp",
107
+If ``val`` is not in range [0, 1] then an out-of-bounds memory access will take
93
- .instance_size = sizeof(BDRVSheepdogState),
108
+place when ``unit`` is dereferenced. The code must check that ``val`` is 0 or
94
- .bdrv_parse_filename = sd_parse_filename,
109
+1 and handle the case where it is invalid.
95
- .bdrv_file_open = sd_open,
110
+
96
- .bdrv_reopen_prepare = sd_reopen_prepare,
111
+Unexpected Device Accesses
97
- .bdrv_reopen_commit = sd_reopen_commit,
112
+--------------------------
98
- .bdrv_reopen_abort = sd_reopen_abort,
113
+The guest may access device registers in unusual orders or at unexpected
99
- .bdrv_close = sd_close,
114
+moments. Device emulation code must not assume that the guest follows the
100
- .bdrv_create = sd_create,
115
+typical "theory of operation" presented in driver writer manuals. The guest
101
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
116
+may make nonsense accesses to device registers such as starting operations
102
- .bdrv_getlength = sd_getlength,
117
+before the device has been fully initialized.
103
+ .format_name = "sheepdog",
118
+
104
+ .protocol_name = "sheepdog+tcp",
119
+A related issue is that device emulation code must be prepared for unexpected
105
+ .instance_size = sizeof(BDRVSheepdogState),
120
+device register accesses while asynchronous operations are in progress. A
106
+ .bdrv_parse_filename = sd_parse_filename,
121
+well-behaved guest might wait for a completion interrupt before accessing
107
+ .bdrv_file_open = sd_open,
122
+certain device registers. Device emulation code must handle the case where the
108
+ .bdrv_reopen_prepare = sd_reopen_prepare,
123
+guest overwrites registers or submits further requests before an ongoing
109
+ .bdrv_reopen_commit = sd_reopen_commit,
124
+request completes. Unexpected accesses must not cause memory corruption or
110
+ .bdrv_reopen_abort = sd_reopen_abort,
125
+leaks in QEMU.
111
+ .bdrv_close = sd_close,
126
+
112
+ .bdrv_create = sd_create,
127
+Invalid device register accesses can be reported with
113
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
128
+``qemu_log_mask(LOG_GUEST_ERROR, ...)``. The ``-d guest_errors`` command-line
114
+ .bdrv_getlength = sd_getlength,
129
+option enables these log messages.
115
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
130
+
116
- .bdrv_truncate = sd_truncate,
131
+Live Migration
117
+ .bdrv_truncate = sd_truncate,
132
+--------------
118
133
+Device state can be saved to disk image files and shared with other users.
119
- .bdrv_co_readv = sd_co_readv,
134
+Live migration code must validate inputs when loading device state so an
120
- .bdrv_co_writev = sd_co_writev,
135
+attacker cannot gain control by crafting invalid device states. Device state
121
- .bdrv_co_flush_to_disk = sd_co_flush_to_disk,
136
+is therefore considered untrusted even though it is typically generated by QEMU
122
- .bdrv_co_pdiscard = sd_co_pdiscard,
137
+itself.
123
- .bdrv_co_get_block_status = sd_co_get_block_status,
138
+
124
+ .bdrv_co_readv = sd_co_readv,
139
+Guest Memory Access Races
125
+ .bdrv_co_writev = sd_co_writev,
140
+-------------------------
126
+ .bdrv_co_flush_to_disk = sd_co_flush_to_disk,
141
+Guests with multiple vCPUs may modify guest RAM while device emulation code is
127
+ .bdrv_co_pdiscard = sd_co_pdiscard,
142
+running. Device emulation code must copy in descriptors and other guest RAM
128
+ .bdrv_co_get_block_status = sd_co_get_block_status,
143
+structures and only process the local copy. This prevents
129
144
+time-of-check-to-time-of-use (TOCTOU) race conditions that could cause QEMU to
130
- .bdrv_snapshot_create = sd_snapshot_create,
145
+crash when a vCPU thread modifies guest RAM while device emulation is
131
- .bdrv_snapshot_goto = sd_snapshot_goto,
146
+processing it.
132
- .bdrv_snapshot_delete = sd_snapshot_delete,
133
- .bdrv_snapshot_list = sd_snapshot_list,
134
+ .bdrv_snapshot_create = sd_snapshot_create,
135
+ .bdrv_snapshot_goto = sd_snapshot_goto,
136
+ .bdrv_snapshot_delete = sd_snapshot_delete,
137
+ .bdrv_snapshot_list = sd_snapshot_list,
138
139
- .bdrv_save_vmstate = sd_save_vmstate,
140
- .bdrv_load_vmstate = sd_load_vmstate,
141
+ .bdrv_save_vmstate = sd_save_vmstate,
142
+ .bdrv_load_vmstate = sd_load_vmstate,
143
144
- .bdrv_detach_aio_context = sd_detach_aio_context,
145
- .bdrv_attach_aio_context = sd_attach_aio_context,
146
+ .bdrv_detach_aio_context = sd_detach_aio_context,
147
+ .bdrv_attach_aio_context = sd_attach_aio_context,
148
149
- .create_opts = &sd_create_opts,
150
+ .create_opts = &sd_create_opts,
151
};
152
153
static BlockDriver bdrv_sheepdog_unix = {
154
- .format_name = "sheepdog",
155
- .protocol_name = "sheepdog+unix",
156
- .instance_size = sizeof(BDRVSheepdogState),
157
- .bdrv_parse_filename = sd_parse_filename,
158
- .bdrv_file_open = sd_open,
159
- .bdrv_reopen_prepare = sd_reopen_prepare,
160
- .bdrv_reopen_commit = sd_reopen_commit,
161
- .bdrv_reopen_abort = sd_reopen_abort,
162
- .bdrv_close = sd_close,
163
- .bdrv_create = sd_create,
164
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
165
- .bdrv_getlength = sd_getlength,
166
+ .format_name = "sheepdog",
167
+ .protocol_name = "sheepdog+unix",
168
+ .instance_size = sizeof(BDRVSheepdogState),
169
+ .bdrv_parse_filename = sd_parse_filename,
170
+ .bdrv_file_open = sd_open,
171
+ .bdrv_reopen_prepare = sd_reopen_prepare,
172
+ .bdrv_reopen_commit = sd_reopen_commit,
173
+ .bdrv_reopen_abort = sd_reopen_abort,
174
+ .bdrv_close = sd_close,
175
+ .bdrv_create = sd_create,
176
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
177
+ .bdrv_getlength = sd_getlength,
178
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
179
- .bdrv_truncate = sd_truncate,
180
+ .bdrv_truncate = sd_truncate,
181
182
- .bdrv_co_readv = sd_co_readv,
183
- .bdrv_co_writev = sd_co_writev,
184
- .bdrv_co_flush_to_disk = sd_co_flush_to_disk,
185
- .bdrv_co_pdiscard = sd_co_pdiscard,
186
- .bdrv_co_get_block_status = sd_co_get_block_status,
187
+ .bdrv_co_readv = sd_co_readv,
188
+ .bdrv_co_writev = sd_co_writev,
189
+ .bdrv_co_flush_to_disk = sd_co_flush_to_disk,
190
+ .bdrv_co_pdiscard = sd_co_pdiscard,
191
+ .bdrv_co_get_block_status = sd_co_get_block_status,
192
193
- .bdrv_snapshot_create = sd_snapshot_create,
194
- .bdrv_snapshot_goto = sd_snapshot_goto,
195
- .bdrv_snapshot_delete = sd_snapshot_delete,
196
- .bdrv_snapshot_list = sd_snapshot_list,
197
+ .bdrv_snapshot_create = sd_snapshot_create,
198
+ .bdrv_snapshot_goto = sd_snapshot_goto,
199
+ .bdrv_snapshot_delete = sd_snapshot_delete,
200
+ .bdrv_snapshot_list = sd_snapshot_list,
201
202
- .bdrv_save_vmstate = sd_save_vmstate,
203
- .bdrv_load_vmstate = sd_load_vmstate,
204
+ .bdrv_save_vmstate = sd_save_vmstate,
205
+ .bdrv_load_vmstate = sd_load_vmstate,
206
207
- .bdrv_detach_aio_context = sd_detach_aio_context,
208
- .bdrv_attach_aio_context = sd_attach_aio_context,
209
+ .bdrv_detach_aio_context = sd_detach_aio_context,
210
+ .bdrv_attach_aio_context = sd_attach_aio_context,
211
212
- .create_opts = &sd_create_opts,
213
+ .create_opts = &sd_create_opts,
214
};
215
216
static void bdrv_sheepdog_init(void)
217
--
147
--
218
2.9.5
148
2.21.0
219
149
220
150
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This new chapter in the QEMU documentation covers the security
2
requirements that QEMU is designed to meet and principles for securely
3
deploying QEMU.
2
4
3
We should not copy non-dirty clusters in write notifiers. So,
5
It is just a starting point that can be extended in the future with more
4
initialize copy_bitmap from sync_bitmap.
6
information.
5
7
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
9
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20171012135313.227864-4-vsementsov@virtuozzo.com
12
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
11
Signed-off-by: Jeff Cody <jcody@redhat.com>
13
Reviewed-by: Li Qiang <liq3ea@gmail.com>
14
Message-id: 20190509121820.16294-3-stefanha@redhat.com
15
Message-Id: <20190509121820.16294-3-stefanha@redhat.com>
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
17
---
13
block/backup.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
18
Makefile | 2 +-
14
1 file changed, 43 insertions(+), 1 deletion(-)
19
docs/security.texi | 131 +++++++++++++++++++++++++++++++++++++++++++++
20
qemu-doc.texi | 3 ++
21
3 files changed, 135 insertions(+), 1 deletion(-)
22
create mode 100644 docs/security.texi
15
23
16
diff --git a/block/backup.c b/block/backup.c
24
diff --git a/Makefile b/Makefile
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/block/backup.c
26
--- a/Makefile
19
+++ b/block/backup.c
27
+++ b/Makefile
20
@@ -XXX,XX +XXX,XX @@ out:
28
@@ -XXX,XX +XXX,XX @@ qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
21
return ret;
29
    qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \
22
}
30
    qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
23
31
    qemu-monitor-info.texi docs/qemu-block-drivers.texi \
24
+/* init copy_bitmap from sync_bitmap */
32
-    docs/qemu-cpu-models.texi
25
+static void backup_incremental_init_copy_bitmap(BackupBlockJob *job)
33
+    docs/qemu-cpu-models.texi docs/security.texi
26
+{
34
27
+ BdrvDirtyBitmapIter *dbi;
35
docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \
28
+ int64_t offset;
36
docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \
29
+ int64_t end = DIV_ROUND_UP(bdrv_dirty_bitmap_size(job->sync_bitmap),
37
diff --git a/docs/security.texi b/docs/security.texi
30
+ job->cluster_size);
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/docs/security.texi
42
@@ -XXX,XX +XXX,XX @@
43
+@node Security
44
+@chapter Security
31
+
45
+
32
+ dbi = bdrv_dirty_iter_new(job->sync_bitmap);
46
+@section Overview
33
+ while ((offset = bdrv_dirty_iter_next(dbi)) != -1) {
34
+ int64_t cluster = offset / job->cluster_size;
35
+ int64_t next_cluster;
36
+
47
+
37
+ offset += bdrv_dirty_bitmap_granularity(job->sync_bitmap);
48
+This chapter explains the security requirements that QEMU is designed to meet
38
+ if (offset >= bdrv_dirty_bitmap_size(job->sync_bitmap)) {
49
+and principles for securely deploying QEMU.
39
+ hbitmap_set(job->copy_bitmap, cluster, end - cluster);
40
+ break;
41
+ }
42
+
50
+
43
+ offset = bdrv_dirty_bitmap_next_zero(job->sync_bitmap, offset);
51
+@section Security Requirements
44
+ if (offset == -1) {
45
+ hbitmap_set(job->copy_bitmap, cluster, end - cluster);
46
+ break;
47
+ }
48
+
52
+
49
+ next_cluster = DIV_ROUND_UP(offset, job->cluster_size);
53
+QEMU supports many different use cases, some of which have stricter security
50
+ hbitmap_set(job->copy_bitmap, cluster, next_cluster - cluster);
54
+requirements than others. The community has agreed on the overall security
51
+ if (next_cluster >= end) {
55
+requirements that users may depend on. These requirements define what is
52
+ break;
56
+considered supported from a security perspective.
53
+ }
54
+
57
+
55
+ bdrv_set_dirty_iter(dbi, next_cluster * job->cluster_size);
58
+@subsection Virtualization Use Case
56
+ }
57
+
59
+
58
+ bdrv_dirty_iter_free(dbi);
60
+The virtualization use case covers cloud and virtual private server (VPS)
59
+}
61
+hosting, as well as traditional data center and desktop virtualization. These
62
+use cases rely on hardware virtualization extensions to execute guest code
63
+safely on the physical CPU at close-to-native speed.
60
+
64
+
61
static void coroutine_fn backup_run(void *opaque)
65
+The following entities are untrusted, meaning that they may be buggy or
62
{
66
+malicious:
63
BackupBlockJob *job = opaque;
64
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
65
66
nb_clusters = DIV_ROUND_UP(job->common.len, job->cluster_size);
67
job->copy_bitmap = hbitmap_alloc(nb_clusters, 0);
68
- hbitmap_set(job->copy_bitmap, 0, nb_clusters);
69
+ if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
70
+ backup_incremental_init_copy_bitmap(job);
71
+ } else {
72
+ hbitmap_set(job->copy_bitmap, 0, nb_clusters);
73
+ }
74
+
67
+
75
68
+@itemize
76
job->before_write.notify = backup_before_write_notify;
69
+@item Guest
77
bdrv_add_before_write_notifier(bs, &job->before_write);
70
+@item User-facing interfaces (e.g. VNC, SPICE, WebSocket)
71
+@item Network protocols (e.g. NBD, live migration)
72
+@item User-supplied files (e.g. disk images, kernels, device trees)
73
+@item Passthrough devices (e.g. PCI, USB)
74
+@end itemize
75
+
76
+Bugs affecting these entities are evaluated on whether they can cause damage in
77
+real-world use cases and treated as security bugs if this is the case.
78
+
79
+@subsection Non-virtualization Use Case
80
+
81
+The non-virtualization use case covers emulation using the Tiny Code Generator
82
+(TCG). In principle the TCG and device emulation code used in conjunction with
83
+the non-virtualization use case should meet the same security requirements as
84
+the virtualization use case. However, for historical reasons much of the
85
+non-virtualization use case code was not written with these security
86
+requirements in mind.
87
+
88
+Bugs affecting the non-virtualization use case are not considered security
89
+bugs at this time. Users with non-virtualization use cases must not rely on
90
+QEMU to provide guest isolation or any security guarantees.
91
+
92
+@section Architecture
93
+
94
+This section describes the design principles that ensure the security
95
+requirements are met.
96
+
97
+@subsection Guest Isolation
98
+
99
+Guest isolation is the confinement of guest code to the virtual machine. When
100
+guest code gains control of execution on the host this is called escaping the
101
+virtual machine. Isolation also includes resource limits such as throttling of
102
+CPU, memory, disk, or network. Guests must be unable to exceed their resource
103
+limits.
104
+
105
+QEMU presents an attack surface to the guest in the form of emulated devices.
106
+The guest must not be able to gain control of QEMU. Bugs in emulated devices
107
+could allow malicious guests to gain code execution in QEMU. At this point the
108
+guest has escaped the virtual machine and is able to act in the context of the
109
+QEMU process on the host.
110
+
111
+Guests often interact with other guests and share resources with them. A
112
+malicious guest must not gain control of other guests or access their data.
113
+Disk image files and network traffic must be protected from other guests unless
114
+explicitly shared between them by the user.
115
+
116
+@subsection Principle of Least Privilege
117
+
118
+The principle of least privilege states that each component only has access to
119
+the privileges necessary for its function. In the case of QEMU this means that
120
+each process only has access to resources belonging to the guest.
121
+
122
+The QEMU process should not have access to any resources that are inaccessible
123
+to the guest. This way the guest does not gain anything by escaping into the
124
+QEMU process since it already has access to those same resources from within
125
+the guest.
126
+
127
+Following the principle of least privilege immediately fulfills guest isolation
128
+requirements. For example, guest A only has access to its own disk image file
129
+@code{a.img} and not guest B's disk image file @code{b.img}.
130
+
131
+In reality certain resources are inaccessible to the guest but must be
132
+available to QEMU to perform its function. For example, host system calls are
133
+necessary for QEMU but are not exposed to guests. A guest that escapes into
134
+the QEMU process can then begin invoking host system calls.
135
+
136
+New features must be designed to follow the principle of least privilege.
137
+Should this not be possible for technical reasons, the security risk must be
138
+clearly documented so users are aware of the trade-off of enabling the feature.
139
+
140
+@subsection Isolation mechanisms
141
+
142
+Several isolation mechanisms are available to realize this architecture of
143
+guest isolation and the principle of least privilege. With the exception of
144
+Linux seccomp, these mechanisms are all deployed by management tools that
145
+launch QEMU, such as libvirt. They are also platform-specific so they are only
146
+described briefly for Linux here.
147
+
148
+The fundamental isolation mechanism is that QEMU processes must run as
149
+unprivileged users. Sometimes it seems more convenient to launch QEMU as
150
+root to give it access to host devices (e.g. @code{/dev/net/tun}) but this poses a
151
+huge security risk. File descriptor passing can be used to give an otherwise
152
+unprivileged QEMU process access to host devices without running QEMU as root.
153
+It is also possible to launch QEMU as a non-root user and configure UNIX groups
154
+for access to @code{/dev/kvm}, @code{/dev/net/tun}, and other device nodes.
155
+Some Linux distros already ship with UNIX groups for these devices by default.
156
+
157
+@itemize
158
+@item SELinux and AppArmor make it possible to confine processes beyond the
159
+traditional UNIX process and file permissions model. They restrict the QEMU
160
+process from accessing processes and files on the host system that are not
161
+needed by QEMU.
162
+
163
+@item Resource limits and cgroup controllers provide throughput and utilization
164
+limits on key resources such as CPU time, memory, and I/O bandwidth.
165
+
166
+@item Linux namespaces can be used to make process, file system, and other system
167
+resources unavailable to QEMU. A namespaced QEMU process is restricted to only
168
+those resources that were granted to it.
169
+
170
+@item Linux seccomp is available via the QEMU @option{--sandbox} option. It disables
171
+system calls that are not needed by QEMU, thereby reducing the host kernel
172
+attack surface.
173
+@end itemize
174
diff --git a/qemu-doc.texi b/qemu-doc.texi
175
index XXXXXXX..XXXXXXX 100644
176
--- a/qemu-doc.texi
177
+++ b/qemu-doc.texi
178
@@ -XXX,XX +XXX,XX @@
179
* QEMU Guest Agent::
180
* QEMU User space emulator::
181
* System requirements::
182
+* Security::
183
* Implementation notes::
184
* Deprecated features::
185
* Supported build platforms::
186
@@ -XXX,XX +XXX,XX @@ added with Linux 4.5 which is supported by the major distros. And even
187
if RHEL7 has kernel 3.10, KVM there has the required functionality there
188
to make it close to a 4.5 or newer kernel.
189
190
+@include docs/security.texi
191
+
192
@include qemu-tech.texi
193
194
@include qemu-deprecated.texi
78
--
195
--
79
2.9.5
196
2.21.0
80
197
81
198
diff view generated by jsdifflib