| CVE: CVE-2018-16872 |
| Upstream-Status: Backport [https://git.qemu.org/?p=qemu.git;a=commit;h=bab9df35] |
| |
| Signed-off-by: Kai Kang <kai.kang@windriver.com> |
| |
| From bab9df35ce73d1c8e19a37e2737717ea1c984dc1 Mon Sep 17 00:00:00 2001 |
| From: Gerd Hoffmann <kraxel@redhat.com> |
| Date: Thu, 13 Dec 2018 13:25:11 +0100 |
| Subject: [PATCH] usb-mtp: use O_NOFOLLOW and O_CLOEXEC. |
| |
| Open files and directories with O_NOFOLLOW to avoid symlinks attacks. |
| While being at it also add O_CLOEXEC. |
| |
| usb-mtp only handles regular files and directories and ignores |
| everything else, so users should not see a difference. |
| |
| Because qemu ignores symlinks, carrying out a successful symlink attack |
| requires swapping an existing file or directory below rootdir for a |
| symlink and winning the race against the inotify notification to qemu. |
| |
| Fixes: CVE-2018-16872 |
| Cc: Prasad J Pandit <ppandit@redhat.com> |
| Cc: Bandan Das <bsd@redhat.com> |
| Reported-by: Michael Hanselmann <public@hansmi.ch> |
| Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> |
| Reviewed-by: Michael Hanselmann <public@hansmi.ch> |
| Message-id: 20181213122511.13853-1-kraxel@redhat.com |
| --- |
| hw/usb/dev-mtp.c | 13 +++++++++---- |
| 1 file changed, 9 insertions(+), 4 deletions(-) |
| |
| diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c |
| index 100b7171f4..36c43b8c20 100644 |
| --- a/hw/usb/dev-mtp.c |
| +++ b/hw/usb/dev-mtp.c |
| @@ -653,13 +653,18 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) |
| { |
| struct dirent *entry; |
| DIR *dir; |
| + int fd; |
| |
| if (o->have_children) { |
| return; |
| } |
| o->have_children = true; |
| |
| - dir = opendir(o->path); |
| + fd = open(o->path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); |
| + if (fd < 0) { |
| + return; |
| + } |
| + dir = fdopendir(fd); |
| if (!dir) { |
| return; |
| } |
| @@ -1007,7 +1012,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c, |
| |
| trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path); |
| |
| - d->fd = open(o->path, O_RDONLY); |
| + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); |
| if (d->fd == -1) { |
| usb_mtp_data_free(d); |
| return NULL; |
| @@ -1031,7 +1036,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c, |
| c->argv[1], c->argv[2]); |
| |
| d = usb_mtp_data_alloc(c); |
| - d->fd = open(o->path, O_RDONLY); |
| + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); |
| if (d->fd == -1) { |
| usb_mtp_data_free(d); |
| return NULL; |
| @@ -1658,7 +1663,7 @@ static void usb_mtp_write_data(MTPState *s) |
| 0, 0, 0, 0); |
| goto done; |
| } |
| - d->fd = open(path, O_CREAT | O_WRONLY, mask); |
| + d->fd = open(path, O_CREAT | O_WRONLY | O_CLOEXEC | O_NOFOLLOW, mask); |
| if (d->fd == -1) { |
| usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, |
| 0, 0, 0, 0); |
| -- |
| 2.20.1 |
| |