1
The following changes since commit c416eecea5f3aea863ab8fda5a36a24157b8f704:
1
The following changes since commit 812b835fb4d23dd108b2f9802158472d50b73579:
2
2
3
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2018-05-15 17:02:00 +0100)
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 c82be42cc803b36fd7aed5dceec68312c7056fd5:
9
for you to fetch changes up to e84125761f78919fe63616d9888ea45e72dc956f:
10
10
11
nfs: Remove processed options from QDict (2018-05-16 13:37:47 -0400)
11
docs: add Security chapter to the documentation (2019-05-10 10:53:52 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches
14
Pull request
15
15
----------------------------------------------------------------
16
----------------------------------------------------------------
16
17
17
Kevin Wolf (2):
18
Andrey Shinkevich (1):
18
nfs: Fix error path in nfs_options_qdict_to_qapi()
19
block/io.c: fix for the allocation failure
19
nfs: Remove processed options from QDict
20
21
Jules Irenge (3):
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
26
27
Nikita Alekseev (1):
28
block: Add coroutine_fn to bdrv_check_co_entry
29
30
Paolo Bonzini (1):
31
aio-posix: ensure poll mode is left when aio_notify is called
20
32
21
Stefan Hajnoczi (2):
33
Stefan Hajnoczi (2):
22
qemu-iotests: reduce chance of races in 185
34
docs: add Secure Coding Practices to developer docs
23
blockjob: do not cancel timer in resume
35
docs: add Security chapter to the documentation
24
36
25
block/nfs.c | 8 ++++++++
37
Makefile | 2 +-
26
blockjob.c | 22 +++++++++++++++-------
38
block.c | 2 +-
27
tests/qemu-iotests/185 | 17 +++++++++++++----
39
block/io.c | 2 +-
28
tests/qemu-iotests/185.out | 12 +++++-------
40
util/aio-posix.c | 12 +-
29
4 files changed, 41 insertions(+), 18 deletions(-)
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
30
49
31
--
50
--
32
2.13.6
51
2.21.0
33
52
34
53
diff view generated by jsdifflib
New patch
1
From: Jules Irenge <jbi.octave@gmail.com>
1
2
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>
13
---
14
util/readline.c | 34 +++++++++++++++++-----------------
15
1 file changed, 17 insertions(+), 17 deletions(-)
16
17
diff --git a/util/readline.c b/util/readline.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/util/readline.c
20
+++ b/util/readline.c
21
@@ -XXX,XX +XXX,XX @@ static void readline_update(ReadLineState *rs)
22
23
if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
24
memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
25
- for(i = 0; i < rs->last_cmd_buf_index; i++) {
26
+ for (i = 0; i < rs->last_cmd_buf_index; i++) {
27
rs->printf_func(rs->opaque, "\033[D");
28
}
29
rs->cmd_buf[rs->cmd_buf_size] = '\0';
30
if (rs->read_password) {
31
len = strlen(rs->cmd_buf);
32
- for(i = 0; i < len; i++)
33
+ for (i = 0; i < len; i++)
34
rs->printf_func(rs->opaque, "*");
35
} else {
36
rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
37
@@ -XXX,XX +XXX,XX @@ static void readline_update(ReadLineState *rs)
38
if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
39
delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
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;
140
--
141
2.21.0
142
143
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Jules Irenge <jbi.octave@gmail.com>
2
2
3
Currently the timer is cancelled and the block job is entered by
3
Replace tab indent by four spaces to fix errors issued by checkpatch.pl tool
4
block_job_resume(). This behavior causes drain to run extra blockjob
4
"ERROR: code indent should never use tabs" within "util/readline.c" file.
5
iterations when the job was sleeping due to the ratelimit.
6
5
7
This patch leaves the job asleep when block_job_resume() is called.
6
Signed-off-by: Jules Irenge <jbi.octave@gmail.com>
8
Jobs can still be forcibly woken up using block_job_enter(), which is
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
9
used to cancel jobs.
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
After this patch drain no longer runs extra blockjob iterations. This
15
diff --git a/util/readline.c b/util/readline.c
12
is the expected behavior that qemu-iotests 185 used to rely on. We
13
temporarily changed the 185 test output to make it pass for the QEMU
14
2.12 release but now it's time to address this issue.
15
16
Cc: QingFeng Hao <haoqf@linux.vnet.ibm.com>
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
20
Message-id: 20180508135436.30140-3-stefanha@redhat.com
21
Reviewed-by: Jeff Cody <jcody@redhat.com>
22
Signed-off-by: Jeff Cody <jcody@redhat.com>
23
---
24
blockjob.c | 22 +++++++++++++++-------
25
tests/qemu-iotests/185 | 5 +----
26
tests/qemu-iotests/185.out | 12 +++++-------
27
3 files changed, 21 insertions(+), 18 deletions(-)
28
29
diff --git a/blockjob.c b/blockjob.c
30
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
31
--- a/blockjob.c
17
--- a/util/readline.c
32
+++ b/blockjob.c
18
+++ b/util/readline.c
33
@@ -XXX,XX +XXX,XX @@ static void block_job_txn_del_job(BlockJob *job)
19
@@ -XXX,XX +XXX,XX @@ static void readline_up_char(ReadLineState *rs)
20
int idx;
21
22
if (rs->hist_entry == 0)
23
-    return;
24
+ return;
25
if (rs->hist_entry == -1) {
26
-    /* Find latest entry */
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);
34
}
46
}
35
}
47
}
36
48
37
+/* Assumes the block_job_mutex is held */
49
@@ -XXX,XX +XXX,XX @@ static void readline_down_char(ReadLineState *rs)
38
+static bool block_job_timer_pending(BlockJob *job)
39
+{
40
+ return timer_pending(&job->sleep_timer);
41
+}
42
+
43
+/* Assumes the block_job_mutex is held */
44
+static bool block_job_timer_not_pending(BlockJob *job)
45
+{
46
+ return !block_job_timer_pending(job);
47
+}
48
+
49
static void block_job_pause(BlockJob *job)
50
{
51
job->pause_count++;
52
@@ -XXX,XX +XXX,XX @@ static void block_job_resume(BlockJob *job)
53
if (job->pause_count) {
54
return;
50
return;
51
if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
52
rs->history[++rs->hist_entry] != NULL) {
53
-    pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
54
+ pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
55
rs->history[rs->hist_entry]);
56
} else {
57
rs->cmd_buf[0] = 0;
58
-    rs->hist_entry = -1;
59
+ rs->hist_entry = -1;
55
}
60
}
56
- block_job_enter(job);
61
rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
57
+
58
+ /* kick only if no timer is pending */
59
+ block_job_enter_cond(job, block_job_timer_not_pending);
60
}
62
}
61
63
@@ -XXX,XX +XXX,XX @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
62
void block_job_ref(BlockJob *job)
64
int idx;
63
@@ -XXX,XX +XXX,XX @@ static void block_job_completed_txn_success(BlockJob *job)
65
66
if (cmdline[0] == '\0')
67
-    return;
68
+ return;
69
new_entry = NULL;
70
if (rs->hist_entry != -1) {
71
-    /* We were editing an existing history entry: replace it */
72
-    hist_entry = rs->history[rs->hist_entry];
73
-    idx = rs->hist_entry;
74
-    if (strcmp(hist_entry, cmdline) == 0) {
75
-     goto same_entry;
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
+ }
64
}
83
}
65
}
84
/* Search cmdline in history buffers */
66
85
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
67
-/* Assumes the block_job_mutex is held */
86
-    hist_entry = rs->history[idx];
68
-static bool block_job_timer_pending(BlockJob *job)
87
-    if (hist_entry == NULL)
69
-{
88
-     break;
70
- return timer_pending(&job->sleep_timer);
89
-    if (strcmp(hist_entry, cmdline) == 0) {
71
-}
90
-    same_entry:
72
-
91
-     new_entry = hist_entry;
73
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
92
-     /* Put this entry at the end of history */
74
{
93
-     memmove(&rs->history[idx], &rs->history[idx + 1],
75
int64_t old_speed = job->speed;
94
-         (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
76
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
95
-     rs->history[READLINE_MAX_CMDS - 1] = NULL;
77
index XXXXXXX..XXXXXXX 100755
96
-     for (; idx < READLINE_MAX_CMDS; idx++) {
78
--- a/tests/qemu-iotests/185
97
-        if (rs->history[idx] == NULL)
79
+++ b/tests/qemu-iotests/185
98
-         break;
80
@@ -XXX,XX +XXX,XX @@ echo
99
-     }
81
# command to be received (after receiving the command, the rest runs
100
-     break;
82
# synchronously, so jobs can arbitrarily continue or complete).
101
-    }
83
#
102
+ hist_entry = rs->history[idx];
84
-# Jobs present while QEMU is terminating iterate once more due to
103
+ if (hist_entry == NULL)
85
-# bdrv_drain_all().
104
+ break;
86
-#
105
+ if (strcmp(hist_entry, cmdline) == 0) {
87
# The buffer size for commit and streaming is 512k (waiting for 8 seconds after
106
+ same_entry:
88
# the first request), for active commit and mirror it's large enough to cover
107
+ new_entry = hist_entry;
89
# the full 4M, and for backup it's the qcow2 cluster size, which we know is
108
+ /* Put this entry at the end of history */
90
# 64k. As all of these are at least as large as the speed, we are sure that the
109
+ memmove(&rs->history[idx], &rs->history[idx + 1],
91
-# offset advances exactly twice before qemu exits.
110
+ (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
92
+# offset advances exactly once before qemu exits.
111
+ rs->history[READLINE_MAX_CMDS - 1] = NULL;
93
112
+ for (; idx < READLINE_MAX_CMDS; idx++) {
94
_send_qemu_cmd $h \
113
+ if (rs->history[idx] == NULL)
95
"{ 'execute': 'block-commit',
114
+ break;
96
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
115
+ }
97
index XXXXXXX..XXXXXXX 100644
116
+ break;
98
--- a/tests/qemu-iotests/185.out
117
+ }
99
+++ b/tests/qemu-iotests/185.out
118
}
100
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q
119
if (idx == READLINE_MAX_CMDS) {
101
{"return": {}}
120
-    /* Need to get one free slot */
102
{"return": {}}
121
+ /* Need to get one free slot */
103
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
122
g_free(rs->history[0]);
104
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 1048576, "speed": 65536, "type": "commit"}}
123
-    memmove(rs->history, &rs->history[1],
105
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "commit"}}
124
-     (READLINE_MAX_CMDS - 1) * sizeof(char *));
106
125
-    rs->history[READLINE_MAX_CMDS - 1] = NULL;
107
=== Start active commit job and exit qemu ===
126
-    idx = READLINE_MAX_CMDS - 1;
108
127
+ memmove(rs->history, &rs->history[1],
109
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q
128
+ (READLINE_MAX_CMDS - 1) * sizeof(char *));
110
{"return": {}}
129
+ rs->history[READLINE_MAX_CMDS - 1] = NULL;
111
{"return": {}}
130
+ idx = READLINE_MAX_CMDS - 1;
112
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
131
}
113
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}}
132
if (new_entry == NULL)
114
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}}
133
new_entry = g_strdup(cmdline);
115
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}}
134
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
116
135
case 8:
117
=== Start mirror job and exit qemu ===
136
readline_backspace(rs);
118
137
break;
119
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
138
-    case 155:
120
{"return": {}}
139
+ case 155:
121
{"return": {}}
140
rs->esc_state = IS_CSI;
122
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
141
-     break;
123
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
142
+ break;
124
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
143
default:
125
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
144
if (ch >= 32) {
126
145
readline_insert_char(rs, ch);
127
=== Start backup job and exit qemu ===
146
@@ -XXX,XX +XXX,XX @@ void readline_handle_byte(ReadLineState *rs, int ch)
128
147
break;
129
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
148
case IS_CSI:
130
{"return": {}}
149
switch (ch) {
131
{"return": {}}
150
-    case 'A':
132
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
151
-    case 'F':
133
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 131072, "speed": 65536, "type": "backup"}}
152
-     readline_up_char(rs);
134
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 65536, "speed": 65536, "type": "backup"}}
153
-     break;
135
154
-    case 'B':
136
=== Start streaming job and exit qemu ===
155
-    case 'E':
137
156
-     readline_down_char(rs);
138
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
157
-     break;
139
{"return": {}}
158
+ case 'A':
140
{"return": {}}
159
+ case 'F':
141
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
160
+ readline_up_char(rs);
142
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 1048576, "speed": 65536, "type": "stream"}}
161
+ break;
143
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "stream"}}
162
+ case 'B':
144
No errors were found on the image.
163
+ case 'E':
145
*** done
164
+ readline_down_char(rs);
165
+ break;
166
case 'D':
167
readline_backward_char(rs);
168
break;
146
--
169
--
147
2.13.6
170
2.21.0
148
171
149
172
diff view generated by jsdifflib
1
From: Kevin Wolf <kwolf@redhat.com>
1
From: Jules Irenge <jbi.octave@gmail.com>
2
2
3
Commit c22a03454 QAPIfied option parsing in the NFS block driver, but
3
Add braces to fix errors issued by checkpatch.pl tool
4
forgot to remove all the options we processed. Therefore, we get an
4
"ERROR: braces {} are necessary for all arms of this statement"
5
error in bdrv_open_inherit(), which thinks the remaining options are
5
Within "util/readline.c" file
6
invalid. Trying to open an NFS image will result in an error like this:
6
Message-Id: <20190330112142.14082-1-jbi.octave@gmail.com>
7
7
8
Block protocol 'nfs' doesn't support the option 'server.host'
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
util/readline.c | 50 ++++++++++++++++++++++++++++++++-----------------
11
1 file changed, 33 insertions(+), 17 deletions(-)
9
12
10
Remove all options from the QDict to make the NFS driver work again.
13
diff --git a/util/readline.c b/util/readline.c
11
12
Cc: qemu-stable@nongnu.org
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Message-id: 20180516160816.26259-1-kwolf@redhat.com
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Reviewed-by: Jeff Cody <jcody@redhat.com>
17
Signed-off-by: Jeff Cody <jcody@redhat.com>
18
---
19
block/nfs.c | 7 +++++++
20
1 file changed, 7 insertions(+)
21
22
diff --git a/block/nfs.c b/block/nfs.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/block/nfs.c
15
--- a/util/readline.c
25
+++ b/block/nfs.c
16
+++ b/util/readline.c
26
@@ -XXX,XX +XXX,XX @@ static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options,
17
@@ -XXX,XX +XXX,XX @@ static void readline_update(ReadLineState *rs)
27
BlockdevOptionsNfs *opts = NULL;
18
rs->cmd_buf[rs->cmd_buf_size] = '\0';
28
QObject *crumpled = NULL;
19
if (rs->read_password) {
29
Visitor *v;
20
len = strlen(rs->cmd_buf);
30
+ const QDictEntry *e;
21
- for (i = 0; i < len; i++)
31
Error *local_err = NULL;
22
+ for (i = 0; i < len; i++) {
32
23
rs->printf_func(rs->opaque, "*");
33
crumpled = qdict_crumple(options, errp);
24
+ }
34
@@ -XXX,XX +XXX,XX @@ static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options,
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)
29
{
30
int idx;
31
32
- if (rs->hist_entry == 0)
33
+ if (rs->hist_entry == 0) {
34
return;
35
+ }
36
if (rs->hist_entry == -1) {
37
/* Find latest entry */
38
for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
39
- if (rs->history[idx] == NULL)
40
+ if (rs->history[idx] == NULL) {
41
break;
42
+ }
43
}
44
rs->hist_entry = idx;
45
}
46
@@ -XXX,XX +XXX,XX @@ static void readline_up_char(ReadLineState *rs)
47
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;
140
+ }
141
}
142
if (max_prefix > 0)
143
for (i = rs->completion_index; i < max_prefix; i++) {
144
readline_insert_char(rs, rs->completions[0][i]);
145
}
146
max_width += 2;
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) {
35
return NULL;
174
return NULL;
36
}
37
38
+ /* Remove the processed options from the QDict (the visitor processes
39
+ * _all_ options in the QDict) */
40
+ while ((e = qdict_first(options))) {
41
+ qdict_del(options, e->key);
42
+ }
175
+ }
43
+
176
return rs->history[index];
44
return opts;
45
}
177
}
46
178
47
--
179
--
48
2.13.6
180
2.21.0
49
181
50
182
diff view generated by jsdifflib
New patch
1
From: Nikita Alekseev <n.alekseev2104@gmail.com>
1
2
3
bdrv_check_co_entry calls bdrv_co_check, which is a coroutine function.
4
Thus, it also needs to be marked as a coroutine.
5
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>
10
---
11
block.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
17
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct CheckCo {
19
int ret;
20
} CheckCo;
21
22
-static void bdrv_check_co_entry(void *opaque)
23
+static void coroutine_fn bdrv_check_co_entry(void *opaque)
24
{
25
CheckCo *cco = opaque;
26
cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
27
--
28
2.21.0
29
30
diff view generated by jsdifflib
1
From: Kevin Wolf <kwolf@redhat.com>
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
2
3
Don't throw away local_err, but propagate it to errp.
3
On a file system used by the customer, fallocate() returns an error
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.
4
8
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Suggested-by: Denis V. Lunev <den@openvz.org>
6
Message-id: 20180516161034.27440-1-kwolf@redhat.com
10
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
12
Message-id: 1554474244-553661-1-git-send-email-andrey.shinkevich@virtuozzo.com
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
13
Message-Id: <1554474244-553661-1-git-send-email-andrey.shinkevich@virtuozzo.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
15
---
11
block/nfs.c | 1 +
16
block/io.c | 2 +-
12
1 file changed, 1 insertion(+)
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
18
14
diff --git a/block/nfs.c b/block/nfs.c
19
diff --git a/block/io.c b/block/io.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/block/nfs.c
21
--- a/block/io.c
17
+++ b/block/nfs.c
22
+++ b/block/io.c
18
@@ -XXX,XX +XXX,XX @@ static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options,
23
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
19
qobject_unref(crumpled);
24
assert(!bs->supported_zero_flags);
20
25
}
21
if (local_err) {
26
22
+ error_propagate(errp, local_err);
27
- if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) {
23
return NULL;
28
+ if (ret < 0 && !(flags & BDRV_REQ_NO_FALLBACK)) {
24
}
29
/* Fall back to bounce buffer if write zeroes is unsupported */
30
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
25
31
26
--
32
--
27
2.13.6
33
2.21.0
28
34
29
35
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
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.
6
7
event_notifier_poll() does run while polling, detecting that
8
a bottom half was scheduled by a worker thread, but because
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.
13
14
With this change, ThreadPool still cannot participate in polling
15
but at least it does not suffer from extra latency.
16
17
Reported-by: Sergio Lopez <slp@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>
28
---
29
util/aio-posix.c | 12 ++++++++----
30
1 file changed, 8 insertions(+), 4 deletions(-)
31
32
diff --git a/util/aio-posix.c b/util/aio-posix.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/util/aio-posix.c
35
+++ b/util/aio-posix.c
36
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers_once(AioContext *ctx, int64_t *timeout)
37
if (!node->deleted && node->io_poll &&
38
aio_node_check(ctx, node->is_external) &&
39
node->io_poll(node->opaque)) {
40
+ /*
41
+ * Polling was successful, exit try_poll_mode immediately
42
+ * to adjust the next polling time.
43
+ */
44
*timeout = 0;
45
if (node->opaque != &ctx->notifier) {
46
progress = true;
47
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
48
do {
49
progress = run_poll_handlers_once(ctx, timeout);
50
elapsed_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time;
51
- } while (!progress && elapsed_time < max_ns
52
- && !atomic_read(&ctx->poll_disable_cnt));
53
+ max_ns = qemu_soonest_timeout(*timeout, max_ns);
54
+ assert(!(max_ns && progress));
55
+ } while (elapsed_time < max_ns && !atomic_read(&ctx->poll_disable_cnt));
56
57
/* If time has passed with no successful polling, adjust *timeout to
58
* keep the same ending time.
59
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
60
*/
61
static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
62
{
63
- /* See qemu_soonest_timeout() uint64_t hack */
64
- int64_t max_ns = MIN((uint64_t)*timeout, (uint64_t)ctx->poll_ns);
65
+ int64_t max_ns = qemu_soonest_timeout(*timeout, ctx->poll_ns);
66
67
if (max_ns && !atomic_read(&ctx->poll_disable_cnt)) {
68
poll_set_started(ctx, true);
69
--
70
2.21.0
71
72
diff view generated by jsdifflib
New patch
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)
1
4
5
This patch adds a guide to secure coding practices. This document
6
covers things that developers should know about security in QEMU. It is
7
just a starting point that we can expand on later. I hope it will be
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>
20
---
21
docs/devel/index.rst | 1 +
22
docs/devel/secure-coding-practices.rst | 106 +++++++++++++++++++++++++
23
2 files changed, 107 insertions(+)
24
create mode 100644 docs/devel/secure-coding-practices.rst
25
26
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
27
index XXXXXXX..XXXXXXX 100644
28
--- a/docs/devel/index.rst
29
+++ b/docs/devel/index.rst
30
@@ -XXX,XX +XXX,XX @@ Contents:
31
stable-process
32
testing
33
decodetree
34
+ secure-coding-practices
35
diff --git a/docs/devel/secure-coding-practices.rst b/docs/devel/secure-coding-practices.rst
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/docs/devel/secure-coding-practices.rst
40
@@ -XXX,XX +XXX,XX @@
41
+=======================
42
+Secure Coding Practices
43
+=======================
44
+This document covers topics that both developers and security researchers must
45
+be aware of so that they can develop safe code and audit existing code
46
+properly.
47
+
48
+Reporting Security Bugs
49
+-----------------------
50
+For details on how to report security bugs or ask questions about potential
51
+security bugs, see the `Security Process wiki page
52
+<https://wiki.qemu.org/SecurityProcess>`_.
53
+
54
+General Secure C Coding Practices
55
+---------------------------------
56
+Most CVEs (security bugs) reported against QEMU are not specific to
57
+virtualization or emulation. They are simply C programming bugs. Therefore
58
+it's critical to be aware of common classes of security bugs.
59
+
60
+There is a wide selection of resources available covering secure C coding. For
61
+example, the `CERT C Coding Standard
62
+<https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard>`_
63
+covers the most important classes of security bugs.
64
+
65
+Instead of describing them in detail here, only the names of the most important
66
+classes of security bugs are mentioned:
67
+
68
+* Buffer overflows
69
+* Use-after-free and double-free
70
+* Integer overflows
71
+* Format string vulnerabilities
72
+
73
+Some of these classes of bugs can be detected by analyzers. Static analysis is
74
+performed regularly by Coverity and the most obvious of these bugs are even
75
+reported by compilers. Dynamic analysis is possible with valgrind, tsan, and
76
+asan.
77
+
78
+Input Validation
79
+----------------
80
+Inputs from the guest or external sources (e.g. network, files) cannot be
81
+trusted and may be invalid. Inputs must be checked before using them in a way
82
+that could crash the program, expose host memory to the guest, or otherwise be
83
+exploitable by an attacker.
84
+
85
+The most sensitive attack surface is device emulation. All hardware register
86
+accesses and data read from guest memory must be validated. A typical example
87
+is a device that contains multiple units that are selectable by the guest via
88
+an index register::
89
+
90
+ typedef struct {
91
+ ProcessingUnit unit[2];
92
+ ...
93
+ } MyDeviceState;
94
+
95
+ static void mydev_writel(void *opaque, uint32_t addr, uint32_t val)
96
+ {
97
+ MyDeviceState *mydev = opaque;
98
+ ProcessingUnit *unit;
99
+
100
+ switch (addr) {
101
+ case MYDEV_SELECT_UNIT:
102
+ unit = &mydev->unit[val]; <-- this input wasn't validated!
103
+ ...
104
+ }
105
+ }
106
+
107
+If ``val`` is not in range [0, 1] then an out-of-bounds memory access will take
108
+place when ``unit`` is dereferenced. The code must check that ``val`` is 0 or
109
+1 and handle the case where it is invalid.
110
+
111
+Unexpected Device Accesses
112
+--------------------------
113
+The guest may access device registers in unusual orders or at unexpected
114
+moments. Device emulation code must not assume that the guest follows the
115
+typical "theory of operation" presented in driver writer manuals. The guest
116
+may make nonsense accesses to device registers such as starting operations
117
+before the device has been fully initialized.
118
+
119
+A related issue is that device emulation code must be prepared for unexpected
120
+device register accesses while asynchronous operations are in progress. A
121
+well-behaved guest might wait for a completion interrupt before accessing
122
+certain device registers. Device emulation code must handle the case where the
123
+guest overwrites registers or submits further requests before an ongoing
124
+request completes. Unexpected accesses must not cause memory corruption or
125
+leaks in QEMU.
126
+
127
+Invalid device register accesses can be reported with
128
+``qemu_log_mask(LOG_GUEST_ERROR, ...)``. The ``-d guest_errors`` command-line
129
+option enables these log messages.
130
+
131
+Live Migration
132
+--------------
133
+Device state can be saved to disk image files and shared with other users.
134
+Live migration code must validate inputs when loading device state so an
135
+attacker cannot gain control by crafting invalid device states. Device state
136
+is therefore considered untrusted even though it is typically generated by QEMU
137
+itself.
138
+
139
+Guest Memory Access Races
140
+-------------------------
141
+Guests with multiple vCPUs may modify guest RAM while device emulation code is
142
+running. Device emulation code must copy in descriptors and other guest RAM
143
+structures and only process the local copy. This prevents
144
+time-of-check-to-time-of-use (TOCTOU) race conditions that could cause QEMU to
145
+crash when a vCPU thread modifies guest RAM while device emulation is
146
+processing it.
147
--
148
2.21.0
149
150
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.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
Commit 8565c3ab537e78f3e69977ec2c609dc9417a806e ("qemu-iotests: fix
5
It is just a starting point that can be extended in the future with more
4
185") identified a race condition in a sub-test.
6
information.
5
7
6
Similar issues also affect the other sub-tests. If disk I/O completes
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
quickly, it races with the QMP 'quit' command. This causes spurious
9
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
8
test failures because QMP events are emitted in an unpredictable order.
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Daniel P. Berrangé <berrange@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>
17
---
18
Makefile | 2 +-
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
9
23
10
This test relies on QEMU internals and there is no QMP API for getting
24
diff --git a/Makefile b/Makefile
11
deterministic behavior needed to make this test 100% reliable. At the
25
index XXXXXXX..XXXXXXX 100644
12
same time, the test is useful and it would be a shame to remove it.
26
--- a/Makefile
13
27
+++ b/Makefile
14
Add sleep 0.5 to reduce the chance of races. This is not a real fix but
28
@@ -XXX,XX +XXX,XX @@ qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
15
appears to reduce spurious failures in practice.
29
    qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \
16
30
    qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
17
Cc: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
31
    qemu-monitor-info.texi docs/qemu-block-drivers.texi \
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
32
-    docs/qemu-cpu-models.texi
19
Reviewed-by: Eric Blake <eblake@redhat.com>
33
+    docs/qemu-cpu-models.texi docs/security.texi
20
Message-id: 20180508135436.30140-2-stefanha@redhat.com
34
21
Reviewed-by: Jeff Cody <jcody@redhat.com>
35
docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \
22
Signed-off-by: Jeff Cody <jcody@redhat.com>
36
docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \
23
---
37
diff --git a/docs/security.texi b/docs/security.texi
24
tests/qemu-iotests/185 | 12 ++++++++++++
38
new file mode 100644
25
1 file changed, 12 insertions(+)
39
index XXXXXXX..XXXXXXX
26
40
--- /dev/null
27
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
41
+++ b/docs/security.texi
28
index XXXXXXX..XXXXXXX 100755
42
@@ -XXX,XX +XXX,XX @@
29
--- a/tests/qemu-iotests/185
43
+@node Security
30
+++ b/tests/qemu-iotests/185
44
+@chapter Security
31
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $h \
32
'speed': 65536 } }" \
33
"return"
34
35
+# If we don't sleep here 'quit' command races with disk I/O
36
+sleep 0.5
37
+
45
+
38
_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
46
+@section Overview
39
wait=1 _cleanup_qemu
40
41
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $h \
42
'speed': 65536 } }" \
43
"return"
44
45
+# If we don't sleep here 'quit' command races with disk I/O
46
+sleep 0.5
47
+
47
+
48
_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
48
+This chapter explains the security requirements that QEMU is designed to meet
49
wait=1 _cleanup_qemu
49
+and principles for securely deploying QEMU.
50
51
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $h \
52
'speed': 65536 } }" \
53
"return"
54
55
+# If we don't sleep here 'quit' command races with disk I/O
56
+sleep 0.5
57
+
50
+
58
_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
51
+@section Security Requirements
59
wait=1 _cleanup_qemu
60
61
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $h \
62
'speed': 65536 } }" \
63
"return"
64
65
+# If we don't sleep here 'quit' command races with disk I/O
66
+sleep 0.5
67
+
52
+
68
_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
53
+QEMU supports many different use cases, some of which have stricter security
69
wait=1 _cleanup_qemu
54
+requirements than others. The community has agreed on the overall security
70
55
+requirements that users may depend on. These requirements define what is
56
+considered supported from a security perspective.
57
+
58
+@subsection Virtualization Use Case
59
+
60
+The virtualization use case covers cloud and virtual private server (VPS)
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.
64
+
65
+The following entities are untrusted, meaning that they may be buggy or
66
+malicious:
67
+
68
+@itemize
69
+@item Guest
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
71
--
195
--
72
2.13.6
196
2.21.0
73
197
74
198
diff view generated by jsdifflib