Merge tag 'v3.4.113' into lineage-16.0

This is the 3.4.113 stable release

Change-Id: I80791430656359c5447a675cbff4431362d18df0
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
Kevin F. Haggerty
2019-08-05 14:20:47 +02:00
committed by Francescodario Cuzzocrea
parent 36738e5d0d
commit 238a0fb5ad
3036 changed files with 50479 additions and 23994 deletions
+1
View File
@@ -41,6 +41,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
GCOV_PROFILE_hweight.o := n
CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+5 -12
View File
@@ -31,7 +31,11 @@
static union {
raw_spinlock_t lock;
char pad[L1_CACHE_BYTES];
} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp;
} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp = {
[0 ... (NR_LOCKS - 1)] = {
.lock = __RAW_SPIN_LOCK_UNLOCKED(atomic64_lock.lock),
},
};
static inline raw_spinlock_t *lock_addr(const atomic64_t *v)
{
@@ -173,14 +177,3 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u)
return ret;
}
EXPORT_SYMBOL(atomic64_add_unless);
static int init_atomic64_lock(void)
{
int i;
for (i = 0; i < NR_LOCKS; ++i)
raw_spin_lock_init(&atomic64_lock[i].lock);
return 0;
}
pure_initcall(init_atomic64_lock);
+15 -10
View File
@@ -131,7 +131,9 @@ void __bitmap_shift_right(unsigned long *dst,
lower = src[off + k];
if (left && off + k == lim - 1)
lower &= mask;
dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
dst[k] = lower >> rem;
if (rem)
dst[k] |= upper << (BITS_PER_LONG - rem);
if (left && k == lim - 1)
dst[k] &= mask;
}
@@ -172,7 +174,9 @@ void __bitmap_shift_left(unsigned long *dst,
upper = src[k];
if (left && k == lim - 1)
upper &= (1UL << left) - 1;
dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
dst[k + off] = upper << rem;
if (rem)
dst[k + off] |= lower >> (BITS_PER_LONG - rem);
if (left && k + off == lim - 1)
dst[k + off] &= (1UL << left) - 1;
}
@@ -601,12 +605,12 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
unsigned a, b;
int c, old_c, totaldigits;
const char __user __force *ubuf = (const char __user __force *)buf;
int exp_digit, in_range;
int at_start, in_range;
totaldigits = c = 0;
bitmap_zero(maskp, nmaskbits);
do {
exp_digit = 1;
at_start = 1;
in_range = 0;
a = b = 0;
@@ -635,11 +639,10 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
break;
if (c == '-') {
if (exp_digit || in_range)
if (at_start || in_range)
return -EINVAL;
b = 0;
in_range = 1;
exp_digit = 1;
continue;
}
@@ -649,16 +652,18 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
b = b * 10 + (c - '0');
if (!in_range)
a = b;
exp_digit = 0;
at_start = 0;
totaldigits++;
}
if (!(a <= b))
return -EINVAL;
if (b >= nmaskbits)
return -ERANGE;
while (a <= b) {
set_bit(a, maskp);
a++;
if (!at_start) {
while (a <= b) {
set_bit(a, maskp);
a++;
}
}
} while (buflen && c == ',');
return 0;
+3 -2
View File
@@ -198,6 +198,7 @@ EXPORT_SYMBOL_GPL(btree_init);
void btree_destroy(struct btree_head *head)
{
mempool_free(head->node, head->mempool);
mempool_destroy(head->mempool);
head->mempool = NULL;
}
@@ -319,8 +320,8 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
if (head->height == 0)
return NULL;
retry:
longcpy(key, __key, geo->keylen);
retry:
dec_key(geo, key);
node = head->node;
@@ -351,7 +352,7 @@ retry:
}
miss:
if (retry_key) {
__key = retry_key;
longcpy(key, retry_key, geo->keylen);
retry_key = NULL;
goto retry;
}
+10 -2
View File
@@ -179,6 +179,15 @@ csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
EXPORT_SYMBOL(csum_partial_copy);
#ifndef csum_tcpudp_nofold
static inline u32 from64to32(u64 x)
{
/* add up 32-bit and 32-bit for 32+c bit */
x = (x & 0xffffffff) + (x >> 32);
/* add up carry.. */
x = (x & 0xffffffff) + (x >> 32);
return (u32)x;
}
__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
@@ -193,8 +202,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
#else
s += (proto + len) << 8;
#endif
s += (s >> 32);
return (__force __wsum)s;
return (__force __wsum)from64to32(s);
}
EXPORT_SYMBOL(csum_tcpudp_nofold);
#endif
+1 -1
View File
@@ -31,7 +31,7 @@
*/
#ifdef STATIC
#include "lzo/lzo1x_decompress.c"
#include "lzo/lzo1x_decompress_safe.c"
#else
#include <linux/decompress/unlzo.h>
#endif
+1 -1
View File
@@ -421,7 +421,7 @@ void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
if (!iomap)
return;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
for (i = 0; i < PCIM_IOMAP_MAX; i++) {
if (!(mask & (1 << i)))
continue;
+7 -3
View File
@@ -162,10 +162,14 @@ static int digsig_verify_rsa(struct key *key,
memset(out1, 0, head);
memcpy(out1 + head, p, l);
err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
kfree(p);
if (!err && len == hlen)
err = memcmp(out2, h, hlen);
err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
if (err)
goto err;
if (len != hlen || memcmp(out2, h, hlen))
err = -EINVAL;
err:
mpi_free(in);
+11 -7
View File
@@ -10,23 +10,27 @@
#include <linux/jiffies.h>
#include <linux/dynamic_queue_limits.h>
#define POSDIFF(A, B) ((A) > (B) ? (A) - (B) : 0)
#define POSDIFF(A, B) ((int)((A) - (B)) > 0 ? (A) - (B) : 0)
#define AFTER_EQ(A, B) ((int)((A) - (B)) >= 0)
/* Records completed count and recalculates the queue limit */
void dql_completed(struct dql *dql, unsigned int count)
{
unsigned int inprogress, prev_inprogress, limit;
unsigned int ovlimit, all_prev_completed, completed;
unsigned int ovlimit, completed, num_queued;
bool all_prev_completed;
num_queued = ACCESS_ONCE(dql->num_queued);
/* Can't complete more than what's in queue */
BUG_ON(count > dql->num_queued - dql->num_completed);
BUG_ON(count > num_queued - dql->num_completed);
completed = dql->num_completed + count;
limit = dql->limit;
ovlimit = POSDIFF(dql->num_queued - dql->num_completed, limit);
inprogress = dql->num_queued - completed;
ovlimit = POSDIFF(num_queued - dql->num_completed, limit);
inprogress = num_queued - completed;
prev_inprogress = dql->prev_num_queued - dql->num_completed;
all_prev_completed = POSDIFF(completed, dql->prev_num_queued);
all_prev_completed = AFTER_EQ(completed, dql->prev_num_queued);
if ((ovlimit && !inprogress) ||
(dql->prev_ovlimit && all_prev_completed)) {
@@ -104,7 +108,7 @@ void dql_completed(struct dql *dql, unsigned int count)
dql->prev_ovlimit = ovlimit;
dql->prev_last_obj_cnt = dql->last_obj_cnt;
dql->num_completed = completed;
dql->prev_num_queued = dql->num_queued;
dql->prev_num_queued = num_queued;
}
EXPORT_SYMBOL(dql_completed);
+3
View File
@@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b)
if (a < b)
swap(a, b);
if (!b)
return a;
while ((r = a % b) != 0) {
a = b;
b = r;
+22 -14
View File
@@ -39,6 +39,14 @@
static struct kmem_cache *idr_layer_cache;
static DEFINE_SPINLOCK(simple_ida_lock);
/* the maximum ID which can be allocated given idr->layers */
static int idr_max(int layers)
{
int bits = min_t(int, layers * IDR_BITS, MAX_ID_SHIFT);
return (1 << bits) - 1;
}
static struct idr_layer *get_from_free_list(struct idr *idp)
{
struct idr_layer *p;
@@ -223,7 +231,7 @@ build_up:
* Add a new layer to the top of the tree if the requested
* id is larger than the currently allocated space.
*/
while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
while (id > idr_max(layers)) {
layers++;
if (!p->count) {
/* special case: if the tree is currently empty,
@@ -265,7 +273,7 @@ build_up:
static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
{
struct idr_layer *pa[MAX_LEVEL];
struct idr_layer *pa[MAX_LEVEL + 1];
int id;
id = idr_get_empty_slot(idp, starting_id, pa);
@@ -357,7 +365,7 @@ static void idr_remove_warning(int id)
static void sub_remove(struct idr *idp, int shift, int id)
{
struct idr_layer *p = idp->top;
struct idr_layer **pa[MAX_LEVEL];
struct idr_layer **pa[MAX_LEVEL + 1];
struct idr_layer ***paa = &pa[0];
struct idr_layer *to_free;
int n;
@@ -451,16 +459,16 @@ void idr_remove_all(struct idr *idp)
int n, id, max;
int bt_mask;
struct idr_layer *p;
struct idr_layer *pa[MAX_LEVEL];
struct idr_layer *pa[MAX_LEVEL + 1];
struct idr_layer **paa = &pa[0];
n = idp->layers * IDR_BITS;
p = idp->top;
rcu_assign_pointer(idp->top, NULL);
max = 1 << n;
max = idr_max(idp->layers);
id = 0;
while (id < max) {
while (id >= 0 && id <= max) {
while (n > IDR_BITS && p) {
n -= IDR_BITS;
*paa++ = p;
@@ -519,7 +527,7 @@ void *idr_find(struct idr *idp, int id)
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
if (id >= (1 << n))
if (id > idr_max(p->layer + 1))
return NULL;
BUG_ON(n == 0);
@@ -555,15 +563,15 @@ int idr_for_each(struct idr *idp,
{
int n, id, max, error = 0;
struct idr_layer *p;
struct idr_layer *pa[MAX_LEVEL];
struct idr_layer *pa[MAX_LEVEL + 1];
struct idr_layer **paa = &pa[0];
n = idp->layers * IDR_BITS;
p = rcu_dereference_raw(idp->top);
max = 1 << n;
max = idr_max(idp->layers);
id = 0;
while (id < max) {
while (id >= 0 && id <= max) {
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
@@ -601,7 +609,7 @@ EXPORT_SYMBOL(idr_for_each);
*/
void *idr_get_next(struct idr *idp, int *nextidp)
{
struct idr_layer *p, *pa[MAX_LEVEL];
struct idr_layer *p, *pa[MAX_LEVEL + 1];
struct idr_layer **paa = &pa[0];
int id = *nextidp;
int n, max;
@@ -611,9 +619,9 @@ void *idr_get_next(struct idr *idp, int *nextidp)
if (!p)
return NULL;
n = (p->layer + 1) * IDR_BITS;
max = 1 << n;
max = idr_max(p->layer + 1);
while (id < max) {
while (id >= 0 && id <= max) {
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
@@ -787,7 +795,7 @@ EXPORT_SYMBOL(ida_pre_get);
*/
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
{
struct idr_layer *pa[MAX_LEVEL];
struct idr_layer *pa[MAX_LEVEL + 1];
struct ida_bitmap *bitmap;
unsigned long flags;
int idr_id = starting_id / IDA_BITMAP_BITS;
+8 -1
View File
@@ -531,6 +531,13 @@ struct kobject *kobject_get(struct kobject *kobj)
return kobj;
}
static struct kobject *kobject_get_unless_zero(struct kobject *kobj)
{
if (!kref_get_unless_zero(&kobj->kref))
kobj = NULL;
return kobj;
}
/*
* kobject_cleanup - free kobject resources.
* @kobj: object to cleanup
@@ -753,7 +760,7 @@ struct kobject *kset_find_obj(struct kset *kset, const char *name)
list_for_each_entry(k, &kset->list, entry) {
if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
ret = kobject_get(k);
ret = kobject_get_unless_zero(k);
break;
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
lzo_compress-objs := lzo1x_compress.o
lzo_decompress-objs := lzo1x_decompress.o
lzo_decompress-objs := lzo1x_decompress_safe.o
obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
+201 -148
View File
@@ -1,194 +1,243 @@
/*
* LZO1X Compressor from MiniLZO
* LZO1X Compressor from LZO
*
* Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
* Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
* Changed for kernel use by:
* Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/lzo.h>
#include <asm/unaligned.h>
#include <linux/lzo.h>
#include "lzodefs.h"
static noinline size_t
_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len, void *wrkmem)
lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len,
size_t ti, void *wrkmem)
{
const unsigned char *ip;
unsigned char *op;
const unsigned char * const in_end = in + in_len;
const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
const unsigned char ** const dict = wrkmem;
const unsigned char *ip = in, *ii = ip;
const unsigned char *end, *m, *m_pos;
size_t m_off, m_len, dindex;
unsigned char *op = out;
const unsigned char * const ip_end = in + in_len - 20;
const unsigned char *ii;
lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
ip += 4;
op = out;
ip = in;
ii = ip;
ip += ti < 4 ? 4 - ti : 0;
for (;;) {
dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
m_pos = dict[dindex];
if (m_pos < in)
goto literal;
if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
goto literal;
m_off = ip - m_pos;
if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
goto try_match;
dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
m_pos = dict[dindex];
if (m_pos < in)
goto literal;
if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
goto literal;
m_off = ip - m_pos;
if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
goto try_match;
goto literal;
try_match:
if (get_unaligned((const unsigned short *)m_pos)
== get_unaligned((const unsigned short *)ip)) {
if (likely(m_pos[2] == ip[2]))
goto match;
}
const unsigned char *m_pos;
size_t t, m_len, m_off;
u32 dv;
literal:
dict[dindex] = ip;
++ip;
ip += 1 + ((ip - ii) >> 5);
next:
if (unlikely(ip >= ip_end))
break;
continue;
match:
dict[dindex] = ip;
if (ip != ii) {
size_t t = ip - ii;
dv = get_unaligned_le32(ip);
t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
m_pos = in + dict[t];
dict[t] = (lzo_dict_t) (ip - in);
if (unlikely(dv != get_unaligned_le32(m_pos)))
goto literal;
ii -= ti;
ti = 0;
t = ip - ii;
if (t != 0) {
if (t <= 3) {
op[-2] |= t;
} else if (t <= 18) {
COPY4(op, ii);
op += t;
} else if (t <= 16) {
*op++ = (t - 3);
COPY8(op, ii);
COPY8(op + 8, ii + 8);
op += t;
} else {
size_t tt = t - 18;
*op++ = 0;
while (tt > 255) {
tt -= 255;
if (t <= 18) {
*op++ = (t - 3);
} else {
size_t tt = t - 18;
*op++ = 0;
}
*op++ = tt;
}
do {
*op++ = *ii++;
} while (--t > 0);
}
ip += 3;
if (m_pos[3] != *ip++ || m_pos[4] != *ip++
|| m_pos[5] != *ip++ || m_pos[6] != *ip++
|| m_pos[7] != *ip++ || m_pos[8] != *ip++) {
--ip;
m_len = ip - ii;
if (m_off <= M2_MAX_OFFSET) {
m_off -= 1;
*op++ = (((m_len - 1) << 5)
| ((m_off & 7) << 2));
*op++ = (m_off >> 3);
} else if (m_off <= M3_MAX_OFFSET) {
m_off -= 1;
*op++ = (M3_MARKER | (m_len - 2));
goto m3_m4_offset;
} else {
m_off -= 0x4000;
*op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
| (m_len - 2));
goto m3_m4_offset;
}
} else {
end = in_end;
m = m_pos + M2_MAX_LEN + 1;
while (ip < end && *m == *ip) {
m++;
ip++;
}
m_len = ip - ii;
if (m_off <= M3_MAX_OFFSET) {
m_off -= 1;
if (m_len <= 33) {
*op++ = (M3_MARKER | (m_len - 2));
} else {
m_len -= 33;
*op++ = M3_MARKER | 0;
goto m3_m4_len;
}
} else {
m_off -= 0x4000;
if (m_len <= M4_MAX_LEN) {
*op++ = (M4_MARKER
| ((m_off & 0x4000) >> 11)
| (m_len - 2));
} else {
m_len -= M4_MAX_LEN;
*op++ = (M4_MARKER
| ((m_off & 0x4000) >> 11));
m3_m4_len:
while (m_len > 255) {
m_len -= 255;
while (unlikely(tt > 255)) {
tt -= 255;
*op++ = 0;
}
*op++ = (m_len);
*op++ = tt;
}
do {
COPY8(op, ii);
COPY8(op + 8, ii + 8);
op += 16;
ii += 16;
t -= 16;
} while (t >= 16);
if (t > 0) do {
*op++ = *ii++;
} while (--t > 0);
}
m3_m4_offset:
*op++ = ((m_off & 63) << 2);
*op++ = (m_off >> 6);
}
ii = ip;
if (unlikely(ip >= ip_end))
break;
}
m_len = 4;
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
u64 v;
v = get_unaligned((const u64 *) (ip + m_len)) ^
get_unaligned((const u64 *) (m_pos + m_len));
if (unlikely(v == 0)) {
do {
m_len += 8;
v = get_unaligned((const u64 *) (ip + m_len)) ^
get_unaligned((const u64 *) (m_pos + m_len));
if (unlikely(ip + m_len >= ip_end))
goto m_len_done;
} while (v == 0);
}
# if defined(__LITTLE_ENDIAN)
m_len += (unsigned) __builtin_ctzll(v) / 8;
# elif defined(__BIG_ENDIAN)
m_len += (unsigned) __builtin_clzll(v) / 8;
# else
# error "missing endian definition"
# endif
#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
u32 v;
v = get_unaligned((const u32 *) (ip + m_len)) ^
get_unaligned((const u32 *) (m_pos + m_len));
if (unlikely(v == 0)) {
do {
m_len += 4;
v = get_unaligned((const u32 *) (ip + m_len)) ^
get_unaligned((const u32 *) (m_pos + m_len));
if (v != 0)
break;
m_len += 4;
v = get_unaligned((const u32 *) (ip + m_len)) ^
get_unaligned((const u32 *) (m_pos + m_len));
if (unlikely(ip + m_len >= ip_end))
goto m_len_done;
} while (v == 0);
}
# if defined(__LITTLE_ENDIAN)
m_len += (unsigned) __builtin_ctz(v) / 8;
# elif defined(__BIG_ENDIAN)
m_len += (unsigned) __builtin_clz(v) / 8;
# else
# error "missing endian definition"
# endif
#else
if (unlikely(ip[m_len] == m_pos[m_len])) {
do {
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (ip[m_len] != m_pos[m_len])
break;
m_len += 1;
if (unlikely(ip + m_len >= ip_end))
goto m_len_done;
} while (ip[m_len] == m_pos[m_len]);
}
#endif
}
m_len_done:
m_off = ip - m_pos;
ip += m_len;
ii = ip;
if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
m_off -= 1;
*op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
*op++ = (m_off >> 3);
} else if (m_off <= M3_MAX_OFFSET) {
m_off -= 1;
if (m_len <= M3_MAX_LEN)
*op++ = (M3_MARKER | (m_len - 2));
else {
m_len -= M3_MAX_LEN;
*op++ = M3_MARKER | 0;
while (unlikely(m_len > 255)) {
m_len -= 255;
*op++ = 0;
}
*op++ = (m_len);
}
*op++ = (m_off << 2);
*op++ = (m_off >> 6);
} else {
m_off -= 0x4000;
if (m_len <= M4_MAX_LEN)
*op++ = (M4_MARKER | ((m_off >> 11) & 8)
| (m_len - 2));
else {
m_len -= M4_MAX_LEN;
*op++ = (M4_MARKER | ((m_off >> 11) & 8));
while (unlikely(m_len > 255)) {
m_len -= 255;
*op++ = 0;
}
*op++ = (m_len);
}
*op++ = (m_off << 2);
*op++ = (m_off >> 6);
}
goto next;
}
*out_len = op - out;
return in_end - ii;
return in_end - (ii - ti);
}
int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
size_t *out_len, void *wrkmem)
int lzo1x_1_compress(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len,
void *wrkmem)
{
const unsigned char *ii;
const unsigned char *ip = in;
unsigned char *op = out;
size_t t;
size_t l = in_len;
size_t t = 0;
if (unlikely(in_len <= M2_MAX_LEN + 5)) {
t = in_len;
} else {
t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
while (l > 20) {
size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
uintptr_t ll_end = (uintptr_t) ip + ll;
if ((ll_end + ((t + ll) >> 5)) <= ll_end)
break;
BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
ip += ll;
op += *out_len;
l -= ll;
}
t += l;
if (t > 0) {
ii = in + in_len - t;
const unsigned char *ii = in + in_len - t;
if (op == out && t <= 238) {
*op++ = (17 + t);
@@ -198,16 +247,21 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
*op++ = (t - 3);
} else {
size_t tt = t - 18;
*op++ = 0;
while (tt > 255) {
tt -= 255;
*op++ = 0;
}
*op++ = tt;
}
do {
if (t >= 16) do {
COPY8(op, ii);
COPY8(op + 8, ii + 8);
op += 16;
ii += 16;
t -= 16;
} while (t >= 16);
if (t > 0) do {
*op++ = *ii++;
} while (--t > 0);
}
@@ -223,4 +277,3 @@ EXPORT_SYMBOL_GPL(lzo1x_1_compress);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO1X-1 Compressor");
-255
View File
@@ -1,255 +0,0 @@
/*
* LZO1X Decompressor from MiniLZO
*
* Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
* Changed for kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
#ifndef STATIC
#include <linux/module.h>
#include <linux/kernel.h>
#endif
#include <asm/unaligned.h>
#include <linux/lzo.h>
#include "lzodefs.h"
#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
#define COPY4(dst, src) \
put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len)
{
const unsigned char * const ip_end = in + in_len;
unsigned char * const op_end = out + *out_len;
const unsigned char *ip = in, *m_pos;
unsigned char *op = out;
size_t t;
*out_len = 0;
if (*ip > 17) {
t = *ip++ - 17;
if (t < 4)
goto match_next;
if (HAVE_OP(t, op_end, op))
goto output_overrun;
if (HAVE_IP(t + 1, ip_end, ip))
goto input_overrun;
do {
*op++ = *ip++;
} while (--t > 0);
goto first_literal_run;
}
while ((ip < ip_end)) {
t = *ip++;
if (t >= 16)
goto match;
if (t == 0) {
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
while (*ip == 0) {
t += 255;
ip++;
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
}
t += 15 + *ip++;
}
if (HAVE_OP(t + 3, op_end, op))
goto output_overrun;
if (HAVE_IP(t + 4, ip_end, ip))
goto input_overrun;
COPY4(op, ip);
op += 4;
ip += 4;
if (--t > 0) {
if (t >= 4) {
do {
COPY4(op, ip);
op += 4;
ip += 4;
t -= 4;
} while (t >= 4);
if (t > 0) {
do {
*op++ = *ip++;
} while (--t > 0);
}
} else {
do {
*op++ = *ip++;
} while (--t > 0);
}
}
first_literal_run:
t = *ip++;
if (t >= 16)
goto match;
m_pos = op - (1 + M2_MAX_OFFSET);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(3, op_end, op))
goto output_overrun;
*op++ = *m_pos++;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
do {
match:
if (t >= 64) {
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(t + 3 - 1, op_end, op))
goto output_overrun;
goto copy_match;
} else if (t >= 32) {
t &= 31;
if (t == 0) {
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
while (*ip == 0) {
t += 255;
ip++;
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= get_unaligned_le16(ip) >> 2;
ip += 2;
} else if (t >= 16) {
m_pos = op;
m_pos -= (t & 8) << 11;
t &= 7;
if (t == 0) {
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
while (*ip == 0) {
t += 255;
ip++;
if (HAVE_IP(1, ip_end, ip))
goto input_overrun;
}
t += 7 + *ip++;
}
m_pos -= get_unaligned_le16(ip) >> 2;
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
} else {
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(2, op_end, op))
goto output_overrun;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
}
if (HAVE_LB(m_pos, out, op))
goto lookbehind_overrun;
if (HAVE_OP(t + 3 - 1, op_end, op))
goto output_overrun;
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
COPY4(op, m_pos);
op += 4;
m_pos += 4;
t -= 4 - (3 - 1);
do {
COPY4(op, m_pos);
op += 4;
m_pos += 4;
t -= 4;
} while (t >= 4);
if (t > 0)
do {
*op++ = *m_pos++;
} while (--t > 0);
} else {
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
do {
*op++ = *m_pos++;
} while (--t > 0);
}
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
match_next:
if (HAVE_OP(t, op_end, op))
goto output_overrun;
if (HAVE_IP(t + 1, ip_end, ip))
goto input_overrun;
*op++ = *ip++;
if (t > 1) {
*op++ = *ip++;
if (t > 2)
*op++ = *ip++;
}
t = *ip++;
} while (ip < ip_end);
}
*out_len = op - out;
return LZO_E_EOF_NOT_FOUND;
eof_found:
*out_len = op - out;
return (ip == ip_end ? LZO_E_OK :
(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
input_overrun:
*out_len = op - out;
return LZO_E_INPUT_OVERRUN;
output_overrun:
*out_len = op - out;
return LZO_E_OUTPUT_OVERRUN;
lookbehind_overrun:
*out_len = op - out;
return LZO_E_LOOKBEHIND_OVERRUN;
}
#ifndef STATIC
EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO1X Decompressor");
#endif
+268
View File
@@ -0,0 +1,268 @@
/*
* LZO1X Decompressor from LZO
*
* Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
* Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
#ifndef STATIC
#include <linux/module.h>
#include <linux/kernel.h>
#endif
#include <asm/unaligned.h>
#include <linux/lzo.h>
#include "lzodefs.h"
#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x))
#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun
#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
* count without overflowing an integer. The multiply will overflow when
* multiplying 255 by more than MAXINT/255. The sum will overflow earlier
* depending on the base count. Since the base count is taken from a u8
* and a few bits, it is safe to assume that it will always be lower than
* or equal to 2*255, thus we can always prevent any overflow by accepting
* two less 255 steps. See Documentation/lzo.txt for more information.
*/
#define MAX_255_COUNT ((((size_t)~0) / 255) - 2)
int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
unsigned char *out, size_t *out_len)
{
unsigned char *op;
const unsigned char *ip;
size_t t, next;
size_t state = 0;
const unsigned char *m_pos;
const unsigned char * const ip_end = in + in_len;
unsigned char * const op_end = out + *out_len;
op = out;
ip = in;
if (unlikely(in_len < 3))
goto input_overrun;
if (*ip > 17) {
t = *ip++ - 17;
if (t < 4) {
next = t;
goto match_next;
}
goto copy_literal_run;
}
for (;;) {
t = *ip++;
if (t < 16) {
if (likely(state == 0)) {
if (unlikely(t == 0)) {
size_t offset;
const unsigned char *ip_last = ip;
while (unlikely(*ip == 0)) {
ip++;
NEED_IP(1);
}
offset = ip - ip_last;
if (unlikely(offset > MAX_255_COUNT))
return LZO_E_ERROR;
offset = (offset << 8) - offset;
t += offset + 15 + *ip++;
}
t += 3;
copy_literal_run:
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
const unsigned char *ie = ip + t;
unsigned char *oe = op + t;
do {
COPY8(op, ip);
op += 8;
ip += 8;
COPY8(op, ip);
op += 8;
ip += 8;
} while (ip < ie);
ip = ie;
op = oe;
} else
#endif
{
NEED_OP(t);
NEED_IP(t + 3);
do {
*op++ = *ip++;
} while (--t > 0);
}
state = 4;
continue;
} else if (state != 4) {
next = t & 3;
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
TEST_LB(m_pos);
NEED_OP(2);
op[0] = m_pos[0];
op[1] = m_pos[1];
op += 2;
goto match_next;
} else {
next = t & 3;
m_pos = op - (1 + M2_MAX_OFFSET);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
t = 3;
}
} else if (t >= 64) {
next = t & 3;
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1 + (3 - 1);
} else if (t >= 32) {
t = (t & 31) + (3 - 1);
if (unlikely(t == 2)) {
size_t offset;
const unsigned char *ip_last = ip;
while (unlikely(*ip == 0)) {
ip++;
NEED_IP(1);
}
offset = ip - ip_last;
if (unlikely(offset > MAX_255_COUNT))
return LZO_E_ERROR;
offset = (offset << 8) - offset;
t += offset + 31 + *ip++;
NEED_IP(2);
}
m_pos = op - 1;
next = get_unaligned_le16(ip);
ip += 2;
m_pos -= next >> 2;
next &= 3;
} else {
m_pos = op;
m_pos -= (t & 8) << 11;
t = (t & 7) + (3 - 1);
if (unlikely(t == 2)) {
size_t offset;
const unsigned char *ip_last = ip;
while (unlikely(*ip == 0)) {
ip++;
NEED_IP(1);
}
offset = ip - ip_last;
if (unlikely(offset > MAX_255_COUNT))
return LZO_E_ERROR;
offset = (offset << 8) - offset;
t += offset + 7 + *ip++;
NEED_IP(2);
}
next = get_unaligned_le16(ip);
ip += 2;
m_pos -= next >> 2;
next &= 3;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
}
TEST_LB(m_pos);
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
if (op - m_pos >= 8) {
unsigned char *oe = op + t;
if (likely(HAVE_OP(t + 15))) {
do {
COPY8(op, m_pos);
op += 8;
m_pos += 8;
COPY8(op, m_pos);
op += 8;
m_pos += 8;
} while (op < oe);
op = oe;
if (HAVE_IP(6)) {
state = next;
COPY4(op, ip);
op += next;
ip += next;
continue;
}
} else {
NEED_OP(t);
do {
*op++ = *m_pos++;
} while (op < oe);
}
} else
#endif
{
unsigned char *oe = op + t;
NEED_OP(t);
op[0] = m_pos[0];
op[1] = m_pos[1];
op += 2;
m_pos += 2;
do {
*op++ = *m_pos++;
} while (op < oe);
}
match_next:
state = next;
t = next;
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
if (likely(HAVE_IP(6) && HAVE_OP(4))) {
COPY4(op, ip);
op += t;
ip += t;
} else
#endif
{
NEED_IP(t + 3);
NEED_OP(t);
while (t > 0) {
*op++ = *ip++;
t--;
}
}
}
eof_found:
*out_len = op - out;
return (t != 3 ? LZO_E_ERROR :
ip == ip_end ? LZO_E_OK :
ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
input_overrun:
*out_len = op - out;
return LZO_E_INPUT_OVERRUN;
output_overrun:
*out_len = op - out;
return LZO_E_OUTPUT_OVERRUN;
lookbehind_overrun:
*out_len = op - out;
return LZO_E_LOOKBEHIND_OVERRUN;
}
#ifndef STATIC
EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO1X Decompressor");
#endif
+27 -11
View File
@@ -1,19 +1,37 @@
/*
* lzodefs.h -- architecture, OS and compiler specific defines
*
* Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
* Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
* Changed for kernel use by:
* Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
#define LZO_VERSION 0x2020
#define LZO_VERSION_STRING "2.02"
#define LZO_VERSION_DATE "Oct 17 2005"
#define COPY4(dst, src) \
put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
#if defined(__x86_64__)
#define COPY8(dst, src) \
put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
#else
#define COPY8(dst, src) \
COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
#endif
#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
#error "conflicting endian definitions"
#elif defined(__x86_64__)
#define LZO_USE_CTZ64 1
#define LZO_USE_CTZ32 1
#elif defined(__i386__) || defined(__powerpc__)
#define LZO_USE_CTZ32 1
#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
#define LZO_USE_CTZ32 1
#endif
#define M1_MAX_OFFSET 0x0400
#define M2_MAX_OFFSET 0x0800
@@ -34,10 +52,8 @@
#define M3_MARKER 32
#define M4_MARKER 16
#define D_BITS 14
#define D_MASK ((1u << D_BITS) - 1)
#define lzo_dict_t unsigned short
#define D_BITS 13
#define D_SIZE (1u << D_BITS)
#define D_MASK (D_SIZE - 1)
#define D_HIGH ((D_MASK >> 1) + 1)
#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
<< (s1)) ^ (p)[0])
#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
+17 -2
View File
@@ -703,7 +703,14 @@ do { \
************** MIPS *****************
***************************************/
#if defined(__mips__) && W_TYPE_SIZE == 32
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
#define umul_ppmm(w1, w0, u, v) \
do { \
UDItype __ll = (UDItype)(u) * (v); \
w1 = __ll >> 32; \
w0 = __ll; \
} while (0)
#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("multu %2,%3" \
: "=l" ((USItype)(w0)), \
@@ -728,7 +735,15 @@ do { \
************** MIPS/64 **************
***************************************/
#if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
#define umul_ppmm(w1, w0, u, v) \
do { \
typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \
__ll_UTItype __ll = (__ll_UTItype)(u) * (v); \
w1 = __ll >> 64; \
w0 = __ll; \
} while (0)
#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("dmultu %2,%3" \
: "=l" ((UDItype)(w0)), \
+11 -4
View File
@@ -13,6 +13,7 @@
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ratelimit.h>
#include <net/netlink.h>
static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
@@ -197,8 +198,8 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
}
if (unlikely(rem > 0))
printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
"attributes.\n", rem);
pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
rem, current->comm);
err = 0;
errout:
@@ -299,9 +300,15 @@ int nla_memcmp(const struct nlattr *nla, const void *data,
*/
int nla_strcmp(const struct nlattr *nla, const char *str)
{
int len = strlen(str) + 1;
int d = nla_len(nla) - len;
int len = strlen(str);
char *buf = nla_data(nla);
int attrlen = nla_len(nla);
int d;
if (attrlen > 0 && buf[attrlen - 1] == '\0')
attrlen--;
d = attrlen - len;
if (d == 0)
d = memcmp(nla_data(nla), str, len);
+3
View File
@@ -673,6 +673,9 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
* during iterating; it can be zero only at the beginning.
* And we cannot overflow iter->next_index in a single step,
* because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.
*
* This condition also used by radix_tree_next_slot() to stop
* contiguous iterating, and forbid swithing to the next chunk.
*/
index = iter->next_index;
if (!index && iter->index)
+7 -7
View File
@@ -92,7 +92,7 @@ void srandom32(u32 entropy)
*/
for_each_possible_cpu (i) {
struct rnd_state *state = &per_cpu(net_rand_state, i);
state->s1 = __seed(state->s1 ^ entropy, 1);
state->s1 = __seed(state->s1 ^ entropy, 2);
}
}
EXPORT_SYMBOL(srandom32);
@@ -109,9 +109,9 @@ static int __init random32_init(void)
struct rnd_state *state = &per_cpu(net_rand_state,i);
#define LCG(x) ((x) * 69069) /* super-duper LCG */
state->s1 = __seed(LCG(i + jiffies), 1);
state->s2 = __seed(LCG(state->s1), 7);
state->s3 = __seed(LCG(state->s2), 15);
state->s1 = __seed(LCG(i + jiffies), 2);
state->s2 = __seed(LCG(state->s1), 8);
state->s3 = __seed(LCG(state->s2), 16);
/* "warm it up" */
prandom32(state);
@@ -138,9 +138,9 @@ static int __init random32_reseed(void)
u32 seeds[3];
get_random_bytes(&seeds, sizeof(seeds));
state->s1 = __seed(seeds[0], 1);
state->s2 = __seed(seeds[1], 7);
state->s3 = __seed(seeds[2], 15);
state->s1 = __seed(seeds[0], 2);
state->s2 = __seed(seeds[1], 8);
state->s3 = __seed(seeds[2], 16);
/* mix it in */
prandom32(state);
+2 -1
View File
@@ -421,7 +421,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
if (miter->addr) {
miter->__offset += miter->consumed;
if (miter->__flags & SG_MITER_TO_SG)
if ((miter->__flags & SG_MITER_TO_SG) &&
!PageSlab(miter->page))
flush_kernel_dcache_page(miter->page);
if (miter->__flags & SG_MITER_ATOMIC) {
+3
View File
@@ -18,6 +18,9 @@ void show_mem(unsigned int filter)
printk("Mem-Info:\n");
show_free_areas(filter);
if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
return;
for_each_online_pgdat(pgdat) {
unsigned long i, flags;
+16
View File
@@ -586,6 +586,22 @@ void *memset(void *s, int c, size_t count)
EXPORT_SYMBOL(memset);
#endif
/**
* memzero_explicit - Fill a region of memory (e.g. sensitive
* keying data) with 0s.
* @s: Pointer to the start of the area.
* @count: The size of the area.
*
* memzero_explicit() doesn't need an arch-specific version as
* it just invokes the one of memset() implicitly.
*/
void memzero_explicit(void *s, size_t count)
{
memset(s, 0, count);
OPTIMIZER_HIDE_VAR(s);
}
EXPORT_SYMBOL(memzero_explicit);
#ifndef __HAVE_ARCH_MEMCPY
/**
* memcpy - Copy one area of memory to another
+32 -4
View File
@@ -25,6 +25,7 @@
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/ioport.h>
#include <linux/cred.h>
#include <net/addrconf.h>
#include <asm/page.h> /* for PAGE_SIZE */
@@ -926,16 +927,43 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
* %pK cannot be used in IRQ context because its test
* for CAP_SYSLOG would be meaningless.
*/
if (in_irq() || in_serving_softirq() || in_nmi()) {
if (kptr_restrict && (in_irq() || in_serving_softirq() ||
in_nmi())) {
if (spec.field_width == -1)
spec.field_width = 2 * sizeof(void *);
return string(buf, end, "pK-error", spec);
}
if (!((kptr_restrict == 0) ||
(kptr_restrict == 1 &&
has_capability_noaudit(current, CAP_SYSLOG))))
switch (kptr_restrict) {
case 0:
/* Always print %pK values */
break;
case 1: {
/*
* Only print the real pointer value if the current
* process has CAP_SYSLOG and is running with the
* same credentials it started with. This is because
* access to files is checked at open() time, but %pK
* checks permission at read() time. We don't want to
* leak pointer values if a binary opens a file using
* %pK and then elevates privileges before reading it.
*/
const struct cred *cred = current_cred();
if (!has_capability_noaudit(current, CAP_SYSLOG) ||
(cred->euid != cred->uid) ||
(cred->egid != cred->gid))
ptr = NULL;
break;
}
case 2:
default:
/* Always print 0's for %pK */
ptr = NULL;
break;
}
break;
case 'N':
switch (fmt[1]) {
case 'F':