linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: Mike Marshall <hubcap@omnibond.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: Re: updated orangefs tree at kernel.org
Date: Fri, 9 Oct 2015 20:22:39 +0100	[thread overview]
Message-ID: <20151009192239.GC22011@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20151009034126.GY22011@ZenIV.linux.org.uk>

On Fri, Oct 09, 2015 at 04:41:26AM +0100, Al Viro wrote:

> where dec_string(pptr, pbuf, plen) is defined as
>         __u32 len = (*(__u32 *) *(pptr)); \
>         *pbuf = *(pptr) + 4; \
>         *(pptr) += roundup8(4 + len + 1); \
>         if (plen) \
>                 *plen = len;\
> 
> Note that we do *not* validate len, so this code might end up dereferencing
> any address within +-2Gb from the buffer.  You really can't assume that
> server is neither insane nor compromised; this is a blatant security hole.
> 
> And please, drop these macros - you are not using enc_string() at all while
> dec_string() is used only in decode_dirents() and would be easier to
> understand if it had been spelled out right there.  Especially since you
> need to add sanity checks (and buggering off should they fail) to it.

Actually, validation is bloody weak in pvfs2_devreq_writev() as well.
And frankly, the layout it's expecting is downright insane.

What you have is some initial segment of
	* 32bit protocol version.  Never checked, which renders it useless.
	* 32bit magic.  That one _is_ checked, so basically they work
together as 64bit protocol version, with bloody odd validation.
	* 64bit tag, used to match with requests
	* 32bit type, apparently never checked - that of the matching request is
used
	* 32bit status
	* 64bit trailer_size, apparently used only with readdir, so
probably non-zero only if type is PVFS2_VFS_OP_READDIR or
PVFS2_VFS_OP_READDIRPLUS (the latter doesn't seem to be ever issued, though).
	* pointer-sized junk.  Ignored.
	* big fat union *NOT* including anything for readdir
possibly followed by readdir response.

To make things even funnier, you require 4- or 5-element iovec array,
the first 4 covering the aforementioned "some initial segment".  The 5th
is quietly ignored unless trailer_size is positive and status is zero.
If trailer_size > 0 && status == 0, you verify that the length of the 5th
segment is no more than trailer_size and copy it to vmalloc'ed buffer.
Without bothering to zero the rest of that buffer out.

The member of that big fat union for getattr has a bit of additional insanity -
several pointer-sized gaps.  Entirely unused.

Far be it from me to support The War On Some Drugs, but really, staying away
from the stuff that induces trips _that_ bad is just plain common sense...

First of all, this "exactly 4 or 5 iovecs in array" thing is beyond ugly - 
it's a way to separate large variable-length segment, all right, but why
the hell not just declare e.g. that if request is at least 32 bytes long
and has trailer_size > 0 && status == 0, trailer_size must be no more than
request size - 32 and that much bytes in the end will go into vmalloc'ed
buffer?  Everything else must fit into MAX_ALIGNED_DEV_REQ_DOWNSIZE.
AFAICS, that would be compatible with what your server is doing now.

Next, and that can't be fixed without a protocol change, I'd suggest losing
those pointer-sized gaps (and probably reordering struct PVFS_sys_attr_s
to make sure that all u64 are naturally aligned there).  Why make your
protocol wordsize-sensitive, when it's trivial to avoid?

In any case, the current code is asking for serious trouble if the 5th segment
is there and _shorter_ than trailer_size.  As the absolute minimum we need to
zero the rest of vmalloc'ed buffer, and I seriously suspect that we need
to outright reject such requests.  And I would really prefer to get rid of
this "exactly 4 or 5" thing as well (see above)...

  parent reply	other threads:[~2015-10-09 19:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-07 20:07 updated orangefs tree at kernel.org Mike Marshall
2015-10-08 21:07 ` Al Viro
2015-10-08 23:03   ` Al Viro
2015-10-09  3:41     ` Al Viro
2015-10-09  6:13       ` Al Viro
2015-10-09 19:22       ` Al Viro [this message]
2015-10-10  2:31     ` Al Viro
2015-10-10 20:23       ` Al Viro
2015-10-10 23:10       ` orangefs: NAK until the ABI is documented (was Re: updated orangefs tree at kernel.org) Al Viro
2015-10-12 16:20         ` Mike Marshall
2015-10-12 19:16           ` Al Viro
2015-10-13 17:46             ` Mike Marshall
2015-10-13 23:34               ` Al Viro
  -- strict thread matches above, loose matches on Subject: below --
2015-11-16 20:01 updated orangefs tree at kernel.org Mike Marshall

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=20151009192239.GC22011@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=hubcap@omnibond.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).