All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Tuomas Tynkkynen <tuomas@tuxera.com>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: Re: Weird writev() behaviour on EFAULT - also successfully modifying the file
Date: Fri, 12 Aug 2016 00:03:09 +0100	[thread overview]
Message-ID: <20160811230309.GV2356@ZenIV.linux.org.uk> (raw)
In-Reply-To: <CA+55aFwb6CGXPBkuvGR05kPVsJhksXoZv5sDyV2+FNKGbo1Q+Q@mail.gmail.com>

On Thu, Aug 11, 2016 at 03:39:22PM -0700, Linus Torvalds wrote:

> But at the same time, the basic rule really is:
> 
>  "If you give bad virtual memory regions to system calls, you get to
> keep the resulting broken piece and blame yourself".
> 
> anything the kernel does better is purely about us being polite, not
> about correctness or caring deeply.

Yes, but... it doesn't need to be a bad region at all.  Look: we have a 20Kb
array of char starting at 0x....3ff.  We feed it to write().  Everything
is mapped, etc. - no EFAULT in sight.  However, it is all swapped out at
the moment.  And somebody else has that file mmapped; again, no pathological
cases, not even in the same address space as writer, etc.  File contains no
zero bytes.  Neither does the buffer we are writing.  File position is 0 and
file is considerably longer than 20Kb.

We do a fault-in; fine, the first page (with one byte of useful data) is
swapped in.  We call ->write_begin(), then __copy_from_user_inatomic()
(with pagefaults disabled) the first 4Kb into the page with index 0 in
the file's page cache.  Copy fails after 1 byte, since the next page
is currently still swapped out.  We advance by 1 byte and fault that page
in; fine, now we'll copy 4095 bytes successfully, advance by 4095 and
proceed to writing into the page with index 1 in file's page cache, etc.
In the end everything works fine - no short writes, no EFAULT, all the
data copied into file.

However, _during_ the write the other process had seen something very odd -
it had mmapped a zero-free file, it knows that nobody had been writing any
zero-containing data into it, but it had seen zeroes come and go in the
mmapped area.  That "copied 1 byte" is actually "copied 1 byte, zeroed the
next 4095 bytes".  Sure, it's followed by "copy the next 4095 bytes over
those zeroes", but only after the next chunk of buffer got swapped in.  And
if the writer got killed, the things are even nastier - these zeroes are
*not* overwritten by subsequent data.

Again, it's about as tame case as they come - no NULLs, no EFAULT, no
buffers mmapped from the file we are writing to; just a normal write()
replacing the data in the very beginning of file from a buffer that isn't
page-aligned...

  reply	other threads:[~2016-08-11 23:03 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-11 18:46 Weird writev() behaviour on EFAULT - also successfully modifying the file Tuomas Tynkkynen
2016-08-11 22:10 ` Al Viro
2016-08-11 22:39   ` Linus Torvalds
2016-08-11 23:03     ` Al Viro [this message]
2016-08-11 23:10       ` Linus Torvalds
2016-08-11 23:13       ` Linus Torvalds

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=20160811230309.GV2356@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=tuomas@tuxera.com \
    /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.