Commit 79c7c7ac authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'strscpy' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile

Pull strscpy fixes from Chris Metcalf :
 "This patch series fixes up a couple of architecture issues where
  strscpy wasn't configured correctly (missing on h8300, duplicating
  local and asm-generic copies on powerpc and tile).

  It also adds a use of zero_bytemask() to the final store for strscpy
  to avoid writing uninitialized data to the destination.  However, to
  make this work we had to add support for zero_bytemask() to the two
  architectures that didn't have it (alpha and tile), because they were
  providing their own local copies, but didn't provide the
  zero_bytemask() that was previously only required when building with
  CONFIG_DCACHE_WORD_ACCESS"

[ Side note: there is still no actual users of strscpy except for the
  one preexisting use in arch/tile that predates the generic version.
  So this is all about fixing the infrastructure so that we eventually
  can start using it.  - Linus ]

* 'strscpy' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  strscpy: zero any trailing garbage bytes in the destination
  word-at-a-time.h: support zero_bytemask() on alpha and tile
  word-at-a-time.h: fix some Kbuild files
parents 3f5e4a31 990486c8
...@@ -52,4 +52,6 @@ static inline unsigned long find_zero(unsigned long bits) ...@@ -52,4 +52,6 @@ static inline unsigned long find_zero(unsigned long bits)
#endif #endif
} }
#define zero_bytemask(mask) ((2ul << (find_zero(mask) * 8)) - 1)
#endif /* _ASM_WORD_AT_A_TIME_H */ #endif /* _ASM_WORD_AT_A_TIME_H */
...@@ -73,4 +73,5 @@ generic-y += uaccess.h ...@@ -73,4 +73,5 @@ generic-y += uaccess.h
generic-y += ucontext.h generic-y += ucontext.h
generic-y += unaligned.h generic-y += unaligned.h
generic-y += vga.h generic-y += vga.h
generic-y += word-at-a-time.h
generic-y += xor.h generic-y += xor.h
...@@ -7,4 +7,3 @@ generic-y += mcs_spinlock.h ...@@ -7,4 +7,3 @@ generic-y += mcs_spinlock.h
generic-y += preempt.h generic-y += preempt.h
generic-y += rwsem.h generic-y += rwsem.h
generic-y += vtime.h generic-y += vtime.h
generic-y += word-at-a-time.h
...@@ -40,5 +40,4 @@ generic-y += termbits.h ...@@ -40,5 +40,4 @@ generic-y += termbits.h
generic-y += termios.h generic-y += termios.h
generic-y += trace_clock.h generic-y += trace_clock.h
generic-y += types.h generic-y += types.h
generic-y += word-at-a-time.h
generic-y += xor.h generic-y += xor.h
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
struct word_at_a_time { /* unused */ }; struct word_at_a_time { /* unused */ };
#define WORD_AT_A_TIME_CONSTANTS {} #define WORD_AT_A_TIME_CONSTANTS {}
/* Generate 0x01 byte values for non-zero bytes using a SIMD instruction. */ /* Generate 0x01 byte values for zero bytes using a SIMD instruction. */
static inline unsigned long has_zero(unsigned long val, unsigned long *data, static inline unsigned long has_zero(unsigned long val, unsigned long *data,
const struct word_at_a_time *c) const struct word_at_a_time *c)
{ {
...@@ -33,4 +33,10 @@ static inline long find_zero(unsigned long mask) ...@@ -33,4 +33,10 @@ static inline long find_zero(unsigned long mask)
#endif #endif
} }
#ifdef __BIG_ENDIAN
#define zero_bytemask(mask) (~1ul << (63 - __builtin_clzl(mask)))
#else
#define zero_bytemask(mask) ((2ul << __builtin_ctzl(mask)) - 1)
#endif
#endif /* _ASM_WORD_AT_A_TIME_H */ #endif /* _ASM_WORD_AT_A_TIME_H */
...@@ -203,12 +203,13 @@ ssize_t strscpy(char *dest, const char *src, size_t count) ...@@ -203,12 +203,13 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
unsigned long c, data; unsigned long c, data;
c = *(unsigned long *)(src+res); c = *(unsigned long *)(src+res);
*(unsigned long *)(dest+res) = c;
if (has_zero(c, &data, &constants)) { if (has_zero(c, &data, &constants)) {
data = prep_zero_mask(c, data, &constants); data = prep_zero_mask(c, data, &constants);
data = create_zero_mask(data); data = create_zero_mask(data);
*(unsigned long *)(dest+res) = c & zero_bytemask(data);
return res + find_zero(data); return res + find_zero(data);
} }
*(unsigned long *)(dest+res) = c;
res += sizeof(unsigned long); res += sizeof(unsigned long);
count -= sizeof(unsigned long); count -= sizeof(unsigned long);
max -= sizeof(unsigned long); max -= sizeof(unsigned long);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment