linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Ingo Molnar <mingo@kernel.org>,
	Chris Metcalf <cmetcalf@ezchip.com>,
	open list <linux-kernel@vger.kernel.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H. Peter Anvin" <hpa@zytor.com>, Borislav Petkov <bp@alien8.de>
Subject: Re: [PATCH] string: Improve the generic strlcpy() implementation
Date: Wed, 7 Oct 2015 10:22:53 +0100	[thread overview]
Message-ID: <CA+55aFx6mSs_7qcove4cnbptRsYWa5De8pM2mD8S-=RGuWQN1A@mail.gmail.com> (raw)
In-Reply-To: <87y4ffuk0r.fsf@rasmusvillemoes.dk>

On Wed, Oct 7, 2015 at 10:04 AM, Rasmus Villemoes
<linux@rasmusvillemoes.dk> wrote:
>
> Well, if truncation has happened the return value is different
> (larger). But assuming the output buffer is large enough, the 'compute
> strlen, then do copying, potentially copying a nul byte which wasn't
> there moments before' is pretty obvious:
[snip]

So I really refuse to worry about the snprintf() family of functions
wrt this race. I don't think it was hugely important for strlcpy()
either - more of a "quality of implementation" issue rather than
anything fundamental - but for snprintf and friends it's an almost
unavoidable issue because of how snprintf works.

Saying that 'strlcpy()' and 'snprintf("%s")' are equivalent is true
only in the loosest sense. Yes, they return the same return value.
Yes, the result string should be the same. But the two are completely
different despite that.

snprintf() has to handle all the *other* cases than just "%s",
including right-justification, string precision handling, etc etc. It
is effectively impossible to do without doing "strlen()" on the source
of the string beforehand. As a result, snprintf() is fundamentally
always going to be racy wrt the string changing during the call.

So the simple end result is that we shouldn't worry about it, and if
you are doing snprintf() on a changing string, you should just be
aware of it. We *do* actually do that, for things like "current->comm"
that really can change while being printed out. We just don't care
deeply, and have in fact been removing locks in this area, because the
end result is still guaranteed to be NUL-terminated etc.

Can we get odd truncated printouts in the (very very very unlikely)
case that the string is being changed? Yes. We just don't care.

With strlcpy(), the situation is different at least in the sense that
we *can* write a source-modification-safe version. Of course, the end
result will still be undefined, but at least the resulting string
length in the destination can be made to not disagree violently with
the return value.

Do we care? Probably not. If you do strlcpy() on strings that change
without using locking, it's either a serialization bug, or you really
don't care very deeply about the end result anyway (ie it's something
like the "current->comm" issue). But just from a quality of
implementation standpoint, I think it would be good to just do the
RightThing(tm) anyway.

That's particularly true since we should be able to do it trivially by
just implementing strlcpy() using strscpy() plus the overflow fixup.
But let's wait with that until people are happy about the state of
strscpy. There's absolutely no rush, and in fact the one thing I
absolutely wanted to avoid was to have the introduction of strscpy()
resulting in pointless churn elsewhere, so let's do the *opposite* of
rushing into this, and just say :"ok, some day we should do this, just
in case"

> Here's a few pseudo-datapoints. About half the strlcpy instances (just
> from lazy grepping) has a string literal as src, and those only have
> about 1/8th chance of being aligned.

Hmm. I think gcc actually tends to align string literals - at least on
architectures where unaligned accesses tend to be more expensive and
we do the whole SLOW_UNALIGNEd handling etc.

I don't think gcc does it on x86, but on x86 we don't much care.
Somebody on ppc or ARM might want to check.

                 Linus

  reply	other threads:[~2015-10-07  9:22 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-10 19:43 [GIT PULL] strscpy string copy function Chris Metcalf
2015-10-04 15:55 ` Linus Torvalds
2015-10-05 11:27   ` [PATCH] string: Improve the generic strlcpy() implementation Ingo Molnar
2015-10-05 11:53     ` Ingo Molnar
2015-10-05 13:15       ` Ingo Molnar
2015-10-05 14:04         ` Ingo Molnar
     [not found]         ` <CA+55aFx2McOeEiB7fJ-BV=vBsH=i2cC-qW8_EBEnScfQhugD_w@mail.gmail.com>
2015-10-05 14:07           ` Ingo Molnar
2015-10-05 14:33           ` Ingo Molnar
2015-10-05 15:32             ` Linus Torvalds
2015-10-05 16:03               ` Ingo Molnar
2015-10-05 12:28     ` Linus Torvalds
2015-10-05 13:10       ` Ingo Molnar
2015-10-05 22:28     ` Rasmus Villemoes
2015-10-06  7:54       ` Ingo Molnar
2015-10-06  8:03       ` Ingo Molnar
2015-10-06 22:00         ` Rasmus Villemoes
2015-10-07  7:18           ` Ingo Molnar
2015-10-07  9:04             ` Rasmus Villemoes
2015-10-07  9:22               ` Linus Torvalds [this message]
2015-10-08  8:48                 ` Ingo Molnar
2015-10-09  8:10                   ` Rasmus Villemoes
2015-10-09  9:10                     ` [RFC 0/3] eliminate potential race in string() (was: [PATCH] string: Improve the generic strlcpy() implementation) Rasmus Villemoes
2015-10-09  9:14                       ` [RFC 1/3] lib/vsprintf.c: pull out padding code from dentry_name() Rasmus Villemoes
2015-10-09  9:14                       ` [RFC 2/3] lib/vsprintf.c: move string() below widen_string() Rasmus Villemoes
2015-10-09  9:14                       ` [RFC 3/3] lib/vsprintf.c: eliminate potential race in string() Rasmus Villemoes
2015-10-10  7:47                       ` [RFC 0/3] eliminate potential race in string() (was: [PATCH] string: Improve the generic strlcpy() implementation) Ingo Molnar
2015-10-19 12:42     ` [PATCH] string: Improve the generic strlcpy() implementation Rasmus Villemoes
2015-10-19 16:24       ` Chris Metcalf
2015-10-05 15:38 Alexey Dobriyan
2015-10-05 16:11 ` Ingo Molnar
2015-10-05 16:13   ` Ingo Molnar
     [not found] ` <CA+55aFyTVJfCt00gYJpiQW5kqPaRGJ93JmfRRni-73zCf5ivqg@mail.gmail.com>
2015-10-05 16:22   ` Ingo Molnar
2015-10-05 16:28     ` Ingo Molnar
2015-10-05 20:40     ` 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='CA+55aFx6mSs_7qcove4cnbptRsYWa5De8pM2mD8S-=RGuWQN1A@mail.gmail.com' \
    --to=torvalds@linux-foundation.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=bp@alien8.de \
    --cc=cmetcalf@ezchip.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=mingo@kernel.org \
    --cc=tglx@linutronix.de \
    /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).