[PATCH 04/18] vchecker: prepare per object memory for vchecker

From: js1304
Date: Tue Nov 28 2017 - 02:53:14 EST


From: Joonsoo Kim <iamjoonsoo.kim@xxxxxxx>

To prepare per object memory for vchecker, we need to change the layout
of the object when kmem_cache initialization. Add such code on
vchecker_cache_create() which is called when kmem_cache initialization.

And, this memory should be initialized when object is populated. Do it
with another hook.

This memory will be used in the following patch.

Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@xxxxxxx>
---
mm/kasan/vchecker.c | 15 +++++++++++++++
mm/kasan/vchecker.h | 4 ++++
mm/slab.c | 2 ++
mm/slub.c | 2 ++
4 files changed, 23 insertions(+)

diff --git a/mm/kasan/vchecker.c b/mm/kasan/vchecker.c
index 0b8a1e7..be0f0cd 100644
--- a/mm/kasan/vchecker.c
+++ b/mm/kasan/vchecker.c
@@ -31,6 +31,10 @@ enum vchecker_type_num {
VCHECKER_TYPE_MAX,
};

+struct vchecker_data {
+ void *dummy;
+};
+
struct vchecker_type {
char *name;
const struct file_operations *fops;
@@ -109,10 +113,21 @@ static int remove_cbs(struct kmem_cache *s, struct vchecker_type *t)
return 0;
}

+void vchecker_init_slab_obj(struct kmem_cache *s, const void *object)
+{
+ struct vchecker_data *data;
+
+ data = (void *)object + s->vchecker_cache.data_offset;
+ __memset(data, 0, sizeof(*data));
+}
+
void vchecker_cache_create(struct kmem_cache *s,
size_t *size, slab_flags_t *flags)
{
*flags |= SLAB_VCHECKER;
+
+ s->vchecker_cache.data_offset = *size;
+ *size += sizeof(struct vchecker_data);
}

void vchecker_kmalloc(struct kmem_cache *s, const void *object, size_t size)
diff --git a/mm/kasan/vchecker.h b/mm/kasan/vchecker.h
index aa22e8d..efebc63 100644
--- a/mm/kasan/vchecker.h
+++ b/mm/kasan/vchecker.h
@@ -7,6 +7,7 @@ struct vchecker_cb;
struct vchecker_cache {
struct vchecker *checker;
struct dentry *dir;
+ int data_offset;
};


@@ -18,6 +19,7 @@ int init_vchecker(struct kmem_cache *s);
void fini_vchecker(struct kmem_cache *s);
void vchecker_cache_create(struct kmem_cache *s, size_t *size,
slab_flags_t *flags);
+void vchecker_init_slab_obj(struct kmem_cache *s, const void *object);
void vchecker_enable_cache(struct kmem_cache *s, bool enable);
void vchecker_enable_obj(struct kmem_cache *s, const void *object,
size_t size, bool enable);
@@ -31,6 +33,8 @@ static inline int init_vchecker(struct kmem_cache *s) { return 0; }
static inline void fini_vchecker(struct kmem_cache *s) { }
static inline void vchecker_cache_create(struct kmem_cache *s,
size_t *size, slab_flags_t *flags) {}
+static inline void vchecker_init_slab_obj(struct kmem_cache *s,
+ const void *object) {}

#endif

diff --git a/mm/slab.c b/mm/slab.c
index ba45c15..64d768b 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2076,6 +2076,7 @@ int __kmem_cache_create(struct kmem_cache *cachep, slab_flags_t flags)
}
#endif

+ vchecker_cache_create(cachep, &size, &flags);
kasan_cache_create(cachep, &size, &flags);

size = ALIGN(size, cachep->align);
@@ -2601,6 +2602,7 @@ static void cache_init_objs(struct kmem_cache *cachep,

for (i = 0; i < cachep->num; i++) {
objp = index_to_obj(cachep, page, i);
+ vchecker_init_slab_obj(cachep, objp);
kasan_init_slab_obj(cachep, objp);

/* constructor could break poison info */
diff --git a/mm/slub.c b/mm/slub.c
index 67364cb..c099b33 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1418,6 +1418,7 @@ static void setup_object(struct kmem_cache *s, struct page *page,
void *object)
{
setup_object_debug(s, page, object);
+ vchecker_init_slab_obj(s, object);
kasan_init_slab_obj(s, object);
if (unlikely(s->ctor)) {
kasan_unpoison_object_data(s, object);
@@ -3550,6 +3551,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
size += 2 * sizeof(struct track);
#endif

+ vchecker_cache_create(s, &size, &s->flags);
kasan_cache_create(s, &size, &s->flags);
#ifdef CONFIG_SLUB_DEBUG
if (flags & SLAB_RED_ZONE) {
--
2.7.4