Rebase to 2.9.1 stable release

This commit is contained in:
Cole Robinson 2017-09-08 15:46:18 -04:00
parent ceebe0743f
commit 1df6e75814
21 changed files with 8 additions and 1425 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@
/qemu-2.9.0-rc3.tar.xz
/qemu-2.9.0-rc4.tar.xz
/qemu-2.9.0.tar.xz
/qemu-2.9.1.tar.xz

View File

@ -1,30 +0,0 @@
From: P J P <ppandit@redhat.com>
Date: Tue, 25 Apr 2017 18:36:23 +0530
Subject: [PATCH] vmw_pvscsi: check message ring page count at initialisation
A guest could set the message ring page count to zero, resulting in
infinite loop. Add check to avoid it.
Reported-by: YY Z <bigbird475958471@gmail.com>
Signed-off-by: P J P <ppandit@redhat.com>
Message-Id: <20170425130623.3649-1-ppandit@redhat.com>
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit f68826989cd4d1217797251339579c57b3c0934e)
---
hw/scsi/vmw_pvscsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 75575461e2..4a106da856 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -202,7 +202,7 @@ pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
uint32_t len_log2;
uint32_t ring_size;
- if (ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) {
+ if (!ri->numPages || ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) {
return -1;
}
ring_size = ri->numPages * PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;

View File

@ -1,35 +0,0 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 28 Apr 2017 09:56:12 +0200
Subject: [PATCH] audio: release capture buffers
AUD_add_capture() allocates two buffers which are never released.
Add the missing calls to AUD_del_capture().
Impact: Allows vnc clients to exhaust host memory by repeatedly
starting and stopping audio capture.
Fixes: CVE-2017-8309
Cc: P J P <ppandit@redhat.com>
Cc: Huawei PSIRT <PSIRT@huawei.com>
Reported-by: "Jiangxin (hunter, SCC)" <jiangxin1@huawei.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 20170428075612.9997-1-kraxel@redhat.com
(cherry picked from commit 3268a845f41253fb55852a8429c32b50f36f349a)
---
audio/audio.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/audio/audio.c b/audio/audio.c
index c8898d8422..beafed209b 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -2028,6 +2028,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
sw = sw1;
}
QLIST_REMOVE (cap, entries);
+ g_free (cap->hw.mix_buf);
+ g_free (cap->buf);
g_free (cap);
}
return;

View File

@ -1,87 +0,0 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 28 Apr 2017 10:42:37 +0200
Subject: [PATCH] input: limit kbd queue depth
Apply a limit to the number of items we accept into the keyboard queue.
Impact: Without this limit vnc clients can exhaust host memory by
sending keyboard events faster than qemu feeds them to the guest.
Fixes: CVE-2017-8379
Cc: P J P <ppandit@redhat.com>
Cc: Huawei PSIRT <PSIRT@huawei.com>
Reported-by: jiangxin1@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20170428084237.23960-1-kraxel@redhat.com
(cherry picked from commit fa18f36a461984eae50ab957e47ec78dae3c14fc)
---
ui/input.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/ui/input.c b/ui/input.c
index ed88cda6d6..fb1f404095 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -41,6 +41,8 @@ static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
QTAILQ_HEAD_INITIALIZER(kbd_queue);
static QEMUTimer *kbd_timer;
static uint32_t kbd_default_delay_ms = 10;
+static uint32_t queue_count;
+static uint32_t queue_limit = 1024;
QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
QemuInputHandler *handler)
@@ -268,6 +270,7 @@ static void qemu_input_queue_process(void *opaque)
break;
}
QTAILQ_REMOVE(queue, item, node);
+ queue_count--;
g_free(item);
}
}
@@ -282,6 +285,7 @@ static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
item->delay_ms = delay_ms;
item->timer = timer;
QTAILQ_INSERT_TAIL(queue, item, node);
+ queue_count++;
if (start_timer) {
timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
@@ -298,6 +302,7 @@ static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
item->src = src;
item->evt = evt;
QTAILQ_INSERT_TAIL(queue, item, node);
+ queue_count++;
}
static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
@@ -306,6 +311,7 @@ static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
item->type = QEMU_INPUT_QUEUE_SYNC;
QTAILQ_INSERT_TAIL(queue, item, node);
+ queue_count++;
}
void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
@@ -381,7 +387,7 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
qemu_input_event_send(src, evt);
qemu_input_event_sync();
qapi_free_InputEvent(evt);
- } else {
+ } else if (queue_count < queue_limit) {
qemu_input_queue_event(&kbd_queue, src, evt);
qemu_input_queue_sync(&kbd_queue);
}
@@ -409,8 +415,10 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms)
kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
&kbd_queue);
}
- qemu_input_queue_delay(&kbd_queue, kbd_timer,
- delay_ms ? delay_ms : kbd_default_delay_ms);
+ if (queue_count < queue_limit) {
+ qemu_input_queue_delay(&kbd_queue, kbd_timer,
+ delay_ms ? delay_ms : kbd_default_delay_ms);
+ }
}
InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)

View File

@ -1,42 +0,0 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Mon, 24 Apr 2017 17:36:34 +0530
Subject: [PATCH] scsi: avoid an off-by-one error in megasas_mmio_write
While reading magic sequence(MFI_SEQ) in megasas_mmio_write,
an off-by-one error could occur as 's->adp_reset' index is not
reset after reading the last sequence.
Reported-by: YY Z <bigbird475958471@gmail.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <20170424120634.12268-1-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 24dfa9fa2f90a95ac33c7372de4f4f2c8a2c141f)
---
hw/scsi/megasas.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 84b8caf901..804122ab05 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2138,15 +2138,15 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
case MFI_SEQ:
trace_megasas_mmio_writel("MFI_SEQ", val);
/* Magic sequence to start ADP reset */
- if (adp_reset_seq[s->adp_reset] == val) {
- s->adp_reset++;
+ if (adp_reset_seq[s->adp_reset++] == val) {
+ if (s->adp_reset == 6) {
+ s->adp_reset = 0;
+ s->diag = MFI_DIAG_WRITE_ENABLE;
+ }
} else {
s->adp_reset = 0;
s->diag = 0;
}
- if (s->adp_reset == 6) {
- s->diag = MFI_DIAG_WRITE_ENABLE;
- }
break;
case MFI_DIAG:
trace_megasas_mmio_writel("MFI_DIAG", val);

View File

@ -1,171 +0,0 @@
From: Greg Kurz <groug@kaod.org>
Date: Fri, 5 May 2017 14:48:08 +0200
Subject: [PATCH] 9pfs: local: forbid client access to metadata (CVE-2017-7493)
When using the mapped-file security mode, we shouldn't let the client mess
with the metadata. The current code already tries to hide the metadata dir
from the client by skipping it in local_readdir(). But the client can still
access or modify it through several other operations. This can be used to
escalate privileges in the guest.
Affected backend operations are:
- local_mknod()
- local_mkdir()
- local_open2()
- local_symlink()
- local_link()
- local_unlinkat()
- local_renameat()
- local_rename()
- local_name_to_path()
Other operations are safe because they are only passed a fid path, which
is computed internally in local_name_to_path().
This patch converts all the functions listed above to fail and return
EINVAL when being passed the name of the metadata dir. This may look
like a poor choice for errno, but there's no such thing as an illegal
path name on Linux and I could not think of anything better.
This fixes CVE-2017-7493.
Reported-by: Leo Gaspard <leo@gaspard.io>
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 7a95434e0ca8a037fd8aa1a2e2461f92585eb77b)
---
hw/9pfs/9p-local.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 56 insertions(+), 2 deletions(-)
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index f3ebca4f7a..a2486566af 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -452,6 +452,11 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
return telldir(fs->dir.stream);
}
+static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name)
+{
+ return !strcmp(name, VIRTFS_META_DIR);
+}
+
static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
{
struct dirent *entry;
@@ -465,8 +470,8 @@ again:
if (ctx->export_flags & V9FS_SM_MAPPED) {
entry->d_type = DT_UNKNOWN;
} else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- if (!strcmp(entry->d_name, VIRTFS_META_DIR)) {
- /* skp the meta data directory */
+ if (local_is_mapped_file_metadata(ctx, entry->d_name)) {
+ /* skip the meta data directory */
goto again;
}
entry->d_type = DT_UNKNOWN;
@@ -559,6 +564,12 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
int err = -1;
int dirfd;
+ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(fs_ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
if (dirfd == -1) {
return -1;
@@ -605,6 +616,12 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
int err = -1;
int dirfd;
+ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(fs_ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
if (dirfd == -1) {
return -1;
@@ -694,6 +711,12 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
int err = -1;
int dirfd;
+ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(fs_ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
/*
* Mark all the open to not follow symlinks
*/
@@ -752,6 +775,12 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
int err = -1;
int dirfd;
+ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(fs_ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
dirfd = local_opendir_nofollow(fs_ctx, dir_path->data);
if (dirfd == -1) {
return -1;
@@ -826,6 +855,12 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
int ret = -1;
int odirfd, ndirfd;
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
odirfd = local_opendir_nofollow(ctx, odirpath);
if (odirfd == -1) {
goto out;
@@ -1096,6 +1131,12 @@ static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
const char *name, V9fsPath *target)
{
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
if (dir_path) {
v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
} else if (strcmp(name, "/")) {
@@ -1116,6 +1157,13 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir,
int ret;
int odirfd, ndirfd;
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ (local_is_mapped_file_metadata(ctx, old_name) ||
+ local_is_mapped_file_metadata(ctx, new_name))) {
+ errno = EINVAL;
+ return -1;
+ }
+
odirfd = local_opendir_nofollow(ctx, olddir->data);
if (odirfd == -1) {
return -1;
@@ -1206,6 +1254,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
int ret;
int dirfd;
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
+ local_is_mapped_file_metadata(ctx, name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
dirfd = local_opendir_nofollow(ctx, dir->data);
if (dirfd == -1) {
return -1;

View File

@ -1,30 +0,0 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 1 Jun 2017 17:18:39 +0200
Subject: [PATCH] megasas: do not read sense length more than once from frame
Avoid TOC-TOU bugs depending on how the compiler behaves.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 134550bf81a026e18cf58b81e2c2cceaf516f92e)
---
hw/scsi/megasas.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 804122ab05..1888118e5f 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -309,9 +309,11 @@ static int megasas_build_sense(MegasasCmd *cmd, uint8_t *sense_ptr,
PCIDevice *pcid = PCI_DEVICE(cmd->state);
uint32_t pa_hi = 0, pa_lo;
hwaddr pa;
+ int frame_sense_len;
- if (sense_len > cmd->frame->header.sense_len) {
- sense_len = cmd->frame->header.sense_len;
+ frame_sense_len = cmd->frame->header.sense_len;
+ if (sense_len > frame_sense_len) {
+ sense_len = frame_sense_len;
}
if (sense_len) {
pa_lo = le32_to_cpu(cmd->frame->pass.sense_addr_lo);

View File

@ -1,37 +0,0 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 1 Jun 2017 17:18:57 +0200
Subject: [PATCH] megasas: do not read iovec count more than once from frame
Avoid TOC-TOU bugs depending on how the compiler behaves.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 24c0c77af515acbf0f9705e8096f33ef24d37430)
---
hw/scsi/megasas.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 1888118e5f..c353118882 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -675,15 +675,16 @@ out:
static int megasas_map_dcmd(MegasasState *s, MegasasCmd *cmd)
{
dma_addr_t iov_pa, iov_size;
+ int iov_count;
cmd->flags = le16_to_cpu(cmd->frame->header.flags);
- if (!cmd->frame->header.sge_count) {
+ iov_count = cmd->frame->header.sge_count;
+ if (!iov_count) {
trace_megasas_dcmd_zero_sge(cmd->index);
cmd->iov_size = 0;
return 0;
- } else if (cmd->frame->header.sge_count > 1) {
- trace_megasas_dcmd_invalid_sge(cmd->index,
- cmd->frame->header.sge_count);
+ } else if (iov_count > 1) {
+ trace_megasas_dcmd_invalid_sge(cmd->index, iov_count);
cmd->iov_size = 0;
return -EINVAL;
}

View File

@ -1,111 +0,0 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 1 Jun 2017 17:18:23 +0200
Subject: [PATCH] megasas: do not read DCMD opcode more than once from frame
Avoid TOC-TOU bugs by storing the DCMD opcode in the MegasasCmd
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 5104fac8539eaf155fc6de93e164be43e1e62242)
---
hw/scsi/megasas.c | 25 +++++++++++--------------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index c353118882..a3f75c1650 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -63,6 +63,7 @@ typedef struct MegasasCmd {
hwaddr pa;
hwaddr pa_size;
+ uint32_t dcmd_opcode;
union mfi_frame *frame;
SCSIRequest *req;
QEMUSGList qsg;
@@ -513,6 +514,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
cmd->context &= (uint64_t)0xFFFFFFFF;
}
cmd->count = count;
+ cmd->dcmd_opcode = -1;
s->busy++;
if (s->consumer_pa) {
@@ -1562,22 +1564,21 @@ static const struct dcmd_cmd_tbl_t {
static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd)
{
- int opcode;
int retval = 0;
size_t len;
const struct dcmd_cmd_tbl_t *cmdptr = dcmd_cmd_tbl;
- opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
- trace_megasas_handle_dcmd(cmd->index, opcode);
+ cmd->dcmd_opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
+ trace_megasas_handle_dcmd(cmd->index, cmd->dcmd_opcode);
if (megasas_map_dcmd(s, cmd) < 0) {
return MFI_STAT_MEMORY_NOT_AVAILABLE;
}
- while (cmdptr->opcode != -1 && cmdptr->opcode != opcode) {
+ while (cmdptr->opcode != -1 && cmdptr->opcode != cmd->dcmd_opcode) {
cmdptr++;
}
len = cmd->iov_size;
if (cmdptr->opcode == -1) {
- trace_megasas_dcmd_unhandled(cmd->index, opcode, len);
+ trace_megasas_dcmd_unhandled(cmd->index, cmd->dcmd_opcode, len);
retval = megasas_dcmd_dummy(s, cmd);
} else {
trace_megasas_dcmd_enter(cmd->index, cmdptr->desc, len);
@@ -1592,13 +1593,11 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd)
static int megasas_finish_internal_dcmd(MegasasCmd *cmd,
SCSIRequest *req)
{
- int opcode;
int retval = MFI_STAT_OK;
int lun = req->lun;
- opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
- trace_megasas_dcmd_internal_finish(cmd->index, opcode, lun);
- switch (opcode) {
+ trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun);
+ switch (cmd->dcmd_opcode) {
case MFI_DCMD_PD_GET_INFO:
retval = megasas_pd_get_info_submit(req->dev, lun, cmd);
break;
@@ -1606,7 +1605,7 @@ static int megasas_finish_internal_dcmd(MegasasCmd *cmd,
retval = megasas_ld_get_info_submit(req->dev, lun, cmd);
break;
default:
- trace_megasas_dcmd_internal_invalid(cmd->index, opcode);
+ trace_megasas_dcmd_internal_invalid(cmd->index, cmd->dcmd_opcode);
retval = MFI_STAT_INVALID_DCMD;
break;
}
@@ -1827,7 +1826,6 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
{
MegasasCmd *cmd = req->hba_private;
uint8_t *buf;
- uint32_t opcode;
trace_megasas_io_complete(cmd->index, len);
@@ -1837,8 +1835,7 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
}
buf = scsi_req_get_buf(req);
- opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
- if (opcode == MFI_DCMD_PD_GET_INFO && cmd->iov_buf) {
+ if (cmd->dcmd_opcode == MFI_DCMD_PD_GET_INFO && cmd->iov_buf) {
struct mfi_pd_info *info = cmd->iov_buf;
if (info->inquiry_data[0] == 0x7f) {
@@ -1849,7 +1846,7 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
memcpy(info->vpd_page83, buf, len);
}
scsi_req_continue(req);
- } else if (opcode == MFI_DCMD_LD_GET_INFO) {
+ } else if (cmd->dcmd_opcode == MFI_DCMD_LD_GET_INFO) {
struct mfi_ld_info *info = cmd->iov_buf;
if (cmd->iov_buf) {

View File

@ -1,218 +0,0 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 1 Jun 2017 17:23:13 +0200
Subject: [PATCH] megasas: do not read command more than once from frame
Avoid TOC-TOU bugs by passing the frame_cmd down, and checking
cmd->dcmd_opcode instead of cmd->frame->header.frame_cmd.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 36c327a69d723571f02a7691631667cdb1865ee1)
---
hw/scsi/megasas.c | 60 +++++++++++++++++++++++--------------------------------
1 file changed, 25 insertions(+), 35 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index a3f75c1650..38e0a2f5ef 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1591,12 +1591,13 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd)
}
static int megasas_finish_internal_dcmd(MegasasCmd *cmd,
- SCSIRequest *req)
+ SCSIRequest *req, size_t resid)
{
int retval = MFI_STAT_OK;
int lun = req->lun;
trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun);
+ cmd->iov_size -= resid;
switch (cmd->dcmd_opcode) {
case MFI_DCMD_PD_GET_INFO:
retval = megasas_pd_get_info_submit(req->dev, lun, cmd);
@@ -1649,11 +1650,12 @@ static int megasas_enqueue_req(MegasasCmd *cmd, bool is_write)
}
static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
- bool is_logical)
+ int frame_cmd)
{
uint8_t *cdb;
bool is_write;
struct SCSIDevice *sdev = NULL;
+ bool is_logical = (frame_cmd == MFI_CMD_LD_SCSI_IO);
cdb = cmd->frame->pass.cdb;
@@ -1661,7 +1663,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
if (cmd->frame->header.target_id >= MFI_MAX_LD ||
cmd->frame->header.lun_id != 0) {
trace_megasas_scsi_target_not_present(
- mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical,
+ mfi_frame_desc[frame_cmd], is_logical,
cmd->frame->header.target_id, cmd->frame->header.lun_id);
return MFI_STAT_DEVICE_NOT_FOUND;
}
@@ -1671,19 +1673,20 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len);
trace_megasas_handle_scsi(mfi_frame_desc[cmd->frame->header.frame_cmd],
- is_logical, cmd->frame->header.target_id,
+ trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical,
+ cmd->frame->header.target_id,
cmd->frame->header.lun_id, sdev, cmd->iov_size);
if (!sdev || (megasas_is_jbod(s) && is_logical)) {
trace_megasas_scsi_target_not_present(
- mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical,
+ mfi_frame_desc[frame_cmd], is_logical,
cmd->frame->header.target_id, cmd->frame->header.lun_id);
return MFI_STAT_DEVICE_NOT_FOUND;
}
if (cmd->frame->header.cdb_len > 16) {
trace_megasas_scsi_invalid_cdb_len(
- mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical,
+ mfi_frame_desc[frame_cmd], is_logical,
cmd->frame->header.target_id, cmd->frame->header.lun_id,
cmd->frame->header.cdb_len);
megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
@@ -1703,7 +1706,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
cmd->frame->header.lun_id, cdb, cmd);
if (!cmd->req) {
trace_megasas_scsi_req_alloc_failed(
- mfi_frame_desc[cmd->frame->header.frame_cmd],
+ mfi_frame_desc[frame_cmd],
cmd->frame->header.target_id, cmd->frame->header.lun_id);
megasas_write_sense(cmd, SENSE_CODE(NO_SENSE));
cmd->frame->header.scsi_status = BUSY;
@@ -1725,11 +1728,11 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
return MFI_STAT_INVALID_STATUS;
}
-static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd)
+static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
{
uint32_t lba_count, lba_start_hi, lba_start_lo;
uint64_t lba_start;
- bool is_write = (cmd->frame->header.frame_cmd == MFI_CMD_LD_WRITE);
+ bool is_write = (frame_cmd == MFI_CMD_LD_WRITE);
uint8_t cdb[16];
int len;
struct SCSIDevice *sdev = NULL;
@@ -1746,20 +1749,20 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd)
}
trace_megasas_handle_io(cmd->index,
- mfi_frame_desc[cmd->frame->header.frame_cmd],
+ mfi_frame_desc[frame_cmd],
cmd->frame->header.target_id,
cmd->frame->header.lun_id,
(unsigned long)lba_start, (unsigned long)lba_count);
if (!sdev) {
trace_megasas_io_target_not_present(cmd->index,
- mfi_frame_desc[cmd->frame->header.frame_cmd],
+ mfi_frame_desc[frame_cmd],
cmd->frame->header.target_id, cmd->frame->header.lun_id);
return MFI_STAT_DEVICE_NOT_FOUND;
}
if (cmd->frame->header.cdb_len > 16) {
trace_megasas_scsi_invalid_cdb_len(
- mfi_frame_desc[cmd->frame->header.frame_cmd], 1,
+ mfi_frame_desc[frame_cmd], 1,
cmd->frame->header.target_id, cmd->frame->header.lun_id,
cmd->frame->header.cdb_len);
megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
@@ -1781,7 +1784,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd)
cmd->frame->header.lun_id, cdb, cmd);
if (!cmd->req) {
trace_megasas_scsi_req_alloc_failed(
- mfi_frame_desc[cmd->frame->header.frame_cmd],
+ mfi_frame_desc[frame_cmd],
cmd->frame->header.target_id, cmd->frame->header.lun_id);
megasas_write_sense(cmd, SENSE_CODE(NO_SENSE));
cmd->frame->header.scsi_status = BUSY;
@@ -1799,23 +1802,11 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd)
return MFI_STAT_INVALID_STATUS;
}
-static int megasas_finish_internal_command(MegasasCmd *cmd,
- SCSIRequest *req, size_t resid)
-{
- int retval = MFI_STAT_INVALID_CMD;
-
- if (cmd->frame->header.frame_cmd == MFI_CMD_DCMD) {
- cmd->iov_size -= resid;
- retval = megasas_finish_internal_dcmd(cmd, req);
- }
- return retval;
-}
-
static QEMUSGList *megasas_get_sg_list(SCSIRequest *req)
{
MegasasCmd *cmd = req->hba_private;
- if (cmd->frame->header.frame_cmd == MFI_CMD_DCMD) {
+ if (cmd->dcmd_opcode != -1) {
return NULL;
} else {
return &cmd->qsg;
@@ -1829,7 +1820,7 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
trace_megasas_io_complete(cmd->index, len);
- if (cmd->frame->header.frame_cmd != MFI_CMD_DCMD) {
+ if (cmd->dcmd_opcode != -1) {
scsi_req_continue(req);
return;
}
@@ -1872,7 +1863,7 @@ static void megasas_command_complete(SCSIRequest *req, uint32_t status,
/*
* Internal command complete
*/
- cmd_status = megasas_finish_internal_command(cmd, req, resid);
+ cmd_status = megasas_finish_internal_dcmd(cmd, req, resid);
if (cmd_status == MFI_STAT_INVALID_STATUS) {
return;
}
@@ -1943,6 +1934,7 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
{
uint8_t frame_status = MFI_STAT_INVALID_CMD;
uint64_t frame_context;
+ int frame_cmd;
MegasasCmd *cmd;
/*
@@ -1961,7 +1953,8 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
s->event_count++;
return;
}
- switch (cmd->frame->header.frame_cmd) {
+ frame_cmd = cmd->frame->header.frame_cmd;
+ switch (frame_cmd) {
case MFI_CMD_INIT:
frame_status = megasas_init_firmware(s, cmd);
break;
@@ -1972,18 +1965,15 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
frame_status = megasas_handle_abort(s, cmd);
break;
case MFI_CMD_PD_SCSI_IO:
- frame_status = megasas_handle_scsi(s, cmd, 0);
- break;
case MFI_CMD_LD_SCSI_IO:
- frame_status = megasas_handle_scsi(s, cmd, 1);
+ frame_status = megasas_handle_scsi(s, cmd, frame_cmd);
break;
case MFI_CMD_LD_READ:
case MFI_CMD_LD_WRITE:
- frame_status = megasas_handle_io(s, cmd);
+ frame_status = megasas_handle_io(s, cmd, frame_cmd);
break;
default:
- trace_megasas_unhandled_frame_cmd(cmd->index,
- cmd->frame->header.frame_cmd);
+ trace_megasas_unhandled_frame_cmd(cmd->index, frame_cmd);
s->event_count++;
break;
}

View File

@ -1,145 +0,0 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 1 Jun 2017 17:25:03 +0200
Subject: [PATCH] megasas: do not read SCSI req parameters more than once from
frame
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit b356807fcdfc45583c437f761fc579ab2a8eab11)
---
hw/scsi/megasas.c | 60 ++++++++++++++++++++++++-------------------------------
1 file changed, 26 insertions(+), 34 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 38e0a2f5ef..135662df31 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1653,42 +1653,39 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
int frame_cmd)
{
uint8_t *cdb;
+ int target_id, lun_id, cdb_len;
bool is_write;
struct SCSIDevice *sdev = NULL;
bool is_logical = (frame_cmd == MFI_CMD_LD_SCSI_IO);
cdb = cmd->frame->pass.cdb;
+ target_id = cmd->frame->header.target_id;
+ lun_id = cmd->frame->header.lun_id;
+ cdb_len = cmd->frame->header.cdb_len;
if (is_logical) {
- if (cmd->frame->header.target_id >= MFI_MAX_LD ||
- cmd->frame->header.lun_id != 0) {
+ if (target_id >= MFI_MAX_LD || lun_id != 0) {
trace_megasas_scsi_target_not_present(
- mfi_frame_desc[frame_cmd], is_logical,
- cmd->frame->header.target_id, cmd->frame->header.lun_id);
+ mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id);
return MFI_STAT_DEVICE_NOT_FOUND;
}
}
- sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id,
- cmd->frame->header.lun_id);
+ sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len);
- trace_megasas_handle_scsi(mfi_frame_desc[cmd->frame->header.frame_cmd],
trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical,
- cmd->frame->header.target_id,
- cmd->frame->header.lun_id, sdev, cmd->iov_size);
+ target_id, lun_id, sdev, cmd->iov_size);
if (!sdev || (megasas_is_jbod(s) && is_logical)) {
trace_megasas_scsi_target_not_present(
- mfi_frame_desc[frame_cmd], is_logical,
- cmd->frame->header.target_id, cmd->frame->header.lun_id);
+ mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id);
return MFI_STAT_DEVICE_NOT_FOUND;
}
- if (cmd->frame->header.cdb_len > 16) {
+ if (cdb_len > 16) {
trace_megasas_scsi_invalid_cdb_len(
mfi_frame_desc[frame_cmd], is_logical,
- cmd->frame->header.target_id, cmd->frame->header.lun_id,
- cmd->frame->header.cdb_len);
+ target_id, lun_id, cdb_len);
megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
cmd->frame->header.scsi_status = CHECK_CONDITION;
s->event_count++;
@@ -1702,12 +1699,10 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
return MFI_STAT_SCSI_DONE_WITH_ERROR;
}
- cmd->req = scsi_req_new(sdev, cmd->index,
- cmd->frame->header.lun_id, cdb, cmd);
+ cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd);
if (!cmd->req) {
trace_megasas_scsi_req_alloc_failed(
- mfi_frame_desc[frame_cmd],
- cmd->frame->header.target_id, cmd->frame->header.lun_id);
+ mfi_frame_desc[frame_cmd], target_id, lun_id);
megasas_write_sense(cmd, SENSE_CODE(NO_SENSE));
cmd->frame->header.scsi_status = BUSY;
s->event_count++;
@@ -1736,35 +1731,33 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
uint8_t cdb[16];
int len;
struct SCSIDevice *sdev = NULL;
+ int target_id, lun_id, cdb_len;
lba_count = le32_to_cpu(cmd->frame->io.header.data_len);
lba_start_lo = le32_to_cpu(cmd->frame->io.lba_lo);
lba_start_hi = le32_to_cpu(cmd->frame->io.lba_hi);
lba_start = ((uint64_t)lba_start_hi << 32) | lba_start_lo;
- if (cmd->frame->header.target_id < MFI_MAX_LD &&
- cmd->frame->header.lun_id == 0) {
- sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id,
- cmd->frame->header.lun_id);
+ target_id = cmd->frame->header.target_id;
+ lun_id = cmd->frame->header.lun_id;
+ cdb_len = cmd->frame->header.cdb_len;
+
+ if (target_id < MFI_MAX_LD && lun_id == 0) {
+ sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
}
trace_megasas_handle_io(cmd->index,
- mfi_frame_desc[frame_cmd],
- cmd->frame->header.target_id,
- cmd->frame->header.lun_id,
+ mfi_frame_desc[frame_cmd], target_id, lun_id,
(unsigned long)lba_start, (unsigned long)lba_count);
if (!sdev) {
trace_megasas_io_target_not_present(cmd->index,
- mfi_frame_desc[frame_cmd],
- cmd->frame->header.target_id, cmd->frame->header.lun_id);
+ mfi_frame_desc[frame_cmd], target_id, lun_id);
return MFI_STAT_DEVICE_NOT_FOUND;
}
- if (cmd->frame->header.cdb_len > 16) {
+ if (cdb_len > 16) {
trace_megasas_scsi_invalid_cdb_len(
- mfi_frame_desc[frame_cmd], 1,
- cmd->frame->header.target_id, cmd->frame->header.lun_id,
- cmd->frame->header.cdb_len);
+ mfi_frame_desc[frame_cmd], 1, target_id, lun_id, cdb_len);
megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
cmd->frame->header.scsi_status = CHECK_CONDITION;
s->event_count++;
@@ -1781,11 +1774,10 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
megasas_encode_lba(cdb, lba_start, lba_count, is_write);
cmd->req = scsi_req_new(sdev, cmd->index,
- cmd->frame->header.lun_id, cdb, cmd);
+ lun_id, cdb, cmd);
if (!cmd->req) {
trace_megasas_scsi_req_alloc_failed(
- mfi_frame_desc[frame_cmd],
- cmd->frame->header.target_id, cmd->frame->header.lun_id);
+ mfi_frame_desc[frame_cmd], target_id, lun_id);
megasas_write_sense(cmd, SENSE_CODE(NO_SENSE));
cmd->frame->header.scsi_status = BUSY;
s->event_count++;

View File

@ -1,47 +0,0 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 9 May 2017 13:01:28 +0200
Subject: [PATCH] usb-redir: fix stack overflow in usbredir_log_data
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Don't reinvent a broken wheel, just use the hexdump function we have.
Impact: low, broken code doesn't run unless you have debug logging
enabled.
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20170509110128.27261-1-kraxel@redhat.com
(cherry picked from commit bd4a683505b27adc1ac809f71e918e58573d851d)
---
hw/usb/redirect.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 0efe62f725..eb70dc7218 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -229,21 +229,10 @@ static void usbredir_log(void *priv, int level, const char *msg)
static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
const uint8_t *data, int len)
{
- int i, j, n;
-
if (dev->debug < usbredirparser_debug_data) {
return;
}
-
- for (i = 0; i < len; i += j) {
- char buf[128];
-
- n = sprintf(buf, "%s", desc);
- for (j = 0; j < 8 && i + j < len; j++) {
- n += sprintf(buf + n, " %02X", data[i + j]);
- }
- error_report("%s", buf);
- }
+ qemu_hexdump((char *)data, stderr, desc, len);
}
/*

View File

@ -1,77 +0,0 @@
From: Eric Blake <eblake@redhat.com>
Date: Fri, 26 May 2017 22:04:21 -0500
Subject: [PATCH] nbd: Fully initialize client in case of failed negotiation
If a non-NBD client connects to qemu-nbd, we would end up with
a SIGSEGV in nbd_client_put() because we were trying to
unregister the client's association to the export, even though
we skipped inserting the client into that list. Easy trigger
in two terminals:
$ qemu-nbd -p 30001 --format=raw file
$ nmap 127.0.0.1 -p 30001
nmap claims that it thinks it connected to a pago-services1
server (which probably means nmap could be updated to learn the
NBD protocol and give a more accurate diagnosis of the open
port - but that's not our problem), then terminates immediately,
so our call to nbd_negotiate() fails. The fix is to reorder
nbd_co_client_start() to ensure that all initialization occurs
before we ever try talking to a client in nbd_negotiate(), so
that the teardown sequence on negotiation failure doesn't fault
while dereferencing a half-initialized object.
While debugging this, I also noticed that nbd_update_server_watch()
called by nbd_client_closed() was still adding a channel to accept
the next client, even when the state was no longer RUNNING. That
is fixed by making nbd_can_accept() pay attention to the current
state.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170527030421.28366-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit df8ad9f128c15aa0a0ebc7b24e9a22c9775b67af)
---
nbd/server.c | 8 +++-----
qemu-nbd.c | 2 +-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/nbd/server.c b/nbd/server.c
index 924a1fe2db..edfda84d43 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1376,16 +1376,14 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
if (exp) {
nbd_export_get(exp);
+ QTAILQ_INSERT_TAIL(&exp->clients, client, next);
}
+ qemu_co_mutex_init(&client->send_lock);
+
if (nbd_negotiate(data)) {
client_close(client);
goto out;
}
- qemu_co_mutex_init(&client->send_lock);
-
- if (exp) {
- QTAILQ_INSERT_TAIL(&exp->clients, client, next);
- }
nbd_client_receive_next_request(client);
diff --git a/qemu-nbd.c b/qemu-nbd.c
index e080fb7c75..b44764eb87 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -324,7 +324,7 @@ out:
static int nbd_can_accept(void)
{
- return nb_fds < shared;
+ return state == RUNNING && nb_fds < shared;
}
static void nbd_export_closed(NBDExport *exp)

View File

@ -1,194 +0,0 @@
From: Eric Blake <eblake@redhat.com>
Date: Thu, 8 Jun 2017 17:26:17 -0500
Subject: [PATCH] nbd: Fix regression on resiliency to port scan
Back in qemu 2.5, qemu-nbd was immune to port probes (a transient
server would not quit, regardless of how many probe connections
came and went, until a connection actually negotiated). But we
broke that in commit ee7d7aa when removing the return value to
nbd_client_new(), although that patch also introduced a bug causing
an assertion failure on a client that fails negotiation. We then
made it worse during refactoring in commit 1a6245a (a segfault
before we could even assert); the (masked) assertion was cleaned
up in d3780c2 (still in 2.6), and just recently we finally fixed
the segfault ("nbd: Fully intialize client in case of failed
negotiation"). But that still means that ever since we added
TLS support to qemu-nbd, we have been vulnerable to an ill-timed
port-scan being able to cause a denial of service by taking down
qemu-nbd before a real client has a chance to connect.
Since negotiation is now handled asynchronously via coroutines,
we no longer have a synchronous point of return by re-adding a
return value to nbd_client_new(). So this patch instead wires
things up to pass the negotiation status through the close_fn
callback function.
Simple test across two terminals:
$ qemu-nbd -f raw -p 30001 file
$ nmap 127.0.0.1 -p 30001 && \
qemu-io -c 'r 0 512' -f raw nbd://localhost:30001
Note that this patch does not change what constitutes successful
negotiation (thus, a client must enter transmission phase before
that client can be considered as a reason to terminate the server
when the connection ends). Perhaps we may want to tweak things
in a later patch to also treat a client that uses NBD_OPT_ABORT
as being a 'successful' negotiation (the client correctly talked
the NBD protocol, and informed us it was not going to use our
export after all), but that's a discussion for another day.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170608222617.20376-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 0c9390d978cbf61e8f16c9f580fa96b305c43568)
---
blockdev-nbd.c | 6 +++++-
include/block/nbd.h | 2 +-
nbd/server.c | 24 +++++++++++++++---------
qemu-nbd.c | 4 ++--
4 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 8a11807df3..8d7284ac56 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -27,6 +27,10 @@ typedef struct NBDServerData {
static NBDServerData *nbd_server;
+static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
+{
+ nbd_client_put(client);
+}
static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
gpointer opaque)
@@ -46,7 +50,7 @@ static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
nbd_client_new(NULL, cioc,
nbd_server->tlscreds, NULL,
- nbd_client_put);
+ nbd_blockdev_client_closed);
object_unref(OBJECT(cioc));
return TRUE;
}
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 3e373f0498..b69c30d063 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -160,7 +160,7 @@ void nbd_client_new(NBDExport *exp,
QIOChannelSocket *sioc,
QCryptoTLSCreds *tlscreds,
const char *tlsaclname,
- void (*close)(NBDClient *));
+ void (*close_fn)(NBDClient *, bool));
void nbd_client_get(NBDClient *client);
void nbd_client_put(NBDClient *client);
diff --git a/nbd/server.c b/nbd/server.c
index edfda84d43..a98bb21a0a 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -81,7 +81,7 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
struct NBDClient {
int refcount;
- void (*close)(NBDClient *client);
+ void (*close_fn)(NBDClient *client, bool negotiated);
bool no_zeroes;
NBDExport *exp;
@@ -796,7 +796,7 @@ void nbd_client_put(NBDClient *client)
}
}
-static void client_close(NBDClient *client)
+static void client_close(NBDClient *client, bool negotiated)
{
if (client->closing) {
return;
@@ -811,8 +811,8 @@ static void client_close(NBDClient *client)
NULL);
/* Also tell the client, so that they release their reference. */
- if (client->close) {
- client->close(client);
+ if (client->close_fn) {
+ client->close_fn(client, negotiated);
}
}
@@ -993,7 +993,7 @@ void nbd_export_close(NBDExport *exp)
nbd_export_get(exp);
QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
- client_close(client);
+ client_close(client, true);
}
nbd_export_set_name(exp, NULL);
nbd_export_set_description(exp, NULL);
@@ -1355,7 +1355,7 @@ done:
out:
nbd_request_put(req);
- client_close(client);
+ client_close(client, true);
nbd_client_put(client);
}
@@ -1381,7 +1381,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
qemu_co_mutex_init(&client->send_lock);
if (nbd_negotiate(data)) {
- client_close(client);
+ client_close(client, false);
goto out;
}
@@ -1391,11 +1391,17 @@ out:
g_free(data);
}
+/*
+ * Create a new client listener on the given export @exp, using the
+ * given channel @sioc. Begin servicing it in a coroutine. When the
+ * connection closes, call @close_fn with an indication of whether the
+ * client completed negotiation.
+ */
void nbd_client_new(NBDExport *exp,
QIOChannelSocket *sioc,
QCryptoTLSCreds *tlscreds,
const char *tlsaclname,
- void (*close_fn)(NBDClient *))
+ void (*close_fn)(NBDClient *, bool))
{
NBDClient *client;
NBDClientNewData *data = g_new(NBDClientNewData, 1);
@@ -1412,7 +1418,7 @@ void nbd_client_new(NBDExport *exp,
object_ref(OBJECT(client->sioc));
client->ioc = QIO_CHANNEL(sioc);
object_ref(OBJECT(client->ioc));
- client->close = close_fn;
+ client->close_fn = close_fn;
data->client = client;
data->co = qemu_coroutine_create(nbd_co_client_start, data);
diff --git a/qemu-nbd.c b/qemu-nbd.c
index b44764eb87..483dd77a77 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -335,10 +335,10 @@ static void nbd_export_closed(NBDExport *exp)
static void nbd_update_server_watch(void);
-static void nbd_client_closed(NBDClient *client)
+static void nbd_client_closed(NBDClient *client, bool negotiated)
{
nb_fds--;
- if (nb_fds == 0 && !persistent && state == RUNNING) {
+ if (negotiated && nb_fds == 0 && !persistent && state == RUNNING) {
state = TERMINATE;
}
nbd_update_server_watch();

View File

@ -1,44 +0,0 @@
From: Max Reitz <mreitz@redhat.com>
Date: Sun, 11 Jun 2017 14:37:14 +0200
Subject: [PATCH] qemu-nbd: Ignore SIGPIPE
qemu proper has done so for 13 years
(8a7ddc38a60648257dc0645ab4a05b33d6040063), qemu-img and qemu-io have
done so for four years (526eda14a68d5b3596be715505289b541288ef2a).
Ignoring this signal is especially important in qemu-nbd because
otherwise a client can easily take down the qemu-nbd server by dropping
the connection when the server wants to send something, for example:
$ qemu-nbd -x foo -f raw -t null-co:// &
[1] 12726
$ qemu-io -c quit nbd://localhost/bar
can't open device nbd://localhost/bar: No export with name 'bar' available
[1] + 12726 broken pipe qemu-nbd -x foo -f raw -t null-co://
In this case, the client sends an NBD_OPT_ABORT and closes the
connection (because it is not required to wait for a reply), but the
server replies with an NBD_REP_ACK (because it is required to reply).
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20170611123714.31292-1-mreitz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 041e32b8d9d076980b4e35317c0339e57ab888f1)
---
qemu-nbd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 483dd77a77..5deb37e03e 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -581,6 +581,10 @@ int main(int argc, char **argv)
sa_sigterm.sa_handler = termsig_handler;
sigaction(SIGTERM, &sa_sigterm, NULL);
+#ifdef CONFIG_POSIX
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
module_call_init(MODULE_INIT_TRACE);
qcrypto_init(&error_fatal);

View File

@ -1,34 +0,0 @@
From 77b0359bf414ad666d1714dc9888f1017c08e283 Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Thu, 22 Jun 2017 09:41:58 +0200
Subject: [PATCH] input: Decrement queue count on kbd delay
Delays in the input layer are special cased input events. Every input
event is accounted for in a global intput queue count. The special cased
delays however did not get removed from the queue, leading to queue overruns
and thus silent key drops after typing quite a few characters.
Signed-off-by: Alexander Graf <agraf@suse.de>
Message-id: 1498117318-162102-1-git-send-email-agraf@suse.de
Fixes: be1a7176 ("input: add support for kbd delays")
Cc: qemu-stable@nongnu.org
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
ui/input.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/input.c b/ui/input.c
index 2abd46de93..af05f06368 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -256,6 +256,7 @@ static void qemu_input_queue_process(void *opaque)
item = QTAILQ_FIRST(queue);
g_assert(item->type == QEMU_INPUT_QUEUE_DELAY);
QTAILQ_REMOVE(queue, item, node);
+ queue_count--;
g_free(item);
while (!QTAILQ_EMPTY(queue)) {
--
2.14.1

View File

@ -1,32 +0,0 @@
From 51dbea77a29ea46173373a6dad4ebd95d4661f42 Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Thu, 22 Jun 2017 09:41:35 +0200
Subject: [PATCH] hid: Reset kbd modifiers on reset
When resetting the keyboard, we need to reset not just the pending keystrokes,
but also any pending modifiers. Otherwise there's a race when we're getting
reset while running an escape sequence (modifier 0x100).
Cc: qemu-stable@nongnu.org
Signed-off-by: Alexander Graf <agraf@suse.de>
Message-id: 1498117295-162030-1-git-send-email-agraf@suse.de
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/input/hid.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/input/hid.c b/hw/input/hid.c
index 93887ecc43..0d049ff61c 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -487,6 +487,7 @@ void hid_reset(HIDState *hs)
memset(hs->kbd.keycodes, 0, sizeof(hs->kbd.keycodes));
memset(hs->kbd.key, 0, sizeof(hs->kbd.key));
hs->kbd.keys = 0;
+ hs->kbd.modifiers = 0;
break;
case HID_MOUSE:
case HID_TABLET:
--
2.14.1

View File

@ -1,54 +0,0 @@
From d3b0db6dfea6b3a9ee0d96aceb796bdcafa84314 Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Wed, 12 Jul 2017 14:43:45 +0200
Subject: [PATCH] vnc: Set default kbd delay to 10ms
The current VNC default keyboard delay is 1ms. With that we're constantly
typing faster than the guest receives keyboard events from an XHCI attached
USB HID device.
The default keyboard delay time in the input layer however is 10ms. I don't know
how that number came to be, but empirical tests on some OpenQA driven ARM
systems show that 10ms really is a reasonable default number for the delay.
This patch moves the VNC delay also to 10ms. That way our default is much
safer (good!) and also consistent with the input layer default (also good!).
Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Message-id: 1499863425-103133-1-git-send-email-agraf@suse.de
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
qemu-options.hx | 2 +-
ui/vnc.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index 76b1c67737..6909285e85 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1753,7 +1753,7 @@ spec but is traditional QEMU behavior.
@item key-delay-ms
Set keyboard delay, for key down and key up events, in milliseconds.
-Default is 1. Keyboards are low-bandwidth devices, so this slowdown
+Default is 10. Keyboards are low-bandwidth devices, so this slowdown
can help the device and guest to keep up and not lose events in case
events are arriving in bulk. Possible causes for the latter are flaky
network connections, or scripts for automated testing.
diff --git a/ui/vnc.c b/ui/vnc.c
index 26136f5d29..eb91559b6b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3808,7 +3808,7 @@ void vnc_display_open(const char *id, Error **errp)
}
lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true);
- key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 1);
+ key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 10);
sasl = qemu_opt_get_bool(opts, "sasl", false);
#ifndef CONFIG_VNC_SASL
if (sasl) {
--
2.14.1

View File

@ -91,8 +91,8 @@ Requires: %{name}-block-ssh = %{epoch}:%{version}-%{release}
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 2.9.0
Release: 5%{?rcrel}%{?dist}
Version: 2.9.1
Release: 1%{?rcrel}%{?dist}
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
Group: Development/Tools
@ -126,42 +126,9 @@ Source21: 50-kvm-s390x.conf
# /etc/security/limits.d/95-kvm-ppc64-memlock.conf
Source22: 95-kvm-ppc64-memlock.conf
# CVE-2017-8112: vmw_pvscsi: infinite loop in pvscsi_log2 (bz #1445622)
Patch0001: 0001-vmw_pvscsi-check-message-ring-page-count-at-initiali.patch
# CVE-2017-8309: audio: host memory lekage via capture buffer (bz #1446520)
Patch0002: 0002-audio-release-capture-buffers.patch
# CVE-2017-8379: input: host memory lekage via keyboard events (bz #1446560)
Patch0003: 0003-input-limit-kbd-queue-depth.patch
# CVE-2017-8380: scsi: megasas: out-of-bounds read in megasas_mmio_write (bz
# #1446578)
Patch0004: 0004-scsi-avoid-an-off-by-one-error-in-megasas_mmio_write.patch
# CVE-2017-7493: 9pfs: guest privilege escalation in virtfs mapped-file mode
# (bz #1451711)
Patch0005: 0005-9pfs-local-forbid-client-access-to-metadata-CVE-2017.patch
# CVE-2017-9503: megasas: null pointer dereference while processing megasas
# command (bz #1459478)
Patch0006: 0006-megasas-do-not-read-sense-length-more-than-once-from.patch
Patch0007: 0007-megasas-do-not-read-iovec-count-more-than-once-from-.patch
Patch0008: 0008-megasas-do-not-read-DCMD-opcode-more-than-once-from-.patch
Patch0009: 0009-megasas-do-not-read-command-more-than-once-from-fram.patch
Patch0010: 0010-megasas-do-not-read-SCSI-req-parameters-more-than-on.patch
Patch0011: 0011-megasas-always-store-SCSIRequest-into-MegasasCmd.patch
# CVE-2017-10806: usb-redirect: stack buffer overflow in debug logging (bz
# #1468497)
Patch0101: 0101-usb-redir-fix-stack-overflow-in-usbredir_log_data.patch
# CVE-2017-9524: nbd: segfault due to client non-negotiation (bz #1460172)
Patch0102: 0102-nbd-Fully-initialize-client-in-case-of-failed-negoti.patch
Patch0103: 0103-nbd-Fix-regression-on-resiliency-to-port-scan.patch
# CVE-2017-10664: qemu-nbd: server breaks with SIGPIPE upon client abort (bz
# #1466192)
Patch0104: 0104-qemu-nbd-Ignore-SIGPIPE.patch
# Backported fixes for VNC input issues after the implementation of queue
# depth limit in input-limit-kbd-queue-depth.patch (bz #1481858)
Patch0201: 0201-input-Decrement-queue-count-on-kbd-delay.patch
Patch0202: 0202-hid-Reset-kbd-modifiers-on-reset.patch
Patch0203: 0203-vnc-Set-default-kbd-delay-to-10ms.patch
Patch0001: 0001-megasas-always-store-SCSIRequest-into-MegasasCmd.patch
# documentation deps
BuildRequires: texinfo
@ -2040,6 +2007,9 @@ getent passwd qemu >/dev/null || \
%changelog
* Fri Sep 08 2017 Cole Robinson <crobinso@redhat.com> - 2:2.9.1-1
- Rebase to 2.9.1 stable release
* Tue Aug 15 2017 Adam Williamson <awilliam@redhat.com> - 2:2.9.0-5
- Backport fixes for input issues (esp. openQA) after CVE-2017-8379 fix

View File

@ -1 +1 @@
SHA512 (qemu-2.9.0.tar.xz) = a5259b888ac336db559f4483a9c50ad434fb82aedce37d9be957e79f696736509af1841489ee10e7362ef1506f3a04786c483a2e37d342b2bec46f0a726fb60f
SHA512 (qemu-2.9.1.tar.xz) = 013056fbd167e1f191dadc615e33fb10410582ca583c6b69e575c6f3dff205c02550da175be1ea3b6c92382219e93a92bbe9d5a1a17fa18a6c8877968647a197