diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig | 1 | ||||
| -rw-r--r-- | lib/Kconfig.debug | 1 | ||||
| -rw-r--r-- | lib/fault-inject.c | 2 | ||||
| -rw-r--r-- | lib/iommu-common.c | 6 | ||||
| -rw-r--r-- | lib/rhashtable.c | 5 | ||||
| -rw-r--r-- | lib/string.c | 89 | ||||
| -rw-r--r-- | lib/string_helpers.c | 6 | 
7 files changed, 101 insertions, 9 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 2e491ac15622..f0df318104e7 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -220,6 +220,7 @@ config ZLIB_INFLATE  config ZLIB_DEFLATE  	tristate +	select BITREVERSE  config LZO_COMPRESS  	tristate diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ab76b99adc85..1d1521c26302 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -197,6 +197,7 @@ config ENABLE_MUST_CHECK  config FRAME_WARN  	int "Warn for stack frames larger than (needs gcc 4.4)"  	range 0 8192 +	default 0 if KASAN  	default 1024 if !64BIT  	default 2048 if 64BIT  	help diff --git a/lib/fault-inject.c b/lib/fault-inject.c index f1cdeb024d17..6a823a53e357 100644 --- a/lib/fault-inject.c +++ b/lib/fault-inject.c @@ -44,7 +44,7 @@ static void fail_dump(struct fault_attr *attr)  		printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n"  		       "name %pd, interval %lu, probability %lu, "  		       "space %d, times %d\n", attr->dname, -		       attr->probability, attr->interval, +		       attr->interval, attr->probability,  		       atomic_read(&attr->space),  		       atomic_read(&attr->times));  		if (attr->verbose > 1) diff --git a/lib/iommu-common.c b/lib/iommu-common.c index ff19f66d3f7f..b1c93e94ca7a 100644 --- a/lib/iommu-common.c +++ b/lib/iommu-common.c @@ -21,8 +21,7 @@ static	DEFINE_PER_CPU(unsigned int, iommu_hash_common);  static inline bool need_flush(struct iommu_map_table *iommu)  { -	return (iommu->lazy_flush != NULL && -		(iommu->flags & IOMMU_NEED_FLUSH) != 0); +	return ((iommu->flags & IOMMU_NEED_FLUSH) != 0);  }  static inline void set_flush(struct iommu_map_table *iommu) @@ -211,7 +210,8 @@ unsigned long iommu_tbl_range_alloc(struct device *dev,  			goto bail;  		}  	} -	if (n < pool->hint || need_flush(iommu)) { +	if (iommu->lazy_flush && +	    (n < pool->hint || need_flush(iommu))) {  		clear_flush(iommu);  		iommu->lazy_flush(iommu);  	} diff --git a/lib/rhashtable.c b/lib/rhashtable.c index cc0c69710dcf..a54ff8949f91 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -187,10 +187,7 @@ static int rhashtable_rehash_one(struct rhashtable *ht, unsigned int old_hash)  	head = rht_dereference_bucket(new_tbl->buckets[new_hash],  				      new_tbl, new_hash); -	if (rht_is_a_nulls(head)) -		INIT_RHT_NULLS_HEAD(entry->next, ht, new_hash); -	else -		RCU_INIT_POINTER(entry->next, head); +	RCU_INIT_POINTER(entry->next, head);  	rcu_assign_pointer(new_tbl->buckets[new_hash], entry);  	spin_unlock(new_bucket_lock); diff --git a/lib/string.c b/lib/string.c index 13d1e84ddb80..84775ba873b9 100644 --- a/lib/string.c +++ b/lib/string.c @@ -27,6 +27,10 @@  #include <linux/bug.h>  #include <linux/errno.h> +#include <asm/byteorder.h> +#include <asm/word-at-a-time.h> +#include <asm/page.h> +  #ifndef __HAVE_ARCH_STRNCASECMP  /**   * strncasecmp - Case insensitive, length-limited string comparison @@ -146,6 +150,91 @@ size_t strlcpy(char *dest, const char *src, size_t size)  EXPORT_SYMBOL(strlcpy);  #endif +#ifndef __HAVE_ARCH_STRSCPY +/** + * strscpy - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. + * The routine returns the number of characters copied (not including + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. + * The behavior is undefined if the string buffers overlap. + * The destination buffer is always NUL terminated, unless it's zero-sized. + * + * Preferred to strlcpy() since the API doesn't require reading memory + * from the src string beyond the specified "count" bytes, and since + * the return value is easier to error-check than strlcpy()'s. + * In addition, the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation. + * + * Preferred to strncpy() since it always returns a valid string, and + * doesn't unnecessarily force the tail of the destination buffer to be + * zeroed.  If the zeroing is desired, it's likely cleaner to use strscpy() + * with an overflow test, then just memset() the tail of the dest buffer. + */ +ssize_t strscpy(char *dest, const char *src, size_t count) +{ +	const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; +	size_t max = count; +	long res = 0; + +	if (count == 0) +		return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +	/* +	 * If src is unaligned, don't cross a page boundary, +	 * since we don't know if the next page is mapped. +	 */ +	if ((long)src & (sizeof(long) - 1)) { +		size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); +		if (limit < max) +			max = limit; +	} +#else +	/* If src or dest is unaligned, don't do word-at-a-time. */ +	if (((long) dest | (long) src) & (sizeof(long) - 1)) +		max = 0; +#endif + +	while (max >= sizeof(unsigned long)) { +		unsigned long c, data; + +		c = *(unsigned long *)(src+res); +		if (has_zero(c, &data, &constants)) { +			data = prep_zero_mask(c, data, &constants); +			data = create_zero_mask(data); +			*(unsigned long *)(dest+res) = c & zero_bytemask(data); +			return res + find_zero(data); +		} +		*(unsigned long *)(dest+res) = c; +		res += sizeof(unsigned long); +		count -= sizeof(unsigned long); +		max -= sizeof(unsigned long); +	} + +	while (count) { +		char c; + +		c = src[res]; +		dest[res] = c; +		if (!c) +			return res; +		res++; +		count--; +	} + +	/* Hit buffer length without finding a NUL; force NUL-termination. */ +	if (res) +		dest[res-1] = '\0'; + +	return -E2BIG; +} +EXPORT_SYMBOL(strscpy); +#endif +  #ifndef __HAVE_ARCH_STRCAT  /**   * strcat - Append one %NUL-terminated string to another diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 54036ce2e2dd..5939f63d90cd 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -59,7 +59,11 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,  	}  	exp = divisor[units] / (u32)blk_size; -	if (size >= exp) { +	/* +	 * size must be strictly greater than exp here to ensure that remainder +	 * is greater than divisor[units] coming out of the if below. +	 */ +	if (size > exp) {  		remainder = do_div(size, divisor[units]);  		remainder *= blk_size;  		i++;  | 

