From: Ingo Molnar <mingo@kernel.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: 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: Mon, 5 Oct 2015 15:10:34 +0200 [thread overview]
Message-ID: <20151005131034.GA27954@gmail.com> (raw)
In-Reply-To: <CA+55aFyWOXJ9vxnd=vJqch0DfcMGAeSim1fbFwSrrd6jr7B6sw@mail.gmail.com>
* Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Mon, Oct 5, 2015 at 12:27 PM, Ingo Molnar <mingo@kernel.org> wrote:
> >
> > Interesting. I noticed that strscpy() says this in its comments:
> >
> > * In addition, the implementation is robust to the string changing out
> > * from underneath it, unlike the current strlcpy() implementation.
> >
> > The strscpy() interface is very nice, but shouldn't we also fix this strlcpy()
> > unrobustness/race it refers to, in light of the 2000+ existing strlcpy() call
> > sites?
>
> Well, I'm not sure the race really matters. [...]
Yeah, so if we do the word-by-word optimization for strlcpy() then the race is
fixed 'automatically', for free.
But you are right:
> [...] I personally think strlcpy() is a horrible interface, and the thing is,
> the return value of strlcpy (which is what can race) is kind of useless because
> it's not actually the size of the resulting string *anyway* (because of the
> overflow issue).
>
> So I'm not sure it's worth even fixing.
> Also, if you do this, then you're better off using the (hopefully optimized)
> "strlen()" for the tail part of the strlcpy destination for the overflow case
> that didn't get copied.
Indeed, this on top of my patch should do that:
lib/string.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lib/string.c b/lib/string.c
index e0cfca299606..dfd24b557e84 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -212,10 +212,7 @@ size_t strlcpy(char *dest, const char *src, size_t dest_size)
if (dest_size)
dest[dest_size-1] = '\0';
- while (src[src_len])
- src_len++;
-
- return src_len;
+ return strlen(src) + src_len;
}
EXPORT_SYMBOL(strlcpy);
#endif
(untested)
> In other words, I think your patch is overly fragile and complex.
Well, it's mostly a copy of strscpy() with obvious conversion of the return
convention, but you are right to point out:
> Instead, you might choose to implement strlcpy() in terms of
> "strscpy()" and "strlen()".
>
> Something like
>
> int strlcpy(dst, src, len)
> {
> // do the actual copy
> int n = strscpy(dst, src, len);
>
> // handle the insane and broken strlcpy overflow return value
> if (n < 0)
> return len + strlen(src+len);
>
> return n;
> }
>
> but I didn't actually verify that the above is correct for all the corner case.
Hm, so I considered doing that initially, but managed to convince myself that it's
not equivalent: but on a second thought your variant should indeed work!
> The point being, that you really shouldn't waste your time implementing the
> broken BSD strlcpy crap as an actual first-class implementation. You're better
> off just using a strscpy() as the primary engine, and then implementing the
> broken strlcpy interfaces on top of it.
>
> Does the above work? I'd take a patch that implements that if it's tested and
> somebody has thought about it a lot. But I don't like your patch that open-codes
> the insane interface with complex and fragile code.
So the below untested variant does that plus an overflow check - it's only FYI,
not signed off yet.
Thanks,
Ingo
==============>
Not-Signed-off-by: Ingo Molnar <mingo@kernel.org>
lib/string.c | 60 ++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 34 insertions(+), 26 deletions(-)
diff --git a/lib/string.c b/lib/string.c
index 8dbb7b1eab50..6b89c035df74 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -124,32 +124,6 @@ char *strncpy(char *dest, const char *src, size_t count)
EXPORT_SYMBOL(strncpy);
#endif
-#ifndef __HAVE_ARCH_STRLCPY
-/**
- * strlcpy - Copy a C-string into a sized buffer
- * @dest: Where to copy the string to
- * @src: Where to copy the string from
- * @size: size of destination buffer
- *
- * Compatible with *BSD: the result is always a valid
- * NUL-terminated string that fits in the buffer (unless,
- * of course, the buffer size is zero). It does not pad
- * out the result like strncpy() does.
- */
-size_t strlcpy(char *dest, const char *src, size_t size)
-{
- size_t ret = strlen(src);
-
- if (size) {
- size_t len = (ret >= size) ? size - 1 : ret;
- memcpy(dest, src, len);
- dest[len] = '\0';
- }
- return ret;
-}
-EXPORT_SYMBOL(strlcpy);
-#endif
-
#ifndef __HAVE_ARCH_STRSCPY
/**
* strscpy - Copy a C-string into a sized buffer
@@ -234,6 +208,40 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
EXPORT_SYMBOL(strscpy);
#endif
+#ifndef __HAVE_ARCH_STRLCPY
+/**
+ * strlcpy - Copy a C-string into a sized buffer
+ * @dst: Where to copy the string to
+ * @src: Where to copy the string from
+ * @dst_size: size of destination buffer
+ *
+ * Compatible with *BSD: the result is always a valid
+ * NUL-terminated string that fits in the buffer (unless,
+ * of course, the buffer size is zero). It does not pad
+ * out the result like strncpy() does.
+ */
+size_t strlcpy(char *dst, const char *src, size_t dst_size)
+{
+ int ret;
+
+ /* Overflow check: */
+ if (unlikely((ssize_t)dst_size < 0)) {
+ WARN_ONCE(1, "strlcpy(): dst_size < 0 underflow!");
+ return strlen(src);
+ }
+
+ ret = strscpy(dst, src, dst_size);
+
+ /* Handle the insane and broken strlcpy() overflow return value: */
+ if (ret < 0)
+ return dst_size + strlen(src+dst_size);
+
+ return ret;
+}
+EXPORT_SYMBOL(strlcpy);
+#endif
+
+
#ifndef __HAVE_ARCH_STRCAT
/**
* strcat - Append one %NUL-terminated string to another
next prev parent reply other threads:[~2015-10-05 13:10 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 [this message]
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
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
-- strict thread matches above, loose matches on Subject: below --
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=20151005131034.GA27954@gmail.com \
--to=mingo@kernel.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=tglx@linutronix.de \
--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).