Branch data Line data Source code
1 : : #include <linux/kernel.h>
2 : : #include <linux/export.h>
3 : : #include <linux/uaccess.h>
4 : :
5 : : #include <asm/word-at-a-time.h>
6 : :
7 : : /* Set bits in the first 'n' bytes when loaded from memory */
8 : : #ifdef __LITTLE_ENDIAN
9 : : # define aligned_byte_mask(n) ((1ul << 8*(n))-1)
10 : : #else
11 : : # define aligned_byte_mask(n) (~0xfful << (BITS_PER_LONG - 8 - 8*(n)))
12 : : #endif
13 : :
14 : : /*
15 : : * Do a strnlen, return length of string *with* final '\0'.
16 : : * 'count' is the user-supplied count, while 'max' is the
17 : : * address space maximum.
18 : : *
19 : : * Return 0 for exceptions (which includes hitting the address
20 : : * space maximum), or 'count+1' if hitting the user-supplied
21 : : * maximum count.
22 : : *
23 : : * NOTE! We can sometimes overshoot the user-supplied maximum
24 : : * if it fits in a aligned 'long'. The caller needs to check
25 : : * the return value against "> max".
26 : : */
27 : : static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max)
28 : : {
29 : : const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
30 : : long align, res = 0;
31 : : unsigned long c;
32 : :
33 : : /*
34 : : * Truncate 'max' to the user-specified limit, so that
35 : : * we only have one limit we need to check in the loop
36 : : */
37 [ + + ]: 3116397 : if (max > count)
38 : : max = count;
39 : :
40 : : /*
41 : : * Do everything aligned. But that means that we
42 : : * need to also expand the maximum..
43 : : */
44 : 3116397 : align = (sizeof(long) - 1) & (unsigned long)src;
45 : 3116397 : src -= align;
46 : 3116397 : max += align;
47 : :
48 [ # # ][ + + ]: 3116397 : if (unlikely(__get_user(c,(unsigned long __user *)src)))
49 : : return 0;
50 : 3116221 : c |= aligned_byte_mask(align);
51 : :
52 : : for (;;) {
53 : : unsigned long data;
54 [ # # ][ + + ]: 4112028759 : if (has_zero(c, &data, &constants)) {
55 : : data = prep_zero_mask(c, data, &constants);
56 : : data = create_zero_mask(data);
57 : 3116372 : return res + find_zero(data) + 1 - align;
58 : : }
59 : 4105796018 : res += sizeof(unsigned long);
60 [ # # ][ + - ]: 4105796018 : if (unlikely(max < sizeof(unsigned long)))
61 : : break;
62 : 4105796018 : max -= sizeof(unsigned long);
63 [ # # ][ + ]: 4105796018 : if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
64 : : return 0;
65 : : }
66 : 0 : res -= align;
67 : :
68 : : /*
69 : : * Uhhuh. We hit 'max'. But was that the user-specified maximum
70 : : * too? If so, return the marker for "too long".
71 : : */
72 [ # # ]: 0 : if (res >= count)
73 : 0 : return count+1;
74 : :
75 : : /*
76 : : * Nope: we hit the address space limit, and we still had more
77 : : * characters the caller would have wanted. That's 0.
78 : : */
79 : : return 0;
80 : : }
81 : :
82 : : /**
83 : : * strnlen_user: - Get the size of a user string INCLUDING final NUL.
84 : : * @str: The string to measure.
85 : : * @count: Maximum count (including NUL character)
86 : : *
87 : : * Context: User context only. This function may sleep.
88 : : *
89 : : * Get the size of a NUL-terminated string in user space.
90 : : *
91 : : * Returns the size of the string INCLUDING the terminating NUL.
92 : : * If the string is too long, returns 'count+1'.
93 : : * On exception (or invalid count), returns 0.
94 : : */
95 : 0 : long strnlen_user(const char __user *str, long count)
96 : : {
97 : : unsigned long max_addr, src_addr;
98 : :
99 [ + ]: 3116369 : if (unlikely(count <= 0))
100 : : return 0;
101 : :
102 [ + + ]: 3116382 : max_addr = user_addr_max();
103 : 3116382 : src_addr = (unsigned long)str;
104 [ + ]: 3116382 : if (likely(src_addr < max_addr)) {
105 : 3116397 : unsigned long max = max_addr - src_addr;
106 : 3116417 : return do_strnlen_user(str, count, max);
107 : : }
108 : : return 0;
109 : : }
110 : : EXPORT_SYMBOL(strnlen_user);
111 : :
112 : : /**
113 : : * strlen_user: - Get the size of a user string INCLUDING final NUL.
114 : : * @str: The string to measure.
115 : : *
116 : : * Context: User context only. This function may sleep.
117 : : *
118 : : * Get the size of a NUL-terminated string in user space.
119 : : *
120 : : * Returns the size of the string INCLUDING the terminating NUL.
121 : : * On exception, returns 0.
122 : : *
123 : : * If there is a limit on the length of a valid string, you may wish to
124 : : * consider using strnlen_user() instead.
125 : : */
126 : 0 : long strlen_user(const char __user *str)
127 : : {
128 : : unsigned long max_addr, src_addr;
129 : :
130 [ # # ]: 0 : max_addr = user_addr_max();
131 : 0 : src_addr = (unsigned long)str;
132 [ # # ]: 0 : if (likely(src_addr < max_addr)) {
133 : 0 : unsigned long max = max_addr - src_addr;
134 : 0 : return do_strnlen_user(str, ~0ul, max);
135 : : }
136 : : return 0;
137 : : }
138 : : EXPORT_SYMBOL(strlen_user);
|