Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
qemu.3557
0276-9pfs-handle-walk-of-.-in-the-root-d.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0276-9pfs-handle-walk-of-.-in-the-root-d.patch of Package qemu.3557
From 9bf6bda475ea0d5dd1d2b18be4ad84f94d76114c Mon Sep 17 00:00:00 2001 From: Greg Kurz <groug@kaod.org> Date: Tue, 30 Aug 2016 17:02:27 +0200 Subject: [PATCH] 9pfs: handle walk of ".." in the root directory The 9P spec at http://man.cat-v.org/plan_9/5/intro says: All directories must support walks to the directory .. (dot-dot) meaning parent directory, although by convention directories contain no explicit entry for .. or . (dot). The parent of the root directory of a server's tree is itself. This means that a client cannot walk further than the root directory exported by the server. In other words, if the client wants to walk "/.." or "/foo/../..", the server should answer like the request was to walk "/". This patch just does that: - we cache the QID of the root directory at attach time - during the walk we compare the QID of each path component with the root QID to detect if we're in a "/.." situation - if so, we skip the current component and go to the next one Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> (cherry picked from commit 56f101ecce0eafd09e2daf1c4eeb1377d6959261) [BR: CVE-2016-7116 BSC#996441] Signed-off-by: Bruce Rogers <brogers@suse.com> Conflicts: hw/9pfs/9p.h hw/9pfs/virtio-9p.c --- hw/9pfs/virtio-9p.c | 40 +++++++++++++++++++++++++++++++--------- hw/9pfs/virtio-9p.h | 1 + 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 83e4e93..ef47d3a 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -979,6 +979,7 @@ static void v9fs_attach(void *opaque) goto out; } err += offset; + memcpy(&s->root_qid, &qid, sizeof(qid)); trace_v9fs_attach_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); /* @@ -1226,6 +1227,14 @@ static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) return offset; } +static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2) +{ + return + qid1->type != qid2->type || + qid1->version != qid2->version || + qid1->path != qid2->path; +} + static void v9fs_walk(void *opaque) { int name_idx; @@ -1241,6 +1250,7 @@ static void v9fs_walk(void *opaque) V9fsFidState *newfidp = NULL; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; + V9fsQID qid; err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames); if (err < 0) { @@ -1270,6 +1280,12 @@ static void v9fs_walk(void *opaque) err = -ENOENT; goto out_nofid; } + + err = fid_to_qid(pdu, fidp, &qid); + if (err < 0) { + goto out; + } + v9fs_path_init(&dpath); v9fs_path_init(&path); /* @@ -1279,16 +1295,22 @@ static void v9fs_walk(void *opaque) v9fs_path_copy(&dpath, &fidp->path); v9fs_path_copy(&path, &fidp->path); for (name_idx = 0; name_idx < nwnames; name_idx++) { - err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, &path); - if (err < 0) { - goto out; - } - err = v9fs_co_lstat(pdu, &path, &stbuf); - if (err < 0) { - goto out; + if (not_same_qid(&pdu->s->root_qid, &qid) || + strcmp("..", wnames[name_idx].data)) { + err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, + &path); + if (err < 0) { + goto out; + } + + err = v9fs_co_lstat(pdu, &path, &stbuf); + if (err < 0) { + goto out; + } + stat_to_qid(&stbuf, &qid); + v9fs_path_copy(&dpath, &path); } - stat_to_qid(&stbuf, &qids[name_idx]); - v9fs_path_copy(&dpath, &path); + memcpy(&qids[name_idx], &qid, sizeof(qid)); } if (fid == newfid) { BUG_ON(fidp->fid_type != P9_FID_NONE); diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 2c3603a..7400063 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -225,6 +225,7 @@ typedef struct V9fsState int32_t root_fid; Error *migration_blocker; V9fsConf fsconf; + V9fsQID root_qid; } V9fsState; typedef struct V9fsStatState {
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor