Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame^] | 1 | CVE: CVE-2018-16872 |
| 2 | Upstream-Status: Backport [https://git.qemu.org/?p=qemu.git;a=commit;h=bab9df35] |
| 3 | |
| 4 | Signed-off-by: Kai Kang <kai.kang@windriver.com> |
| 5 | |
| 6 | From bab9df35ce73d1c8e19a37e2737717ea1c984dc1 Mon Sep 17 00:00:00 2001 |
| 7 | From: Gerd Hoffmann <kraxel@redhat.com> |
| 8 | Date: Thu, 13 Dec 2018 13:25:11 +0100 |
| 9 | Subject: [PATCH] usb-mtp: use O_NOFOLLOW and O_CLOEXEC. |
| 10 | |
| 11 | Open files and directories with O_NOFOLLOW to avoid symlinks attacks. |
| 12 | While being at it also add O_CLOEXEC. |
| 13 | |
| 14 | usb-mtp only handles regular files and directories and ignores |
| 15 | everything else, so users should not see a difference. |
| 16 | |
| 17 | Because qemu ignores symlinks, carrying out a successful symlink attack |
| 18 | requires swapping an existing file or directory below rootdir for a |
| 19 | symlink and winning the race against the inotify notification to qemu. |
| 20 | |
| 21 | Fixes: CVE-2018-16872 |
| 22 | Cc: Prasad J Pandit <ppandit@redhat.com> |
| 23 | Cc: Bandan Das <bsd@redhat.com> |
| 24 | Reported-by: Michael Hanselmann <public@hansmi.ch> |
| 25 | Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> |
| 26 | Reviewed-by: Michael Hanselmann <public@hansmi.ch> |
| 27 | Message-id: 20181213122511.13853-1-kraxel@redhat.com |
| 28 | --- |
| 29 | hw/usb/dev-mtp.c | 13 +++++++++---- |
| 30 | 1 file changed, 9 insertions(+), 4 deletions(-) |
| 31 | |
| 32 | diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c |
| 33 | index 100b7171f4..36c43b8c20 100644 |
| 34 | --- a/hw/usb/dev-mtp.c |
| 35 | +++ b/hw/usb/dev-mtp.c |
| 36 | @@ -653,13 +653,18 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) |
| 37 | { |
| 38 | struct dirent *entry; |
| 39 | DIR *dir; |
| 40 | + int fd; |
| 41 | |
| 42 | if (o->have_children) { |
| 43 | return; |
| 44 | } |
| 45 | o->have_children = true; |
| 46 | |
| 47 | - dir = opendir(o->path); |
| 48 | + fd = open(o->path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); |
| 49 | + if (fd < 0) { |
| 50 | + return; |
| 51 | + } |
| 52 | + dir = fdopendir(fd); |
| 53 | if (!dir) { |
| 54 | return; |
| 55 | } |
| 56 | @@ -1007,7 +1012,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c, |
| 57 | |
| 58 | trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path); |
| 59 | |
| 60 | - d->fd = open(o->path, O_RDONLY); |
| 61 | + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); |
| 62 | if (d->fd == -1) { |
| 63 | usb_mtp_data_free(d); |
| 64 | return NULL; |
| 65 | @@ -1031,7 +1036,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c, |
| 66 | c->argv[1], c->argv[2]); |
| 67 | |
| 68 | d = usb_mtp_data_alloc(c); |
| 69 | - d->fd = open(o->path, O_RDONLY); |
| 70 | + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); |
| 71 | if (d->fd == -1) { |
| 72 | usb_mtp_data_free(d); |
| 73 | return NULL; |
| 74 | @@ -1658,7 +1663,7 @@ static void usb_mtp_write_data(MTPState *s) |
| 75 | 0, 0, 0, 0); |
| 76 | goto done; |
| 77 | } |
| 78 | - d->fd = open(path, O_CREAT | O_WRONLY, mask); |
| 79 | + d->fd = open(path, O_CREAT | O_WRONLY | O_CLOEXEC | O_NOFOLLOW, mask); |
| 80 | if (d->fd == -1) { |
| 81 | usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, |
| 82 | 0, 0, 0, 0); |
| 83 | -- |
| 84 | 2.20.1 |
| 85 | |