* [PATCH 0/3] add new strscpy() API for string copy [not found] <CA+55aFwbRZe5gVsTyHvjKqE5eA3zQ_58_UQW7KACCt7V7FpZbQ@mail.gmail.com> @ 2015-04-30 16:01 ` Chris Metcalf 2015-04-30 16:01 ` [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf ` (5 more replies) 0 siblings, 6 replies; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch This patch series addresses limitations in strncpy() and strlcpy(); both the old APIs are unpleasant, as Linus nicely summarized here a couple of days ago: https://lkml.org/lkml/2015/4/28/570 and of course as other folks (Greg K-H and Linus again) said last year: https://plus.google.com/+gregkroahhartman/posts/1amLbuhWbh5 The proposed new API (strscpy(), for "s"afe string copy) has an easy-to-use API for detecting buffer overflow, avoids unsafe truncation by default, and isn't subject to thread-safety attacks like the current strlcpy implementation. See patch 2/3 for more on why strscpy() is a good thing. To make strscpy() work more efficiently I did the minimum tweaking necessary to allow <asm/word-at-a-time.h> to work on all architectures, though of course individual maintainers can still make their versions more efficient as needed. It's likely not necessary for per-architecture implementations of strscpy() to be written, but I stuck with the standard __HAVE_ARCH_XXX model just for consistency with the rest of <linux/string.h>. I tested the implementation with a simple user-space harness, so I believe it is correct for the corner cases I could think of. In particular I pairwise-tested all the unaligned values of source and dest, and tested the restriction on src page-crossing at all unaligned offsets approaching the page boundary. This builds on an earlier version of strscpy() submitted as a file-static method in the arch/tile/gxio tree last year, after an attempt to gather interest in a new generic strscpy failed: https://lkml.org/lkml/2014/8/7/368 The patch series is available to be pulled from git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git strscpy Chris Metcalf (3): Make asm/word-at-a-time.h available on all architectures string: provide strscpy() and strscpy_truncate() tile: use global strscpy() rather than private copy arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/gxio/mpipe.c | 33 ++--------- arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++--- include/linux/string.h | 6 ++ lib/string.c | 109 +++++++++++++++++++++++++++++++++++ 25 files changed, 212 insertions(+), 37 deletions(-) -- 2.1.2 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures 2015-04-30 16:01 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf @ 2015-04-30 16:01 ` Chris Metcalf 2015-04-30 16:01 ` Chris Metcalf 2015-04-30 16:01 ` [PATCH 2/3] string: provide strscpy() and strscpy_truncate() Chris Metcalf ` (4 subsequent siblings) 5 siblings, 1 reply; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch Added the x86 implementation of word-at-a-time to the generic version, which previously only supported big-endian. Omitted the x86-specific load_unaligned_zeropad(), which in any case is also not present for the existing BE-only implementation of a word-at-a-time, and is only used under CONFIG_DCACHE_WORD_ACCESS. Added as a "generic-y" to the Kbuilds of all architectures that didn't previously have it. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++++++++++++---- 22 files changed, 93 insertions(+), 8 deletions(-) diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index be0c39e76f7c..be895ef03a51 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -49,4 +49,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index 528d70d47a54..10dd6e8470bd 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -20,4 +20,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild index 4bd3c3cfc9ab..9705a527b7b0 100644 --- a/arch/blackfin/include/asm/Kbuild +++ b/arch/blackfin/include/asm/Kbuild @@ -46,4 +46,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index ae0a51f5376c..535efdb0692d 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -59,4 +59,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index 057e51859b0a..4991539a25f6 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index e3f81b53578e..ca34d1cf2cdf 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index c7a99f860b40..872920fba0a6 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -58,4 +58,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 9b41b4bcc073..614579fa1e49 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -8,3 +8,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 2edc793372fc..36f850dd4a1e 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild index 0bf5d525b945..a291b3b2529e 100644 --- a/arch/metag/include/asm/Kbuild +++ b/arch/metag/include/asm/Kbuild @@ -54,4 +54,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index ab564a6db5c3..966f221b2d67 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@ -10,3 +10,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += syscalls.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 526539cbc99f..c3cfb83aca1d 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -18,4 +18,5 @@ generic-y += serial.h generic-y += trace_clock.h generic-y += ucontext.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index f892d9de47d9..30a06e2d6e42 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index 24b3d8999ac7..bc87081c0669 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -61,4 +61,5 @@ generic-y += types.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 4b87205c230c..dfc61a151890 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += rwsem.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index c631f98fd524..27c37b3d1dad 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -6,3 +6,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index 83ed116d414c..16958f529aa7 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -13,3 +13,4 @@ generic-y += sections.h generic-y += trace_clock.h generic-y += xor.h generic-y += serial.h +generic-y += word-at-a-time.h diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index f5433e0e34e0..0804122e579a 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -39,4 +39,5 @@ generic-y += termbits.h generic-y += termios.h generic-y += trace_clock.h generic-y += types.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index 9176fa11d49b..ee02364d8922 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += switch_to.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 3e0c19d0f4c5..f456bfa1dd54 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -62,4 +62,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 86a9ab2e2ca9..6ac0a9ab3ea3 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -29,4 +29,5 @@ generic-y += statfs.h generic-y += termios.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/include/asm-generic/word-at-a-time.h b/include/asm-generic/word-at-a-time.h index 94f9ea8abcae..011dde083f23 100644 --- a/include/asm-generic/word-at-a-time.h +++ b/include/asm-generic/word-at-a-time.h @@ -1,15 +1,10 @@ #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H -/* - * This says "generic", but it's actually big-endian only. - * Little-endian can use more efficient versions of these - * interfaces, see for example - * arch/x86/include/asm/word-at-a-time.h - * for those. - */ - #include <linux/kernel.h> +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN struct word_at_a_time { const unsigned long high_bits, low_bits; @@ -53,4 +48,73 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct #define zero_bytemask(mask) (~1ul << __fls(mask)) #endif +#else + +/* + * The optimal byte mask counting is probably going to be something + * that is architecture-specific. If you have a reliably fast + * bit count instruction, that might be better than the multiply + * and shift, for example. + */ +struct word_at_a_time { + const unsigned long one_bits, high_bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } + +#ifdef CONFIG_64BIT + +/* + * Jan Achrenius on G+: microoptimized version of + * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" + * that works for the bytemasks without having to + * mask them first. + */ +static inline long count_masked_bytes(unsigned long mask) +{ + return mask*0x0001020304050608ul >> 56; +} + +#else /* 32-bit case */ + +/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ +static inline long count_masked_bytes(long mask) +{ + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + long a = (0x0ff0001+mask) >> 23; + /* Fix the 1 for 00 case */ + return a & mask; +} + +#endif + +/* Return nonzero if it has a zero */ +static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) +{ + unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; + *bits = mask; + return mask; +} + +static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) +{ + return bits; +} + +static inline unsigned long create_zero_mask(unsigned long bits) +{ + bits = (bits - 1) & ~bits; + return bits >> 7; +} + +/* The mask we created is directly usable as a bytemask */ +#define zero_bytemask(mask) (mask) + +static inline unsigned long find_zero(unsigned long mask) +{ + return count_masked_bytes(mask); +} + +#endif /* __BIG_ENDIAN */ + #endif /* _ASM_WORD_AT_A_TIME_H */ -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures 2015-04-30 16:01 ` [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf @ 2015-04-30 16:01 ` Chris Metcalf 0 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch Added the x86 implementation of word-at-a-time to the generic version, which previously only supported big-endian. Omitted the x86-specific load_unaligned_zeropad(), which in any case is also not present for the existing BE-only implementation of a word-at-a-time, and is only used under CONFIG_DCACHE_WORD_ACCESS. Added as a "generic-y" to the Kbuilds of all architectures that didn't previously have it. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++++++++++++---- 22 files changed, 93 insertions(+), 8 deletions(-) diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index be0c39e76f7c..be895ef03a51 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -49,4 +49,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index 528d70d47a54..10dd6e8470bd 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -20,4 +20,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild index 4bd3c3cfc9ab..9705a527b7b0 100644 --- a/arch/blackfin/include/asm/Kbuild +++ b/arch/blackfin/include/asm/Kbuild @@ -46,4 +46,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index ae0a51f5376c..535efdb0692d 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -59,4 +59,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index 057e51859b0a..4991539a25f6 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index e3f81b53578e..ca34d1cf2cdf 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index c7a99f860b40..872920fba0a6 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -58,4 +58,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 9b41b4bcc073..614579fa1e49 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -8,3 +8,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 2edc793372fc..36f850dd4a1e 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild index 0bf5d525b945..a291b3b2529e 100644 --- a/arch/metag/include/asm/Kbuild +++ b/arch/metag/include/asm/Kbuild @@ -54,4 +54,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index ab564a6db5c3..966f221b2d67 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@ -10,3 +10,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += syscalls.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 526539cbc99f..c3cfb83aca1d 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -18,4 +18,5 @@ generic-y += serial.h generic-y += trace_clock.h generic-y += ucontext.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index f892d9de47d9..30a06e2d6e42 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index 24b3d8999ac7..bc87081c0669 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -61,4 +61,5 @@ generic-y += types.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 4b87205c230c..dfc61a151890 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += rwsem.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index c631f98fd524..27c37b3d1dad 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -6,3 +6,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index 83ed116d414c..16958f529aa7 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -13,3 +13,4 @@ generic-y += sections.h generic-y += trace_clock.h generic-y += xor.h generic-y += serial.h +generic-y += word-at-a-time.h diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index f5433e0e34e0..0804122e579a 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -39,4 +39,5 @@ generic-y += termbits.h generic-y += termios.h generic-y += trace_clock.h generic-y += types.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index 9176fa11d49b..ee02364d8922 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += switch_to.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 3e0c19d0f4c5..f456bfa1dd54 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -62,4 +62,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 86a9ab2e2ca9..6ac0a9ab3ea3 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -29,4 +29,5 @@ generic-y += statfs.h generic-y += termios.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/include/asm-generic/word-at-a-time.h b/include/asm-generic/word-at-a-time.h index 94f9ea8abcae..011dde083f23 100644 --- a/include/asm-generic/word-at-a-time.h +++ b/include/asm-generic/word-at-a-time.h @@ -1,15 +1,10 @@ #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H -/* - * This says "generic", but it's actually big-endian only. - * Little-endian can use more efficient versions of these - * interfaces, see for example - * arch/x86/include/asm/word-at-a-time.h - * for those. - */ - #include <linux/kernel.h> +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN struct word_at_a_time { const unsigned long high_bits, low_bits; @@ -53,4 +48,73 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct #define zero_bytemask(mask) (~1ul << __fls(mask)) #endif +#else + +/* + * The optimal byte mask counting is probably going to be something + * that is architecture-specific. If you have a reliably fast + * bit count instruction, that might be better than the multiply + * and shift, for example. + */ +struct word_at_a_time { + const unsigned long one_bits, high_bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } + +#ifdef CONFIG_64BIT + +/* + * Jan Achrenius on G+: microoptimized version of + * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" + * that works for the bytemasks without having to + * mask them first. + */ +static inline long count_masked_bytes(unsigned long mask) +{ + return mask*0x0001020304050608ul >> 56; +} + +#else /* 32-bit case */ + +/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ +static inline long count_masked_bytes(long mask) +{ + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + long a = (0x0ff0001+mask) >> 23; + /* Fix the 1 for 00 case */ + return a & mask; +} + +#endif + +/* Return nonzero if it has a zero */ +static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) +{ + unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; + *bits = mask; + return mask; +} + +static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) +{ + return bits; +} + +static inline unsigned long create_zero_mask(unsigned long bits) +{ + bits = (bits - 1) & ~bits; + return bits >> 7; +} + +/* The mask we created is directly usable as a bytemask */ +#define zero_bytemask(mask) (mask) + +static inline unsigned long find_zero(unsigned long mask) +{ + return count_masked_bytes(mask); +} + +#endif /* __BIG_ENDIAN */ + #endif /* _ASM_WORD_AT_A_TIME_H */ -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-04-30 16:01 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf 2015-04-30 16:01 ` [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf @ 2015-04-30 16:01 ` Chris Metcalf 2015-04-30 16:01 ` Chris Metcalf 2015-05-06 15:01 ` Dan Carpenter 2015-04-30 16:01 ` [PATCH 3/3] tile: use global strscpy() rather than private copy Chris Metcalf ` (3 subsequent siblings) 5 siblings, 2 replies; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch The strscpy() API is intended to be used instead of strlcpy(), and instead of most uses of strncpy(). - The API provides an easy way to check for destination buffer overflow: a -E2BIG error return value. - By default, truncation causes the destination buffer to be the empty string, so users don't blindly assume a truncated string is valid. If you know a truncated string still has valid semantics, you can use the provided strscpy_truncate(), which has the same return value semantics but does not make the destination an empty string on error. - The provided implementation is robust in the face of the source buffer being asynchronously changed during the copy, unlike the current implementation of strlcpy(). - The implementation should be reasonably performant on all platforms since it uses the asm/word-at-a-time.h API rather than simple byte copy. Kernel-to-kernel string copy is not considered to be performance critical in any case. - If the remainder of the destination buffer must be zeroed for some reason, strscpy() + error check + memset() is probably the easiest pattern, but using strncpy() in a pattern where the last byte of the buffer is first set non-NUL, then tested for NUL afterwards, can also be safely used. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- include/linux/string.h | 6 +++ lib/string.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index e40099e585c9..7942944f3abb 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -25,6 +25,12 @@ extern char * strncpy(char *,const char *, __kernel_size_t); #ifndef __HAVE_ARCH_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif +#ifndef __HAVE_ARCH_STRSCPY +ssize_t strscpy(char *, const char *, size_t); +#endif +#ifndef __HAVE_ARCH_STRSCPY_TRUNCATE +ssize_t strscpy_truncate(char *, const char *, size_t); +#endif #ifndef __HAVE_ARCH_STRCAT extern char * strcat(char *, const char *); #endif diff --git a/lib/string.c b/lib/string.c index a5792019193c..84d5b6eceb74 100644 --- a/lib/string.c +++ b/lib/string.c @@ -27,6 +27,9 @@ #include <linux/bug.h> #include <linux/errno.h> +#include <asm/byteorder.h> +#include <asm/word-at-a-time.h> + #ifndef __HAVE_ARCH_STRNCASECMP /** * strncasecmp - Case insensitive, length-limited string comparison @@ -146,6 +149,112 @@ size_t strlcpy(char *dest, const char *src, size_t size) EXPORT_SYMBOL(strlcpy); #endif +#ifndef __HAVE_ARCH_STRSCPY_TRUNCATE +/** + * strscpy_truncate - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. + * The routine returns the number of characters copied (not including + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. + * The behavior is undefined if the string buffers overlap. + * + * Note that the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation, + * and it is easier to check overflow than with strlcpy()'s API. + * + * strscpy() is preferred over this function unless a truncated string + * provides some valid semantics in the destination buffer. + */ +ssize_t strscpy_truncate(char *dest, const char *src, size_t count) +{ + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; + size_t max = count; + long res = 0; + + if (count == 0) + return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* + * If src is unaligned, don't cross a page boundary, + * since we don't know if the next page is mapped. + */ + if ((long)src & (sizeof(long) - 1)) { + size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); + if (limit < max) + max = limit; + } +#else + /* If src or dest is unaligned, don't do word-at-a-time. */ + if (((long) dest | (long) src) & (sizeof(long) - 1)) + max = 0; +#endif + + while (max >= sizeof(unsigned long)) { + unsigned long c, data; + + c = *(unsigned long *)(src+res); + *(unsigned long *)(dest+res) = c; + if (has_zero(c, &data, &constants)) { + data = prep_zero_mask(c, data, &constants); + data = create_zero_mask(data); + return res + find_zero(data); + } + res += sizeof(unsigned long); + count -= sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +EXPORT_SYMBOL(strscpy_truncate); +#endif + +#ifndef __HAVE_ARCH_STRSCPY +/** + * strscpy - Copy a C-string into a sized buffer, but only if it fits + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string into the dest buffer. The routine returns the + * number of characters copied (not including the trailing NUL) or + * -E2BIG if the destination buffer wasn't big enough. The behavior + * is undefined if the string buffers overlap. The destination buffer + * is set to the empty string if the buffer is not big enough. + * + * Preferred over strlcpy() in all cases, and over strncpy() unless + * the latter's zero-fill behavior is desired and truncation of the + * source string is known not to be an issue. + */ +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + ssize_t res = strscpy_truncate(dest, src, count); + if (res < 0 && count != 0) + dest[0] = '\0'; + return res; +} +EXPORT_SYMBOL(strscpy); +#endif + #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-04-30 16:01 ` [PATCH 2/3] string: provide strscpy() and strscpy_truncate() Chris Metcalf @ 2015-04-30 16:01 ` Chris Metcalf 2015-05-06 15:01 ` Dan Carpenter 1 sibling, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch The strscpy() API is intended to be used instead of strlcpy(), and instead of most uses of strncpy(). - The API provides an easy way to check for destination buffer overflow: a -E2BIG error return value. - By default, truncation causes the destination buffer to be the empty string, so users don't blindly assume a truncated string is valid. If you know a truncated string still has valid semantics, you can use the provided strscpy_truncate(), which has the same return value semantics but does not make the destination an empty string on error. - The provided implementation is robust in the face of the source buffer being asynchronously changed during the copy, unlike the current implementation of strlcpy(). - The implementation should be reasonably performant on all platforms since it uses the asm/word-at-a-time.h API rather than simple byte copy. Kernel-to-kernel string copy is not considered to be performance critical in any case. - If the remainder of the destination buffer must be zeroed for some reason, strscpy() + error check + memset() is probably the easiest pattern, but using strncpy() in a pattern where the last byte of the buffer is first set non-NUL, then tested for NUL afterwards, can also be safely used. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- include/linux/string.h | 6 +++ lib/string.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index e40099e585c9..7942944f3abb 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -25,6 +25,12 @@ extern char * strncpy(char *,const char *, __kernel_size_t); #ifndef __HAVE_ARCH_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif +#ifndef __HAVE_ARCH_STRSCPY +ssize_t strscpy(char *, const char *, size_t); +#endif +#ifndef __HAVE_ARCH_STRSCPY_TRUNCATE +ssize_t strscpy_truncate(char *, const char *, size_t); +#endif #ifndef __HAVE_ARCH_STRCAT extern char * strcat(char *, const char *); #endif diff --git a/lib/string.c b/lib/string.c index a5792019193c..84d5b6eceb74 100644 --- a/lib/string.c +++ b/lib/string.c @@ -27,6 +27,9 @@ #include <linux/bug.h> #include <linux/errno.h> +#include <asm/byteorder.h> +#include <asm/word-at-a-time.h> + #ifndef __HAVE_ARCH_STRNCASECMP /** * strncasecmp - Case insensitive, length-limited string comparison @@ -146,6 +149,112 @@ size_t strlcpy(char *dest, const char *src, size_t size) EXPORT_SYMBOL(strlcpy); #endif +#ifndef __HAVE_ARCH_STRSCPY_TRUNCATE +/** + * strscpy_truncate - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. + * The routine returns the number of characters copied (not including + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. + * The behavior is undefined if the string buffers overlap. + * + * Note that the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation, + * and it is easier to check overflow than with strlcpy()'s API. + * + * strscpy() is preferred over this function unless a truncated string + * provides some valid semantics in the destination buffer. + */ +ssize_t strscpy_truncate(char *dest, const char *src, size_t count) +{ + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; + size_t max = count; + long res = 0; + + if (count == 0) + return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* + * If src is unaligned, don't cross a page boundary, + * since we don't know if the next page is mapped. + */ + if ((long)src & (sizeof(long) - 1)) { + size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); + if (limit < max) + max = limit; + } +#else + /* If src or dest is unaligned, don't do word-at-a-time. */ + if (((long) dest | (long) src) & (sizeof(long) - 1)) + max = 0; +#endif + + while (max >= sizeof(unsigned long)) { + unsigned long c, data; + + c = *(unsigned long *)(src+res); + *(unsigned long *)(dest+res) = c; + if (has_zero(c, &data, &constants)) { + data = prep_zero_mask(c, data, &constants); + data = create_zero_mask(data); + return res + find_zero(data); + } + res += sizeof(unsigned long); + count -= sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +EXPORT_SYMBOL(strscpy_truncate); +#endif + +#ifndef __HAVE_ARCH_STRSCPY +/** + * strscpy - Copy a C-string into a sized buffer, but only if it fits + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string into the dest buffer. The routine returns the + * number of characters copied (not including the trailing NUL) or + * -E2BIG if the destination buffer wasn't big enough. The behavior + * is undefined if the string buffers overlap. The destination buffer + * is set to the empty string if the buffer is not big enough. + * + * Preferred over strlcpy() in all cases, and over strncpy() unless + * the latter's zero-fill behavior is desired and truncation of the + * source string is known not to be an issue. + */ +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + ssize_t res = strscpy_truncate(dest, src, count); + if (res < 0 && count != 0) + dest[0] = '\0'; + return res; +} +EXPORT_SYMBOL(strscpy); +#endif + #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-04-30 16:01 ` [PATCH 2/3] string: provide strscpy() and strscpy_truncate() Chris Metcalf 2015-04-30 16:01 ` Chris Metcalf @ 2015-05-06 15:01 ` Dan Carpenter 2015-05-06 15:21 ` Chris Metcalf 1 sibling, 1 reply; 27+ messages in thread From: Dan Carpenter @ 2015-05-06 15:01 UTC (permalink / raw) To: Chris Metcalf Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch On Thu, Apr 30, 2015 at 12:01:16PM -0400, Chris Metcalf wrote: > +ssize_t strscpy(char *dest, const char *src, size_t count) > +{ > + ssize_t res = strscpy_truncate(dest, src, count); > + if (res < 0 && count != 0) > + dest[0] = '\0'; How is this better than returning a truncated string? Is it just because the caller was naughty so we give them a spanking? > + return res; > +} regards, dan carpenter ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-05-06 15:01 ` Dan Carpenter @ 2015-05-06 15:21 ` Chris Metcalf 2015-05-06 15:59 ` Dan Carpenter 0 siblings, 1 reply; 27+ messages in thread From: Chris Metcalf @ 2015-05-06 15:21 UTC (permalink / raw) To: Dan Carpenter Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch On 5/6/2015 11:01 AM, Dan Carpenter wrote: > On Thu, Apr 30, 2015 at 12:01:16PM -0400, Chris Metcalf wrote: >> >+ssize_t strscpy(char *dest, const char *src, size_t count) >> >+{ >> >+ ssize_t res = strscpy_truncate(dest, src, count); >> >+ if (res < 0 && count != 0) >> >+ dest[0] = '\0'; > How is this better than returning a truncated string? Is it just > because the caller was naughty so we give them a spanking? There are basically two issues here: 1. A truncated string with an error return may still cause program errors, even if the caller checks for the error return, if the buffer is later interpreted as a valid string due to some other program error. It's defensive programming. 2. Programmers are fond of ignoring error returns. My experience with truncated strings is that in too many cases, truncation causes program errors down the line. It's better to ensure that no partial string is returned in this case. In a perfect world, all error returns would be checked, and there would be no need for this, but we definitely don't live in that world :-) That said, although I think my approach is correct, I'm open to a consensus that having strscpy() leave a truncated string in the dest buffer is better. -- Chris Metcalf, EZChip Semiconductor http://www.ezchip.com ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-05-06 15:21 ` Chris Metcalf @ 2015-05-06 15:59 ` Dan Carpenter 2015-05-06 16:45 ` Geert Uytterhoeven 0 siblings, 1 reply; 27+ messages in thread From: Dan Carpenter @ 2015-05-06 15:59 UTC (permalink / raw) To: Chris Metcalf Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch We actually do have a __must_check tag so it's easy enough to force people to check. A different option is we could make it trigger a WARN_ONCE(). #define strXcpy(dest, src, len) (({ \ ssize_t __ret = strscpy_truncate(dest, src, len); \ WARN_ONCE(__ret < 0, "strXcpy trancates\n"); \ __ret; })) I have never really cared about truncation, though. I think not caring is the common case. regards, dan carpenter ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-05-06 15:59 ` Dan Carpenter @ 2015-05-06 16:45 ` Geert Uytterhoeven 2015-05-07 9:00 ` Dan Carpenter 0 siblings, 1 reply; 27+ messages in thread From: Geert Uytterhoeven @ 2015-05-06 16:45 UTC (permalink / raw) To: Dan Carpenter Cc: Chris Metcalf, Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, Greg KH, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, Linux-Arch On Wed, May 6, 2015 at 5:59 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote: > We actually do have a __must_check tag so it's easy enough to force > people to check. A different option is we could make it trigger a People tend to ignore compiler warnings... > WARN_ONCE(). > > #define strXcpy(dest, src, len) (({ \ > ssize_t __ret = strscpy_truncate(dest, src, len); \ > WARN_ONCE(__ret < 0, "strXcpy trancates\n"); \ > __ret; })) Which will probably trigger only in extreme cases in the wild, not during development. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-05-06 16:45 ` Geert Uytterhoeven @ 2015-05-07 9:00 ` Dan Carpenter 2015-05-07 15:10 ` Chris Metcalf 0 siblings, 1 reply; 27+ messages in thread From: Dan Carpenter @ 2015-05-07 9:00 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Chris Metcalf, Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, Greg KH, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, Linux-Arch On Wed, May 06, 2015 at 06:45:56PM +0200, Geert Uytterhoeven wrote: > On Wed, May 6, 2015 at 5:59 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote: > > We actually do have a __must_check tag so it's easy enough to force > > people to check. A different option is we could make it trigger a > > People tend to ignore compiler warnings... We're doing a lot better these days with zero day build testing. There is not even one ignored __must_check return in my allmodconfig. > > > WARN_ONCE(). > > > > #define strXcpy(dest, src, len) (({ \ > > ssize_t __ret = strscpy_truncate(dest, src, len); \ > > WARN_ONCE(__ret < 0, "strXcpy trancates\n"); \ > > __ret; })) > > Which will probably trigger only in extreme cases in the wild, not during > development. It's less subtle than just putting an empty string there so we're more likely to get bug reports than with the original code. regards, dan carpenter ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] string: provide strscpy() and strscpy_truncate() 2015-05-07 9:00 ` Dan Carpenter @ 2015-05-07 15:10 ` Chris Metcalf 0 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-05-07 15:10 UTC (permalink / raw) To: Dan Carpenter, Geert Uytterhoeven Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, Greg KH, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, Linux-Arch On 05/07/2015 05:00 AM, Dan Carpenter wrote: > On Wed, May 06, 2015 at 06:45:56PM +0200, Geert Uytterhoeven wrote: >> On Wed, May 6, 2015 at 5:59 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote: >>> We actually do have a __must_check tag so it's easy enough to force >>> people to check. A different option is we could make it trigger a >> People tend to ignore compiler warnings... > We're doing a lot better these days with zero day build testing. There > is not even one ignored __must_check return in my allmodconfig. If we keep the strscpy/strscpy_truncate distinction, I agree that having __must_check on strscpy seems like a good idea. >>> WARN_ONCE(). >>> >>> #define strXcpy(dest, src, len) (({ \ >>> ssize_t __ret = strscpy_truncate(dest, src, len); \ >>> WARN_ONCE(__ret < 0, "strXcpy trancates\n"); \ >>> __ret; })) >> Which will probably trigger only in extreme cases in the wild, not during >> development. > It's less subtle than just putting an empty string there so we're more > likely to get bug reports than with the original code. The problem with WARN_ONCE() here is that we may be using strscpy() to take user input of some kind. If so, we don't want to warn if we are truncating the string - we just want to return a suitable error up the call stack. -- Chris Metcalf, EZChip Semiconductor http://www.ezchip.com ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 3/3] tile: use global strscpy() rather than private copy 2015-04-30 16:01 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf 2015-04-30 16:01 ` [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf 2015-04-30 16:01 ` [PATCH 2/3] string: provide strscpy() and strscpy_truncate() Chris Metcalf @ 2015-04-30 16:01 ` Chris Metcalf 2015-04-30 16:01 ` Chris Metcalf 2015-05-11 15:37 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf ` (2 subsequent siblings) 5 siblings, 1 reply; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch Now that strscpy() is a standard API, remove the local copy. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/tile/gxio/mpipe.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c index ee186e13dfe6..f102048d9c0e 100644 --- a/arch/tile/gxio/mpipe.c +++ b/arch/tile/gxio/mpipe.c @@ -19,6 +19,7 @@ #include <linux/errno.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/string.h> #include <gxio/iorpc_globals.h> #include <gxio/iorpc_mpipe.h> @@ -29,32 +30,6 @@ /* HACK: Avoid pointless "shadow" warnings. */ #define link link_shadow -/** - * strscpy - Copy a C-string into a sized buffer, but only if it fits - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Use this routine to avoid copying too-long strings. - * The routine returns the total number of bytes copied - * (including the trailing NUL) or zero if the buffer wasn't - * big enough. To ensure that programmers pay attention - * to the return code, the destination has a single NUL - * written at the front (if size is non-zero) when the - * buffer is not big enough. - */ -static size_t strscpy(char *dest, const char *src, size_t size) -{ - size_t len = strnlen(src, size) + 1; - if (len > size) { - if (size) - dest[0] = '\0'; - return 0; - } - memcpy(dest, src, len); - return len; -} - int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index) { char file[32]; @@ -540,7 +515,7 @@ int gxio_mpipe_link_instance(const char *link_name) if (!context) return GXIO_ERR_NO_DEVICE; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; return gxio_mpipe_info_instance_aux(context, name); @@ -559,7 +534,7 @@ int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac) rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac); if (rv >= 0) { - if (strscpy(link_name, name.name, sizeof(name.name)) == 0) + if (strscpy(link_name, name.name, sizeof(name.name)) < 0) return GXIO_ERR_INVAL_MEMORY_SIZE; memcpy(link_mac, mac.mac, sizeof(mac.mac)); } @@ -576,7 +551,7 @@ int gxio_mpipe_link_open(gxio_mpipe_link_t *link, _gxio_mpipe_link_name_t name; int rv; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; rv = gxio_mpipe_link_open_aux(context, name, flags); -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 3/3] tile: use global strscpy() rather than private copy 2015-04-30 16:01 ` [PATCH 3/3] tile: use global strscpy() rather than private copy Chris Metcalf @ 2015-04-30 16:01 ` Chris Metcalf 0 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-04-30 16:01 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch Now that strscpy() is a standard API, remove the local copy. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/tile/gxio/mpipe.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c index ee186e13dfe6..f102048d9c0e 100644 --- a/arch/tile/gxio/mpipe.c +++ b/arch/tile/gxio/mpipe.c @@ -19,6 +19,7 @@ #include <linux/errno.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/string.h> #include <gxio/iorpc_globals.h> #include <gxio/iorpc_mpipe.h> @@ -29,32 +30,6 @@ /* HACK: Avoid pointless "shadow" warnings. */ #define link link_shadow -/** - * strscpy - Copy a C-string into a sized buffer, but only if it fits - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Use this routine to avoid copying too-long strings. - * The routine returns the total number of bytes copied - * (including the trailing NUL) or zero if the buffer wasn't - * big enough. To ensure that programmers pay attention - * to the return code, the destination has a single NUL - * written at the front (if size is non-zero) when the - * buffer is not big enough. - */ -static size_t strscpy(char *dest, const char *src, size_t size) -{ - size_t len = strnlen(src, size) + 1; - if (len > size) { - if (size) - dest[0] = '\0'; - return 0; - } - memcpy(dest, src, len); - return len; -} - int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index) { char file[32]; @@ -540,7 +515,7 @@ int gxio_mpipe_link_instance(const char *link_name) if (!context) return GXIO_ERR_NO_DEVICE; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; return gxio_mpipe_info_instance_aux(context, name); @@ -559,7 +534,7 @@ int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac) rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac); if (rv >= 0) { - if (strscpy(link_name, name.name, sizeof(name.name)) == 0) + if (strscpy(link_name, name.name, sizeof(name.name)) < 0) return GXIO_ERR_INVAL_MEMORY_SIZE; memcpy(link_mac, mac.mac, sizeof(mac.mac)); } @@ -576,7 +551,7 @@ int gxio_mpipe_link_open(gxio_mpipe_link_t *link, _gxio_mpipe_link_name_t name; int rv; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; rv = gxio_mpipe_link_open_aux(context, name, flags); -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 0/3] add new strscpy() API for string copy 2015-04-30 16:01 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf ` (2 preceding siblings ...) 2015-04-30 16:01 ` [PATCH 3/3] tile: use global strscpy() rather than private copy Chris Metcalf @ 2015-05-11 15:37 ` Chris Metcalf 2015-05-14 23:10 ` Michael Ellerman [not found] ` <CA+55aFwokKo9X4=wwZ1sKLmLfye=a65KPzMhe-QzuHT6Prp0tA@mail.gmail.com> 5 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-05-11 15:37 UTC (permalink / raw) To: Linus Torvalds Cc: Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch Ping! There was a little feedback on the strscpy() patch series, but I think at this point it boiled down to adding a __must_check on strscpy(), which I've done. Any further opinions? Would anyone like to volunteer to take this into their tree? Or Linus, are you ready to pull it directly when the merge window opens? git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git strscpy Thanks! On 04/30/2015 12:01 PM, Chris Metcalf wrote: > This patch series addresses limitations in strncpy() and strlcpy(); > both the old APIs are unpleasant, as Linus nicely summarized here > a couple of days ago: > > https://lkml.org/lkml/2015/4/28/570 > > and of course as other folks (Greg K-H and Linus again) said last year: > > https://plus.google.com/+gregkroahhartman/posts/1amLbuhWbh5 > > The proposed new API (strscpy(), for "s"afe string copy) has an > easy-to-use API for detecting buffer overflow, avoids unsafe truncation > by default, and isn't subject to thread-safety attacks like the current > strlcpy implementation. See patch 2/3 for more on why strscpy() is a > good thing. > > To make strscpy() work more efficiently I did the minimum tweaking > necessary to allow <asm/word-at-a-time.h> to work on all architectures, > though of course individual maintainers can still make their versions > more efficient as needed. > > It's likely not necessary for per-architecture implementations of > strscpy() to be written, but I stuck with the standard __HAVE_ARCH_XXX > model just for consistency with the rest of <linux/string.h>. > > I tested the implementation with a simple user-space harness, so I > believe it is correct for the corner cases I could think of. In > particular I pairwise-tested all the unaligned values of source and > dest, and tested the restriction on src page-crossing at all > unaligned offsets approaching the page boundary. > > This builds on an earlier version of strscpy() submitted as > a file-static method in the arch/tile/gxio tree last year, after > an attempt to gather interest in a new generic strscpy failed: > > https://lkml.org/lkml/2014/8/7/368 > > The patch series is available to be pulled from > > git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git strscpy > > Chris Metcalf (3): > Make asm/word-at-a-time.h available on all architectures > string: provide strscpy() and strscpy_truncate() > tile: use global strscpy() rather than private copy > > arch/arc/include/asm/Kbuild | 1 + > arch/avr32/include/asm/Kbuild | 1 + > arch/blackfin/include/asm/Kbuild | 1 + > arch/c6x/include/asm/Kbuild | 1 + > arch/cris/include/asm/Kbuild | 1 + > arch/frv/include/asm/Kbuild | 1 + > arch/hexagon/include/asm/Kbuild | 1 + > arch/ia64/include/asm/Kbuild | 1 + > arch/m32r/include/asm/Kbuild | 1 + > arch/metag/include/asm/Kbuild | 1 + > arch/microblaze/include/asm/Kbuild | 1 + > arch/mips/include/asm/Kbuild | 1 + > arch/mn10300/include/asm/Kbuild | 1 + > arch/nios2/include/asm/Kbuild | 1 + > arch/powerpc/include/asm/Kbuild | 1 + > arch/s390/include/asm/Kbuild | 1 + > arch/score/include/asm/Kbuild | 1 + > arch/tile/gxio/mpipe.c | 33 ++--------- > arch/tile/include/asm/Kbuild | 1 + > arch/um/include/asm/Kbuild | 1 + > arch/unicore32/include/asm/Kbuild | 1 + > arch/xtensa/include/asm/Kbuild | 1 + > include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++--- > include/linux/string.h | 6 ++ > lib/string.c | 109 +++++++++++++++++++++++++++++++++++ > 25 files changed, 212 insertions(+), 37 deletions(-) > -- Chris Metcalf, EZChip Semiconductor http://www.ezchip.com ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 0/3] add new strscpy() API for string copy 2015-04-30 16:01 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf ` (3 preceding siblings ...) 2015-05-11 15:37 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf @ 2015-05-14 23:10 ` Michael Ellerman 2015-05-15 15:15 ` Chris Metcalf [not found] ` <CA+55aFwokKo9X4=wwZ1sKLmLfye=a65KPzMhe-QzuHT6Prp0tA@mail.gmail.com> 5 siblings, 1 reply; 27+ messages in thread From: Michael Ellerman @ 2015-05-14 23:10 UTC (permalink / raw) To: Chris Metcalf Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch On Thu, 2015-04-30 at 12:01 -0400, Chris Metcalf wrote: > This patch series addresses limitations in strncpy() and strlcpy(); > both the old APIs are unpleasant, as Linus nicely summarized here > a couple of days ago: > > https://lkml.org/lkml/2015/4/28/570 > > and of course as other folks (Greg K-H and Linus again) said last year: > > https://plus.google.com/+gregkroahhartman/posts/1amLbuhWbh5 > > The proposed new API (strscpy(), for "s"afe string copy) has an > easy-to-use API for detecting buffer overflow, avoids unsafe truncation > by default, and isn't subject to thread-safety attacks like the current > strlcpy implementation. See patch 2/3 for more on why strscpy() is a > good thing. +1 on the concept. > To make strscpy() work more efficiently I did the minimum tweaking > necessary to allow <asm/word-at-a-time.h> to work on all architectures, > though of course individual maintainers can still make their versions > more efficient as needed. > > It's likely not necessary for per-architecture implementations of > strscpy() to be written, but I stuck with the standard __HAVE_ARCH_XXX > model just for consistency with the rest of <linux/string.h>. > > I tested the implementation with a simple user-space harness, so I > believe it is correct for the corner cases I could think of. In > particular I pairwise-tested all the unaligned values of source and > dest, and tested the restriction on src page-crossing at all > unaligned offsets approaching the page boundary. Can you please put that in tools/testing/selftests and merge it as part of the series? That way I can run the tests and be confident it works on powerpc. cheers ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 0/3] add new strscpy() API for string copy 2015-05-14 23:10 ` Michael Ellerman @ 2015-05-15 15:15 ` Chris Metcalf 2015-05-18 1:13 ` Michael Ellerman 0 siblings, 1 reply; 27+ messages in thread From: Chris Metcalf @ 2015-05-15 15:15 UTC (permalink / raw) To: Michael Ellerman Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch On 05/14/2015 07:10 PM, Michael Ellerman wrote: > On Thu, 2015-04-30 at 12:01 -0400, Chris Metcalf wrote: >> This patch series addresses limitations in strncpy() and strlcpy(); >> both the old APIs are unpleasant, as Linus nicely summarized here >> a couple of days ago: >> >> https://lkml.org/lkml/2015/4/28/570 >> >> and of course as other folks (Greg K-H and Linus again) said last year: >> >> https://plus.google.com/+gregkroahhartman/posts/1amLbuhWbh5 >> >> The proposed new API (strscpy(), for "s"afe string copy) has an >> easy-to-use API for detecting buffer overflow, avoids unsafe truncation >> by default, and isn't subject to thread-safety attacks like the current >> strlcpy implementation. See patch 2/3 for more on why strscpy() is a >> good thing. > +1 on the concept. Thanks. >> To make strscpy() work more efficiently I did the minimum tweaking >> necessary to allow <asm/word-at-a-time.h> to work on all architectures, >> though of course individual maintainers can still make their versions >> more efficient as needed. >> >> It's likely not necessary for per-architecture implementations of >> strscpy() to be written, but I stuck with the standard __HAVE_ARCH_XXX >> model just for consistency with the rest of <linux/string.h>. >> >> I tested the implementation with a simple user-space harness, so I >> believe it is correct for the corner cases I could think of. In >> particular I pairwise-tested all the unaligned values of source and >> dest, and tested the restriction on src page-crossing at all >> unaligned offsets approaching the page boundary. > Can you please put that in tools/testing/selftests and merge it as part of the > series? That way I can run the tests and be confident it works on powerpc. Unfortunately, the strscpy patch series only changes the one previous user of the API, which is a tile-architecture-only driver piece, not particularly useful for anyone else for testing. The testing I did pulled strscpy() and word-at-a-time out into a separate, standalone userspace implementation, and tested it there, rather than doing tests through the syscall API like tools/testing/selftests. So I don't really see a way of committing my test framework, other than as a real Kconfig-enabled boot-time self-test or some such; I can certainly do that but I don't know how excited people are to have that additional level of source-code and Kconfig bloat. -- Chris Metcalf, EZChip Semiconductor http://www.ezchip.com ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 0/3] add new strscpy() API for string copy 2015-05-15 15:15 ` Chris Metcalf @ 2015-05-18 1:13 ` Michael Ellerman 2015-05-26 19:33 ` Chris Metcalf 0 siblings, 1 reply; 27+ messages in thread From: Michael Ellerman @ 2015-05-18 1:13 UTC (permalink / raw) To: Chris Metcalf Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch On Fri, 2015-05-15 at 11:15 -0400, Chris Metcalf wrote: > On 05/14/2015 07:10 PM, Michael Ellerman wrote: > > On Thu, 2015-04-30 at 12:01 -0400, Chris Metcalf wrote: > >> > >> I tested the implementation with a simple user-space harness, so I > >> believe it is correct for the corner cases I could think of. In > >> particular I pairwise-tested all the unaligned values of source and > >> dest, and tested the restriction on src page-crossing at all > >> unaligned offsets approaching the page boundary. > > Can you please put that in tools/testing/selftests and merge it as part of the > > series? That way I can run the tests and be confident it works on powerpc. > > Unfortunately, the strscpy patch series only changes the one previous > user of the API, which is a tile-architecture-only driver piece, not > particularly useful for anyone else for testing. > > The testing I did pulled strscpy() and word-at-a-time out into a > separate, standalone userspace implementation, and tested it there, > rather than doing tests through the syscall API like > tools/testing/selftests. Not everything in selftests has to or does go through the syscall API. We (powerpc) have tests of our memcpy/memcmp/load_unaligned_zeropad that are built as standalone test programs. Doing that for stuff in lib/string.c does look a bit complicated, because you'd need to pull in a bunch of kernel headers. Do you mind posting your test code somewhere so I can run it, and maybe I can work out how to fold it into a selftest. cheers ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 0/3] add new strscpy() API for string copy 2015-05-18 1:13 ` Michael Ellerman @ 2015-05-26 19:33 ` Chris Metcalf 0 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-05-26 19:33 UTC (permalink / raw) To: Michael Ellerman Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Linux Kernel Mailing List, linux-arch On 05/17/2015 09:13 PM, Michael Ellerman wrote: > On Fri, 2015-05-15 at 11:15 -0400, Chris Metcalf wrote: >> On 05/14/2015 07:10 PM, Michael Ellerman wrote: >>> On Thu, 2015-04-30 at 12:01 -0400, Chris Metcalf wrote: >>>> >>>> I tested the implementation with a simple user-space harness, so I >>>> believe it is correct for the corner cases I could think of. In >>>> particular I pairwise-tested all the unaligned values of source and >>>> dest, and tested the restriction on src page-crossing at all >>>> unaligned offsets approaching the page boundary. >>> Can you please put that in tools/testing/selftests and merge it as part of the >>> series? That way I can run the tests and be confident it works on powerpc. >> >> Unfortunately, the strscpy patch series only changes the one previous >> user of the API, which is a tile-architecture-only driver piece, not >> particularly useful for anyone else for testing. >> >> The testing I did pulled strscpy() and word-at-a-time out into a >> separate, standalone userspace implementation, and tested it there, >> rather than doing tests through the syscall API like >> tools/testing/selftests. > > Not everything in selftests has to or does go through the syscall API. > > We (powerpc) have tests of our memcpy/memcmp/load_unaligned_zeropad that are > built as standalone test programs. > > Doing that for stuff in lib/string.c does look a bit complicated, because you'd > need to pull in a bunch of kernel headers. > > Do you mind posting your test code somewhere so I can run it, and maybe I can > work out how to fold it into a selftest. Seems easiest to just post it to LKML so anyone else who wants to can take a look at it. Trying to post a collection of files without violating the "no MIME parts" rule for LKML made me dust off my Usenet memories and track down a version of shar to use to bundle up the test.c harness, the strscpy.c code (excerpted from lib/string.c with suitable #defines and #includes so it builds in userspace), and a version of word-at-a-time.h that works for the two environments I tested it in (x86_64 and tile). -- Chris Metcalf, EZChip Semiconductor http://www.ezchip.com #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.2.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # existing files WILL be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 2294 -rw-r--r-- test.c # 3321 -rw-r--r-- strscpy.c # 2905 -rw-r--r-- word-at-a-time.h # echo=echo if mkdir _sh15429; then $echo 'x -' 'creating lock directory' else $echo 'failed to create lock directory' exit 1 fi # ============= test.c ============== $echo 'x -' extracting 'test.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'test.c' && /* Compile "gcc -O -o test test.c strscpy.c" and run "./test" */ X #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/mman.h> X size_t strscpy_truncate(char *dest, const char *src, size_t count); size_t strscpy(char *dest, const char *src, size_t count); X char dest[1024] __attribute__((aligned(8))); char src[1024] __attribute__((aligned(8))); X #define assert(check) do { \ X if (!(check)) { \ X printf("%s: %d: %d: %s @%zd: %d => %d\n", #check, i, j, s, count, rc, ret); \ X exit(1); \ X } } while (0) X void test(int i, int j, char *s, size_t count, int ret) { X int rc; X X if (ret == -1) X ret = strlen(s); X X memset(dest, 0, sizeof(dest)); X memset(src, 0, sizeof(src)); X strcpy(&src[i], s); X rc = strscpy(&dest[j], &src[i], count); X assert(rc == ret); X if (rc > 0) X assert(strcmp(&dest[j], s) == 0); X else if (count > 0) X assert(dest[j] == '\0'); X X memset(dest, 0, sizeof(dest)); X memset(src, 0, sizeof(src)); X strcpy(&src[i], s); X rc = strscpy_truncate(&dest[j], &src[i], count); X assert(rc == ret); X if (rc > 0) X assert(strcmp(&dest[j], s) == 0); X else if (count > 0) { X assert(strncmp(&dest[j], s, count-1) == 0); X assert(dest[j+count-1] == '\0'); X } } X int main() { X int i, j; X X for (i = 0; i < 15; ++i) { X for (j = 0; j < 15; ++j) { X test(i, j, "Hello, world", sizeof(src) - i, -1); X test(i, j, "Hello, world", 12, -E2BIG); X test(i, j, "foo", 0, -E2BIG); X test(i, j, "foo", 1, -E2BIG); X } X } X X /* Check we never walk across a page boundary past the source. */ X char *p = mmap(NULL, 2*getpagesize(), PROT_READ|PROT_WRITE, X MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); X mprotect(p+getpagesize(), getpagesize(), PROT_NONE); X char *base = p + getpagesize() - 16; X strcpy(base, "This is some ra"); X for (i = 0; i < 15; ++i) { X memset(dest, 0, 16); X int rc = strscpy_truncate(dest, base + i, sizeof(dest)); X if (rc != 16 - i - 1 || strcmp(dest, base + i) != 0) { X printf("Badness at %d %d\n", i, rc); X exit(1); X } X } X X printf("OK!\n"); X return 0; } SHAR_EOF chmod 0644 'test.c' || $echo 'restore of' 'test.c' 'failed' # ============= strscpy.c ============== $echo 'x -' extracting 'strscpy.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'strscpy.c' && #include <sys/types.h> #include <unistd.h> #include <errno.h> #include "word-at-a-time.h" #ifndef __tile__ #define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #endif #define PAGE_SIZE getpagesize() #define EXPORT_SYMBOL(sym) X #ifndef __HAVE_ARCH_STRSCPY_TRUNCATE /** X * strscpy_truncate - Copy a C-string into a sized buffer X * @dest: Where to copy the string to X * @src: Where to copy the string from X * @count: Size of destination buffer X * X * Copy the string, or as much of it as fits, into the dest buffer. X * The routine returns the number of characters copied (not including X * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. X * The behavior is undefined if the string buffers overlap. X * X * Note that the implementation is robust to the string changing out X * from underneath it, unlike the current strlcpy() implementation, X * and it is easier to check overflow than with strlcpy()'s API. X * X * strscpy() is preferred over this function unless a truncated string X * provides some valid semantics in the destination buffer. X */ ssize_t strscpy_truncate(char *dest, const char *src, size_t count) { X const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; X size_t max = count; X long res = 0; X X if (count == 0) X return -E2BIG; X #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS X /* X * If src is unaligned, don't cross a page boundary, X * since we don't know if the next page is mapped. X */ X if ((long)src & (sizeof(long) - 1)) { X size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); X if (limit < max) X max = limit; X } #else X /* If src or dest is unaligned, don't do word-at-a-time. */ X if (((long) dest | (long) src) & (sizeof(long) - 1)) X max = 0; #endif X X while (max >= sizeof(unsigned long)) { X unsigned long c, data; X X c = *(unsigned long *)(src+res); X *(unsigned long *)(dest+res) = c; X if (has_zero(c, &data, &constants)) { X data = prep_zero_mask(c, data, &constants); X data = create_zero_mask(data); X return res + find_zero(data); X } X res += sizeof(unsigned long); X count -= sizeof(unsigned long); X max -= sizeof(unsigned long); X } X X while (count) { X char c; X X c = src[res]; X dest[res] = c; X if (!c) X return res; X res++; X count--; X } X X /* Hit buffer length without finding a NUL; force NUL-termination. */ X if (res) X dest[res-1] = '\0'; X X return -E2BIG; } EXPORT_SYMBOL(strscpy_truncate); #endif X #ifndef __HAVE_ARCH_STRSCPY /** X * strscpy - Copy a C-string into a sized buffer, but only if it fits X * @dest: Where to copy the string to X * @src: Where to copy the string from X * @count: Size of destination buffer X * X * Copy the string into the dest buffer. The routine returns the X * number of characters copied (not including the trailing NUL) or X * -E2BIG if the destination buffer wasn't big enough. The behavior X * is undefined if the string buffers overlap. The destination buffer X * is set to the empty string if the buffer is not big enough. X * X * Preferred over strlcpy() in all cases, and over strncpy() unless X * the latter's zero-fill behavior is desired and truncation of the X * source string is known not to be an issue. X */ ssize_t strscpy(char *dest, const char *src, size_t count) { X ssize_t res = strscpy_truncate(dest, src, count); X if (res < 0 && count != 0) X dest[0] = '\0'; X return res; } EXPORT_SYMBOL(strscpy); #endif SHAR_EOF chmod 0644 'strscpy.c' || $echo 'restore of' 'strscpy.c' 'failed' # ============= word-at-a-time.h ============== $echo 'x -' extracting 'word-at-a-time.h' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'word-at-a-time.h' && #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H X #define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) X #ifndef __tile__ #define IS_UNALIGNED(src, dst) 0 #else #define IS_UNALIGNED(src, dst) \ X (((long) dst | (long) src) & (sizeof(long) - 1)) #endif X #ifdef __BIG_ENDIAN__ X struct word_at_a_time { X const unsigned long high_bits, low_bits; }; X #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0xfe) + 1, REPEAT_BYTE(0x7f) } X /* Bit set in the bytes that have a zero */ static inline long prep_zero_mask(unsigned long val, unsigned long rhs, const struct word_at_a_time *c) { X unsigned long mask = (val & c->low_bits) + c->low_bits; X return ~(mask | rhs); } X #define create_zero_mask(mask) (mask) X static inline long find_zero(unsigned long mask) { X long byte = 0; #ifdef _LP64 X if (mask >> 32) X mask >>= 32; X else X byte = 4; #endif X if (mask >> 16) X mask >>= 16; X else X byte += 2; X return (mask >> 8) ? byte : byte + 1; } X static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) { X unsigned long rhs = val | c->low_bits; X *data = rhs; X return (val + c->high_bits) & ~rhs; } X #ifndef zero_bytemask #define zero_bytemask(mask) (~1ul << __fls(mask)) #endif X #else X /* X * The optimal byte mask counting is probably going to be something X * that is architecture-specific. If you have a reliably fast X * bit count instruction, that might be better than the multiply X * and shift, for example. X */ struct word_at_a_time { X const unsigned long one_bits, high_bits; }; X #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } X #ifdef _LP64 X /* X * Jan Achrenius on G+: microoptimized version of X * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" X * that works for the bytemasks without having to X * mask them first. X */ static inline long count_masked_bytes(unsigned long mask) { X return mask*0x0001020304050608ul >> 56; } X #else /* 32-bit case */ X /* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ static inline long count_masked_bytes(long mask) { X /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ X long a = (0x0ff0001+mask) >> 23; X /* Fix the 1 for 00 case */ X return a & mask; } X #endif X /* Return nonzero if it has a zero */ static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) { X unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; X *bits = mask; X return mask; } X static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) { X return bits; } X static inline unsigned long create_zero_mask(unsigned long bits) { X bits = (bits - 1) & ~bits; X return bits >> 7; } X /* The mask we created is directly usable as a bytemask */ #define zero_bytemask(mask) (mask) X static inline unsigned long find_zero(unsigned long mask) { X return count_masked_bytes(mask); } X #endif /* __BIG_ENDIAN */ X #endif /* _ASM_WORD_AT_A_TIME_H */ SHAR_EOF chmod 0644 'word-at-a-time.h' || $echo 'restore of' 'word-at-a-time.h' 'failed' rm -fr _sh15429 exit 0 ^ permalink raw reply [flat|nested] 27+ messages in thread
[parent not found: <CA+55aFwokKo9X4=wwZ1sKLmLfye=a65KPzMhe-QzuHT6Prp0tA@mail.gmail.com>]
* [PATCH v2 0/3] add new strscpy() API for string copy [not found] ` <CA+55aFwokKo9X4=wwZ1sKLmLfye=a65KPzMhe-QzuHT6Prp0tA@mail.gmail.com> @ 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf ` (3 more replies) 0 siblings, 4 replies; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch v2: eliminate strscpy_truncate(); the single strscpy() API in v2 just tolerates a truncated string (while returning an error value) Also, improve some of the comparison language with strlcpy/strncpy. This patch series addresses limitations in strncpy() and strlcpy(); both the old APIs are unpleasant, as Linus nicely summarized here: https://lkml.org/lkml/2015/4/28/570 and of course as other folks (Greg K-H and Linus again) said last year: https://plus.google.com/+gregkroahhartman/posts/1amLbuhWbh5 The proposed new API (strscpy(), for "s"afe string copy) has an easy-to-use API for detecting buffer overflow, doesn't walk past the requested copy size on the source string, and isn't subject to thread-safety attacks like the current strlcpy implementation. See patch 2/3 for more on why strscpy() is a good thing. To make strscpy() work more efficiently I did the minimum tweaking necessary to allow <asm/word-at-a-time.h> to work on all architectures, though of course individual maintainers can still make their versions more efficient as needed. It's likely not necessary for per-architecture implementations of strscpy() to be written, but I stuck with the standard __HAVE_ARCH_XXX model just for consistency with the rest of <linux/string.h>. I tested the implementation with a simple user-space harness, so I believe it is correct for the corner cases I could think of. In particular I pairwise-tested all the unaligned values of source and dest, and tested the restriction on src page-crossing at all unaligned offsets approaching the page boundary. The patch series is available to be pulled from git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git strscpy Chris Metcalf (3): Make asm/word-at-a-time.h available on all architectures string: provide strscpy() tile: use global strscpy() rather than private copy arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/gxio/mpipe.c | 33 ++------------ arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++++++++---- include/linux/string.h | 3 ++ lib/string.c | 88 ++++++++++++++++++++++++++++++++++++ 25 files changed, 188 insertions(+), 37 deletions(-) -- 2.1.2 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 0/3] add new strscpy() API for string copy 2015-07-08 20:20 ` [PATCH v2 " Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` [PATCH v2 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf ` (2 subsequent siblings) 3 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch v2: eliminate strscpy_truncate(); the single strscpy() API in v2 just tolerates a truncated string (while returning an error value) Also, improve some of the comparison language with strlcpy/strncpy. This patch series addresses limitations in strncpy() and strlcpy(); both the old APIs are unpleasant, as Linus nicely summarized here: https://lkml.org/lkml/2015/4/28/570 and of course as other folks (Greg K-H and Linus again) said last year: https://plus.google.com/+gregkroahhartman/posts/1amLbuhWbh5 The proposed new API (strscpy(), for "s"afe string copy) has an easy-to-use API for detecting buffer overflow, doesn't walk past the requested copy size on the source string, and isn't subject to thread-safety attacks like the current strlcpy implementation. See patch 2/3 for more on why strscpy() is a good thing. To make strscpy() work more efficiently I did the minimum tweaking necessary to allow <asm/word-at-a-time.h> to work on all architectures, though of course individual maintainers can still make their versions more efficient as needed. It's likely not necessary for per-architecture implementations of strscpy() to be written, but I stuck with the standard __HAVE_ARCH_XXX model just for consistency with the rest of <linux/string.h>. I tested the implementation with a simple user-space harness, so I believe it is correct for the corner cases I could think of. In particular I pairwise-tested all the unaligned values of source and dest, and tested the restriction on src page-crossing at all unaligned offsets approaching the page boundary. The patch series is available to be pulled from git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git strscpy Chris Metcalf (3): Make asm/word-at-a-time.h available on all architectures string: provide strscpy() tile: use global strscpy() rather than private copy arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/gxio/mpipe.c | 33 ++------------ arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++++++++---- include/linux/string.h | 3 ++ lib/string.c | 88 ++++++++++++++++++++++++++++++++++++ 25 files changed, 188 insertions(+), 37 deletions(-) -- 2.1.2 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 1/3] Make asm/word-at-a-time.h available on all architectures 2015-07-08 20:20 ` [PATCH v2 " Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` [PATCH v2 2/3] string: provide strscpy() Chris Metcalf 2015-07-08 20:20 ` [PATCH v2 3/3] tile: use global strscpy() rather than private copy Chris Metcalf 3 siblings, 1 reply; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch Added the x86 implementation of word-at-a-time to the generic version, which previously only supported big-endian. Omitted the x86-specific load_unaligned_zeropad(), which in any case is also not present for the existing BE-only implementation of a word-at-a-time, and is only used under CONFIG_DCACHE_WORD_ACCESS. Added as a "generic-y" to the Kbuilds of all architectures that didn't previously have it. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++++++++++++---- 22 files changed, 93 insertions(+), 8 deletions(-) diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index be0c39e76f7c..be895ef03a51 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -49,4 +49,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index 528d70d47a54..10dd6e8470bd 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -20,4 +20,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild index 4bd3c3cfc9ab..9705a527b7b0 100644 --- a/arch/blackfin/include/asm/Kbuild +++ b/arch/blackfin/include/asm/Kbuild @@ -46,4 +46,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index ae0a51f5376c..535efdb0692d 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -59,4 +59,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index 057e51859b0a..4991539a25f6 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index e3f81b53578e..ca34d1cf2cdf 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index c7a99f860b40..872920fba0a6 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -58,4 +58,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 9b41b4bcc073..614579fa1e49 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -8,3 +8,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 2edc793372fc..36f850dd4a1e 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild index 0bf5d525b945..a291b3b2529e 100644 --- a/arch/metag/include/asm/Kbuild +++ b/arch/metag/include/asm/Kbuild @@ -54,4 +54,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index ab564a6db5c3..966f221b2d67 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@ -10,3 +10,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += syscalls.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 526539cbc99f..c3cfb83aca1d 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -18,4 +18,5 @@ generic-y += serial.h generic-y += trace_clock.h generic-y += ucontext.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index f892d9de47d9..30a06e2d6e42 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index 24b3d8999ac7..bc87081c0669 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -61,4 +61,5 @@ generic-y += types.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 4b87205c230c..dfc61a151890 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += rwsem.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index c631f98fd524..27c37b3d1dad 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -6,3 +6,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index 83ed116d414c..16958f529aa7 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -13,3 +13,4 @@ generic-y += sections.h generic-y += trace_clock.h generic-y += xor.h generic-y += serial.h +generic-y += word-at-a-time.h diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index f5433e0e34e0..0804122e579a 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -39,4 +39,5 @@ generic-y += termbits.h generic-y += termios.h generic-y += trace_clock.h generic-y += types.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index 9176fa11d49b..ee02364d8922 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += switch_to.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 3e0c19d0f4c5..f456bfa1dd54 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -62,4 +62,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 86a9ab2e2ca9..6ac0a9ab3ea3 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -29,4 +29,5 @@ generic-y += statfs.h generic-y += termios.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/include/asm-generic/word-at-a-time.h b/include/asm-generic/word-at-a-time.h index 94f9ea8abcae..011dde083f23 100644 --- a/include/asm-generic/word-at-a-time.h +++ b/include/asm-generic/word-at-a-time.h @@ -1,15 +1,10 @@ #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H -/* - * This says "generic", but it's actually big-endian only. - * Little-endian can use more efficient versions of these - * interfaces, see for example - * arch/x86/include/asm/word-at-a-time.h - * for those. - */ - #include <linux/kernel.h> +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN struct word_at_a_time { const unsigned long high_bits, low_bits; @@ -53,4 +48,73 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct #define zero_bytemask(mask) (~1ul << __fls(mask)) #endif +#else + +/* + * The optimal byte mask counting is probably going to be something + * that is architecture-specific. If you have a reliably fast + * bit count instruction, that might be better than the multiply + * and shift, for example. + */ +struct word_at_a_time { + const unsigned long one_bits, high_bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } + +#ifdef CONFIG_64BIT + +/* + * Jan Achrenius on G+: microoptimized version of + * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" + * that works for the bytemasks without having to + * mask them first. + */ +static inline long count_masked_bytes(unsigned long mask) +{ + return mask*0x0001020304050608ul >> 56; +} + +#else /* 32-bit case */ + +/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ +static inline long count_masked_bytes(long mask) +{ + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + long a = (0x0ff0001+mask) >> 23; + /* Fix the 1 for 00 case */ + return a & mask; +} + +#endif + +/* Return nonzero if it has a zero */ +static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) +{ + unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; + *bits = mask; + return mask; +} + +static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) +{ + return bits; +} + +static inline unsigned long create_zero_mask(unsigned long bits) +{ + bits = (bits - 1) & ~bits; + return bits >> 7; +} + +/* The mask we created is directly usable as a bytemask */ +#define zero_bytemask(mask) (mask) + +static inline unsigned long find_zero(unsigned long mask) +{ + return count_masked_bytes(mask); +} + +#endif /* __BIG_ENDIAN */ + #endif /* _ASM_WORD_AT_A_TIME_H */ -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 1/3] Make asm/word-at-a-time.h available on all architectures 2015-07-08 20:20 ` [PATCH v2 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 0 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch Added the x86 implementation of word-at-a-time to the generic version, which previously only supported big-endian. Omitted the x86-specific load_unaligned_zeropad(), which in any case is also not present for the existing BE-only implementation of a word-at-a-time, and is only used under CONFIG_DCACHE_WORD_ACCESS. Added as a "generic-y" to the Kbuilds of all architectures that didn't previously have it. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/arc/include/asm/Kbuild | 1 + arch/avr32/include/asm/Kbuild | 1 + arch/blackfin/include/asm/Kbuild | 1 + arch/c6x/include/asm/Kbuild | 1 + arch/cris/include/asm/Kbuild | 1 + arch/frv/include/asm/Kbuild | 1 + arch/hexagon/include/asm/Kbuild | 1 + arch/ia64/include/asm/Kbuild | 1 + arch/m32r/include/asm/Kbuild | 1 + arch/metag/include/asm/Kbuild | 1 + arch/microblaze/include/asm/Kbuild | 1 + arch/mips/include/asm/Kbuild | 1 + arch/mn10300/include/asm/Kbuild | 1 + arch/nios2/include/asm/Kbuild | 1 + arch/powerpc/include/asm/Kbuild | 1 + arch/s390/include/asm/Kbuild | 1 + arch/score/include/asm/Kbuild | 1 + arch/tile/include/asm/Kbuild | 1 + arch/um/include/asm/Kbuild | 1 + arch/unicore32/include/asm/Kbuild | 1 + arch/xtensa/include/asm/Kbuild | 1 + include/asm-generic/word-at-a-time.h | 80 ++++++++++++++++++++++++++++++++---- 22 files changed, 93 insertions(+), 8 deletions(-) diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index be0c39e76f7c..be895ef03a51 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -49,4 +49,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index 528d70d47a54..10dd6e8470bd 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -20,4 +20,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild index 4bd3c3cfc9ab..9705a527b7b0 100644 --- a/arch/blackfin/include/asm/Kbuild +++ b/arch/blackfin/include/asm/Kbuild @@ -46,4 +46,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index ae0a51f5376c..535efdb0692d 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -59,4 +59,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index 057e51859b0a..4991539a25f6 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index e3f81b53578e..ca34d1cf2cdf 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild @@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index c7a99f860b40..872920fba0a6 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -58,4 +58,5 @@ generic-y += types.h generic-y += ucontext.h generic-y += unaligned.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 9b41b4bcc073..614579fa1e49 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -8,3 +8,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 2edc793372fc..36f850dd4a1e 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild index 0bf5d525b945..a291b3b2529e 100644 --- a/arch/metag/include/asm/Kbuild +++ b/arch/metag/include/asm/Kbuild @@ -54,4 +54,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index ab564a6db5c3..966f221b2d67 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild @@ -10,3 +10,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += syscalls.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 526539cbc99f..c3cfb83aca1d 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -18,4 +18,5 @@ generic-y += serial.h generic-y += trace_clock.h generic-y += ucontext.h generic-y += user.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index f892d9de47d9..30a06e2d6e42 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += preempt.h generic-y += scatterlist.h generic-y += sections.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index 24b3d8999ac7..bc87081c0669 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -61,4 +61,5 @@ generic-y += types.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 4b87205c230c..dfc61a151890 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -9,3 +9,4 @@ generic-y += rwsem.h generic-y += scatterlist.h generic-y += trace_clock.h generic-y += vtime.h +generic-y += word-at-a-time.h diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index c631f98fd524..27c37b3d1dad 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -6,3 +6,4 @@ generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += scatterlist.h generic-y += trace_clock.h +generic-y += word-at-a-time.h diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index 83ed116d414c..16958f529aa7 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -13,3 +13,4 @@ generic-y += sections.h generic-y += trace_clock.h generic-y += xor.h generic-y += serial.h +generic-y += word-at-a-time.h diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index f5433e0e34e0..0804122e579a 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -39,4 +39,5 @@ generic-y += termbits.h generic-y += termios.h generic-y += trace_clock.h generic-y += types.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index 9176fa11d49b..ee02364d8922 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -26,4 +26,5 @@ generic-y += sections.h generic-y += switch_to.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 3e0c19d0f4c5..f456bfa1dd54 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -62,4 +62,5 @@ generic-y += ucontext.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 86a9ab2e2ca9..6ac0a9ab3ea3 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -29,4 +29,5 @@ generic-y += statfs.h generic-y += termios.h generic-y += topology.h generic-y += trace_clock.h +generic-y += word-at-a-time.h generic-y += xor.h diff --git a/include/asm-generic/word-at-a-time.h b/include/asm-generic/word-at-a-time.h index 94f9ea8abcae..011dde083f23 100644 --- a/include/asm-generic/word-at-a-time.h +++ b/include/asm-generic/word-at-a-time.h @@ -1,15 +1,10 @@ #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H -/* - * This says "generic", but it's actually big-endian only. - * Little-endian can use more efficient versions of these - * interfaces, see for example - * arch/x86/include/asm/word-at-a-time.h - * for those. - */ - #include <linux/kernel.h> +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN struct word_at_a_time { const unsigned long high_bits, low_bits; @@ -53,4 +48,73 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct #define zero_bytemask(mask) (~1ul << __fls(mask)) #endif +#else + +/* + * The optimal byte mask counting is probably going to be something + * that is architecture-specific. If you have a reliably fast + * bit count instruction, that might be better than the multiply + * and shift, for example. + */ +struct word_at_a_time { + const unsigned long one_bits, high_bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } + +#ifdef CONFIG_64BIT + +/* + * Jan Achrenius on G+: microoptimized version of + * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" + * that works for the bytemasks without having to + * mask them first. + */ +static inline long count_masked_bytes(unsigned long mask) +{ + return mask*0x0001020304050608ul >> 56; +} + +#else /* 32-bit case */ + +/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ +static inline long count_masked_bytes(long mask) +{ + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + long a = (0x0ff0001+mask) >> 23; + /* Fix the 1 for 00 case */ + return a & mask; +} + +#endif + +/* Return nonzero if it has a zero */ +static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) +{ + unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; + *bits = mask; + return mask; +} + +static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) +{ + return bits; +} + +static inline unsigned long create_zero_mask(unsigned long bits) +{ + bits = (bits - 1) & ~bits; + return bits >> 7; +} + +/* The mask we created is directly usable as a bytemask */ +#define zero_bytemask(mask) (mask) + +static inline unsigned long find_zero(unsigned long mask) +{ + return count_masked_bytes(mask); +} + +#endif /* __BIG_ENDIAN */ + #endif /* _ASM_WORD_AT_A_TIME_H */ -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 2/3] string: provide strscpy() 2015-07-08 20:20 ` [PATCH v2 " Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` [PATCH v2 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:54 ` Geert Uytterhoeven 2015-07-08 20:20 ` [PATCH v2 3/3] tile: use global strscpy() rather than private copy Chris Metcalf 3 siblings, 2 replies; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch The strscpy() API is intended to be used instead of strlcpy(), and instead of most uses of strncpy(). - Unlike strlcpy(), it doesn't read from memory beyond (src + size). - Unlike strlcpy() or strncpy(), the API provides an easy way to check for destination buffer overflow: an -E2BIG error return value. - The provided implementation is robust in the face of the source buffer being asynchronously changed during the copy, unlike the current implementation of strlcpy(). - Unlike strncpy(), the destination buffer will be NUL-terminated if the string in the source buffer is too long. - Also unlike strncpy(), the destination buffer will not be updated beyond the NUL termination, avoiding strncpy's behavior of zeroing the entire tail end of the destination buffer. (A memset() after the strscpy() can be used if this behavior is desired.) - The implementation should be reasonably performant on all platforms since it uses the asm/word-at-a-time.h API rather than simple byte copy. Kernel-to-kernel string copy is not considered to be performance critical in any case. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- include/linux/string.h | 3 ++ lib/string.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index e40099e585c9..213274a0d356 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -25,6 +25,9 @@ extern char * strncpy(char *,const char *, __kernel_size_t); #ifndef __HAVE_ARCH_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif +#ifndef __HAVE_ARCH_STRSCPY +ssize_t __must_check strscpy(char *, const char *, size_t); +#endif #ifndef __HAVE_ARCH_STRCAT extern char * strcat(char *, const char *); #endif diff --git a/lib/string.c b/lib/string.c index a5792019193c..0ff54eb78f52 100644 --- a/lib/string.c +++ b/lib/string.c @@ -27,6 +27,10 @@ #include <linux/bug.h> #include <linux/errno.h> +#include <asm/byteorder.h> +#include <asm/word-at-a-time.h> +#include <asm/page.h> + #ifndef __HAVE_ARCH_STRNCASECMP /** * strncasecmp - Case insensitive, length-limited string comparison @@ -146,6 +150,90 @@ size_t strlcpy(char *dest, const char *src, size_t size) EXPORT_SYMBOL(strlcpy); #endif +#ifndef __HAVE_ARCH_STRSCPY +/** + * strscpy - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. + * The routine returns the number of characters copied (not including + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. + * The behavior is undefined if the string buffers overlap. + * If the destination buffer isn't big enough, it is NUL terminated. + * + * Preferred to strlcpy() since the API doesn't require reading memory + * from the src string beyond the specified "count" bytes, and since + * the return value is easier to error-check than strlcpy()'s. + * In addition, the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation. + * + * Preferred to strncpy() since it always returns a valid string, and + * doesn't unnecessarily force the tail of the destination buffer to be + * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() + * with an overflow test, then just memset() the tail of the dest buffer. + */ +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; + size_t max = count; + long res = 0; + + if (count == 0) + return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* + * If src is unaligned, don't cross a page boundary, + * since we don't know if the next page is mapped. + */ + if ((long)src & (sizeof(long) - 1)) { + size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); + if (limit < max) + max = limit; + } +#else + /* If src or dest is unaligned, don't do word-at-a-time. */ + if (((long) dest | (long) src) & (sizeof(long) - 1)) + max = 0; +#endif + + while (max >= sizeof(unsigned long)) { + unsigned long c, data; + + c = *(unsigned long *)(src+res); + *(unsigned long *)(dest+res) = c; + if (has_zero(c, &data, &constants)) { + data = prep_zero_mask(c, data, &constants); + data = create_zero_mask(data); + return res + find_zero(data); + } + res += sizeof(unsigned long); + count -= sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +EXPORT_SYMBOL(strscpy); +#endif + #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 2/3] string: provide strscpy() 2015-07-08 20:20 ` [PATCH v2 2/3] string: provide strscpy() Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:54 ` Geert Uytterhoeven 1 sibling, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch The strscpy() API is intended to be used instead of strlcpy(), and instead of most uses of strncpy(). - Unlike strlcpy(), it doesn't read from memory beyond (src + size). - Unlike strlcpy() or strncpy(), the API provides an easy way to check for destination buffer overflow: an -E2BIG error return value. - The provided implementation is robust in the face of the source buffer being asynchronously changed during the copy, unlike the current implementation of strlcpy(). - Unlike strncpy(), the destination buffer will be NUL-terminated if the string in the source buffer is too long. - Also unlike strncpy(), the destination buffer will not be updated beyond the NUL termination, avoiding strncpy's behavior of zeroing the entire tail end of the destination buffer. (A memset() after the strscpy() can be used if this behavior is desired.) - The implementation should be reasonably performant on all platforms since it uses the asm/word-at-a-time.h API rather than simple byte copy. Kernel-to-kernel string copy is not considered to be performance critical in any case. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- include/linux/string.h | 3 ++ lib/string.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index e40099e585c9..213274a0d356 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -25,6 +25,9 @@ extern char * strncpy(char *,const char *, __kernel_size_t); #ifndef __HAVE_ARCH_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif +#ifndef __HAVE_ARCH_STRSCPY +ssize_t __must_check strscpy(char *, const char *, size_t); +#endif #ifndef __HAVE_ARCH_STRCAT extern char * strcat(char *, const char *); #endif diff --git a/lib/string.c b/lib/string.c index a5792019193c..0ff54eb78f52 100644 --- a/lib/string.c +++ b/lib/string.c @@ -27,6 +27,10 @@ #include <linux/bug.h> #include <linux/errno.h> +#include <asm/byteorder.h> +#include <asm/word-at-a-time.h> +#include <asm/page.h> + #ifndef __HAVE_ARCH_STRNCASECMP /** * strncasecmp - Case insensitive, length-limited string comparison @@ -146,6 +150,90 @@ size_t strlcpy(char *dest, const char *src, size_t size) EXPORT_SYMBOL(strlcpy); #endif +#ifndef __HAVE_ARCH_STRSCPY +/** + * strscpy - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. + * The routine returns the number of characters copied (not including + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. + * The behavior is undefined if the string buffers overlap. + * If the destination buffer isn't big enough, it is NUL terminated. + * + * Preferred to strlcpy() since the API doesn't require reading memory + * from the src string beyond the specified "count" bytes, and since + * the return value is easier to error-check than strlcpy()'s. + * In addition, the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation. + * + * Preferred to strncpy() since it always returns a valid string, and + * doesn't unnecessarily force the tail of the destination buffer to be + * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() + * with an overflow test, then just memset() the tail of the dest buffer. + */ +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; + size_t max = count; + long res = 0; + + if (count == 0) + return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* + * If src is unaligned, don't cross a page boundary, + * since we don't know if the next page is mapped. + */ + if ((long)src & (sizeof(long) - 1)) { + size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); + if (limit < max) + max = limit; + } +#else + /* If src or dest is unaligned, don't do word-at-a-time. */ + if (((long) dest | (long) src) & (sizeof(long) - 1)) + max = 0; +#endif + + while (max >= sizeof(unsigned long)) { + unsigned long c, data; + + c = *(unsigned long *)(src+res); + *(unsigned long *)(dest+res) = c; + if (has_zero(c, &data, &constants)) { + data = prep_zero_mask(c, data, &constants); + data = create_zero_mask(data); + return res + find_zero(data); + } + res += sizeof(unsigned long); + count -= sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +EXPORT_SYMBOL(strscpy); +#endif + #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/3] string: provide strscpy() 2015-07-08 20:20 ` [PATCH v2 2/3] string: provide strscpy() Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf @ 2015-07-08 20:54 ` Geert Uytterhoeven 1 sibling, 0 replies; 27+ messages in thread From: Geert Uytterhoeven @ 2015-07-08 20:54 UTC (permalink / raw) To: Chris Metcalf Cc: Linus Torvalds, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, Greg KH, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Michael Ellerman, Linux Kernel Mailing List, Linux-Arch Hi Chris, On Wed, Jul 8, 2015 at 10:20 PM, Chris Metcalf <cmetcalf@ezchip.com> wrote: > + * strscpy - Copy a C-string into a sized buffer > + * @dest: Where to copy the string to > + * @src: Where to copy the string from > + * @count: Size of destination buffer > + * > + * Copy the string, or as much of it as fits, into the dest buffer. > + * The routine returns the number of characters copied (not including > + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. > + * The behavior is undefined if the string buffers overlap. > + * If the destination buffer isn't big enough, it is NUL terminated. ... unless count is zero and it's also NUL terminated if it is big enough ;-) Perhaps "The destination buffer is always NUL terminated, unless it's zero-sized." > + * > + * Preferred to strlcpy() since the API doesn't require reading memory > + * from the src string beyond the specified "count" bytes, and since > + * the return value is easier to error-check than strlcpy()'s. > + * In addition, the implementation is robust to the string changing out > + * from underneath it, unlike the current strlcpy() implementation. > + * > + * Preferred to strncpy() since it always returns a valid string, and > + * doesn't unnecessarily force the tail of the destination buffer to be > + * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() > + * with an overflow test, then just memset() the tail of the dest buffer. > + */ > +ssize_t strscpy(char *dest, const char *src, size_t count) > +{ > + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; > + size_t max = count; > + long res = 0; > + > + if (count == 0) > + return -E2BIG; Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 3/3] tile: use global strscpy() rather than private copy 2015-07-08 20:20 ` [PATCH v2 " Chris Metcalf ` (2 preceding siblings ...) 2015-07-08 20:20 ` [PATCH v2 2/3] string: provide strscpy() Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 2015-07-08 20:20 ` Chris Metcalf 3 siblings, 1 reply; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch Now that strscpy() is a standard API, remove the local copy. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/tile/gxio/mpipe.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c index ee186e13dfe6..f102048d9c0e 100644 --- a/arch/tile/gxio/mpipe.c +++ b/arch/tile/gxio/mpipe.c @@ -19,6 +19,7 @@ #include <linux/errno.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/string.h> #include <gxio/iorpc_globals.h> #include <gxio/iorpc_mpipe.h> @@ -29,32 +30,6 @@ /* HACK: Avoid pointless "shadow" warnings. */ #define link link_shadow -/** - * strscpy - Copy a C-string into a sized buffer, but only if it fits - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Use this routine to avoid copying too-long strings. - * The routine returns the total number of bytes copied - * (including the trailing NUL) or zero if the buffer wasn't - * big enough. To ensure that programmers pay attention - * to the return code, the destination has a single NUL - * written at the front (if size is non-zero) when the - * buffer is not big enough. - */ -static size_t strscpy(char *dest, const char *src, size_t size) -{ - size_t len = strnlen(src, size) + 1; - if (len > size) { - if (size) - dest[0] = '\0'; - return 0; - } - memcpy(dest, src, len); - return len; -} - int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index) { char file[32]; @@ -540,7 +515,7 @@ int gxio_mpipe_link_instance(const char *link_name) if (!context) return GXIO_ERR_NO_DEVICE; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; return gxio_mpipe_info_instance_aux(context, name); @@ -559,7 +534,7 @@ int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac) rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac); if (rv >= 0) { - if (strscpy(link_name, name.name, sizeof(name.name)) == 0) + if (strscpy(link_name, name.name, sizeof(name.name)) < 0) return GXIO_ERR_INVAL_MEMORY_SIZE; memcpy(link_mac, mac.mac, sizeof(mac.mac)); } @@ -576,7 +551,7 @@ int gxio_mpipe_link_open(gxio_mpipe_link_t *link, _gxio_mpipe_link_name_t name; int rv; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; rv = gxio_mpipe_link_open_aux(context, name, flags); -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 3/3] tile: use global strscpy() rather than private copy 2015-07-08 20:20 ` [PATCH v2 3/3] tile: use global strscpy() rather than private copy Chris Metcalf @ 2015-07-08 20:20 ` Chris Metcalf 0 siblings, 0 replies; 27+ messages in thread From: Chris Metcalf @ 2015-07-08 20:20 UTC (permalink / raw) To: Linus Torvalds Cc: Chris Metcalf, Al Viro, Fabian Frederick, Randy Dunlap, Rickard Strandqvist, gregkh, Peter Zijlstra, David S. Miller, Frederic Weisbecker, Andrew Morton, Sam Ravnborg, Stephen Rothwell, Theodore Ts'o, Grant Likely, Dan Carpenter, Geert Uytterhoeven, Michael Ellerman, Linux Kernel Mailing List, linux-arch Now that strscpy() is a standard API, remove the local copy. Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> --- arch/tile/gxio/mpipe.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c index ee186e13dfe6..f102048d9c0e 100644 --- a/arch/tile/gxio/mpipe.c +++ b/arch/tile/gxio/mpipe.c @@ -19,6 +19,7 @@ #include <linux/errno.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/string.h> #include <gxio/iorpc_globals.h> #include <gxio/iorpc_mpipe.h> @@ -29,32 +30,6 @@ /* HACK: Avoid pointless "shadow" warnings. */ #define link link_shadow -/** - * strscpy - Copy a C-string into a sized buffer, but only if it fits - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Use this routine to avoid copying too-long strings. - * The routine returns the total number of bytes copied - * (including the trailing NUL) or zero if the buffer wasn't - * big enough. To ensure that programmers pay attention - * to the return code, the destination has a single NUL - * written at the front (if size is non-zero) when the - * buffer is not big enough. - */ -static size_t strscpy(char *dest, const char *src, size_t size) -{ - size_t len = strnlen(src, size) + 1; - if (len > size) { - if (size) - dest[0] = '\0'; - return 0; - } - memcpy(dest, src, len); - return len; -} - int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index) { char file[32]; @@ -540,7 +515,7 @@ int gxio_mpipe_link_instance(const char *link_name) if (!context) return GXIO_ERR_NO_DEVICE; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; return gxio_mpipe_info_instance_aux(context, name); @@ -559,7 +534,7 @@ int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac) rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac); if (rv >= 0) { - if (strscpy(link_name, name.name, sizeof(name.name)) == 0) + if (strscpy(link_name, name.name, sizeof(name.name)) < 0) return GXIO_ERR_INVAL_MEMORY_SIZE; memcpy(link_mac, mac.mac, sizeof(mac.mac)); } @@ -576,7 +551,7 @@ int gxio_mpipe_link_open(gxio_mpipe_link_t *link, _gxio_mpipe_link_name_t name; int rv; - if (strscpy(name.name, link_name, sizeof(name.name)) == 0) + if (strscpy(name.name, link_name, sizeof(name.name)) < 0) return GXIO_ERR_NO_DEVICE; rv = gxio_mpipe_link_open_aux(context, name, flags); -- 2.1.2 ^ permalink raw reply related [flat|nested] 27+ messages in thread
end of thread, other threads:[~2015-07-08 20:54 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CA+55aFwbRZe5gVsTyHvjKqE5eA3zQ_58_UQW7KACCt7V7FpZbQ@mail.gmail.com>
2015-04-30 16:01 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf
2015-04-30 16:01 ` [PATCH 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf
2015-04-30 16:01 ` Chris Metcalf
2015-04-30 16:01 ` [PATCH 2/3] string: provide strscpy() and strscpy_truncate() Chris Metcalf
2015-04-30 16:01 ` Chris Metcalf
2015-05-06 15:01 ` Dan Carpenter
2015-05-06 15:21 ` Chris Metcalf
2015-05-06 15:59 ` Dan Carpenter
2015-05-06 16:45 ` Geert Uytterhoeven
2015-05-07 9:00 ` Dan Carpenter
2015-05-07 15:10 ` Chris Metcalf
2015-04-30 16:01 ` [PATCH 3/3] tile: use global strscpy() rather than private copy Chris Metcalf
2015-04-30 16:01 ` Chris Metcalf
2015-05-11 15:37 ` [PATCH 0/3] add new strscpy() API for string copy Chris Metcalf
2015-05-14 23:10 ` Michael Ellerman
2015-05-15 15:15 ` Chris Metcalf
2015-05-18 1:13 ` Michael Ellerman
2015-05-26 19:33 ` Chris Metcalf
[not found] ` <CA+55aFwokKo9X4=wwZ1sKLmLfye=a65KPzMhe-QzuHT6Prp0tA@mail.gmail.com>
2015-07-08 20:20 ` [PATCH v2 " Chris Metcalf
2015-07-08 20:20 ` Chris Metcalf
2015-07-08 20:20 ` [PATCH v2 1/3] Make asm/word-at-a-time.h available on all architectures Chris Metcalf
2015-07-08 20:20 ` Chris Metcalf
2015-07-08 20:20 ` [PATCH v2 2/3] string: provide strscpy() Chris Metcalf
2015-07-08 20:20 ` Chris Metcalf
2015-07-08 20:54 ` Geert Uytterhoeven
2015-07-08 20:20 ` [PATCH v2 3/3] tile: use global strscpy() rather than private copy Chris Metcalf
2015-07-08 20:20 ` Chris Metcalf
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).