diff options
author | Omar Sandoval <osandov@fb.com> | 2017-02-01 03:02:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-04-21 03:31:24 -0400 |
commit | 86c6667f6a5f6bdb392d8ffbe58fbcbcf6db2704 (patch) | |
tree | 735cdb27c467f3899a5b92e3957063ec31635de8 | |
parent | fb00319317c152bf3528df13a54c28bf8c5daa55 (diff) |
virtio-console: avoid DMA from stack
commit c4baad50297d84bde1a7ad45e50c73adae4a2192 upstream.
put_chars() stuffs the buffer it gets into an sg, but that buffer may be
on the stack. This breaks with CONFIG_VMAP_STACK=y (for me, it
manifested as printks getting turned into NUL bytes).
Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: Brad Spengler <spender@grsecurity.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/char/virtio_console.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 5649234b7316..471a301d63e3 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -1136,6 +1136,8 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
1136 | { | 1136 | { |
1137 | struct port *port; | 1137 | struct port *port; |
1138 | struct scatterlist sg[1]; | 1138 | struct scatterlist sg[1]; |
1139 | void *data; | ||
1140 | int ret; | ||
1139 | 1141 | ||
1140 | if (unlikely(early_put_chars)) | 1142 | if (unlikely(early_put_chars)) |
1141 | return early_put_chars(vtermno, buf, count); | 1143 | return early_put_chars(vtermno, buf, count); |
@@ -1144,8 +1146,14 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
1144 | if (!port) | 1146 | if (!port) |
1145 | return -EPIPE; | 1147 | return -EPIPE; |
1146 | 1148 | ||
1147 | sg_init_one(sg, buf, count); | 1149 | data = kmemdup(buf, count, GFP_ATOMIC); |
1148 | return __send_to_port(port, sg, 1, count, (void *)buf, false); | 1150 | if (!data) |
1151 | return -ENOMEM; | ||
1152 | |||
1153 | sg_init_one(sg, data, count); | ||
1154 | ret = __send_to_port(port, sg, 1, count, data, false); | ||
1155 | kfree(data); | ||
1156 | return ret; | ||
1149 | } | 1157 | } |
1150 | 1158 | ||
1151 | /* | 1159 | /* |