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