From: Christian Schoenebeck <linux_oss@crudebyte.com>
To: Dominique Martinet <asmadeus@codewreck.org>
Cc: v9fs-developer@lists.sourceforge.net,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
Eric Van Hensbergen <ericvh@gmail.com>,
Latchesar Ionkov <lucho@ionkov.net>,
Nikolay Kichukov <nikolay@oldum.net>
Subject: Re: [PATCH v5 10/11] net/9p: add p9_msg_buf_size()
Date: Thu, 14 Jul 2022 15:14:31 +0200 [thread overview]
Message-ID: <1784081.3E5Dq0oo6N@silver> (raw)
In-Reply-To: <Ys8wqPbA5eogtvmG@codewreck.org>
On Mittwoch, 13. Juli 2022 22:52:56 CEST Dominique Martinet wrote:
> Christian Schoenebeck wrote on Wed, Jul 13, 2022 at 03:06:01PM +0200:
> > > > + case P9_TWALK:
> > > > + BUG_ON(strcmp("ddT", fmt));
> > > > + va_arg(ap, int32_t);
> > > > + va_arg(ap, int32_t);
> > > > + {
> > > > + uint i, nwname = max(va_arg(ap, int), 0);
> > >
> > > I was about to say that the max is useless as for loop would be cut
> > > short, but these are unsigned... So the code in protocol.c p9pdu_vwritef
> > > 'T' has a bug (int cast directly to uint16): do you want to fix it or
> > > shall I go ahead?
> >
> > I'd either send a separate patch today for fixing 'T', or if you want
> > to handle it by yourself, then just go ahead.
>
> I'd appreciate if you have time, doesn't make much difference though
Looking closer at this separate issue; there is probably nothing to fix. 'T'
(and 'R') in p9pdu_vwritef() pulls an 'int' argument from the stack. But the
actual variable is passed here:
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
const unsigned char * const *wnames, int clone)
{
...
req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
nwname, wnames);
...
}
So the variable being passed was already uint16_t, which made me re-aware why
this is working anyway: Because C and C++ have this nice language hack that
any variadic integer variable smaller than 'int' is automatically casted to
'int' before being passed.
I mean I could clamp the pulled argument like:
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 3754c33e2974..5fd1e948c86a 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -441,7 +441,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
}
break;
case 'T':{
- uint16_t nwname = va_arg(ap, int);
+ uint16_t nwname = clamp_t(int, va_arg(ap, int), 0, USHRT_MAX);
const char **wnames = va_arg(ap, const char **);
errcode = p9pdu_writef(pdu, proto_version, "w",
@@ -462,7 +462,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
}
break;
case 'R':{
- uint16_t nwqid = va_arg(ap, int);
+ uint16_t nwqid = clamp_t(int, va_arg(ap, int), 0, USHRT_MAX);
struct p9_qid *wqids =
va_arg(ap, struct p9_qid *);
But it's pretty much pointless overhead. Another option would be to change
va_arg(ap, int) -> va_arg(ap, uint16_t), just to make it more clear what was
pushed from the other side.
Which probably also means I can simply drop the max() call in this patch 10
here as well.
For the 'R' case: I haven't found the spot where this is actually used.
> > > > + case P9_TCREATE:
> > > > + BUG_ON(strcmp("dsdb?s", fmt));
> > > > + va_arg(ap, int32_t);
> > > > + {
> > > > + const char *name = va_arg(ap, const char *);
> > > > + if ((c->proto_version != p9_proto_2000u) &&
> > > > + (c->proto_version != p9_proto_2000L))
> > >
> > > (I don't think 9p2000.L can call TCREATE, but it doesn't really hurt
> > > either)
> >
> > Yes, Tcreate is only 9p2000 and 9p2000.u. Semantically this particular
> > check here means "if proto == 9p.2000". I can't remember anymore why I
> > came up with this inverted form here. I'll change it to "if
> > (c->proto_version == p9_proto_legacy)".
>
> Sounds good.
>
> > > > + case P9_TRENAMEAT:
> > > if we have trenameat we probably want trename, tunlinkat as well?
> > > What's your criteria for counting individually vs slapping 8k at it?
> > >
> > > In this particular case, oldname/newname are single component names
> > > within a directory so this is capped at 2*(4+256), that could easily fit
> > > in 4k without bothering.
> >
> > I have not taken the Linux kernel's current filename limit NAME_MAX
> > (255) as basis, in that case you would be right. Instead I looked up
> > what the maximum filename length among file systems in general was,
> > and saw that ReiserFS supports up to slightly below 4k? So I took 4k
> > as basis for the calculation used here, and the intention was to make
> > this code more future proof. Because revisiting this code later on
> > always takes quite some time and always has this certain potential to
> > miss out details.
>
> hmm, that's pretty deeply engrained into the VFS but I guess it might
> change eventually, yes.
>
> I don't mind as long as we're consistent (cf. unlink/mkdir below), in
> practice measuring doesn't cost much.
OK, I also make that more clear from the commit log then that 4k was taken as
basis and why.
> > Independent of the decision; additionally it might make sense to add
> > something like:
> >
> > #if NAME_MAX > 255
> > # error p9_msg_buf_size() needs adjustments
> > #endif
>
> That's probably an understatement but I don't mind either way, it
> doesn't hurt.
>
> > > > + BUG_ON(strcmp("dsds", fmt));
> > > > + va_arg(ap, int32_t);
> > > > + {
> > > > + const char *oldname = va_arg(ap, const char *);
> > > > + va_arg(ap, int32_t);
> > > > + {
> > > > + const char *newname = va_arg(ap, const char *);
> > >
> > > (style nitpick) I don't see the point of nesting another level of
> > > indentation here, it feels cleaner to declare oldname/newname at the
> > > start of the block and be done with it.
> >
> > Because va_arg(ap, int32_t); must remain between those two
> > declarations, and I think either the compiler or style check script
> > was barking at me. But I will recheck, if possible I will remove the
> > additional block scope here.
>
> Yes, I think it'd need to look like this:
>
> case foo:
> BUG_ON(...)
> va_arg(ap, int32_t);
> {
> const char *oldname = va_arg(ap, const char *);
> const char *newname;
> va_arg(ap, int32_t);
> newname = va_arg(ap, const_char *);
> ...
> }
> or
> {
> const char *oldname, *newname;
> oldname = va_arg(ap, const char *);
> va_arg(ap, int32_t)
> newname = va_arg(ap, const char *);
> ...
> }
>
> I guess the later is slightly easier on the eyes
Ah yes, that's your win there.
> > > > + /* small message types */
> > >
> > > ditto: what's your criteria for 4k vs 8k?
> >
> > As above, 4k being the basis for directory entry names, plus PATH_MAX
> > (4k) as basis for maximum path length.
> >
> > However looking at it again, if NAME_MAX == 4k was assumed exactly,
> > then Tsymlink would have the potential to exceed 8k, as it has name[s]
> > and symtgt[s] plus the other fields.
>
> yes.
>
> > > > + case P9_TSTAT:
> > > this is just fid[4], so 4k is more than enough
> >
> > I guess that was a typo and should have been Twstat instead?
>
> Ah, had missed this because 9p2000.L's version of stat[n] is fixed size.
> Sounds good.
>
> > > > + case P9_RSTAT:
> > > also fixed size 4+4+8+8+8+8+8+8+4 -- fits in 4k.
> >
> > Rstat contains stat[n] which in turn contains variable-length string
> > fields (filename, owner name, group name)
>
> Right, same mistake.
>
> > > > + case P9_TSYMLINK:
> > > that one has symlink target which can be arbitrarily long (filesystem
> > > specific, 4k is the usual limit for linux but some filesystem I don't
> > > know might handle more -- it might be worth going through the trouble of
> > > going through it.
> >
> > Like mentioned above, if exactly NAME_MAX == 4k was assumed, then
> > Tsymlink may even be >8k.
>
> And all the other remarks are 'yes if we assume bigger NAME_MAX' -- I'm
> happy either way.
>
> > > rest all looks ok to me.
> >
> > Thanks for the review! I know, that's really a dry patch to look
> > at. :)
>
> Thanks for writing it in the first place ;)
>
> --
> Dominique
next prev parent reply other threads:[~2022-07-14 13:14 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-12 14:35 [PATCH v5 00/11] remove msize limit in virtio transport Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 01/11] 9p/trans_virtio: separate allocation of scatter gather list Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 02/11] 9p/trans_virtio: turn amount of sg lists into runtime info Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 03/11] 9p/trans_virtio: introduce struct virtqueue_sg Christian Schoenebeck
2022-07-12 20:33 ` Dominique Martinet
2022-07-13 9:14 ` Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 04/11] net/9p: add trans_maxsize to struct p9_client Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 05/11] 9p/trans_virtio: support larger msize values Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 06/11] 9p/trans_virtio: resize sg lists to whatever is possible Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 07/11] net/9p: limit 'msize' to KMALLOC_MAX_SIZE for all transports Christian Schoenebeck
2022-07-12 20:38 ` Dominique Martinet
2022-07-12 14:31 ` [PATCH v5 08/11] net/9p: split message size argument into 't_size' and 'r_size' pair Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 09/11] 9p: add P9_ERRMAX for 9p2000 and 9p2000.u Christian Schoenebeck
2022-07-12 14:31 ` [PATCH v5 10/11] net/9p: add p9_msg_buf_size() Christian Schoenebeck
2022-07-13 10:29 ` Dominique Martinet
2022-07-13 13:06 ` Christian Schoenebeck
2022-07-13 20:52 ` Dominique Martinet
2022-07-14 13:14 ` Christian Schoenebeck [this message]
2022-07-12 14:31 ` [PATCH v5 11/11] net/9p: allocate appropriate reduced message buffers Christian Schoenebeck
2022-07-12 19:33 ` Dominique Martinet
2022-07-12 21:11 ` [V9fs-developer] " Dominique Martinet
2022-07-13 9:19 ` Christian Schoenebeck
2022-07-13 9:29 ` Christian Schoenebeck
2022-07-13 9:56 ` Dominique Martinet
2022-07-13 9:29 ` Dominique Martinet
2022-07-13 10:22 ` Christian Schoenebeck
2022-07-12 21:13 ` [PATCH v5 00/11] remove msize limit in virtio transport Dominique Martinet
2022-07-13 8:54 ` Christian Schoenebeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1784081.3E5Dq0oo6N@silver \
--to=linux_oss@crudebyte.com \
--cc=asmadeus@codewreck.org \
--cc=ericvh@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lucho@ionkov.net \
--cc=netdev@vger.kernel.org \
--cc=nikolay@oldum.net \
--cc=v9fs-developer@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.