Merge branch 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/vegard/kmemcheck
* 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/vegard/kmemcheck: (39 commits) signal: fix __send_signal() false positive kmemcheck warning fs: fix do_mount_root() false positive kmemcheck warning fs: introduce __getname_gfp() trace: annotate bitfields in struct ring_buffer_event net: annotate struct sock bitfield c2port: annotate bitfield for kmemcheck net: annotate inet_timewait_sock bitfields ieee1394/csr1212: fix false positive kmemcheck report ieee1394: annotate bitfield net: annotate bitfields in struct inet_sock net: use kmemcheck bitfields API for skbuff kmemcheck: introduce bitfield API kmemcheck: add opcode self-testing at boot x86: unify pte_hidden x86: make _PAGE_HIDDEN conditional kmemcheck: make kconfig accessible for other architectures kmemcheck: enable in the x86 Kconfig kmemcheck: add hooks for the page allocator kmemcheck: add hooks for page- and sg-dma-mappings kmemcheck: don't track page tables ...
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/kmemcheck.h>
|
||||
|
||||
#define C2PORT_NAME_LEN 32
|
||||
|
||||
@@ -20,8 +21,10 @@
|
||||
/* Main struct */
|
||||
struct c2port_ops;
|
||||
struct c2port_device {
|
||||
kmemcheck_bitfield_begin(flags);
|
||||
unsigned int access:1;
|
||||
unsigned int flash_access:1;
|
||||
kmemcheck_bitfield_end(flags);
|
||||
|
||||
int id;
|
||||
char name[C2PORT_NAME_LEN];
|
||||
|
||||
@@ -1919,8 +1919,9 @@ extern void __init vfs_caches_init(unsigned long);
|
||||
|
||||
extern struct kmem_cache *names_cachep;
|
||||
|
||||
#define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL)
|
||||
#define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
|
||||
#define __getname_gfp(gfp) kmem_cache_alloc(names_cachep, (gfp))
|
||||
#define __getname() __getname_gfp(GFP_KERNEL)
|
||||
#define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
|
||||
#ifndef CONFIG_AUDITSYSCALL
|
||||
#define putname(name) __putname(name)
|
||||
#else
|
||||
|
||||
@@ -52,7 +52,19 @@ struct vm_area_struct;
|
||||
#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
|
||||
#define __GFP_MOVABLE ((__force gfp_t)0x100000u) /* Page is movable */
|
||||
|
||||
#define __GFP_BITS_SHIFT 21 /* Room for 21 __GFP_FOO bits */
|
||||
#ifdef CONFIG_KMEMCHECK
|
||||
#define __GFP_NOTRACK ((__force gfp_t)0x200000u) /* Don't track with kmemcheck */
|
||||
#else
|
||||
#define __GFP_NOTRACK ((__force gfp_t)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This may seem redundant, but it's a way of annotating false positives vs.
|
||||
* allocations that simply cannot be supported (e.g. page tables).
|
||||
*/
|
||||
#define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
|
||||
|
||||
#define __GFP_BITS_SHIFT 22 /* Room for 22 __GFP_FOO bits */
|
||||
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
|
||||
|
||||
/* This equals 0, but use constants in case they ever change */
|
||||
|
||||
@@ -472,6 +472,20 @@ static inline void tasklet_hi_schedule(struct tasklet_struct *t)
|
||||
__tasklet_hi_schedule(t);
|
||||
}
|
||||
|
||||
extern void __tasklet_hi_schedule_first(struct tasklet_struct *t);
|
||||
|
||||
/*
|
||||
* This version avoids touching any other tasklets. Needed for kmemcheck
|
||||
* in order not to take any page faults while enqueueing this tasklet;
|
||||
* consider VERY carefully whether you really need this or
|
||||
* tasklet_hi_schedule()...
|
||||
*/
|
||||
static inline void tasklet_hi_schedule_first(struct tasklet_struct *t)
|
||||
{
|
||||
if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
|
||||
__tasklet_hi_schedule_first(t);
|
||||
}
|
||||
|
||||
|
||||
static inline void tasklet_disable_nosync(struct tasklet_struct *t)
|
||||
{
|
||||
|
||||
153
include/linux/kmemcheck.h
Normal file
153
include/linux/kmemcheck.h
Normal file
@@ -0,0 +1,153 @@
|
||||
#ifndef LINUX_KMEMCHECK_H
|
||||
#define LINUX_KMEMCHECK_H
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_KMEMCHECK
|
||||
extern int kmemcheck_enabled;
|
||||
|
||||
/* The slab-related functions. */
|
||||
void kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node);
|
||||
void kmemcheck_free_shadow(struct page *page, int order);
|
||||
void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
|
||||
size_t size);
|
||||
void kmemcheck_slab_free(struct kmem_cache *s, void *object, size_t size);
|
||||
|
||||
void kmemcheck_pagealloc_alloc(struct page *p, unsigned int order,
|
||||
gfp_t gfpflags);
|
||||
|
||||
void kmemcheck_show_pages(struct page *p, unsigned int n);
|
||||
void kmemcheck_hide_pages(struct page *p, unsigned int n);
|
||||
|
||||
bool kmemcheck_page_is_tracked(struct page *p);
|
||||
|
||||
void kmemcheck_mark_unallocated(void *address, unsigned int n);
|
||||
void kmemcheck_mark_uninitialized(void *address, unsigned int n);
|
||||
void kmemcheck_mark_initialized(void *address, unsigned int n);
|
||||
void kmemcheck_mark_freed(void *address, unsigned int n);
|
||||
|
||||
void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n);
|
||||
void kmemcheck_mark_uninitialized_pages(struct page *p, unsigned int n);
|
||||
void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n);
|
||||
|
||||
int kmemcheck_show_addr(unsigned long address);
|
||||
int kmemcheck_hide_addr(unsigned long address);
|
||||
|
||||
#else
|
||||
#define kmemcheck_enabled 0
|
||||
|
||||
static inline void
|
||||
kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
kmemcheck_free_shadow(struct page *page, int order)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
|
||||
size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_slab_free(struct kmem_cache *s, void *object,
|
||||
size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_pagealloc_alloc(struct page *p,
|
||||
unsigned int order, gfp_t gfpflags)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool kmemcheck_page_is_tracked(struct page *p)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_unallocated(void *address, unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_uninitialized(void *address, unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_freed(void *address, unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_unallocated_pages(struct page *p,
|
||||
unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_uninitialized_pages(struct page *p,
|
||||
unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kmemcheck_mark_initialized_pages(struct page *p,
|
||||
unsigned int n)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KMEMCHECK */
|
||||
|
||||
/*
|
||||
* Bitfield annotations
|
||||
*
|
||||
* How to use: If you have a struct using bitfields, for example
|
||||
*
|
||||
* struct a {
|
||||
* int x:8, y:8;
|
||||
* };
|
||||
*
|
||||
* then this should be rewritten as
|
||||
*
|
||||
* struct a {
|
||||
* kmemcheck_bitfield_begin(flags);
|
||||
* int x:8, y:8;
|
||||
* kmemcheck_bitfield_end(flags);
|
||||
* };
|
||||
*
|
||||
* Now the "flags_begin" and "flags_end" members may be used to refer to the
|
||||
* beginning and end, respectively, of the bitfield (and things like
|
||||
* &x.flags_begin is allowed). As soon as the struct is allocated, the bit-
|
||||
* fields should be annotated:
|
||||
*
|
||||
* struct a *a = kmalloc(sizeof(struct a), GFP_KERNEL);
|
||||
* kmemcheck_annotate_bitfield(a, flags);
|
||||
*
|
||||
* Note: We provide the same definitions for both kmemcheck and non-
|
||||
* kmemcheck kernels. This makes it harder to introduce accidental errors. It
|
||||
* is also allowed to pass NULL pointers to kmemcheck_annotate_bitfield().
|
||||
*/
|
||||
#define kmemcheck_bitfield_begin(name) \
|
||||
int name##_begin[0];
|
||||
|
||||
#define kmemcheck_bitfield_end(name) \
|
||||
int name##_end[0];
|
||||
|
||||
#define kmemcheck_annotate_bitfield(ptr, name) \
|
||||
do if (ptr) { \
|
||||
int _n = (long) &((ptr)->name##_end) \
|
||||
- (long) &((ptr)->name##_begin); \
|
||||
BUILD_BUG_ON(_n < 0); \
|
||||
\
|
||||
kmemcheck_mark_initialized(&((ptr)->name##_begin), _n); \
|
||||
} while (0)
|
||||
|
||||
#define kmemcheck_annotate_variable(var) \
|
||||
do { \
|
||||
kmemcheck_mark_initialized(&(var), sizeof(var)); \
|
||||
} while (0) \
|
||||
|
||||
#endif /* LINUX_KMEMCHECK_H */
|
||||
@@ -98,6 +98,14 @@ struct page {
|
||||
#ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
|
||||
unsigned long debug_flags; /* Use atomic bitops on this */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KMEMCHECK
|
||||
/*
|
||||
* kmemcheck wants to track the status of each byte in a page; this
|
||||
* is a pointer to such a status block. NULL if not tracked.
|
||||
*/
|
||||
void *shadow;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _LINUX_RING_BUFFER_H
|
||||
#define _LINUX_RING_BUFFER_H
|
||||
|
||||
#include <linux/kmemcheck.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
@@ -11,7 +12,10 @@ struct ring_buffer_iter;
|
||||
* Don't refer to this struct directly, use functions below.
|
||||
*/
|
||||
struct ring_buffer_event {
|
||||
kmemcheck_bitfield_begin(bitfield);
|
||||
u32 type_len:5, time_delta:27;
|
||||
kmemcheck_bitfield_end(bitfield);
|
||||
|
||||
u32 array[];
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define _LINUX_SKBUFF_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kmemcheck.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/cache.h>
|
||||
@@ -343,6 +344,7 @@ struct sk_buff {
|
||||
};
|
||||
};
|
||||
__u32 priority;
|
||||
kmemcheck_bitfield_begin(flags1);
|
||||
__u8 local_df:1,
|
||||
cloned:1,
|
||||
ip_summed:2,
|
||||
@@ -353,6 +355,7 @@ struct sk_buff {
|
||||
ipvs_property:1,
|
||||
peeked:1,
|
||||
nf_trace:1;
|
||||
kmemcheck_bitfield_end(flags1);
|
||||
__be16 protocol;
|
||||
|
||||
void (*destructor)(struct sk_buff *skb);
|
||||
@@ -372,12 +375,16 @@ struct sk_buff {
|
||||
__u16 tc_verd; /* traffic control verdict */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
kmemcheck_bitfield_begin(flags2);
|
||||
#ifdef CONFIG_IPV6_NDISC_NODETYPE
|
||||
__u8 ndisc_nodetype:2;
|
||||
#endif
|
||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||
__u8 do_not_encrypt:1;
|
||||
#endif
|
||||
kmemcheck_bitfield_end(flags2);
|
||||
|
||||
/* 0/13/14 bit hole */
|
||||
|
||||
#ifdef CONFIG_NET_DMA
|
||||
|
||||
@@ -64,6 +64,13 @@
|
||||
|
||||
#define SLAB_NOLEAKTRACE 0x00800000UL /* Avoid kmemleak tracing */
|
||||
|
||||
/* Don't track use of uninitialized memory */
|
||||
#ifdef CONFIG_KMEMCHECK
|
||||
# define SLAB_NOTRACK 0x01000000UL
|
||||
#else
|
||||
# define SLAB_NOTRACK 0x00000000UL
|
||||
#endif
|
||||
|
||||
/* The following flags affect the page allocator grouping pages by mobility */
|
||||
#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
|
||||
#define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */
|
||||
|
||||
@@ -16,6 +16,87 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kmemtrace.h>
|
||||
|
||||
/*
|
||||
* struct kmem_cache
|
||||
*
|
||||
* manages a cache.
|
||||
*/
|
||||
|
||||
struct kmem_cache {
|
||||
/* 1) per-cpu data, touched during every alloc/free */
|
||||
struct array_cache *array[NR_CPUS];
|
||||
/* 2) Cache tunables. Protected by cache_chain_mutex */
|
||||
unsigned int batchcount;
|
||||
unsigned int limit;
|
||||
unsigned int shared;
|
||||
|
||||
unsigned int buffer_size;
|
||||
u32 reciprocal_buffer_size;
|
||||
/* 3) touched by every alloc & free from the backend */
|
||||
|
||||
unsigned int flags; /* constant flags */
|
||||
unsigned int num; /* # of objs per slab */
|
||||
|
||||
/* 4) cache_grow/shrink */
|
||||
/* order of pgs per slab (2^n) */
|
||||
unsigned int gfporder;
|
||||
|
||||
/* force GFP flags, e.g. GFP_DMA */
|
||||
gfp_t gfpflags;
|
||||
|
||||
size_t colour; /* cache colouring range */
|
||||
unsigned int colour_off; /* colour offset */
|
||||
struct kmem_cache *slabp_cache;
|
||||
unsigned int slab_size;
|
||||
unsigned int dflags; /* dynamic flags */
|
||||
|
||||
/* constructor func */
|
||||
void (*ctor)(void *obj);
|
||||
|
||||
/* 5) cache creation/removal */
|
||||
const char *name;
|
||||
struct list_head next;
|
||||
|
||||
/* 6) statistics */
|
||||
#ifdef CONFIG_DEBUG_SLAB
|
||||
unsigned long num_active;
|
||||
unsigned long num_allocations;
|
||||
unsigned long high_mark;
|
||||
unsigned long grown;
|
||||
unsigned long reaped;
|
||||
unsigned long errors;
|
||||
unsigned long max_freeable;
|
||||
unsigned long node_allocs;
|
||||
unsigned long node_frees;
|
||||
unsigned long node_overflow;
|
||||
atomic_t allochit;
|
||||
atomic_t allocmiss;
|
||||
atomic_t freehit;
|
||||
atomic_t freemiss;
|
||||
|
||||
/*
|
||||
* If debugging is enabled, then the allocator can add additional
|
||||
* fields and/or padding to every object. buffer_size contains the total
|
||||
* object size including these internal fields, the following two
|
||||
* variables contain the offset to the user object and its size.
|
||||
*/
|
||||
int obj_offset;
|
||||
int obj_size;
|
||||
#endif /* CONFIG_DEBUG_SLAB */
|
||||
|
||||
/*
|
||||
* We put nodelists[] at the end of kmem_cache, because we want to size
|
||||
* this array to nr_node_ids slots instead of MAX_NUMNODES
|
||||
* (see kmem_cache_init())
|
||||
* We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
|
||||
* is statically defined, so we reserve the max number of nodes.
|
||||
*/
|
||||
struct kmem_list3 *nodelists[MAX_NUMNODES];
|
||||
/*
|
||||
* Do not add fields after nodelists[]
|
||||
*/
|
||||
};
|
||||
|
||||
/* Size description struct for general caches. */
|
||||
struct cache_sizes {
|
||||
size_t cs_size;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
struct task_struct;
|
||||
|
||||
#ifdef CONFIG_STACKTRACE
|
||||
struct task_struct;
|
||||
|
||||
struct stack_trace {
|
||||
unsigned int nr_entries, max_entries;
|
||||
unsigned long *entries;
|
||||
@@ -11,6 +13,7 @@ struct stack_trace {
|
||||
};
|
||||
|
||||
extern void save_stack_trace(struct stack_trace *trace);
|
||||
extern void save_stack_trace_bp(struct stack_trace *trace, unsigned long bp);
|
||||
extern void save_stack_trace_tsk(struct task_struct *tsk,
|
||||
struct stack_trace *trace);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user