aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/sparc/include/asm/processor_64.h4
-rw-r--r--arch/sparc/include/asm/thread_info_32.h11
-rw-r--r--arch/sparc/include/asm/uaccess.h6
-rw-r--r--arch/sparc/include/asm/uaccess_32.h10
-rw-r--r--arch/sparc/include/asm/uaccess_64.h4
-rw-r--r--arch/sparc/lib/Makefile2
-rw-r--r--arch/sparc/lib/ksyms.c3
-rw-r--r--arch/sparc/lib/strncpy_from_user_32.S47
-rw-r--r--arch/sparc/lib/strncpy_from_user_64.S133
-rw-r--r--arch/sparc/lib/usercopy.c1
-rw-r--r--arch/sparc/mm/srmmu.c27
-rw-r--r--arch/x86/include/asm/word-at-a-time.h4
-rw-r--r--fs/namei.c1
-rw-r--r--include/linux/kernel.h2
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/strncpy_from_user.c146
18 files changed, 170 insertions, 238 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 2d493a3bdfe1..15e9e05740da 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -34,12 +34,12 @@ config SPARC
34 select GENERIC_SMP_IDLE_THREAD 34 select GENERIC_SMP_IDLE_THREAD
35 select GENERIC_CMOS_UPDATE 35 select GENERIC_CMOS_UPDATE
36 select GENERIC_CLOCKEVENTS 36 select GENERIC_CLOCKEVENTS
37 select GENERIC_STRNCPY_FROM_USER
37 38
38config SPARC32 39config SPARC32
39 def_bool !64BIT 40 def_bool !64BIT
40 select GENERIC_ATOMIC64 41 select GENERIC_ATOMIC64
41 select CLZ_TAB 42 select CLZ_TAB
42 select ARCH_THREAD_INFO_ALLOCATOR
43 select ARCH_USES_GETTIMEOFFSET 43 select ARCH_USES_GETTIMEOFFSET
44 44
45config SPARC64 45config SPARC64
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index 67df5cc10011..4e5a483122a0 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -42,7 +42,9 @@
42#define TASK_SIZE_OF(tsk) \ 42#define TASK_SIZE_OF(tsk) \
43 (test_tsk_thread_flag(tsk,TIF_32BIT) ? \ 43 (test_tsk_thread_flag(tsk,TIF_32BIT) ? \
44 (1UL << 32UL) : ((unsigned long)-VPTE_SIZE)) 44 (1UL << 32UL) : ((unsigned long)-VPTE_SIZE))
45#define TASK_SIZE TASK_SIZE_OF(current) 45#define TASK_SIZE \
46 (test_thread_flag(TIF_32BIT) ? \
47 (1UL << 32UL) : ((unsigned long)-VPTE_SIZE))
46#ifdef __KERNEL__ 48#ifdef __KERNEL__
47 49
48#define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE) 50#define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE)
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index 21a38946541d..5af664932452 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -77,18 +77,11 @@ register struct thread_info *current_thread_info_reg asm("g6");
77/* 77/*
78 * thread information allocation 78 * thread information allocation
79 */ 79 */
80#define THREAD_INFO_ORDER 1 80#define THREAD_SIZE_ORDER 1
81
82struct thread_info * alloc_thread_info_node(struct task_struct *tsk, int node);
83void free_thread_info(struct thread_info *);
84 81
85#endif /* __ASSEMBLY__ */ 82#endif /* __ASSEMBLY__ */
86 83
87/* 84/* Size of kernel stack for each process */
88 * Size of kernel stack for each process.
89 * Observe the order of get_free_pages() in alloc_thread_info_node().
90 * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste.
91 */
92#define THREAD_SIZE (2 * PAGE_SIZE) 85#define THREAD_SIZE (2 * PAGE_SIZE)
93 86
94/* 87/*
diff --git a/arch/sparc/include/asm/uaccess.h b/arch/sparc/include/asm/uaccess.h
index e88fbe5c0457..0167d26d0d1d 100644
--- a/arch/sparc/include/asm/uaccess.h
+++ b/arch/sparc/include/asm/uaccess.h
@@ -5,4 +5,10 @@
5#else 5#else
6#include <asm/uaccess_32.h> 6#include <asm/uaccess_32.h>
7#endif 7#endif
8
9#define user_addr_max() \
10 (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL)
11
12extern long strncpy_from_user(char *dest, const char __user *src, long count);
13
8#endif 14#endif
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h
index d50c310f5d38..59586b57ef1a 100644
--- a/arch/sparc/include/asm/uaccess_32.h
+++ b/arch/sparc/include/asm/uaccess_32.h
@@ -304,16 +304,6 @@ static inline unsigned long clear_user(void __user *addr, unsigned long n)
304 return n; 304 return n;
305} 305}
306 306
307extern long __strncpy_from_user(char *dest, const char __user *src, long count);
308
309static inline long strncpy_from_user(char *dest, const char __user *src, long count)
310{
311 if (__access_ok((unsigned long) src, count))
312 return __strncpy_from_user(dest, src, count);
313 else
314 return -EFAULT;
315}
316
317extern long __strlen_user(const char __user *); 307extern long __strlen_user(const char __user *);
318extern long __strnlen_user(const char __user *, long len); 308extern long __strnlen_user(const char __user *, long len);
319 309
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index a1091afb8831..dcdfb89cbf3f 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -257,10 +257,6 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long);
257 257
258#define clear_user __clear_user 258#define clear_user __clear_user
259 259
260extern long __must_check __strncpy_from_user(char *dest, const char __user *src, long count);
261
262#define strncpy_from_user __strncpy_from_user
263
264extern long __strlen_user(const char __user *); 260extern long __strlen_user(const char __user *);
265extern long __strnlen_user(const char __user *, long len); 261extern long __strnlen_user(const char __user *, long len);
266 262
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 389628f50a15..943d98dc4cdb 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -10,7 +10,7 @@ lib-y += strlen.o
10lib-y += checksum_$(BITS).o 10lib-y += checksum_$(BITS).o
11lib-$(CONFIG_SPARC32) += blockops.o 11lib-$(CONFIG_SPARC32) += blockops.o
12lib-y += memscan_$(BITS).o memcmp.o strncmp_$(BITS).o 12lib-y += memscan_$(BITS).o memcmp.o strncmp_$(BITS).o
13lib-y += strncpy_from_user_$(BITS).o strlen_user_$(BITS).o 13lib-y += strlen_user_$(BITS).o
14lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o 14lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
15lib-$(CONFIG_SPARC32) += copy_user.o locks.o 15lib-$(CONFIG_SPARC32) += copy_user.o locks.o
16lib-$(CONFIG_SPARC64) += atomic_64.o 16lib-$(CONFIG_SPARC64) += atomic_64.o
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c
index 2dc30875c8bc..6b278abdb63d 100644
--- a/arch/sparc/lib/ksyms.c
+++ b/arch/sparc/lib/ksyms.c
@@ -33,9 +33,6 @@ EXPORT_SYMBOL(memset);
33EXPORT_SYMBOL(memmove); 33EXPORT_SYMBOL(memmove);
34EXPORT_SYMBOL(__bzero); 34EXPORT_SYMBOL(__bzero);
35 35
36/* Moving data to/from/in userspace. */
37EXPORT_SYMBOL(__strncpy_from_user);
38
39/* Networking helper routines. */ 36/* Networking helper routines. */
40EXPORT_SYMBOL(csum_partial); 37EXPORT_SYMBOL(csum_partial);
41 38
diff --git a/arch/sparc/lib/strncpy_from_user_32.S b/arch/sparc/lib/strncpy_from_user_32.S
deleted file mode 100644
index db0ed2964bdb..000000000000
--- a/arch/sparc/lib/strncpy_from_user_32.S
+++ /dev/null
@@ -1,47 +0,0 @@
1/* strncpy_from_user.S: Sparc strncpy from userspace.
2 *
3 * Copyright(C) 1996 David S. Miller
4 */
5
6#include <linux/linkage.h>
7#include <asm/ptrace.h>
8#include <asm/errno.h>
9
10 .text
11
12 /* Must return:
13 *
14 * -EFAULT for an exception
15 * count if we hit the buffer limit
16 * bytes copied if we hit a null byte
17 */
18
19ENTRY(__strncpy_from_user)
20 /* %o0=dest, %o1=src, %o2=count */
21 mov %o2, %o3
221:
23 subcc %o2, 1, %o2
24 bneg 2f
25 nop
2610:
27 ldub [%o1], %o4
28 add %o0, 1, %o0
29 cmp %o4, 0
30 add %o1, 1, %o1
31 bne 1b
32 stb %o4, [%o0 - 1]
332:
34 add %o2, 1, %o0
35 retl
36 sub %o3, %o0, %o0
37ENDPROC(__strncpy_from_user)
38
39 .section .fixup,#alloc,#execinstr
40 .align 4
414:
42 retl
43 mov -EFAULT, %o0
44
45 .section __ex_table,#alloc
46 .align 4
47 .word 10b, 4b
diff --git a/arch/sparc/lib/strncpy_from_user_64.S b/arch/sparc/lib/strncpy_from_user_64.S
deleted file mode 100644
index d1246b713077..000000000000
--- a/arch/sparc/lib/strncpy_from_user_64.S
+++ /dev/null
@@ -1,133 +0,0 @@
1/*
2 * strncpy_from_user.S: Sparc64 strncpy from userspace.
3 *
4 * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
5 */
6
7#include <linux/linkage.h>
8#include <asm/asi.h>
9#include <asm/errno.h>
10
11 .data
12 .align 8
130: .xword 0x0101010101010101
14
15 .text
16
17 /* Must return:
18 *
19 * -EFAULT for an exception
20 * count if we hit the buffer limit
21 * bytes copied if we hit a null byte
22 * (without the null byte)
23 *
24 * This implementation assumes:
25 * %o1 is 8 aligned => !(%o2 & 7)
26 * %o0 is 8 aligned (if not, it will be slooooow, but will work)
27 *
28 * This is optimized for the common case:
29 * in my stats, 90% of src are 8 aligned (even on sparc32)
30 * and average length is 18 or so.
31 */
32
33ENTRY(__strncpy_from_user)
34 /* %o0=dest, %o1=src, %o2=count */
35 andcc %o1, 7, %g0 ! IEU1 Group
36 bne,pn %icc, 30f ! CTI
37 add %o0, %o2, %g3 ! IEU0
3860: ldxa [%o1] %asi, %g1 ! Load Group
39 brlez,pn %o2, 10f ! CTI
40 mov %o0, %o3 ! IEU0
4150: sethi %hi(0b), %o4 ! IEU0 Group
42 ldx [%o4 + %lo(0b)], %o4 ! Load
43 sllx %o4, 7, %o5 ! IEU1 Group
441: sub %g1, %o4, %g2 ! IEU0 Group
45 stx %g1, [%o0] ! Store
46 add %o0, 8, %o0 ! IEU1
47 andcc %g2, %o5, %g0 ! IEU1 Group
48 bne,pn %xcc, 5f ! CTI
49 add %o1, 8, %o1 ! IEU0
50 cmp %o0, %g3 ! IEU1 Group
51 bl,a,pt %xcc, 1b ! CTI
5261: ldxa [%o1] %asi, %g1 ! Load
5310: retl ! CTI Group
54 mov %o2, %o0 ! IEU0
555: srlx %g2, 32, %g7 ! IEU0 Group
56 sethi %hi(0xff00), %o4 ! IEU1
57 andcc %g7, %o5, %g0 ! IEU1 Group
58 be,pn %icc, 2f ! CTI
59 or %o4, %lo(0xff00), %o4 ! IEU0
60 srlx %g1, 48, %g7 ! IEU0 Group
61 andcc %g7, %o4, %g0 ! IEU1 Group
62 be,pn %icc, 50f ! CTI
63 andcc %g7, 0xff, %g0 ! IEU1 Group
64 be,pn %icc, 51f ! CTI
65 srlx %g1, 32, %g7 ! IEU0
66 andcc %g7, %o4, %g0 ! IEU1 Group
67 be,pn %icc, 52f ! CTI
68 andcc %g7, 0xff, %g0 ! IEU1 Group
69 be,pn %icc, 53f ! CTI
702: andcc %g2, %o5, %g0 ! IEU1 Group
71 be,pn %icc, 2f ! CTI
72 srl %g1, 16, %g7 ! IEU0
73 andcc %g7, %o4, %g0 ! IEU1 Group
74 be,pn %icc, 54f ! CTI
75 andcc %g7, 0xff, %g0 ! IEU1 Group
76 be,pn %icc, 55f ! CTI
77 andcc %g1, %o4, %g0 ! IEU1 Group
78 be,pn %icc, 56f ! CTI
79 andcc %g1, 0xff, %g0 ! IEU1 Group
80 be,a,pn %icc, 57f ! CTI
81 sub %o0, %o3, %o0 ! IEU0
822: cmp %o0, %g3 ! IEU1 Group
83 bl,a,pt %xcc, 50b ! CTI
8462: ldxa [%o1] %asi, %g1 ! Load
85 retl ! CTI Group
86 mov %o2, %o0 ! IEU0
8750: sub %o0, %o3, %o0
88 retl
89 sub %o0, 8, %o0
9051: sub %o0, %o3, %o0
91 retl
92 sub %o0, 7, %o0
9352: sub %o0, %o3, %o0
94 retl
95 sub %o0, 6, %o0
9653: sub %o0, %o3, %o0
97 retl
98 sub %o0, 5, %o0
9954: sub %o0, %o3, %o0
100 retl
101 sub %o0, 4, %o0
10255: sub %o0, %o3, %o0
103 retl
104 sub %o0, 3, %o0
10556: sub %o0, %o3, %o0
106 retl
107 sub %o0, 2, %o0
10857: retl
109 sub %o0, 1, %o0
11030: brlez,pn %o2, 3f
111 sub %g0, %o2, %o3
112 add %o0, %o2, %o0
11363: lduba [%o1] %asi, %o4
1141: add %o1, 1, %o1
115 brz,pn %o4, 2f
116 stb %o4, [%o0 + %o3]
117 addcc %o3, 1, %o3
118 bne,pt %xcc, 1b
11964: lduba [%o1] %asi, %o4
1203: retl
121 mov %o2, %o0
1222: retl
123 add %o2, %o3, %o0
124ENDPROC(__strncpy_from_user)
125
126 .section __ex_table,"a"
127 .align 4
128 .word 60b, __retl_efault
129 .word 61b, __retl_efault
130 .word 62b, __retl_efault
131 .word 63b, __retl_efault
132 .word 64b, __retl_efault
133 .previous
diff --git a/arch/sparc/lib/usercopy.c b/arch/sparc/lib/usercopy.c
index 14b363fec8a2..5c4284ce1c03 100644
--- a/arch/sparc/lib/usercopy.c
+++ b/arch/sparc/lib/usercopy.c
@@ -1,4 +1,5 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/kernel.h>
2#include <linux/bug.h> 3#include <linux/bug.h>
3 4
4void copy_from_user_overflow(void) 5void copy_from_user_overflow(void)
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 8e97e0305b01..256db6b22c54 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -467,33 +467,6 @@ void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
467 flush_tlb_all(); 467 flush_tlb_all();
468} 468}
469 469
470/*
471 * On the SRMMU we do not have the problems with limited tlb entries
472 * for mapping kernel pages, so we just take things from the free page
473 * pool. As a side effect we are putting a little too much pressure
474 * on the gfp() subsystem. This setup also makes the logic of the
475 * iommu mapping code a lot easier as we can transparently handle
476 * mappings on the kernel stack without any special code.
477 */
478struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
479{
480 struct thread_info *ret;
481
482 ret = (struct thread_info *)__get_free_pages(GFP_KERNEL,
483 THREAD_INFO_ORDER);
484#ifdef CONFIG_DEBUG_STACK_USAGE
485 if (ret)
486 memset(ret, 0, PAGE_SIZE << THREAD_INFO_ORDER);
487#endif /* DEBUG_STACK_USAGE */
488
489 return ret;
490}
491
492void free_thread_info(struct thread_info *ti)
493{
494 free_pages((unsigned long)ti, THREAD_INFO_ORDER);
495}
496
497/* tsunami.S */ 470/* tsunami.S */
498extern void tsunami_flush_cache_all(void); 471extern void tsunami_flush_cache_all(void);
499extern void tsunami_flush_cache_mm(struct mm_struct *mm); 472extern void tsunami_flush_cache_mm(struct mm_struct *mm);
diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h
index e58f03b206c3..ae03facfadd6 100644
--- a/arch/x86/include/asm/word-at-a-time.h
+++ b/arch/x86/include/asm/word-at-a-time.h
@@ -1,6 +1,8 @@
1#ifndef _ASM_WORD_AT_A_TIME_H 1#ifndef _ASM_WORD_AT_A_TIME_H
2#define _ASM_WORD_AT_A_TIME_H 2#define _ASM_WORD_AT_A_TIME_H
3 3
4#include <linux/kernel.h>
5
4/* 6/*
5 * This is largely generic for little-endian machines, but the 7 * This is largely generic for little-endian machines, but the
6 * optimal byte mask counting is probably going to be something 8 * optimal byte mask counting is probably going to be something
@@ -35,8 +37,6 @@ static inline long count_masked_bytes(long mask)
35 37
36#endif 38#endif
37 39
38#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
39
40/* Return the high bit set in the first byte that is a zero */ 40/* Return the high bit set in the first byte that is a zero */
41static inline unsigned long has_zero(unsigned long a) 41static inline unsigned long has_zero(unsigned long a)
42{ 42{
diff --git a/fs/namei.c b/fs/namei.c
index e70ebab9624b..93ff12b1a1de 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/export.h> 18#include <linux/export.h>
19#include <linux/kernel.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
20#include <linux/fs.h> 21#include <linux/fs.h>
21#include <linux/namei.h> 22#include <linux/namei.h>
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index c0d34420a913..ec55a3c8ba77 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -38,6 +38,8 @@
38 38
39#define STACK_MAGIC 0xdeadbeef 39#define STACK_MAGIC 0xdeadbeef
40 40
41#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
42
41#define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) 43#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
42#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask)) 44#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
43#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) 45#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
diff --git a/lib/Kconfig b/lib/Kconfig
index 0e25c03939e3..98230ac3db29 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -16,6 +16,9 @@ config BITREVERSE
16config RATIONAL 16config RATIONAL
17 boolean 17 boolean
18 18
19config GENERIC_STRNCPY_FROM_USER
20 bool
21
19config GENERIC_FIND_FIRST_BIT 22config GENERIC_FIND_FIRST_BIT
20 bool 23 bool
21 24
diff --git a/lib/Makefile b/lib/Makefile
index 74290c9e2864..b98df505f335 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -125,6 +125,8 @@ obj-$(CONFIG_CLZ_TAB) += clz_tab.o
125 125
126obj-$(CONFIG_DDR) += jedec_ddr_data.o 126obj-$(CONFIG_DDR) += jedec_ddr_data.o
127 127
128obj-$(CONFIG_GENERIC_STRNCPY_FROM_USER) += strncpy_from_user.o
129
128hostprogs-y := gen_crc32table 130hostprogs-y := gen_crc32table
129clean-files := crc32table.h 131clean-files := crc32table.h
130 132
diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c
new file mode 100644
index 000000000000..c4c09b0e96ba
--- /dev/null
+++ b/lib/strncpy_from_user.c
@@ -0,0 +1,146 @@
1#include <linux/module.h>
2#include <linux/uaccess.h>
3#include <linux/kernel.h>
4#include <linux/errno.h>
5
6#include <asm/byteorder.h>
7
8static inline long find_zero(unsigned long mask)
9{
10 long byte = 0;
11
12#ifdef __BIG_ENDIAN
13#ifdef CONFIG_64BIT
14 if (mask >> 32)
15 mask >>= 32;
16 else
17 byte = 4;
18#endif
19 if (mask >> 16)
20 mask >>= 16;
21 else
22 byte += 2;
23 return (mask >> 8) ? byte : byte + 1;
24#else
25#ifdef CONFIG_64BIT
26 if (!((unsigned int) mask)) {
27 mask >>= 32;
28 byte = 4;
29 }
30#endif
31 if (!(mask & 0xffff)) {
32 mask >>= 16;
33 byte += 2;
34 }
35 return (mask & 0xff) ? byte : byte + 1;
36#endif
37}
38
39#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
40#define IS_UNALIGNED(src, dst) 0
41#else
42#define IS_UNALIGNED(src, dst) \
43 (((long) dst | (long) src) & (sizeof(long) - 1))
44#endif
45
46/*
47 * Do a strncpy, return length of string without final '\0'.
48 * 'count' is the user-supplied count (return 'count' if we
49 * hit it), 'max' is the address space maximum (and we return
50 * -EFAULT if we hit it).
51 */
52static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
53{
54 const unsigned long high_bits = REPEAT_BYTE(0xfe) + 1;
55 const unsigned long low_bits = REPEAT_BYTE(0x7f);
56 long res = 0;
57
58 /*
59 * Truncate 'max' to the user-specified limit, so that
60 * we only have one limit we need to check in the loop
61 */
62 if (max > count)
63 max = count;
64
65 if (IS_UNALIGNED(src, dst))
66 goto byte_at_a_time;
67
68 while (max >= sizeof(unsigned long)) {
69 unsigned long c, v, rhs;
70
71 /* Fall back to byte-at-a-time if we get a page fault */
72 if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
73 break;
74 rhs = c | low_bits;
75 v = (c + high_bits) & ~rhs;
76 *(unsigned long *)(dst+res) = c;
77 if (v) {
78 v = (c & low_bits) + low_bits;
79 v = ~(v | rhs);
80 return res + find_zero(v);
81 }
82 res += sizeof(unsigned long);
83 max -= sizeof(unsigned long);
84 }
85
86byte_at_a_time:
87 while (max) {
88 char c;
89
90 if (unlikely(__get_user(c,src+res)))
91 return -EFAULT;
92 dst[res] = c;
93 if (!c)
94 return res;
95 res++;
96 max--;
97 }
98
99 /*
100 * Uhhuh. We hit 'max'. But was that the user-specified maximum
101 * too? If so, that's ok - we got as much as the user asked for.
102 */
103 if (res >= count)
104 return res;
105
106 /*
107 * Nope: we hit the address space limit, and we still had more
108 * characters the caller would have wanted. That's an EFAULT.
109 */
110 return -EFAULT;
111}
112
113/**
114 * strncpy_from_user: - Copy a NUL terminated string from userspace.
115 * @dst: Destination address, in kernel space. This buffer must be at
116 * least @count bytes long.
117 * @src: Source address, in user space.
118 * @count: Maximum number of bytes to copy, including the trailing NUL.
119 *
120 * Copies a NUL-terminated string from userspace to kernel space.
121 *
122 * On success, returns the length of the string (not including the trailing
123 * NUL).
124 *
125 * If access to userspace fails, returns -EFAULT (some data may have been
126 * copied).
127 *
128 * If @count is smaller than the length of the string, copies @count bytes
129 * and returns @count.
130 */
131long strncpy_from_user(char *dst, const char __user *src, long count)
132{
133 unsigned long max_addr, src_addr;
134
135 if (unlikely(count <= 0))
136 return 0;
137
138 max_addr = user_addr_max();
139 src_addr = (unsigned long)src;
140 if (likely(src_addr < max_addr)) {
141 unsigned long max = max_addr - src_addr;
142 return do_strncpy_from_user(dst, src, count, max);
143 }
144 return -EFAULT;
145}
146EXPORT_SYMBOL(strncpy_from_user);