summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug40
-rw-r--r--lib/Makefile5
-rw-r--r--lib/assoc_array.c2
-rw-r--r--lib/average.c6
-rw-r--r--lib/cmdline.c14
-rw-r--r--lib/decompress_unlz4.c1
-rw-r--r--lib/dma-debug.c133
-rw-r--r--lib/dynamic_debug.c29
-rw-r--r--lib/flex_array.c7
-rw-r--r--lib/fonts/Kconfig6
-rw-r--r--lib/genalloc.c5
-rw-r--r--lib/hash.c39
-rw-r--r--lib/kobject.c1
-rw-r--r--lib/kobject_uevent.c10
-rw-r--r--lib/kstrtox.c1
-rw-r--r--lib/parser.c62
-rw-r--r--lib/percpu_ida.c28
-rw-r--r--lib/radix-tree.c4
-rw-r--r--lib/rbtree_test.c13
-rw-r--r--lib/reciprocal_div.c24
-rw-r--r--lib/swiotlb.c7
-rw-r--r--lib/test_module.c33
-rw-r--r--lib/test_user_copy.c110
-rw-r--r--lib/vsprintf.c33
24 files changed, 489 insertions, 124 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 900b63c1e89..a48abeac753 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -119,7 +119,7 @@ menu "Compile-time checks and compiler options"
config DEBUG_INFO
bool "Compile the kernel with debug info"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL && !COMPILE_TEST
help
If you say Y here the resulting kernel image will include
debugging info resulting in a larger kernel image.
@@ -1556,17 +1556,6 @@ config PROVIDE_OHCI1394_DMA_INIT
See Documentation/debugging-via-ohci1394.txt for more information.
-config FIREWIRE_OHCI_REMOTE_DMA
- bool "Remote debugging over FireWire with firewire-ohci"
- depends on FIREWIRE_OHCI
- help
- This option lets you use the FireWire bus for remote debugging
- with help of the firewire-ohci driver. It enables unfiltered
- remote DMA in firewire-ohci.
- See Documentation/debugging-via-ohci1394.txt for more information.
-
- If unsure, say N.
-
config BUILD_DOCSRC
bool "Build targets in Documentation/ tree"
depends on HEADERS_CHECK
@@ -1595,6 +1584,33 @@ config DMA_API_DEBUG
If unsure, say N.
+config TEST_MODULE
+ tristate "Test module loading with 'hello world' module"
+ default n
+ depends on m
+ help
+ This builds the "test_module" module that emits "Hello, world"
+ on printk when loaded. It is designed to be used for basic
+ evaluation of the module loading subsystem (for example when
+ validating module verification). It lacks any extra dependencies,
+ and will not normally be loaded by the system unless explicitly
+ requested by name.
+
+ If unsure, say N.
+
+config TEST_USER_COPY
+ tristate "Test user/kernel boundary protections"
+ default n
+ depends on m
+ help
+ This builds the "test_user_copy" module that runs sanity checks
+ on the copy_to/from_user infrastructure, making sure basic
+ user/kernel boundary testing is working. If it fails to load,
+ a regression has been detected in the user/kernel memory boundary
+ protections.
+
+ If unsure, say N.
+
source "samples/Kconfig"
source "lib/Kconfig.kgdb"
diff --git a/lib/Makefile b/lib/Makefile
index a459c31e8c6..48140e3ba73 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -26,11 +26,13 @@ obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \
bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \
- percpu-refcount.o percpu_ida.o
+ percpu-refcount.o percpu_ida.o hash.o
obj-y += string_helpers.o
obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
obj-y += kstrtox.o
obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
+obj-$(CONFIG_TEST_MODULE) += test_module.o
+obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
@@ -43,6 +45,7 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
+GCOV_PROFILE_hweight.o := n
CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
diff --git a/lib/assoc_array.c b/lib/assoc_array.c
index 1b6a44f1ec3..c0b1007011e 100644
--- a/lib/assoc_array.c
+++ b/lib/assoc_array.c
@@ -157,7 +157,7 @@ enum assoc_array_walk_status {
assoc_array_walk_tree_empty,
assoc_array_walk_found_terminal_node,
assoc_array_walk_found_wrong_shortcut,
-} status;
+};
struct assoc_array_walk_result {
struct {
diff --git a/lib/average.c b/lib/average.c
index 99a67e662b3..114d1beae0c 100644
--- a/lib/average.c
+++ b/lib/average.c
@@ -53,8 +53,10 @@ EXPORT_SYMBOL(ewma_init);
*/
struct ewma *ewma_add(struct ewma *avg, unsigned long val)
{
- avg->internal = avg->internal ?
- (((avg->internal << avg->weight) - avg->internal) +
+ unsigned long internal = ACCESS_ONCE(avg->internal);
+
+ ACCESS_ONCE(avg->internal) = internal ?
+ (((internal << avg->weight) - internal) +
(val << avg->factor)) >> avg->weight :
(val << avg->factor);
return avg;
diff --git a/lib/cmdline.c b/lib/cmdline.c
index eb6791188cf..d4932f745e9 100644
--- a/lib/cmdline.c
+++ b/lib/cmdline.c
@@ -49,13 +49,13 @@ static int get_range(char **str, int *pint)
* 3 - hyphen found to denote a range
*/
-int get_option (char **str, int *pint)
+int get_option(char **str, int *pint)
{
char *cur = *str;
if (!cur || !(*cur))
return 0;
- *pint = simple_strtol (cur, str, 0);
+ *pint = simple_strtol(cur, str, 0);
if (cur == *str)
return 0;
if (**str == ',') {
@@ -67,6 +67,7 @@ int get_option (char **str, int *pint)
return 1;
}
+EXPORT_SYMBOL(get_option);
/**
* get_options - Parse a string into a list of integers
@@ -84,13 +85,13 @@ int get_option (char **str, int *pint)
* the parse to end (typically a null terminator, if @str is
* completely parseable).
*/
-
+
char *get_options(const char *str, int nints, int *ints)
{
int res, i = 1;
while (i < nints) {
- res = get_option ((char **)&str, ints + i);
+ res = get_option((char **)&str, ints + i);
if (res == 0)
break;
if (res == 3) {
@@ -112,6 +113,7 @@ char *get_options(const char *str, int nints, int *ints)
ints[0] = i - 1;
return (char *)str;
}
+EXPORT_SYMBOL(get_options);
/**
* memparse - parse a string with mem suffixes into a number
@@ -152,8 +154,4 @@ unsigned long long memparse(const char *ptr, char **retptr)
return ret;
}
-
-
EXPORT_SYMBOL(memparse);
-EXPORT_SYMBOL(get_option);
-EXPORT_SYMBOL(get_options);
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c
index 3e67cfad16a..7d1e83caf8a 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,
goto exit_2;
}
+ ret = -1;
if (flush && flush(outp, dest_len) != dest_len)
goto exit_2;
if (output)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index c38083871f1..98f2d7e91a9 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -424,107 +424,134 @@ void debug_dma_dump_mappings(struct device *dev)
EXPORT_SYMBOL(debug_dma_dump_mappings);
/*
- * For each page mapped (initial page in the case of
- * dma_alloc_coherent/dma_map_{single|page}, or each page in a
- * scatterlist) insert into this tree using the pfn as the key. At
+ * For each mapping (initial cacheline in the case of
+ * dma_alloc_coherent/dma_map_page, initial cacheline in each page of a
+ * scatterlist, or the cacheline specified in dma_map_single) insert
+ * into this tree using the cacheline as the key. At
* dma_unmap_{single|sg|page} or dma_free_coherent delete the entry. If
- * the pfn already exists at insertion time add a tag as a reference
+ * the entry already exists at insertion time add a tag as a reference
* count for the overlapping mappings. For now, the overlap tracking
- * just ensures that 'unmaps' balance 'maps' before marking the pfn
- * idle, but we should also be flagging overlaps as an API violation.
+ * just ensures that 'unmaps' balance 'maps' before marking the
+ * cacheline idle, but we should also be flagging overlaps as an API
+ * violation.
*
* Memory usage is mostly constrained by the maximum number of available
* dma-debug entries in that we need a free dma_debug_entry before
- * inserting into the tree. In the case of dma_map_{single|page} and
- * dma_alloc_coherent there is only one dma_debug_entry and one pfn to
- * track per event. dma_map_sg(), on the other hand,
- * consumes a single dma_debug_entry, but inserts 'nents' entries into
- * the tree.
+ * inserting into the tree. In the case of dma_map_page and
+ * dma_alloc_coherent there is only one dma_debug_entry and one
+ * dma_active_cacheline entry to track per event. dma_map_sg(), on the
+ * other hand, consumes a single dma_debug_entry, but inserts 'nents'
+ * entries into the tree.
*
* At any time debug_dma_assert_idle() can be called to trigger a
- * warning if the given page is in the active set.
+ * warning if any cachelines in the given page are in the active set.
*/
-static RADIX_TREE(dma_active_pfn, GFP_NOWAIT);
+static RADIX_TREE(dma_active_cacheline, GFP_NOWAIT);
static DEFINE_SPINLOCK(radix_lock);
-#define ACTIVE_PFN_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
+#define ACTIVE_CACHELINE_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
+#define CACHELINE_PER_PAGE_SHIFT (PAGE_SHIFT - L1_CACHE_SHIFT)
+#define CACHELINES_PER_PAGE (1 << CACHELINE_PER_PAGE_SHIFT)
-static int active_pfn_read_overlap(unsigned long pfn)
+static phys_addr_t to_cacheline_number(struct dma_debug_entry *entry)
+{
+ return (entry->pfn << CACHELINE_PER_PAGE_SHIFT) +
+ (entry->offset >> L1_CACHE_SHIFT);
+}
+
+static int active_cacheline_read_overlap(phys_addr_t cln)
{
int overlap = 0, i;
for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
- if (radix_tree_tag_get(&dma_active_pfn, pfn, i))
+ if (radix_tree_tag_get(&dma_active_cacheline, cln, i))
overlap |= 1 << i;
return overlap;
}
-static int active_pfn_set_overlap(unsigned long pfn, int overlap)
+static int active_cacheline_set_overlap(phys_addr_t cln, int overlap)
{
int i;
- if (overlap > ACTIVE_PFN_MAX_OVERLAP || overlap < 0)
- return 0;
+ if (overlap > ACTIVE_CACHELINE_MAX_OVERLAP || overlap < 0)
+ return overlap;
for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
if (overlap & 1 << i)
- radix_tree_tag_set(&dma_active_pfn, pfn, i);
+ radix_tree_tag_set(&dma_active_cacheline, cln, i);
else
- radix_tree_tag_clear(&dma_active_pfn, pfn, i);
+ radix_tree_tag_clear(&dma_active_cacheline, cln, i);
return overlap;
}
-static void active_pfn_inc_overlap(unsigned long pfn)
+static void active_cacheline_inc_overlap(phys_addr_t cln)
{
- int overlap = active_pfn_read_overlap(pfn);
+ int overlap = active_cacheline_read_overlap(cln);
- overlap = active_pfn_set_overlap(pfn, ++overlap);
+ overlap = active_cacheline_set_overlap(cln, ++overlap);
/* If we overflowed the overlap counter then we're potentially
* leaking dma-mappings. Otherwise, if maps and unmaps are
* balanced then this overflow may cause false negatives in
- * debug_dma_assert_idle() as the pfn may be marked idle
+ * debug_dma_assert_idle() as the cacheline may be marked idle
* prematurely.
*/
- WARN_ONCE(overlap == 0,
- "DMA-API: exceeded %d overlapping mappings of pfn %lx\n",
- ACTIVE_PFN_MAX_OVERLAP, pfn);
+ WARN_ONCE(overlap > ACTIVE_CACHELINE_MAX_OVERLAP,
+ "DMA-API: exceeded %d overlapping mappings of cacheline %pa\n",
+ ACTIVE_CACHELINE_MAX_OVERLAP, &cln);
}
-static int active_pfn_dec_overlap(unsigned long pfn)
+static int active_cacheline_dec_overlap(phys_addr_t cln)
{
- int overlap = active_pfn_read_overlap(pfn);
+ int overlap = active_cacheline_read_overlap(cln);
- return active_pfn_set_overlap(pfn, --overlap);
+ return active_cacheline_set_overlap(cln, --overlap);
}
-static int active_pfn_insert(struct dma_debug_entry *entry)
+static int active_cacheline_insert(struct dma_debug_entry *entry)
{
+ phys_addr_t cln = to_cacheline_number(entry);
unsigned long flags;
int rc;
+ /* If the device is not writing memory then we don't have any
+ * concerns about the cpu consuming stale data. This mitigates
+ * legitimate usages of overlapping mappings.
+ */
+ if (entry->direction == DMA_TO_DEVICE)
+ return 0;
+
spin_lock_irqsave(&radix_lock, flags);
- rc = radix_tree_insert(&dma_active_pfn, entry->pfn, entry);
+ rc = radix_tree_insert(&dma_active_cacheline, cln, entry);
if (rc == -EEXIST)
- active_pfn_inc_overlap(entry->pfn);
+ active_cacheline_inc_overlap(cln);
spin_unlock_irqrestore(&radix_lock, flags);
return rc;
}
-static void active_pfn_remove(struct dma_debug_entry *entry)
+static void active_cacheline_remove(struct dma_debug_entry *entry)
{
+ phys_addr_t cln = to_cacheline_number(entry);
unsigned long flags;
+ /* ...mirror the insert case */
+ if (entry->direction == DMA_TO_DEVICE)
+ return;
+
spin_lock_irqsave(&radix_lock, flags);
- if (active_pfn_dec_overlap(entry->pfn) == 0)
- radix_tree_delete(&dma_active_pfn, entry->pfn);
+ /* since we are counting overlaps the final put of the
+ * cacheline will occur when the overlap count is 0.
+ * active_cacheline_dec_overlap() returns -1 in that case
+ */
+ if (active_cacheline_dec_overlap(cln) < 0)
+ radix_tree_delete(&dma_active_cacheline, cln);
spin_unlock_irqrestore(&radix_lock, flags);
}
/**
* debug_dma_assert_idle() - assert that a page is not undergoing dma
- * @page: page to lookup in the dma_active_pfn tree
+ * @page: page to lookup in the dma_active_cacheline tree
*
* Place a call to this routine in cases where the cpu touching the page
* before the dma completes (page is dma_unmapped) will lead to data
@@ -532,22 +559,38 @@ static void active_pfn_remove(struct dma_debug_entry *entry)
*/
void debug_dma_assert_idle(struct page *page)
{
+ static struct dma_debug_entry *ents[CACHELINES_PER_PAGE];
+ struct dma_debug_entry *entry = NULL;
+ void **results = (void **) &ents;
+ unsigned int nents, i;
unsigned long flags;
- struct dma_debug_entry *entry;
+ phys_addr_t cln;
if (!page)
return;
+ cln = (phys_addr_t) page_to_pfn(page) << CACHELINE_PER_PAGE_SHIFT;
spin_lock_irqsave(&radix_lock, flags);
- entry = radix_tree_lookup(&dma_active_pfn, page_to_pfn(page));
+ nents = radix_tree_gang_lookup(&dma_active_cacheline, results, cln,
+ CACHELINES_PER_PAGE);
+ for (i = 0; i < nents; i++) {
+ phys_addr_t ent_cln = to_cacheline_number(ents[i]);
+
+ if (ent_cln == cln) {
+ entry = ents[i];
+ break;
+ } else if (ent_cln >= cln + CACHELINES_PER_PAGE)
+ break;
+ }
spin_unlock_irqrestore(&radix_lock, flags);
if (!entry)
return;
+ cln = to_cacheline_number(entry);
err_printk(entry->dev, entry,
- "DMA-API: cpu touching an active dma mapped page "
- "[pfn=0x%lx]\n", entry->pfn);
+ "DMA-API: cpu touching an active dma mapped cacheline [cln=%pa]\n",
+ &cln);
}
/*
@@ -564,9 +607,9 @@ static void add_dma_entry(struct dma_debug_entry *entry)
hash_bucket_add(bucket, entry);
put_hash_bucket(bucket, &flags);
- rc = active_pfn_insert(entry);
+ rc = active_cacheline_insert(entry);
if (rc == -ENOMEM) {
- pr_err("DMA-API: pfn tracking ENOMEM, dma-debug disabled\n");
+ pr_err("DMA-API: cacheline tracking ENOMEM, dma-debug disabled\n");
global_disable = true;
}
@@ -627,7 +670,7 @@ static void dma_entry_free(struct dma_debug_entry *entry)
{
unsigned long flags;
- active_pfn_remove(entry);
+ active_cacheline_remove(entry);
/*
* add to beginning of the list - this way the entries are
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index c37aeacd765..7288e38e175 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -8,6 +8,7 @@
* By Greg Banks <gnb@melbourne.sgi.com>
* Copyright (c) 2008 Silicon Graphics Inc. All Rights Reserved.
* Copyright (C) 2011 Bart Van Assche. All Rights Reserved.
+ * Copyright (C) 2013 Du, Changbin <changbin.du@gmail.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
@@ -24,6 +25,7 @@
#include <linux/sysctl.h>
#include <linux/ctype.h>
#include <linux/string.h>
+#include <linux/parser.h>
#include <linux/string_helpers.h>
#include <linux/uaccess.h>
#include <linux/dynamic_debug.h>
@@ -147,7 +149,8 @@ static int ddebug_change(const struct ddebug_query *query,
list_for_each_entry(dt, &ddebug_tables, link) {
/* match against the module name */
- if (query->module && strcmp(query->module, dt->mod_name))
+ if (query->module &&
+ !match_wildcard(query->module, dt->mod_name))
continue;
for (i = 0; i < dt->num_ddebugs; i++) {
@@ -155,14 +158,16 @@ static int ddebug_change(const struct ddebug_query *query,
/* match against the source filename */
if (query->filename &&
- strcmp(query->filename, dp->filename) &&
- strcmp(query->filename, kbasename(dp->filename)) &&
- strcmp(query->filename, trim_prefix(dp->filename)))
+ !match_wildcard(query->filename, dp->filename) &&
+ !match_wildcard(query->filename,
+ kbasename(dp->filename)) &&
+ !match_wildcard(query->filename,
+ trim_prefix(dp->filename)))
continue;
/* match against the function */
if (query->function &&
- strcmp(query->function, dp->function))
+ !match_wildcard(query->function, dp->function))
continue;
/* match against the format */
@@ -263,14 +268,12 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
*/
static inline int parse_lineno(const char *str, unsigned int *val)
{
- char *end = NULL;
BUG_ON(str == NULL);
if (*str == '\0') {
*val = 0;
return 0;
}
- *val = simple_strtoul(str, &end, 10);
- if (end == NULL || end == str || *end != '\0') {
+ if (kstrtouint(str, 10, val) < 0) {
pr_err("bad line-number: %s\n", str);
return -EINVAL;
}
@@ -343,14 +346,14 @@ static int ddebug_parse_query(char *words[], int nwords,
}
if (last)
*last++ = '\0';
- if (parse_lineno(first, &query->first_lineno) < 0) {
- pr_err("line-number is <0\n");
+ if (parse_lineno(first, &query->first_lineno) < 0)
return -EINVAL;
- }
if (last) {
/* range <first>-<last> */
- if (parse_lineno(last, &query->last_lineno)
- < query->first_lineno) {
+ if (parse_lineno(last, &query->last_lineno) < 0)
+ return -EINVAL;
+
+ if (query->last_lineno < query->first_lineno) {
pr_err("last-line:%d < 1st-line:%d\n",
query->last_lineno,
query->first_lineno);
diff --git a/lib/flex_array.c b/lib/flex_array.c
index 6948a6692fc..2eed22fa507 100644
--- a/lib/flex_array.c
+++ b/lib/flex_array.c
@@ -90,8 +90,8 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total,
{
struct flex_array *ret;
int elems_per_part = 0;
- int reciprocal_elems = 0;
int max_size = 0;
+ struct reciprocal_value reciprocal_elems = { 0 };
if (element_size) {
elems_per_part = FLEX_ARRAY_ELEMENTS_PER_PART(element_size);
@@ -119,6 +119,11 @@ EXPORT_SYMBOL(flex_array_alloc);
static int fa_element_to_part_nr(struct flex_array *fa,
unsigned int element_nr)
{
+ /*
+ * if element_size == 0 we don't get here, so we never touch
+ * the zeroed fa->reciprocal_elems, which would yield invalid
+ * results
+ */
return reciprocal_divide(element_nr, fa->reciprocal_elems);
}
diff --git a/lib/fonts/Kconfig b/lib/fonts/Kconfig
index 34fd931b54b..4dc1b990aa2 100644
--- a/lib/fonts/Kconfig
+++ b/lib/fonts/Kconfig
@@ -9,7 +9,7 @@ if FONT_SUPPORT
config FONTS
bool "Select compiled-in fonts"
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE
help
Say Y here if you would like to use fonts other than the default
your frame buffer console usually use.
@@ -22,7 +22,7 @@ config FONTS
config FONT_8x8
bool "VGA 8x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE
default y if !SPARC && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
@@ -45,7 +45,7 @@ config FONT_8x16
config FONT_6x11
bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE
default y if !SPARC && !FONTS && MAC
help
Small console font with Macintosh-style high-half glyphs. Some Mac
diff --git a/lib/genalloc.c b/lib/genalloc.c
index dda31168844..bdb9a456bcb 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -316,7 +316,7 @@ EXPORT_SYMBOL(gen_pool_alloc);
* gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
* @pool: pool to allocate from
* @size: number of bytes to allocate from the pool
- * @dma: dma-view physical address
+ * @dma: dma-view physical address return value. Use NULL if unneeded.
*
* Allocate the requested number of bytes from the specified pool.
* Uses the pool allocation function (with first-fit algorithm by default).
@@ -334,7 +334,8 @@ void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
if (!vaddr)
return NULL;
- *dma = gen_pool_virt_to_phys(pool, vaddr);
+ if (dma)
+ *dma = gen_pool_virt_to_phys(pool, vaddr);
return (void *)vaddr;
}
diff --git a/lib/hash.c b/lib/hash.c
new file mode 100644
index 00000000000..fea973f4bd5
--- /dev/null
+++ b/lib/hash.c
@@ -0,0 +1,39 @@
+/* General purpose hashing library
+ *
+ * That's a start of a kernel hashing library, which can be extended
+ * with further algorithms in future. arch_fast_hash{2,}() will
+ * eventually resolve to an architecture optimized implementation.
+ *
+ * Copyright 2013 Francesco Fusco <ffusco@redhat.com>
+ * Copyright 2013 Daniel Borkmann <dborkman@redhat.com>
+ * Copyright 2013 Thomas Graf <tgraf@redhat.com>
+ * Licensed under the GNU General Public License, version 2.0 (GPLv2)
+ */
+
+#include <linux/jhash.h>
+#include <linux/hash.h>
+#include <linux/cache.h>
+
+static struct fast_hash_ops arch_hash_ops __read_mostly = {
+ .hash = jhash,
+ .hash2 = jhash2,
+};
+
+u32 arch_fast_hash(const void *data, u32 len, u32 seed)
+{
+ return arch_hash_ops.hash(data, len, seed);
+}
+EXPORT_SYMBOL_GPL(arch_fast_hash);
+
+u32 arch_fast_hash2(const u32 *data, u32 len, u32 seed)
+{
+ return arch_hash_ops.hash2(data, len, seed);
+}
+EXPORT_SYMBOL_GPL(arch_fast_hash2);
+
+static int __init hashlib_init(void)
+{
+ setup_arch_fast_hash(&arch_hash_ops);
+ return 0;
+}
+early_initcall(hashlib_init);
diff --git a/lib/kobject.c b/lib/kobject.c
index b0b26665c61..cb14aeac4cc 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -779,6 +779,7 @@ const struct sysfs_ops kobj_sysfs_ops = {
.show = kobj_attr_show,
.store = kobj_attr_store,
};
+EXPORT_SYMBOL_GPL(kobj_sysfs_ops);
/**
* kset_register - initialize and add a kset.
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 52e5abbc41d..5f72767ddd9 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -88,11 +88,17 @@ out:
#ifdef CONFIG_NET
static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
{
- struct kobject *kobj = data;
+ struct kobject *kobj = data, *ksobj;
const struct kobj_ns_type_operations *ops;
ops = kobj_ns_ops(kobj);
- if (ops) {
+ if (!ops && kobj->kset) {
+ ksobj = &kobj->kset->kobj;
+ if (ksobj->parent != NULL)
+ ops = kobj_ns_ops(ksobj->parent);
+ }
+
+ if (ops && ops->netlink_ns && kobj->ktype->namespace) {
const void *sock_ns, *ns;
ns = kobj->ktype->namespace(kobj);
sock_ns = ops->netlink_ns(dsk);
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index f78ae0c0c4e..ec8da78df9b 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)
rv = _parse_integer(s, base, &_res);
if (rv & KSTRTOX_OVERFLOW)
return -ERANGE;
- rv &= ~KSTRTOX_OVERFLOW;
if (rv == 0)
return -EINVAL;
s += rv;
diff --git a/lib/parser.c b/lib/parser.c
index 807b2aaa33f..b6d11631231 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[])
return p->token;
}
+EXPORT_SYMBOL(match_token);
/**
* 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)
{
return match_number(s, result, 0);
}
+EXPORT_SYMBOL(match_int);
/**
* 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)
{
return match_number(s, result, 8);
}
+EXPORT_SYMBOL(match_octal);
/**
* 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)
{
return match_number(s, result, 16);
}
+EXPORT_SYMBOL(match_hex);
+
+/**
+ * match_wildcard: - parse if a string matches given wildcard pattern
+ * @pattern: wildcard pattern
+ * @str: the string to be parsed
+ *
+ * Description: Parse the string @str to check if matches wildcard
+ * pattern @pattern. The pattern may contain two type wildcardes:
+ * '*' - matches zero or more characters
+ * '?' - matches one character
+ * If it's matched, return true, else return false.
+ */
+bool match_wildcard(const char *pattern, const char *str)
+{
+ const char *s = str;
+ const char *p = pattern;
+ bool star = false;
+
+ while (*s) {
+ switch (*p) {
+ case '?':
+ s++;
+ p++;
+ break;
+ case '*':
+ star = true;
+ str = s;
+ if (!*++p)
+ return true;
+ pattern = p;
+ break;
+ default:
+ if (*s == *p) {
+ s++;
+ p++;
+ } else {
+ if (!star)
+ return false;
+ str++;
+ s = str;
+ p = pattern;
+ }
+ break;
+ }
+ }
+
+ if (*p == '*')
+ ++p;
+ return !*p;
+}
+EXPORT_SYMBOL(match_wildcard);
/**
* 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)
}
return ret;
}
+EXPORT_SYMBOL(match_strlcpy);
/**
* match_strdup: - allocate a new string with the contents of a substring_t
@@ -230,10 +286,4 @@ char *match_strdup(const substring_t *s)
match_strlcpy(p, s, sz);
return p;
}
-
-EXPORT_SYMBOL(match_token);
-EXPORT_SYMBOL(match_int);
-EXPORT_SYMBOL(match_octal);
-EXPORT_SYMBOL(match_hex);
-EXPORT_SYMBOL(match_strlcpy);
EXPORT_SYMBOL(match_strdup);
diff --git a/lib/percpu_ida.c b/lib/percpu_ida.c
index 9d054bf91d0..93d145e5539 100644
--- a/lib/percpu_ida.c
+++ b/lib/percpu_ida.c
@@ -54,9 +54,7 @@ static inline void move_tags(unsigned *dst, unsigned *dst_nr,
/*
* Try to steal tags from a remote cpu's percpu freelist.
*
- * We first check how many percpu freelists have tags - we don't steal tags
- * unless enough percpu freelists have tags on them that it's possible more than
- * half the total tags could be stuck on remote percpu freelists.
+ * We first check how many percpu freelists have tags
*
* Then we iterate through the cpus until we find some tags - we don't attempt
* to find the "best" cpu to steal from, to keep cacheline bouncing to a
@@ -69,8 +67,7 @@ static inline void steal_tags(struct percpu_ida *pool,
struct percpu_ida_cpu *remote;
for (cpus_have_tags = cpumask_weight(&pool->cpus_have_tags);
- cpus_have_tags * pool->percpu_max_size > pool->nr_tags / 2;
- cpus_have_tags--) {
+ cpus_have_tags; cpus_have_tags--) {
cpu = cpumask_next(cpu, &pool->cpus_have_tags);
if (cpu >= nr_cpu_ids) {
@@ -132,22 +129,22 @@ static inline unsigned alloc_local_tag(struct percpu_ida_cpu *tags)
/**
* percpu_ida_alloc - allocate a tag
* @pool: pool to allocate from
- * @gfp: gfp flags
+ * @state: task state for prepare_to_wait
*
* Returns a tag - an integer in the range [0..nr_tags) (passed to
* tag_pool_init()), or otherwise -ENOSPC on allocation failure.
*
* Safe to be called from interrupt context (assuming it isn't passed
- * __GFP_WAIT, of course).
+ * TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, of course).
*
* @gfp indicates whether or not to wait until a free id is available (it's not
* used for internal memory allocations); thus if passed __GFP_WAIT we may sleep
* however long it takes until another thread frees an id (same semantics as a
* mempool).
*
- * Will not fail if passed __GFP_WAIT.
+ * Will not fail if passed TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE.
*/
-int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp)
+int percpu_ida_alloc(struct percpu_ida *pool, int state)
{
DEFINE_WAIT(wait);
struct percpu_ida_cpu *tags;
@@ -174,7 +171,8 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp)
*
* global lock held and irqs disabled, don't need percpu lock
*/
- prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
+ if (state != TASK_RUNNING)
+ prepare_to_wait(&pool->wait, &wait, state);
if (!tags->nr_free)
alloc_global_tags(pool, tags);
@@ -191,16 +189,22 @@ int percpu_ida_alloc(struct percpu_ida *pool, gfp_t gfp)
spin_unlock(&pool->lock);
local_irq_restore(flags);
- if (tag >= 0 || !(gfp & __GFP_WAIT))
+ if (tag >= 0 || state == TASK_RUNNING)
break;
+ if (signal_pending_state(state, current)) {
+ tag = -ERESTARTSYS;
+ break;
+ }
+
schedule();
local_irq_save(flags);
tags = this_cpu_ptr(pool->tag_cpu);
}
+ if (state != TASK_RUNNING)
+ finish_wait(&pool->wait, &wait);
- finish_wait(&pool->wait, &wait);
return tag;
}
EXPORT_SYMBOL_GPL(percpu_ida_alloc);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 7811ed3b4e7..bd4a8dfdf0b 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -1253,8 +1253,10 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
node = indirect_to_ptr(node);
max_index = radix_tree_maxindex(node->height);
- if (cur_index > max_index)
+ if (cur_index > max_index) {
+ rcu_read_unlock();
break;
+ }
cur_index = __locate(node, item, cur_index, &found_index);
rcu_read_unlock();
diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c
index 31dd4ccd3ba..8b3c9dc8826 100644
--- a/lib/rbtree_test.c
+++ b/lib/rbtree_test.c
@@ -8,8 +8,8 @@
#define CHECK_LOOPS 100
struct test_node {
- struct rb_node rb;
u32 key;
+ struct rb_node rb;
/* following fields used for testing augmented rbtree functionality */
u32 val;
@@ -114,6 +114,16 @@ static int black_path_count(struct rb_node *rb)
return count;
}
+static void check_postorder_foreach(int nr_nodes)
+{
+ struct test_node *cur, *n;
+ int count = 0;
+ rbtree_postorder_for_each_entry_safe(cur, n, &root, rb)
+ count++;
+
+ WARN_ON_ONCE(count != nr_nodes);
+}
+
static void check_postorder(int nr_nodes)
{
struct rb_node *rb;
@@ -148,6 +158,7 @@ static void check(int nr_nodes)
WARN_ON_ONCE(count < (1 << black_path_count(rb_last(&root))) - 1);
check_postorder(nr_nodes);
+ check_postorder_foreach(nr_nodes);
}
static void check_augmented(int nr_nodes)
diff --git a/lib/reciprocal_div.c b/lib/reciprocal_div.c
index 75510e94f7d..464152410c5 100644
--- a/lib/reciprocal_div.c
+++ b/lib/reciprocal_div.c
@@ -1,11 +1,27 @@
+#include <linux/kernel.h>
#include <asm/div64.h>
#include <linux/reciprocal_div.h>
#include <linux/export.h>
-u32 reciprocal_value(u32 k)
+/*
+ * For a description of the algorithm please have a look at
+ * include/linux/reciprocal_div.h
+ */
+
+struct reciprocal_value reciprocal_value(u32 d)
{
- u64 val = (1LL << 32) + (k - 1);
- do_div(val, k);
- return (u32)val;
+ struct reciprocal_value R;
+ u64 m;
+ int l;
+
+ l = fls(d - 1);
+ m = ((1ULL << 32) * ((1ULL << l) - d));
+ do_div(m, d);
+ ++m;
+ R.m = (u32)m;
+ R.sh1 = min(l, 1);
+ R.sh2 = max(l - 1, 0);
+
+ return R;
}
EXPORT_SYMBOL(reciprocal_value);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 615f3de4b5c..b604b831f4d 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -172,7 +172,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
/*
* Get the overflow emergency buffer
*/
- v_overflow_buffer = memblock_virt_alloc_nopanic(
+ v_overflow_buffer = memblock_virt_alloc_low_nopanic(
PAGE_ALIGN(io_tlb_overflow),
PAGE_SIZE);
if (!v_overflow_buffer)
@@ -220,7 +220,7 @@ swiotlb_init(int verbose)
bytes = io_tlb_nslabs << IO_TLB_SHIFT;
/* Get IO TLB memory from the low pages */
- vstart = memblock_virt_alloc_nopanic(PAGE_ALIGN(bytes), PAGE_SIZE);
+ vstart = memblock_virt_alloc_low_nopanic(PAGE_ALIGN(bytes), PAGE_SIZE);
if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
return;
@@ -510,7 +510,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
not_found:
spin_unlock_irqrestore(&io_tlb_lock, flags);
- dev_warn(hwdev, "swiotlb buffer is full\n");
+ if (printk_ratelimit())
+ dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", size);
return SWIOTLB_MAP_ERROR;
found:
spin_unlock_irqrestore(&io_tlb_lock, flags);
diff --git a/lib/test_module.c b/lib/test_module.c
new file mode 100644
index 00000000000..319b66f1ff6
--- /dev/null
+++ b/lib/test_module.c
@@ -0,0 +1,33 @@
+/*
+ * This module emits "Hello, world" on printk when loaded.
+ *
+ * It is designed to be used for basic evaluation of the module loading
+ * subsystem (for example when validating module signing/verification). It
+ * lacks any extra dependencies, and will not normally be loaded by the
+ * system unless explicitly requested by name.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+static int __init test_module_init(void)
+{
+ pr_warn("Hello, world\n");
+
+ return 0;
+}
+
+module_init(test_module_init);
+
+static void __exit test_module_exit(void)
+{
+ pr_warn("Goodbye\n");
+}
+
+module_exit(test_module_exit);
+
+MODULE_AUTHOR("Kees Cook <keescook@chromium.org>");
+MODULE_LICENSE("GPL");
diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c
new file mode 100644
index 00000000000..0ecef3e4690
--- /dev/null
+++ b/lib/test_user_copy.c
@@ -0,0 +1,110 @@
+/*
+ * Kernel module for testing copy_to/from_user infrastructure.
+ *
+ * Copyright 2013 Google Inc. All Rights Reserved
+ *
+ * Authors:
+ * Kees Cook <keescook@chromium.org>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mman.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
+#define test(condition, msg) \
+({ \
+ int cond = (condition); \
+ if (cond) \
+ pr_warn("%s\n", msg); \
+ cond; \
+})
+
+static int __init test_user_copy_init(void)
+{
+ int ret = 0;
+ char *kmem;
+ char __user *usermem;
+ char *bad_usermem;
+ unsigned long user_addr;
+ unsigned long value = 0x5A;
+
+ kmem = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
+ if (!kmem)
+ return -ENOMEM;
+
+ user_addr = vm_mmap(NULL, 0, PAGE_SIZE * 2,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_ANONYMOUS | MAP_PRIVATE, 0);
+ if (user_addr >= (unsigned long)(TASK_SIZE)) {
+ pr_warn("Failed to allocate user memory\n");
+ kfree(kmem);
+ return -ENOMEM;
+ }
+
+ usermem = (char __user *)user_addr;
+ bad_usermem = (char *)user_addr;
+
+ /* Legitimate usage: none of these should fail. */
+ ret |= test(copy_from_user(kmem, usermem, PAGE_SIZE),
+ "legitimate copy_from_user failed");
+ ret |= test(copy_to_user(usermem, kmem, PAGE_SIZE),
+ "legitimate copy_to_user failed");
+ ret |= test(get_user(value, (unsigned long __user *)usermem),
+ "legitimate get_user failed");
+ ret |= test(put_user(value, (unsigned long __user *)usermem),
+ "legitimate put_user failed");
+
+ /* Invalid usage: none of these should succeed. */
+ ret |= test(!copy_from_user(kmem, (char __user *)(kmem + PAGE_SIZE),
+ PAGE_SIZE),
+ "illegal all-kernel copy_from_user passed");
+ ret |= test(!copy_from_user(bad_usermem, (char __user *)kmem,
+ PAGE_SIZE),
+ "illegal reversed copy_from_user passed");
+ ret |= test(!copy_to_user((char __user *)kmem, kmem + PAGE_SIZE,
+ PAGE_SIZE),
+ "illegal all-kernel copy_to_user passed");
+ ret |= test(!copy_to_user((char __user *)kmem, bad_usermem,
+ PAGE_SIZE),
+ "illegal reversed copy_to_user passed");
+ ret |= test(!get_user(value, (unsigned long __user *)kmem),
+ "illegal get_user passed");
+ ret |= test(!put_user(value, (unsigned long __user *)kmem),
+ "illegal put_user passed");
+
+ vm_munmap(user_addr, PAGE_SIZE * 2);
+ kfree(kmem);
+
+ if (ret == 0) {
+ pr_info("tests passed.\n");
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+module_init(test_user_copy_init);
+
+static void __exit test_user_copy_exit(void)
+{
+ pr_info("unloaded.\n");
+}
+
+module_exit(test_user_copy_exit);
+
+MODULE_AUTHOR("Kees Cook <keescook@chromium.org>");
+MODULE_LICENSE("GPL");
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 10909c57149..185b6d300eb 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1155,6 +1155,30 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr,
return number(buf, end, *(const netdev_features_t *)addr, spec);
}
+static noinline_for_stack
+char *address_val(char *buf, char *end, const void *addr,
+ struct printf_spec spec, const char *fmt)
+{
+ unsigned long long num;
+
+ spec.flags |= SPECIAL | SMALL | ZEROPAD;
+ spec.base = 16;
+
+ switch (fmt[1]) {
+ case 'd':
+ num = *(const dma_addr_t *)addr;
+ spec.field_width = sizeof(dma_addr_t) * 2 + 2;
+ break;
+ case 'p':
+ default:
+ num = *(const phys_addr_t *)addr;
+ spec.field_width = sizeof(phys_addr_t) * 2 + 2;
+ break;
+ }
+
+ return number(buf, end, num, spec);
+}
+
int kptr_restrict __read_mostly;
/*
@@ -1218,7 +1242,8 @@ int kptr_restrict __read_mostly;
* N no separator
* The maximum supported length is 64 bytes of the input. Consider
* to use print_hex_dump() for the larger input.
- * - 'a' For a phys_addr_t type and its derivative types (passed by reference)
+ * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives
+ * (default assumed to be phys_addr_t, passed by reference)
* - 'd[234]' For a dentry name (optionally 2-4 last components)
* - 'D[234]' Same as 'd' but for a struct file
*
@@ -1353,11 +1378,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
}
break;
case 'a':
- spec.flags |= SPECIAL | SMALL | ZEROPAD;
- spec.field_width = sizeof(phys_addr_t) * 2 + 2;
- spec.base = 16;
- return number(buf, end,
- (unsigned long long) *((phys_addr_t *)ptr), spec);
+ return address_val(buf, end, ptr, spec, fmt);
case 'd':
return dentry_name(buf, end, ptr, spec, fmt);
case 'D':