I forgot to pass --edit-patches to stg mail and some mails managed to get away before I hit ^C :\
Please ignore this thread: <147256918576.23038.4177640830854859642.st...@bahia.lab.toulouse-stg.fr.ibm.com> and look at this one instead: <147256922286.23141.1863740247797922944.st...@bahia.lab.toulouse-stg.fr.ibm.com> Sorry for the noise. On Tue, 30 Aug 2016 16:59:52 +0200 Greg Kurz <gr...@kaod.org> wrote: > Empty path components don't make sense for most commands and may cause > undefined behavior, depending on the backend. A notable exception > would be the target of a symbolic link: POSIX requires implementations > to support the empty string for target names. But 9p is only supported > on linux hosts, which don't support empty target names yet, and the > proposal to error out with ENOENT got approved, as indicated here: > > http://austingroupbugs.net/view.php?id=649 > > For the sake of consistency and simplicity, symlink target names will be > treated the same as any other file name argument. > > Also, the walk request described in the 9P spec [1] clearly shows that > the client is supposed to send individual path components: the official > linux client never sends portions of path containing the / character for > example. > > Moreover, the 9P spec [2] also states that a system can decide to restrict > the set of supported characters used in path components, with an explicit > mention "to remove slashes from name components". > > This patch introduces a new name_is_illegal() helper that checks the > names sent by the client are not empty and don't contain unwanted chars. > Since 9pfs is only supported on linux hosts, only the / character is > checked at the moment. When support for other hosts (AKA. win32) is added, > other chars may need to be blacklisted as well. > > If a client sends an illegal path component, the request will fail and > ENOENT is returned to the client. > > [1] http://man.cat-v.org/plan_9/5/walk > [2] http://man.cat-v.org/plan_9/5/intro > > Suggested-by: Peter Maydell <peter.mayd...@linaro.org> > Signed-off-by: Greg Kurz <gr...@kaod.org> > > v3: - fix empty string check in name_is_illegal() > - return ENOENT instead of EINVAL > - added checking of target names for symlinks in create (9P2000.u) > - added some details about symlink target names in the changelog > --- > hw/9pfs/9p.c | 61 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 61 insertions(+) > > diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c > index b6b02b46a9da..fe2d27f12ae1 100644 > --- a/hw/9pfs/9p.c > +++ b/hw/9pfs/9p.c > @@ -1256,6 +1256,11 @@ static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t > nwnames, V9fsQID *qids) > return offset; > } > > +static bool name_is_illegal(const char *name) > +{ > + return !*name || strchr(name, '/') != NULL; > +} > + > static void v9fs_walk(void *opaque) > { > int name_idx; > @@ -1289,6 +1294,10 @@ static void v9fs_walk(void *opaque) > if (err < 0) { > goto out_nofid; > } > + if (name_is_illegal(wnames[i].data)) { > + err = -ENOENT; > + goto out_nofid; > + } > offset += err; > } > } else if (nwnames > P9_MAXWELEM) { > @@ -1483,6 +1492,11 @@ static void v9fs_lcreate(void *opaque) > } > trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid); > > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > fidp = get_fid(pdu, dfid); > if (fidp == NULL) { > err = -ENOENT; > @@ -2077,6 +2091,11 @@ static void v9fs_create(void *opaque) > } > trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode); > > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > fidp = get_fid(pdu, fid); > if (fidp == NULL) { > err = -EINVAL; > @@ -2099,6 +2118,11 @@ static void v9fs_create(void *opaque) > } > fidp->fid_type = P9_FID_DIR; > } else if (perm & P9_STAT_MODE_SYMLINK) { > + if (name_is_illegal(extension.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > err = v9fs_co_symlink(pdu, fidp, &name, > extension.data, -1 , &stbuf); > if (err < 0) { > @@ -2242,6 +2266,11 @@ static void v9fs_symlink(void *opaque) > } > trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, > gid); > > + if (name_is_illegal(name.data) || name_is_illegal(symname.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > dfidp = get_fid(pdu, dfid); > if (dfidp == NULL) { > err = -EINVAL; > @@ -2316,6 +2345,11 @@ static void v9fs_link(void *opaque) > } > trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data); > > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > dfidp = get_fid(pdu, dfid); > if (dfidp == NULL) { > err = -ENOENT; > @@ -2398,6 +2432,12 @@ static void v9fs_unlinkat(void *opaque) > if (err < 0) { > goto out_nofid; > } > + > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > dfidp = get_fid(pdu, dfid); > if (dfidp == NULL) { > err = -EINVAL; > @@ -2504,6 +2544,12 @@ static void v9fs_rename(void *opaque) > if (err < 0) { > goto out_nofid; > } > + > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > fidp = get_fid(pdu, fid); > if (fidp == NULL) { > err = -ENOENT; > @@ -2616,6 +2662,11 @@ static void v9fs_renameat(void *opaque) > goto out_err; > } > > + if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) { > + err = -ENOENT; > + goto out_err; > + } > + > v9fs_path_write_lock(s); > err = v9fs_complete_renameat(pdu, olddirfid, > &old_name, newdirfid, &new_name); > @@ -2826,6 +2877,11 @@ static void v9fs_mknod(void *opaque) > } > trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor); > > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > fidp = get_fid(pdu, fid); > if (fidp == NULL) { > err = -ENOENT; > @@ -2977,6 +3033,11 @@ static void v9fs_mkdir(void *opaque) > } > trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid); > > + if (name_is_illegal(name.data)) { > + err = -ENOENT; > + goto out_nofid; > + } > + > fidp = get_fid(pdu, fid); > if (fidp == NULL) { > err = -ENOENT; > >