Эх сурвалжийг харах

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
Linus Torvalds 10 жил өмнө
parent
commit
79c7c7acd2

+ 2 - 0
arch/alpha/include/asm/word-at-a-time.h

@@ -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 */

+ 1 - 0
arch/h8300/include/asm/Kbuild

@@ -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

+ 0 - 1
arch/powerpc/include/asm/Kbuild

@@ -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

+ 0 - 1
arch/tile/include/asm/Kbuild

@@ -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

+ 7 - 1
arch/tile/include/asm/word-at-a-time.h

@@ -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)
 #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 */

+ 2 - 1
lib/string.c

@@ -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);