| From 5b3c77aa581ebb215125c84b0742119483571e55 Mon Sep 17 00:00:00 2001 |
| From: Greg Kurz <groug@kaod.org> |
| Date: Tue, 20 Nov 2018 13:00:35 +0100 |
| Subject: [PATCH] 9p: take write lock on fid path updates (CVE-2018-19364) |
| |
| Recent commit 5b76ef50f62079a fixed a race where v9fs_co_open2() could |
| possibly overwrite a fid path with v9fs_path_copy() while it is being |
| accessed by some other thread, ie, use-after-free that can be detected |
| by ASAN with a custom 9p client. |
| |
| It turns out that the same can happen at several locations where |
| v9fs_path_copy() is used to set the fid path. The fix is again to |
| take the write lock. |
| |
| Fixes CVE-2018-19364. |
| |
| Cc: P J P <ppandit@redhat.com> |
| Reported-by: zhibin hu <noirfate@gmail.com> |
| Reviewed-by: Prasad J Pandit <pjp@fedoraproject.org> |
| Signed-off-by: Greg Kurz <groug@kaod.org> |
| |
| Upstream-status: Backport |
| Affects: < 3.1.0 |
| CVE: CVE-2018-19364 patch #2 |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| hw/9pfs/9p.c | 15 +++++++++++++++ |
| 1 file changed, 15 insertions(+) |
| |
| diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c |
| index eef289e..267a255 100644 |
| --- a/hw/9pfs/9p.c |
| +++ b/hw/9pfs/9p.c |
| @@ -1391,7 +1391,9 @@ static void coroutine_fn v9fs_walk(void *opaque) |
| err = -EINVAL; |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| } else { |
| newfidp = alloc_fid(s, newfid); |
| if (newfidp == NULL) { |
| @@ -2160,6 +2162,7 @@ static void coroutine_fn v9fs_create(void *opaque) |
| V9fsString extension; |
| int iounit; |
| V9fsPDU *pdu = opaque; |
| + V9fsState *s = pdu->s; |
| |
| v9fs_path_init(&path); |
| v9fs_string_init(&name); |
| @@ -2200,7 +2203,9 @@ static void coroutine_fn v9fs_create(void *opaque) |
| if (err < 0) { |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| err = v9fs_co_opendir(pdu, fidp); |
| if (err < 0) { |
| goto out; |
| @@ -2216,7 +2221,9 @@ static void coroutine_fn v9fs_create(void *opaque) |
| if (err < 0) { |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| } else if (perm & P9_STAT_MODE_LINK) { |
| int32_t ofid = atoi(extension.data); |
| V9fsFidState *ofidp = get_fid(pdu, ofid); |
| @@ -2234,7 +2241,9 @@ static void coroutine_fn v9fs_create(void *opaque) |
| fidp->fid_type = P9_FID_NONE; |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); |
| if (err < 0) { |
| fidp->fid_type = P9_FID_NONE; |
| @@ -2272,7 +2281,9 @@ static void coroutine_fn v9fs_create(void *opaque) |
| if (err < 0) { |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| } else if (perm & P9_STAT_MODE_NAMED_PIPE) { |
| err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, |
| 0, S_IFIFO | (perm & 0777), &stbuf); |
| @@ -2283,7 +2294,9 @@ static void coroutine_fn v9fs_create(void *opaque) |
| if (err < 0) { |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| } else if (perm & P9_STAT_MODE_SOCKET) { |
| err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, |
| 0, S_IFSOCK | (perm & 0777), &stbuf); |
| @@ -2294,7 +2307,9 @@ static void coroutine_fn v9fs_create(void *opaque) |
| if (err < 0) { |
| goto out; |
| } |
| + v9fs_path_write_lock(s); |
| v9fs_path_copy(&fidp->path, &path); |
| + v9fs_path_unlock(s); |
| } else { |
| err = v9fs_co_open2(pdu, fidp, &name, -1, |
| omode_to_uflags(mode)|O_CREAT, perm, &stbuf); |
| -- |
| 2.7.4 |
| |