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