The debugobject core could be slightly harder to corrupt if the debug_obj_descr would be a pointer to const memory. Depending on the architecture, const data structures are placed into read-only memory and thus are harder to corrupt or hijack. This descriptor is used to fix up stuff like timers and workqueues when core kernel data structures are busted, so moving the descriptors to read-only memory will make debugobjects more resilient to something going wrong and then corrupting the function pointers inside struct debug_obj_descr.
Showing the changes to lib/debugobjects.c (1 of 2 files). Show all
Unified · Split
| @@ -90,7 +90,7 @@ static int debug_objects_pool_size __read_mostly · 89 unmodified lines | |||
| 90 | = ODEBUG_POOL_SIZE; | 90 | = ODEBUG_POOL_SIZE; |
| 91 | static int debug_objects_pool_min_level __read_mostly | 91 | static int debug_objects_pool_min_level __read_mostly |
| 92 | = ODEBUG_POOL_MIN_LEVEL; | 92 | = ODEBUG_POOL_MIN_LEVEL; |
| 93 | static struct debug_obj_descr *descr_test __read_mostly; | 93 | static const struct debug_obj_descr *descr_test __read_mostly; |
| 94 | static struct kmem_cache *obj_cache __read_mostly; | 94 | static struct kmem_cache *obj_cache __read_mostly; |
| 95 | 95 | ||
| 96 | /* | 96 | /* |
| @@ -223,7 +223,7 @@ static struct debug_obj *__alloc_object(struct hlist_head *list) · 126 unmodified lines | |||
| 223 | * Must be called with interrupts disabled. | 223 | * Must be called with interrupts disabled. |
| 224 | */ | 224 | */ |
| 225 | static struct debug_obj * | 225 | static struct debug_obj * |
| 226 | alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) | 226 | alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *descr) |
| 227 | { | 227 | { |
| 228 | struct debug_percpu_free *percpu_pool = this_cpu_ptr(&percpu_obj_pool); | 228 | struct debug_percpu_free *percpu_pool = this_cpu_ptr(&percpu_obj_pool); |
| 229 | struct debug_obj *obj; | 229 | struct debug_obj *obj; |
| @@ -475,7 +475,7 @@ static struct debug_bucket *get_bucket(unsigned long addr) · 245 unmodified lines | |||
| 475 | 475 | ||
| 476 | static void debug_print_object(struct debug_obj *obj, char *msg) | 476 | static void debug_print_object(struct debug_obj *obj, char *msg) |
| 477 | { | 477 | { |
| 478 | struct debug_obj_descr *descr = obj->descr; | 478 | const struct debug_obj_descr *descr = obj->descr; |
| 479 | static int limit; | 479 | static int limit; |
| 480 | 480 | ||
| 481 | if (limit < 5 && descr != descr_test) { | 481 | if (limit < 5 && descr != descr_test) { |
| @@ -529,7 +529,7 @@ static void debug_object_is_on_stack(void *addr, int onstack) · 47 unmodified lines | |||
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | static void | 531 | static void |
| 532 | __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack) | 532 | __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack) |
| 533 | { | 533 | { |
| 534 | enum debug_obj_state state; | 534 | enum debug_obj_state state; |
| 535 | bool check_stack = false; | 535 | bool check_stack = false; |
| @@ -587,7 +587,7 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack) · 51 unmodified lines | |||
| 587 | * @addr: address of the object | 587 | * @addr: address of the object |
| 588 | * @descr: pointer to an object specific debug description structure | 588 | * @descr: pointer to an object specific debug description structure |
| 589 | */ | 589 | */ |
| 590 | void debug_object_init(void *addr, struct debug_obj_descr *descr) | 590 | void debug_object_init(void *addr, const struct debug_obj_descr *descr) |
| 591 | { | 591 | { |
| 592 | if (!debug_objects_enabled) | 592 | if (!debug_objects_enabled) |
| 593 | return; | 593 | return; |
| @@ -602,7 +602,7 @@ EXPORT_SYMBOL_GPL(debug_object_init); · 8 unmodified lines | |||
| 602 | * @addr: address of the object | 602 | * @addr: address of the object |
| 603 | * @descr: pointer to an object specific debug description structure | 603 | * @descr: pointer to an object specific debug description structure |
| 604 | */ | 604 | */ |
| 605 | void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) | 605 | void debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr) |
| 606 | { | 606 | { |
| 607 | if (!debug_objects_enabled) | 607 | if (!debug_objects_enabled) |
| 608 | return; | 608 | return; |
| @@ -617,7 +617,7 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_stack); · 8 unmodified lines | |||
| 617 | * @descr: pointer to an object specific debug description structure | 617 | * @descr: pointer to an object specific debug description structure |
| 618 | * Returns 0 for success, -EINVAL for check failed. | 618 | * Returns 0 for success, -EINVAL for check failed. |
| 619 | */ | 619 | */ |
| 620 | int debug_object_activate(void *addr, struct debug_obj_descr *descr) | 620 | int debug_object_activate(void *addr, const struct debug_obj_descr *descr) |
| 621 | { | 621 | { |
| 622 | enum debug_obj_state state; | 622 | enum debug_obj_state state; |
| 623 | struct debug_bucket *db; | 623 | struct debug_bucket *db; |
| @@ -695,7 +695,7 @@ EXPORT_SYMBOL_GPL(debug_object_activate); · 71 unmodified lines | |||
| 695 | * @addr: address of the object | 695 | * @addr: address of the object |
| 696 | * @descr: pointer to an object specific debug description structure | 696 | * @descr: pointer to an object specific debug description structure |
| 697 | */ | 697 | */ |
| 698 | void debug_object_deactivate(void *addr, struct debug_obj_descr *descr) | 698 | void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr) |
| 699 | { | 699 | { |
| 700 | struct debug_bucket *db; | 700 | struct debug_bucket *db; |
| 701 | struct debug_obj *obj; | 701 | struct debug_obj *obj; |
| @@ -747,7 +747,7 @@ EXPORT_SYMBOL_GPL(debug_object_deactivate); · 45 unmodified lines | |||
| 747 | * @addr: address of the object | 747 | * @addr: address of the object |
| 748 | * @descr: pointer to an object specific debug description structure | 748 | * @descr: pointer to an object specific debug description structure |
| 749 | */ | 749 | */ |
| 750 | void debug_object_destroy(void *addr, struct debug_obj_descr *descr) | 750 | void debug_object_destroy(void *addr, const struct debug_obj_descr *descr) |
| 751 | { | 751 | { |
| 752 | enum debug_obj_state state; | 752 | enum debug_obj_state state; |
| 753 | struct debug_bucket *db; | 753 | struct debug_bucket *db; |
| @@ -797,7 +797,7 @@ EXPORT_SYMBOL_GPL(debug_object_destroy); · 43 unmodified lines | |||
| 797 | * @addr: address of the object | 797 | * @addr: address of the object |
| 798 | * @descr: pointer to an object specific debug description structure | 798 | * @descr: pointer to an object specific debug description structure |
| 799 | */ | 799 | */ |
| 800 | void debug_object_free(void *addr, struct debug_obj_descr *descr) | 800 | void debug_object_free(void *addr, const struct debug_obj_descr *descr) |
| 801 | { | 801 | { |
| 802 | enum debug_obj_state state; | 802 | enum debug_obj_state state; |
| 803 | struct debug_bucket *db; | 803 | struct debug_bucket *db; |
| @@ -838,7 +838,7 @@ EXPORT_SYMBOL_GPL(debug_object_free); · 34 unmodified lines | |||
| 838 | * @addr: address of the object | 838 | * @addr: address of the object |
| 839 | * @descr: pointer to an object specific debug description structure | 839 | * @descr: pointer to an object specific debug description structure |
| 840 | */ | 840 | */ |
| 841 | void debug_object_assert_init(void *addr, struct debug_obj_descr *descr) | 841 | void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr) |
| 842 | { | 842 | { |
| 843 | struct debug_bucket *db; | 843 | struct debug_bucket *db; |
| 844 | struct debug_obj *obj; | 844 | struct debug_obj *obj; |
| @@ -886,7 +886,7 @@ EXPORT_SYMBOL_GPL(debug_object_assert_init); · 41 unmodified lines | |||
| 886 | * @next: state to move to if expected state is found | 886 | * @next: state to move to if expected state is found |
| 887 | */ | 887 | */ |
| 888 | void | 888 | void |
| 889 | debug_object_active_state(void *addr, struct debug_obj_descr *descr, | 889 | debug_object_active_state(void *addr, const struct debug_obj_descr *descr, |
| 890 | unsigned int expect, unsigned int next) | 890 | unsigned int expect, unsigned int next) |
| 891 | { | 891 | { |
| 892 | struct debug_bucket *db; | 892 | struct debug_bucket *db; |
| @@ -934,7 +934,7 @@ EXPORT_SYMBOL_GPL(debug_object_active_state); · 41 unmodified lines | |||
| 934 | static void __debug_check_no_obj_freed(const void *address, unsigned long size) | 934 | static void __debug_check_no_obj_freed(const void *address, unsigned long size) |
| 935 | { | 935 | { |
| 936 | unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; | 936 | unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; |
| 937 | struct debug_obj_descr *descr; | 937 | const struct debug_obj_descr *descr; |
| 938 | enum debug_obj_state state; | 938 | enum debug_obj_state state; |
| 939 | struct debug_bucket *db; | 939 | struct debug_bucket *db; |
| 940 | struct hlist_node *tmp; | 940 | struct hlist_node *tmp; |
| @@ -1052,7 +1052,7 @@ struct self_test { · 111 unmodified lines | |||
| 1052 | unsigned long dummy2[3]; | 1052 | unsigned long dummy2[3]; |
| 1053 | }; | 1053 | }; |
| 1054 | 1054 | ||
| 1055 | static __initdata struct debug_obj_descr descr_type_test; | 1055 | static __initconst const struct debug_obj_descr descr_type_test; |
| 1056 | 1056 | ||
| 1057 | static bool __init is_static_object(void *addr) | 1057 | static bool __init is_static_object(void *addr) |
| 1058 | { | 1058 | { |
| @@ -1177,7 +1177,7 @@ out: · 118 unmodified lines | |||
| 1177 | return res; | 1177 | return res; |
| 1178 | } | 1178 | } |
| 1179 | 1179 | ||
| 1180 | static __initdata struct debug_obj_descr descr_type_test = { | 1180 | static __initconst const struct debug_obj_descr descr_type_test = { |
| 1181 | .name = "selftest", | 1181 | .name = "selftest", |
| 1182 | .is_static_object = is_static_object, | 1182 | .is_static_object = is_static_object, |
| 1183 | .fixup_init = fixup_init, | 1183 | .fixup_init = fixup_init, |