mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-19 08:05:27 +08:00
kmemcheck: make bitfield annotations truly no-ops when disabled
It turns out that even zero-sized struct members (int foo[0];) will affect the struct layout, causing us in particular to lose 4 bytes in struct sock. This patch fixes the regression in CONFIG_KMEMCHECK=n case. Reported-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com> Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
cb5a8b2c92
commit
e992cd9b72
@ -36,6 +36,56 @@ int kmemcheck_hide_addr(unsigned long address);
|
|||||||
|
|
||||||
bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
|
bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
*/
|
||||||
|
#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 { \
|
||||||
|
int _n; \
|
||||||
|
\
|
||||||
|
if (!ptr) \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
_n = (long) &((ptr)->name##_end) \
|
||||||
|
- (long) &((ptr)->name##_begin); \
|
||||||
|
MAYBE_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) \
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define kmemcheck_enabled 0
|
#define kmemcheck_enabled 0
|
||||||
|
|
||||||
@ -106,60 +156,16 @@ static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_KMEMCHECK */
|
#define kmemcheck_bitfield_begin(name)
|
||||||
|
#define kmemcheck_bitfield_end(name)
|
||||||
/*
|
#define kmemcheck_annotate_bitfield(ptr, name) \
|
||||||
* Bitfield annotations
|
do { \
|
||||||
*
|
|
||||||
* 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 { \
|
|
||||||
int _n; \
|
|
||||||
\
|
|
||||||
if (!ptr) \
|
|
||||||
break; \
|
|
||||||
\
|
|
||||||
_n = (long) &((ptr)->name##_end) \
|
|
||||||
- (long) &((ptr)->name##_begin); \
|
|
||||||
MAYBE_BUILD_BUG_ON(_n < 0); \
|
|
||||||
\
|
|
||||||
kmemcheck_mark_initialized(&((ptr)->name##_begin), _n); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define kmemcheck_annotate_variable(var) \
|
#define kmemcheck_annotate_variable(var) \
|
||||||
do { \
|
do { \
|
||||||
kmemcheck_mark_initialized(&(var), sizeof(var)); \
|
} while (0)
|
||||||
} while (0) \
|
|
||||||
|
#endif /* CONFIG_KMEMCHECK */
|
||||||
|
|
||||||
#endif /* LINUX_KMEMCHECK_H */
|
#endif /* LINUX_KMEMCHECK_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user