1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/codetag.h> 3 #include <linux/idr.h> 4 #include <linux/kallsyms.h> 5 #include <linux/module.h> 6 #include <linux/seq_buf.h> 7 #include <linux/slab.h> 8 9 struct codetag_type { 10 struct list_head link; 11 unsigned int count; 12 struct idr mod_idr; 13 struct rw_semaphore mod_lock; /* protects mod_idr */ 14 struct codetag_type_desc desc; 15 }; 16 17 struct codetag_range { 18 struct codetag *start; 19 struct codetag *stop; 20 }; 21 22 struct codetag_module { 23 struct module *mod; 24 struct codetag_range range; 25 }; 26 27 static DEFINE_MUTEX(codetag_lock); 28 static LIST_HEAD(codetag_types); 29 30 void codetag_lock_module_list(struct codetag_type *cttype, bool lock) 31 { 32 if (lock) 33 down_read(&cttype->mod_lock); 34 else 35 up_read(&cttype->mod_lock); 36 } 37 38 struct codetag_iterator codetag_get_ct_iter(struct codetag_type *cttype) 39 { 40 struct codetag_iterator iter = { 41 .cttype = cttype, 42 .cmod = NULL, 43 .mod_id = 0, 44 .ct = NULL, 45 }; 46 47 return iter; 48 } 49 50 static inline struct codetag *get_first_module_ct(struct codetag_module *cmod) 51 { 52 return cmod->range.start < cmod->range.stop ? cmod->range.start : NULL; 53 } 54 55 static inline 56 struct codetag *get_next_module_ct(struct codetag_iterator *iter) 57 { 58 struct codetag *res = (struct codetag *) 59 ((char *)iter->ct + iter->cttype->desc.tag_size); 60 61 return res < iter->cmod->range.stop ? res : NULL; 62 } 63 64 struct codetag *codetag_next_ct(struct codetag_iterator *iter) 65 { 66 struct codetag_type *cttype = iter->cttype; 67 struct codetag_module *cmod; 68 struct codetag *ct; 69 70 lockdep_assert_held(&cttype->mod_lock); 71 72 if (unlikely(idr_is_empty(&cttype->mod_idr))) 73 return NULL; 74 75 ct = NULL; 76 while (true) { 77 cmod = idr_find(&cttype->mod_idr, iter->mod_id); 78 79 /* If module was removed move to the next one */ 80 if (!cmod) 81 cmod = idr_get_next_ul(&cttype->mod_idr, 82 &iter->mod_id); 83 84 /* Exit if no more modules */ 85 if (!cmod) 86 break; 87 88 if (cmod != iter->cmod) { 89 iter->cmod = cmod; 90 ct = get_first_module_ct(cmod); 91 } else 92 ct = get_next_module_ct(iter); 93 94 if (ct) 95 break; 96 97 iter->mod_id++; 98 } 99 100 iter->ct = ct; 101 return ct; 102 } 103 104 void codetag_to_text(struct seq_buf *out, struct codetag *ct) 105 { 106 if (ct->modname) 107 seq_buf_printf(out, "%s:%u [%s] func:%s", 108 ct->filename, ct->lineno, 109 ct->modname, ct->function); 110 else 111 seq_buf_printf(out, "%s:%u func:%s", 112 ct->filename, ct->lineno, ct->function); 113 } 114 115 static inline size_t range_size(const struct codetag_type *cttype, 116 const struct codetag_range *range) 117 { 118 return ((char *)range->stop - (char *)range->start) / 119 cttype->desc.tag_size; 120 } 121 122 #ifdef CONFIG_MODULES 123 static void *get_symbol(struct module *mod, const char *prefix, const char *name) 124 { 125 DECLARE_SEQ_BUF(sb, KSYM_NAME_LEN); 126 const char *buf; 127 128 seq_buf_printf(&sb, "%s%s", prefix, name); 129 if (seq_buf_has_overflowed(&sb)) 130 return NULL; 131 132 buf = seq_buf_str(&sb); 133 return mod ? 134 (void *)find_kallsyms_symbol_value(mod, buf) : 135 (void *)kallsyms_lookup_name(buf); 136 } 137 138 static struct codetag_range get_section_range(struct module *mod, 139 const char *section) 140 { 141 return (struct codetag_range) { 142 get_symbol(mod, "__start_", section), 143 get_symbol(mod, "__stop_", section), 144 }; 145 } 146 147 static int codetag_module_init(struct codetag_type *cttype, struct module *mod) 148 { 149 struct codetag_range range; 150 struct codetag_module *cmod; 151 int err; 152 153 range = get_section_range(mod, cttype->desc.section); 154 if (!range.start || !range.stop) { 155 pr_warn("Failed to load code tags of type %s from the module %s\n", 156 cttype->desc.section, 157 mod ? mod->name : "(built-in)"); 158 return -EINVAL; 159 } 160 161 /* Ignore empty ranges */ 162 if (range.start == range.stop) 163 return 0; 164 165 BUG_ON(range.start > range.stop); 166 167 cmod = kmalloc(sizeof(*cmod), GFP_KERNEL); 168 if (unlikely(!cmod)) 169 return -ENOMEM; 170 171 cmod->mod = mod; 172 cmod->range = range; 173 174 down_write(&cttype->mod_lock); 175 err = idr_alloc(&cttype->mod_idr, cmod, 0, 0, GFP_KERNEL); 176 if (err >= 0) 177 cttype->count += range_size(cttype, &range); 178 up_write(&cttype->mod_lock); 179 180 if (err < 0) { 181 kfree(cmod); 182 return err; 183 } 184 185 return 0; 186 } 187 188 #else /* CONFIG_MODULES */ 189 static int codetag_module_init(struct codetag_type *cttype, struct module *mod) { return 0; } 190 #endif /* CONFIG_MODULES */ 191 192 struct codetag_type * 193 codetag_register_type(const struct codetag_type_desc *desc) 194 { 195 struct codetag_type *cttype; 196 int err; 197 198 BUG_ON(desc->tag_size <= 0); 199 200 cttype = kzalloc(sizeof(*cttype), GFP_KERNEL); 201 if (unlikely(!cttype)) 202 return ERR_PTR(-ENOMEM); 203 204 cttype->desc = *desc; 205 idr_init(&cttype->mod_idr); 206 init_rwsem(&cttype->mod_lock); 207 208 err = codetag_module_init(cttype, NULL); 209 if (unlikely(err)) { 210 kfree(cttype); 211 return ERR_PTR(err); 212 } 213 214 mutex_lock(&codetag_lock); 215 list_add_tail(&cttype->link, &codetag_types); 216 mutex_unlock(&codetag_lock); 217 218 return cttype; 219 } 220