diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 22:11:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 22:11:50 -0500 |
commit | 3aacd625f20129f5a41ea3ff3b5353b0e4dabd01 (patch) | |
tree | 7cf4ea65397f80098b30494df31cfc8f5fa26d63 /lib | |
parent | 7e21774db5cc9cf8fe93a64a2f0c6cf47db8ab24 (diff) | |
parent | 2a1d689c9ba42a6066540fb221b6ecbd6298b728 (diff) |
Merge branch 'akpm' (incoming from Andrew)
Merge second patch-bomb from Andrew Morton:
- various misc bits
- the rest of MM
- add generic fixmap.h, use it
- backlight updates
- dynamic_debug updates
- printk() updates
- checkpatch updates
- binfmt_elf
- ramfs
- init/
- autofs4
- drivers/rtc
- nilfs
- hfsplus
- Documentation/
- coredump
- procfs
- fork
- exec
- kexec
- kdump
- partitions
- rapidio
- rbtree
- userns
- memstick
- w1
- decompressors
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (197 commits)
lib/decompress_unlz4.c: always set an error return code on failures
romfs: fix returm err while getting inode in fill_super
drivers/w1/masters/w1-gpio.c: add strong pullup emulation
drivers/memstick/host/rtsx_pci_ms.c: fix ms card data transfer bug
userns: relax the posix_acl_valid() checks
arch/sh/kernel/dwarf.c: use rbtree postorder iteration helper instead of solution using repeated rb_erase()
fs-ext3-use-rbtree-postorder-iteration-helper-instead-of-opencoding-fix
fs/ext3: use rbtree postorder iteration helper instead of opencoding
fs/jffs2: use rbtree postorder iteration helper instead of opencoding
fs/ext4: use rbtree postorder iteration helper instead of opencoding
fs/ubifs: use rbtree postorder iteration helper instead of opencoding
net/netfilter/ipset/ip_set_hash_netiface.c: use rbtree postorder iteration instead of opencoding
rbtree/test: test rbtree_postorder_for_each_entry_safe()
rbtree/test: move rb_node to the middle of the test struct
rapidio: add modular rapidio core build into powerpc and mips branches
partitions/efi: complete documentation of gpt kernel param purpose
kdump: add /sys/kernel/vmcoreinfo ABI documentation
kdump: fix exported size of vmcoreinfo note
kexec: add sysctl to disable kexec_load
fs/exec.c: call arch_pick_mmap_layout() only once
...
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 27 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/cmdline.c | 14 | ||||
-rw-r--r-- | lib/decompress_unlz4.c | 1 | ||||
-rw-r--r-- | lib/dynamic_debug.c | 15 | ||||
-rw-r--r-- | lib/kstrtox.c | 1 | ||||
-rw-r--r-- | lib/parser.c | 62 | ||||
-rw-r--r-- | lib/rbtree_test.c | 13 | ||||
-rw-r--r-- | lib/test_module.c | 33 | ||||
-rw-r--r-- | lib/test_user_copy.c | 110 | ||||
-rw-r--r-- | lib/vsprintf.c | 33 |
11 files changed, 284 insertions, 27 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 900b63c1e899..e0e2eebf7ab3 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -1595,6 +1595,33 @@ config DMA_API_DEBUG | |||
1595 | 1595 | ||
1596 | If unsure, say N. | 1596 | If unsure, say N. |
1597 | 1597 | ||
1598 | config TEST_MODULE | ||
1599 | tristate "Test module loading with 'hello world' module" | ||
1600 | default n | ||
1601 | depends on m | ||
1602 | help | ||
1603 | This builds the "test_module" module that emits "Hello, world" | ||
1604 | on printk when loaded. It is designed to be used for basic | ||
1605 | evaluation of the module loading subsystem (for example when | ||
1606 | validating module verification). It lacks any extra dependencies, | ||
1607 | and will not normally be loaded by the system unless explicitly | ||
1608 | requested by name. | ||
1609 | |||
1610 | If unsure, say N. | ||
1611 | |||
1612 | config TEST_USER_COPY | ||
1613 | tristate "Test user/kernel boundary protections" | ||
1614 | default n | ||
1615 | depends on m | ||
1616 | help | ||
1617 | This builds the "test_user_copy" module that runs sanity checks | ||
1618 | on the copy_to/from_user infrastructure, making sure basic | ||
1619 | user/kernel boundary testing is working. If it fails to load, | ||
1620 | a regression has been detected in the user/kernel memory boundary | ||
1621 | protections. | ||
1622 | |||
1623 | If unsure, say N. | ||
1624 | |||
1598 | source "samples/Kconfig" | 1625 | source "samples/Kconfig" |
1599 | 1626 | ||
1600 | source "lib/Kconfig.kgdb" | 1627 | source "lib/Kconfig.kgdb" |
diff --git a/lib/Makefile b/lib/Makefile index a459c31e8c6b..98ec3b861062 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -31,6 +31,8 @@ obj-y += string_helpers.o | |||
31 | obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o | 31 | obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o |
32 | obj-y += kstrtox.o | 32 | obj-y += kstrtox.o |
33 | obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o | 33 | obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o |
34 | obj-$(CONFIG_TEST_MODULE) += test_module.o | ||
35 | obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o | ||
34 | 36 | ||
35 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) | 37 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) |
36 | CFLAGS_kobject.o += -DDEBUG | 38 | CFLAGS_kobject.o += -DDEBUG |
diff --git a/lib/cmdline.c b/lib/cmdline.c index eb6791188cf5..d4932f745e92 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c | |||
@@ -49,13 +49,13 @@ static int get_range(char **str, int *pint) | |||
49 | * 3 - hyphen found to denote a range | 49 | * 3 - hyphen found to denote a range |
50 | */ | 50 | */ |
51 | 51 | ||
52 | int get_option (char **str, int *pint) | 52 | int get_option(char **str, int *pint) |
53 | { | 53 | { |
54 | char *cur = *str; | 54 | char *cur = *str; |
55 | 55 | ||
56 | if (!cur || !(*cur)) | 56 | if (!cur || !(*cur)) |
57 | return 0; | 57 | return 0; |
58 | *pint = simple_strtol (cur, str, 0); | 58 | *pint = simple_strtol(cur, str, 0); |
59 | if (cur == *str) | 59 | if (cur == *str) |
60 | return 0; | 60 | return 0; |
61 | if (**str == ',') { | 61 | if (**str == ',') { |
@@ -67,6 +67,7 @@ int get_option (char **str, int *pint) | |||
67 | 67 | ||
68 | return 1; | 68 | return 1; |
69 | } | 69 | } |
70 | EXPORT_SYMBOL(get_option); | ||
70 | 71 | ||
71 | /** | 72 | /** |
72 | * get_options - Parse a string into a list of integers | 73 | * get_options - Parse a string into a list of integers |
@@ -84,13 +85,13 @@ int get_option (char **str, int *pint) | |||
84 | * the parse to end (typically a null terminator, if @str is | 85 | * the parse to end (typically a null terminator, if @str is |
85 | * completely parseable). | 86 | * completely parseable). |
86 | */ | 87 | */ |
87 | 88 | ||
88 | char *get_options(const char *str, int nints, int *ints) | 89 | char *get_options(const char *str, int nints, int *ints) |
89 | { | 90 | { |
90 | int res, i = 1; | 91 | int res, i = 1; |
91 | 92 | ||
92 | while (i < nints) { | 93 | while (i < nints) { |
93 | res = get_option ((char **)&str, ints + i); | 94 | res = get_option((char **)&str, ints + i); |
94 | if (res == 0) | 95 | if (res == 0) |
95 | break; | 96 | break; |
96 | if (res == 3) { | 97 | if (res == 3) { |
@@ -112,6 +113,7 @@ char *get_options(const char *str, int nints, int *ints) | |||
112 | ints[0] = i - 1; | 113 | ints[0] = i - 1; |
113 | return (char *)str; | 114 | return (char *)str; |
114 | } | 115 | } |
116 | EXPORT_SYMBOL(get_options); | ||
115 | 117 | ||
116 | /** | 118 | /** |
117 | * memparse - parse a string with mem suffixes into a number | 119 | * memparse - parse a string with mem suffixes into a number |
@@ -152,8 +154,4 @@ unsigned long long memparse(const char *ptr, char **retptr) | |||
152 | 154 | ||
153 | return ret; | 155 | return ret; |
154 | } | 156 | } |
155 | |||
156 | |||
157 | EXPORT_SYMBOL(memparse); | 157 | EXPORT_SYMBOL(memparse); |
158 | EXPORT_SYMBOL(get_option); | ||
159 | EXPORT_SYMBOL(get_options); | ||
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c index 3e67cfad16ad..7d1e83caf8ad 100644 --- a/lib/decompress_unlz4.c +++ b/lib/decompress_unlz4.c | |||
@@ -141,6 +141,7 @@ STATIC inline int INIT unlz4(u8 *input, int in_len, | |||
141 | goto exit_2; | 141 | goto exit_2; |
142 | } | 142 | } |
143 | 143 | ||
144 | ret = -1; | ||
144 | if (flush && flush(outp, dest_len) != dest_len) | 145 | if (flush && flush(outp, dest_len) != dest_len) |
145 | goto exit_2; | 146 | goto exit_2; |
146 | if (output) | 147 | if (output) |
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index c37aeacd7651..600ac57e2777 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * By Greg Banks <gnb@melbourne.sgi.com> | 8 | * By Greg Banks <gnb@melbourne.sgi.com> |
9 | * Copyright (c) 2008 Silicon Graphics Inc. All Rights Reserved. | 9 | * Copyright (c) 2008 Silicon Graphics Inc. All Rights Reserved. |
10 | * Copyright (C) 2011 Bart Van Assche. All Rights Reserved. | 10 | * Copyright (C) 2011 Bart Van Assche. All Rights Reserved. |
11 | * Copyright (C) 2013 Du, Changbin <changbin.du@gmail.com> | ||
11 | */ | 12 | */ |
12 | 13 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ |
@@ -24,6 +25,7 @@ | |||
24 | #include <linux/sysctl.h> | 25 | #include <linux/sysctl.h> |
25 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
26 | #include <linux/string.h> | 27 | #include <linux/string.h> |
28 | #include <linux/parser.h> | ||
27 | #include <linux/string_helpers.h> | 29 | #include <linux/string_helpers.h> |
28 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
29 | #include <linux/dynamic_debug.h> | 31 | #include <linux/dynamic_debug.h> |
@@ -147,7 +149,8 @@ static int ddebug_change(const struct ddebug_query *query, | |||
147 | list_for_each_entry(dt, &ddebug_tables, link) { | 149 | list_for_each_entry(dt, &ddebug_tables, link) { |
148 | 150 | ||
149 | /* match against the module name */ | 151 | /* match against the module name */ |
150 | if (query->module && strcmp(query->module, dt->mod_name)) | 152 | if (query->module && |
153 | !match_wildcard(query->module, dt->mod_name)) | ||
151 | continue; | 154 | continue; |
152 | 155 | ||
153 | for (i = 0; i < dt->num_ddebugs; i++) { | 156 | for (i = 0; i < dt->num_ddebugs; i++) { |
@@ -155,14 +158,16 @@ static int ddebug_change(const struct ddebug_query *query, | |||
155 | 158 | ||
156 | /* match against the source filename */ | 159 | /* match against the source filename */ |
157 | if (query->filename && | 160 | if (query->filename && |
158 | strcmp(query->filename, dp->filename) && | 161 | !match_wildcard(query->filename, dp->filename) && |
159 | strcmp(query->filename, kbasename(dp->filename)) && | 162 | !match_wildcard(query->filename, |
160 | strcmp(query->filename, trim_prefix(dp->filename))) | 163 | kbasename(dp->filename)) && |
164 | !match_wildcard(query->filename, | ||
165 | trim_prefix(dp->filename))) | ||
161 | continue; | 166 | continue; |
162 | 167 | ||
163 | /* match against the function */ | 168 | /* match against the function */ |
164 | if (query->function && | 169 | if (query->function && |
165 | strcmp(query->function, dp->function)) | 170 | !match_wildcard(query->function, dp->function)) |
166 | continue; | 171 | continue; |
167 | 172 | ||
168 | /* match against the format */ | 173 | /* match against the format */ |
diff --git a/lib/kstrtox.c b/lib/kstrtox.c index f78ae0c0c4e2..ec8da78df9be 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c | |||
@@ -92,7 +92,6 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) | |||
92 | rv = _parse_integer(s, base, &_res); | 92 | rv = _parse_integer(s, base, &_res); |
93 | if (rv & KSTRTOX_OVERFLOW) | 93 | if (rv & KSTRTOX_OVERFLOW) |
94 | return -ERANGE; | 94 | return -ERANGE; |
95 | rv &= ~KSTRTOX_OVERFLOW; | ||
96 | if (rv == 0) | 95 | if (rv == 0) |
97 | return -EINVAL; | 96 | return -EINVAL; |
98 | s += rv; | 97 | s += rv; |
diff --git a/lib/parser.c b/lib/parser.c index 807b2aaa33fa..b6d11631231b 100644 --- a/lib/parser.c +++ b/lib/parser.c | |||
@@ -113,6 +113,7 @@ int match_token(char *s, const match_table_t table, substring_t args[]) | |||
113 | 113 | ||
114 | return p->token; | 114 | return p->token; |
115 | } | 115 | } |
116 | EXPORT_SYMBOL(match_token); | ||
116 | 117 | ||
117 | /** | 118 | /** |
118 | * match_number: scan a number in the given base from a substring_t | 119 | * match_number: scan a number in the given base from a substring_t |
@@ -163,6 +164,7 @@ int match_int(substring_t *s, int *result) | |||
163 | { | 164 | { |
164 | return match_number(s, result, 0); | 165 | return match_number(s, result, 0); |
165 | } | 166 | } |
167 | EXPORT_SYMBOL(match_int); | ||
166 | 168 | ||
167 | /** | 169 | /** |
168 | * match_octal: - scan an octal representation of an integer from a substring_t | 170 | * match_octal: - scan an octal representation of an integer from a substring_t |
@@ -177,6 +179,7 @@ int match_octal(substring_t *s, int *result) | |||
177 | { | 179 | { |
178 | return match_number(s, result, 8); | 180 | return match_number(s, result, 8); |
179 | } | 181 | } |
182 | EXPORT_SYMBOL(match_octal); | ||
180 | 183 | ||
181 | /** | 184 | /** |
182 | * match_hex: - scan a hex representation of an integer from a substring_t | 185 | * match_hex: - scan a hex representation of an integer from a substring_t |
@@ -191,6 +194,58 @@ int match_hex(substring_t *s, int *result) | |||
191 | { | 194 | { |
192 | return match_number(s, result, 16); | 195 | return match_number(s, result, 16); |
193 | } | 196 | } |
197 | EXPORT_SYMBOL(match_hex); | ||
198 | |||
199 | /** | ||
200 | * match_wildcard: - parse if a string matches given wildcard pattern | ||
201 | * @pattern: wildcard pattern | ||
202 | * @str: the string to be parsed | ||
203 | * | ||
204 | * Description: Parse the string @str to check if matches wildcard | ||
205 | * pattern @pattern. The pattern may contain two type wildcardes: | ||
206 | * '*' - matches zero or more characters | ||
207 | * '?' - matches one character | ||
208 | * If it's matched, return true, else return false. | ||
209 | */ | ||
210 | bool match_wildcard(const char *pattern, const char *str) | ||
211 | { | ||
212 | const char *s = str; | ||
213 | const char *p = pattern; | ||
214 | bool star = false; | ||
215 | |||
216 | while (*s) { | ||
217 | switch (*p) { | ||
218 | case '?': | ||
219 | s++; | ||
220 | p++; | ||
221 | break; | ||
222 | case '*': | ||
223 | star = true; | ||
224 | str = s; | ||
225 | if (!*++p) | ||
226 | return true; | ||
227 | pattern = p; | ||
228 | break; | ||
229 | default: | ||
230 | if (*s == *p) { | ||
231 | s++; | ||
232 | p++; | ||
233 | } else { | ||
234 | if (!star) | ||
235 | return false; | ||
236 | str++; | ||
237 | s = str; | ||
238 | p = pattern; | ||
239 | } | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | if (*p == '*') | ||
245 | ++p; | ||
246 | return !*p; | ||
247 | } | ||
248 | EXPORT_SYMBOL(match_wildcard); | ||
194 | 249 | ||
195 | /** | 250 | /** |
196 | * match_strlcpy: - Copy the characters from a substring_t to a sized buffer | 251 | * match_strlcpy: - Copy the characters from a substring_t to a sized buffer |
@@ -213,6 +268,7 @@ size_t match_strlcpy(char *dest, const substring_t *src, size_t size) | |||
213 | } | 268 | } |
214 | return ret; | 269 | return ret; |
215 | } | 270 | } |
271 | EXPORT_SYMBOL(match_strlcpy); | ||
216 | 272 | ||
217 | /** | 273 | /** |
218 | * match_strdup: - allocate a new string with the contents of a substring_t | 274 | * match_strdup: - allocate a new string with the contents of a substring_t |
@@ -230,10 +286,4 @@ char *match_strdup(const substring_t *s) | |||
230 | match_strlcpy(p, s, sz); | 286 | match_strlcpy(p, s, sz); |
231 | return p; | 287 | return p; |
232 | } | 288 | } |
233 | |||
234 | EXPORT_SYMBOL(match_token); | ||
235 | EXPORT_SYMBOL(match_int); | ||
236 | EXPORT_SYMBOL(match_octal); | ||
237 | EXPORT_SYMBOL(match_hex); | ||
238 | EXPORT_SYMBOL(match_strlcpy); | ||
239 | EXPORT_SYMBOL(match_strdup); | 289 | EXPORT_SYMBOL(match_strdup); |
diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c index 31dd4ccd3baa..8b3c9dc88262 100644 --- a/lib/rbtree_test.c +++ b/lib/rbtree_test.c | |||
@@ -8,8 +8,8 @@ | |||
8 | #define CHECK_LOOPS 100 | 8 | #define CHECK_LOOPS 100 |
9 | 9 | ||
10 | struct test_node { | 10 | struct test_node { |
11 | struct rb_node rb; | ||
12 | u32 key; | 11 | u32 key; |
12 | struct rb_node rb; | ||
13 | 13 | ||
14 | /* following fields used for testing augmented rbtree functionality */ | 14 | /* following fields used for testing augmented rbtree functionality */ |
15 | u32 val; | 15 | u32 val; |
@@ -114,6 +114,16 @@ static int black_path_count(struct rb_node *rb) | |||
114 | return count; | 114 | return count; |
115 | } | 115 | } |
116 | 116 | ||
117 | static void check_postorder_foreach(int nr_nodes) | ||
118 | { | ||
119 | struct test_node *cur, *n; | ||
120 | int count = 0; | ||
121 | rbtree_postorder_for_each_entry_safe(cur, n, &root, rb) | ||
122 | count++; | ||
123 | |||
124 | WARN_ON_ONCE(count != nr_nodes); | ||
125 | } | ||
126 | |||
117 | static void check_postorder(int nr_nodes) | 127 | static void check_postorder(int nr_nodes) |
118 | { | 128 | { |
119 | struct rb_node *rb; | 129 | struct rb_node *rb; |
@@ -148,6 +158,7 @@ static void check(int nr_nodes) | |||
148 | WARN_ON_ONCE(count < (1 << black_path_count(rb_last(&root))) - 1); | 158 | WARN_ON_ONCE(count < (1 << black_path_count(rb_last(&root))) - 1); |
149 | 159 | ||
150 | check_postorder(nr_nodes); | 160 | check_postorder(nr_nodes); |
161 | check_postorder_foreach(nr_nodes); | ||
151 | } | 162 | } |
152 | 163 | ||
153 | static void check_augmented(int nr_nodes) | 164 | static void check_augmented(int nr_nodes) |
diff --git a/lib/test_module.c b/lib/test_module.c new file mode 100644 index 000000000000..319b66f1ff61 --- /dev/null +++ b/lib/test_module.c | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * This module emits "Hello, world" on printk when loaded. | ||
3 | * | ||
4 | * It is designed to be used for basic evaluation of the module loading | ||
5 | * subsystem (for example when validating module signing/verification). It | ||
6 | * lacks any extra dependencies, and will not normally be loaded by the | ||
7 | * system unless explicitly requested by name. | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/printk.h> | ||
15 | |||
16 | static int __init test_module_init(void) | ||
17 | { | ||
18 | pr_warn("Hello, world\n"); | ||
19 | |||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | module_init(test_module_init); | ||
24 | |||
25 | static void __exit test_module_exit(void) | ||
26 | { | ||
27 | pr_warn("Goodbye\n"); | ||
28 | } | ||
29 | |||
30 | module_exit(test_module_exit); | ||
31 | |||
32 | MODULE_AUTHOR("Kees Cook <keescook@chromium.org>"); | ||
33 | MODULE_LICENSE("GPL"); | ||
diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c new file mode 100644 index 000000000000..0ecef3e4690e --- /dev/null +++ b/lib/test_user_copy.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * Kernel module for testing copy_to/from_user infrastructure. | ||
3 | * | ||
4 | * Copyright 2013 Google Inc. All Rights Reserved | ||
5 | * | ||
6 | * Authors: | ||
7 | * Kees Cook <keescook@chromium.org> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
21 | #include <linux/mman.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/uaccess.h> | ||
26 | #include <linux/vmalloc.h> | ||
27 | |||
28 | #define test(condition, msg) \ | ||
29 | ({ \ | ||
30 | int cond = (condition); \ | ||
31 | if (cond) \ | ||
32 | pr_warn("%s\n", msg); \ | ||
33 | cond; \ | ||
34 | }) | ||
35 | |||
36 | static int __init test_user_copy_init(void) | ||
37 | { | ||
38 | int ret = 0; | ||
39 | char *kmem; | ||
40 | char __user *usermem; | ||
41 | char *bad_usermem; | ||
42 | unsigned long user_addr; | ||
43 | unsigned long value = 0x5A; | ||
44 | |||
45 | kmem = kmalloc(PAGE_SIZE * 2, GFP_KERNEL); | ||
46 | if (!kmem) | ||
47 | return -ENOMEM; | ||
48 | |||
49 | user_addr = vm_mmap(NULL, 0, PAGE_SIZE * 2, | ||
50 | PROT_READ | PROT_WRITE | PROT_EXEC, | ||
51 | MAP_ANONYMOUS | MAP_PRIVATE, 0); | ||
52 | if (user_addr >= (unsigned long)(TASK_SIZE)) { | ||
53 | pr_warn("Failed to allocate user memory\n"); | ||
54 | kfree(kmem); | ||
55 | return -ENOMEM; | ||
56 | } | ||
57 | |||
58 | usermem = (char __user *)user_addr; | ||
59 | bad_usermem = (char *)user_addr; | ||
60 | |||
61 | /* Legitimate usage: none of these should fail. */ | ||
62 | ret |= test(copy_from_user(kmem, usermem, PAGE_SIZE), | ||
63 | "legitimate copy_from_user failed"); | ||
64 | ret |= test(copy_to_user(usermem, kmem, PAGE_SIZE), | ||
65 | "legitimate copy_to_user failed"); | ||
66 | ret |= test(get_user(value, (unsigned long __user *)usermem), | ||
67 | "legitimate get_user failed"); | ||
68 | ret |= test(put_user(value, (unsigned long __user *)usermem), | ||
69 | "legitimate put_user failed"); | ||
70 | |||
71 | /* Invalid usage: none of these should succeed. */ | ||
72 | ret |= test(!copy_from_user(kmem, (char __user *)(kmem + PAGE_SIZE), | ||
73 | PAGE_SIZE), | ||
74 | "illegal all-kernel copy_from_user passed"); | ||
75 | ret |= test(!copy_from_user(bad_usermem, (char __user *)kmem, | ||
76 | PAGE_SIZE), | ||
77 | "illegal reversed copy_from_user passed"); | ||
78 | ret |= test(!copy_to_user((char __user *)kmem, kmem + PAGE_SIZE, | ||
79 | PAGE_SIZE), | ||
80 | "illegal all-kernel copy_to_user passed"); | ||
81 | ret |= test(!copy_to_user((char __user *)kmem, bad_usermem, | ||
82 | PAGE_SIZE), | ||
83 | "illegal reversed copy_to_user passed"); | ||
84 | ret |= test(!get_user(value, (unsigned long __user *)kmem), | ||
85 | "illegal get_user passed"); | ||
86 | ret |= test(!put_user(value, (unsigned long __user *)kmem), | ||
87 | "illegal put_user passed"); | ||
88 | |||
89 | vm_munmap(user_addr, PAGE_SIZE * 2); | ||
90 | kfree(kmem); | ||
91 | |||
92 | if (ret == 0) { | ||
93 | pr_info("tests passed.\n"); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | module_init(test_user_copy_init); | ||
101 | |||
102 | static void __exit test_user_copy_exit(void) | ||
103 | { | ||
104 | pr_info("unloaded.\n"); | ||
105 | } | ||
106 | |||
107 | module_exit(test_user_copy_exit); | ||
108 | |||
109 | MODULE_AUTHOR("Kees Cook <keescook@chromium.org>"); | ||
110 | MODULE_LICENSE("GPL"); | ||
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 10909c571494..185b6d300ebc 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -1155,6 +1155,30 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr, | |||
1155 | return number(buf, end, *(const netdev_features_t *)addr, spec); | 1155 | return number(buf, end, *(const netdev_features_t *)addr, spec); |
1156 | } | 1156 | } |
1157 | 1157 | ||
1158 | static noinline_for_stack | ||
1159 | char *address_val(char *buf, char *end, const void *addr, | ||
1160 | struct printf_spec spec, const char *fmt) | ||
1161 | { | ||
1162 | unsigned long long num; | ||
1163 | |||
1164 | spec.flags |= SPECIAL | SMALL | ZEROPAD; | ||
1165 | spec.base = 16; | ||
1166 | |||
1167 | switch (fmt[1]) { | ||
1168 | case 'd': | ||
1169 | num = *(const dma_addr_t *)addr; | ||
1170 | spec.field_width = sizeof(dma_addr_t) * 2 + 2; | ||
1171 | break; | ||
1172 | case 'p': | ||
1173 | default: | ||
1174 | num = *(const phys_addr_t *)addr; | ||
1175 | spec.field_width = sizeof(phys_addr_t) * 2 + 2; | ||
1176 | break; | ||
1177 | } | ||
1178 | |||
1179 | return number(buf, end, num, spec); | ||
1180 | } | ||
1181 | |||
1158 | int kptr_restrict __read_mostly; | 1182 | int kptr_restrict __read_mostly; |
1159 | 1183 | ||
1160 | /* | 1184 | /* |
@@ -1218,7 +1242,8 @@ int kptr_restrict __read_mostly; | |||
1218 | * N no separator | 1242 | * N no separator |
1219 | * The maximum supported length is 64 bytes of the input. Consider | 1243 | * The maximum supported length is 64 bytes of the input. Consider |
1220 | * to use print_hex_dump() for the larger input. | 1244 | * to use print_hex_dump() for the larger input. |
1221 | * - 'a' For a phys_addr_t type and its derivative types (passed by reference) | 1245 | * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives |
1246 | * (default assumed to be phys_addr_t, passed by reference) | ||
1222 | * - 'd[234]' For a dentry name (optionally 2-4 last components) | 1247 | * - 'd[234]' For a dentry name (optionally 2-4 last components) |
1223 | * - 'D[234]' Same as 'd' but for a struct file | 1248 | * - 'D[234]' Same as 'd' but for a struct file |
1224 | * | 1249 | * |
@@ -1353,11 +1378,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1353 | } | 1378 | } |
1354 | break; | 1379 | break; |
1355 | case 'a': | 1380 | case 'a': |
1356 | spec.flags |= SPECIAL | SMALL | ZEROPAD; | 1381 | return address_val(buf, end, ptr, spec, fmt); |
1357 | spec.field_width = sizeof(phys_addr_t) * 2 + 2; | ||
1358 | spec.base = 16; | ||
1359 | return number(buf, end, | ||
1360 | (unsigned long long) *((phys_addr_t *)ptr), spec); | ||
1361 | case 'd': | 1382 | case 'd': |
1362 | return dentry_name(buf, end, ptr, spec, fmt); | 1383 | return dentry_name(buf, end, ptr, spec, fmt); |
1363 | case 'D': | 1384 | case 'D': |