mirror of https://github.com/xqemu/xqemu.git
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>
This commit is contained in:
parent
805b5d98c6
commit
56f101ecce
26
hw/9pfs/9p.c
26
hw/9pfs/9p.c
|
@ -1010,6 +1010,7 @@ static void v9fs_attach(void *opaque)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err += offset;
|
err += offset;
|
||||||
|
memcpy(&s->root_qid, &qid, sizeof(qid));
|
||||||
trace_v9fs_attach_return(pdu->tag, pdu->id,
|
trace_v9fs_attach_return(pdu->tag, pdu->id,
|
||||||
qid.type, qid.version, qid.path);
|
qid.type, qid.version, qid.path);
|
||||||
/*
|
/*
|
||||||
|
@ -1261,6 +1262,14 @@ static bool name_is_illegal(const char *name)
|
||||||
return !*name || strchr(name, '/') != NULL;
|
return !*name || strchr(name, '/') != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
static void v9fs_walk(void *opaque)
|
||||||
{
|
{
|
||||||
int name_idx;
|
int name_idx;
|
||||||
|
@ -1276,6 +1285,7 @@ static void v9fs_walk(void *opaque)
|
||||||
V9fsFidState *newfidp = NULL;
|
V9fsFidState *newfidp = NULL;
|
||||||
V9fsPDU *pdu = opaque;
|
V9fsPDU *pdu = opaque;
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
|
V9fsQID qid;
|
||||||
|
|
||||||
err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
|
err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -1309,6 +1319,12 @@ static void v9fs_walk(void *opaque)
|
||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
goto out_nofid;
|
goto out_nofid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = fid_to_qid(pdu, fidp, &qid);
|
||||||
|
if (err < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
v9fs_path_init(&dpath);
|
v9fs_path_init(&dpath);
|
||||||
v9fs_path_init(&path);
|
v9fs_path_init(&path);
|
||||||
/*
|
/*
|
||||||
|
@ -1318,17 +1334,23 @@ static void v9fs_walk(void *opaque)
|
||||||
v9fs_path_copy(&dpath, &fidp->path);
|
v9fs_path_copy(&dpath, &fidp->path);
|
||||||
v9fs_path_copy(&path, &fidp->path);
|
v9fs_path_copy(&path, &fidp->path);
|
||||||
for (name_idx = 0; name_idx < nwnames; name_idx++) {
|
for (name_idx = 0; name_idx < nwnames; name_idx++) {
|
||||||
err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, &path);
|
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) {
|
if (err < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = v9fs_co_lstat(pdu, &path, &stbuf);
|
err = v9fs_co_lstat(pdu, &path, &stbuf);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
stat_to_qid(&stbuf, &qids[name_idx]);
|
stat_to_qid(&stbuf, &qid);
|
||||||
v9fs_path_copy(&dpath, &path);
|
v9fs_path_copy(&dpath, &path);
|
||||||
}
|
}
|
||||||
|
memcpy(&qids[name_idx], &qid, sizeof(qid));
|
||||||
|
}
|
||||||
if (fid == newfid) {
|
if (fid == newfid) {
|
||||||
BUG_ON(fidp->fid_type != P9_FID_NONE);
|
BUG_ON(fidp->fid_type != P9_FID_NONE);
|
||||||
v9fs_path_copy(&fidp->path, &path);
|
v9fs_path_copy(&fidp->path, &path);
|
||||||
|
|
|
@ -236,6 +236,7 @@ typedef struct V9fsState
|
||||||
int32_t root_fid;
|
int32_t root_fid;
|
||||||
Error *migration_blocker;
|
Error *migration_blocker;
|
||||||
V9fsConf fsconf;
|
V9fsConf fsconf;
|
||||||
|
V9fsQID root_qid;
|
||||||
} V9fsState;
|
} V9fsState;
|
||||||
|
|
||||||
/* 9p2000.L open flags */
|
/* 9p2000.L open flags */
|
||||||
|
|
Loading…
Reference in New Issue