mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
Codetag iterator use <id,address> pair to guarantee the validness. But both id and address can be reused, there is theoretical possibility when module inserted right after another module removed, kmalloc returns an address same as the address kfree by previous module and IDR key reuses the key recently removed. Add a sequence number to codetag_module and code_iterator, the sequence number is strickly incremented whenever a module is loaded. An iterator is valid if and only if its sequence number match codetag_module's. Link: https://lkml.kernel.org/r/20250609064200.112639-1-00107082@163.com Signed-off-by: David Wang <00107082@163.com> Acked-by: Suren Baghdasaryan <surenb@google.com> Cc: Kent Overstreet <kent.overstreet@linux.dev> Cc: Tim Chen <tim.c.chen@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
113 lines
3.4 KiB
C
113 lines
3.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* code tagging framework
|
|
*/
|
|
#ifndef _LINUX_CODETAG_H
|
|
#define _LINUX_CODETAG_H
|
|
|
|
#include <linux/types.h>
|
|
|
|
struct codetag_iterator;
|
|
struct codetag_type;
|
|
struct codetag_module;
|
|
struct seq_buf;
|
|
struct module;
|
|
|
|
#define CODETAG_SECTION_START_PREFIX "__start_"
|
|
#define CODETAG_SECTION_STOP_PREFIX "__stop_"
|
|
|
|
/*
|
|
* An instance of this structure is created in a special ELF section at every
|
|
* code location being tagged. At runtime, the special section is treated as
|
|
* an array of these.
|
|
*/
|
|
struct codetag {
|
|
unsigned int flags; /* used in later patches */
|
|
unsigned int lineno;
|
|
const char *modname;
|
|
const char *function;
|
|
const char *filename;
|
|
} __aligned(8);
|
|
|
|
union codetag_ref {
|
|
struct codetag *ct;
|
|
};
|
|
|
|
struct codetag_type_desc {
|
|
const char *section;
|
|
size_t tag_size;
|
|
int (*module_load)(struct module *mod,
|
|
struct codetag *start, struct codetag *end);
|
|
void (*module_unload)(struct module *mod,
|
|
struct codetag *start, struct codetag *end);
|
|
#ifdef CONFIG_MODULES
|
|
void (*module_replaced)(struct module *mod, struct module *new_mod);
|
|
bool (*needs_section_mem)(struct module *mod, unsigned long size);
|
|
void *(*alloc_section_mem)(struct module *mod, unsigned long size,
|
|
unsigned int prepend, unsigned long align);
|
|
void (*free_section_mem)(struct module *mod, bool used);
|
|
#endif
|
|
};
|
|
|
|
struct codetag_iterator {
|
|
struct codetag_type *cttype;
|
|
struct codetag_module *cmod;
|
|
unsigned long mod_id;
|
|
struct codetag *ct;
|
|
unsigned long mod_seq;
|
|
};
|
|
|
|
#ifdef MODULE
|
|
#define CT_MODULE_NAME KBUILD_MODNAME
|
|
#else
|
|
#define CT_MODULE_NAME NULL
|
|
#endif
|
|
|
|
#define CODE_TAG_INIT { \
|
|
.modname = CT_MODULE_NAME, \
|
|
.function = __func__, \
|
|
.filename = __FILE__, \
|
|
.lineno = __LINE__, \
|
|
.flags = 0, \
|
|
}
|
|
|
|
void codetag_lock_module_list(struct codetag_type *cttype, bool lock);
|
|
bool codetag_trylock_module_list(struct codetag_type *cttype);
|
|
struct codetag_iterator codetag_get_ct_iter(struct codetag_type *cttype);
|
|
struct codetag *codetag_next_ct(struct codetag_iterator *iter);
|
|
|
|
void codetag_to_text(struct seq_buf *out, struct codetag *ct);
|
|
|
|
struct codetag_type *
|
|
codetag_register_type(const struct codetag_type_desc *desc);
|
|
|
|
#if defined(CONFIG_CODE_TAGGING) && defined(CONFIG_MODULES)
|
|
|
|
bool codetag_needs_module_section(struct module *mod, const char *name,
|
|
unsigned long size);
|
|
void *codetag_alloc_module_section(struct module *mod, const char *name,
|
|
unsigned long size, unsigned int prepend,
|
|
unsigned long align);
|
|
void codetag_free_module_sections(struct module *mod);
|
|
void codetag_module_replaced(struct module *mod, struct module *new_mod);
|
|
int codetag_load_module(struct module *mod);
|
|
void codetag_unload_module(struct module *mod);
|
|
|
|
#else /* defined(CONFIG_CODE_TAGGING) && defined(CONFIG_MODULES) */
|
|
|
|
static inline bool
|
|
codetag_needs_module_section(struct module *mod, const char *name,
|
|
unsigned long size) { return false; }
|
|
static inline void *
|
|
codetag_alloc_module_section(struct module *mod, const char *name,
|
|
unsigned long size, unsigned int prepend,
|
|
unsigned long align) { return NULL; }
|
|
static inline void codetag_free_module_sections(struct module *mod) {}
|
|
static inline void codetag_module_replaced(struct module *mod, struct module *new_mod) {}
|
|
static inline int codetag_load_module(struct module *mod) { return 0; }
|
|
static inline void codetag_unload_module(struct module *mod) {}
|
|
|
|
#endif /* defined(CONFIG_CODE_TAGGING) && defined(CONFIG_MODULES) */
|
|
|
|
#endif /* _LINUX_CODETAG_H */
|