0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/gfp.h>
0012 #include <linux/hash.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mm.h>
0015 #include <linux/percpu.h>
0016 #include <linux/printk.h>
0017 #include <linux/shrinker.h>
0018 #include <linux/slab.h>
0019 #include <linux/srcu.h>
0020 #include <linux/string.h>
0021 #include <linux/types.h>
0022 #include <linux/cpuhotplug.h>
0023
0024 #include "../slab.h"
0025 #include "kasan.h"
0026
0027
0028
0029
0030
0031
0032
0033 struct qlist_head {
0034 struct qlist_node *head;
0035 struct qlist_node *tail;
0036 size_t bytes;
0037 bool offline;
0038 };
0039
0040 #define QLIST_INIT { NULL, NULL, 0 }
0041
0042 static bool qlist_empty(struct qlist_head *q)
0043 {
0044 return !q->head;
0045 }
0046
0047 static void qlist_init(struct qlist_head *q)
0048 {
0049 q->head = q->tail = NULL;
0050 q->bytes = 0;
0051 }
0052
0053 static void qlist_put(struct qlist_head *q, struct qlist_node *qlink,
0054 size_t size)
0055 {
0056 if (unlikely(qlist_empty(q)))
0057 q->head = qlink;
0058 else
0059 q->tail->next = qlink;
0060 q->tail = qlink;
0061 qlink->next = NULL;
0062 q->bytes += size;
0063 }
0064
0065 static void qlist_move_all(struct qlist_head *from, struct qlist_head *to)
0066 {
0067 if (unlikely(qlist_empty(from)))
0068 return;
0069
0070 if (qlist_empty(to)) {
0071 *to = *from;
0072 qlist_init(from);
0073 return;
0074 }
0075
0076 to->tail->next = from->head;
0077 to->tail = from->tail;
0078 to->bytes += from->bytes;
0079
0080 qlist_init(from);
0081 }
0082
0083 #define QUARANTINE_PERCPU_SIZE (1 << 20)
0084 #define QUARANTINE_BATCHES \
0085 (1024 > 4 * CONFIG_NR_CPUS ? 1024 : 4 * CONFIG_NR_CPUS)
0086
0087
0088
0089
0090
0091 static DEFINE_PER_CPU(struct qlist_head, cpu_quarantine);
0092
0093
0094 static struct qlist_head global_quarantine[QUARANTINE_BATCHES];
0095 static int quarantine_head;
0096 static int quarantine_tail;
0097
0098 static unsigned long quarantine_size;
0099 static DEFINE_RAW_SPINLOCK(quarantine_lock);
0100 DEFINE_STATIC_SRCU(remove_cache_srcu);
0101
0102 #ifdef CONFIG_PREEMPT_RT
0103 struct cpu_shrink_qlist {
0104 raw_spinlock_t lock;
0105 struct qlist_head qlist;
0106 };
0107
0108 static DEFINE_PER_CPU(struct cpu_shrink_qlist, shrink_qlist) = {
0109 .lock = __RAW_SPIN_LOCK_UNLOCKED(shrink_qlist.lock),
0110 };
0111 #endif
0112
0113
0114 static unsigned long quarantine_max_size;
0115
0116
0117
0118
0119
0120 static unsigned long quarantine_batch_size;
0121
0122
0123
0124
0125
0126
0127 #define QUARANTINE_FRACTION 32
0128
0129 static struct kmem_cache *qlink_to_cache(struct qlist_node *qlink)
0130 {
0131 return virt_to_slab(qlink)->slab_cache;
0132 }
0133
0134 static void *qlink_to_object(struct qlist_node *qlink, struct kmem_cache *cache)
0135 {
0136 struct kasan_free_meta *free_info =
0137 container_of(qlink, struct kasan_free_meta,
0138 quarantine_link);
0139
0140 return ((void *)free_info) - cache->kasan_info.free_meta_offset;
0141 }
0142
0143 static void qlink_free(struct qlist_node *qlink, struct kmem_cache *cache)
0144 {
0145 void *object = qlink_to_object(qlink, cache);
0146 struct kasan_free_meta *meta = kasan_get_free_meta(cache, object);
0147 unsigned long flags;
0148
0149 if (IS_ENABLED(CONFIG_SLAB))
0150 local_irq_save(flags);
0151
0152
0153
0154
0155
0156
0157
0158 if (slab_want_init_on_free(cache) &&
0159 cache->kasan_info.free_meta_offset == 0)
0160 memzero_explicit(meta, sizeof(*meta));
0161
0162
0163
0164
0165
0166 *(u8 *)kasan_mem_to_shadow(object) = KASAN_SLAB_FREE;
0167
0168 ___cache_free(cache, object, _THIS_IP_);
0169
0170 if (IS_ENABLED(CONFIG_SLAB))
0171 local_irq_restore(flags);
0172 }
0173
0174 static void qlist_free_all(struct qlist_head *q, struct kmem_cache *cache)
0175 {
0176 struct qlist_node *qlink;
0177
0178 if (unlikely(qlist_empty(q)))
0179 return;
0180
0181 qlink = q->head;
0182 while (qlink) {
0183 struct kmem_cache *obj_cache =
0184 cache ? cache : qlink_to_cache(qlink);
0185 struct qlist_node *next = qlink->next;
0186
0187 qlink_free(qlink, obj_cache);
0188 qlink = next;
0189 }
0190 qlist_init(q);
0191 }
0192
0193 bool kasan_quarantine_put(struct kmem_cache *cache, void *object)
0194 {
0195 unsigned long flags;
0196 struct qlist_head *q;
0197 struct qlist_head temp = QLIST_INIT;
0198 struct kasan_free_meta *meta = kasan_get_free_meta(cache, object);
0199
0200
0201
0202
0203
0204 if (!meta)
0205 return false;
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 local_irq_save(flags);
0216
0217 q = this_cpu_ptr(&cpu_quarantine);
0218 if (q->offline) {
0219 local_irq_restore(flags);
0220 return false;
0221 }
0222 qlist_put(q, &meta->quarantine_link, cache->size);
0223 if (unlikely(q->bytes > QUARANTINE_PERCPU_SIZE)) {
0224 qlist_move_all(q, &temp);
0225
0226 raw_spin_lock(&quarantine_lock);
0227 WRITE_ONCE(quarantine_size, quarantine_size + temp.bytes);
0228 qlist_move_all(&temp, &global_quarantine[quarantine_tail]);
0229 if (global_quarantine[quarantine_tail].bytes >=
0230 READ_ONCE(quarantine_batch_size)) {
0231 int new_tail;
0232
0233 new_tail = quarantine_tail + 1;
0234 if (new_tail == QUARANTINE_BATCHES)
0235 new_tail = 0;
0236 if (new_tail != quarantine_head)
0237 quarantine_tail = new_tail;
0238 }
0239 raw_spin_unlock(&quarantine_lock);
0240 }
0241
0242 local_irq_restore(flags);
0243
0244 return true;
0245 }
0246
0247 void kasan_quarantine_reduce(void)
0248 {
0249 size_t total_size, new_quarantine_size, percpu_quarantines;
0250 unsigned long flags;
0251 int srcu_idx;
0252 struct qlist_head to_free = QLIST_INIT;
0253
0254 if (likely(READ_ONCE(quarantine_size) <=
0255 READ_ONCE(quarantine_max_size)))
0256 return;
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 srcu_idx = srcu_read_lock(&remove_cache_srcu);
0268 raw_spin_lock_irqsave(&quarantine_lock, flags);
0269
0270
0271
0272
0273
0274 total_size = (totalram_pages() << PAGE_SHIFT) /
0275 QUARANTINE_FRACTION;
0276 percpu_quarantines = QUARANTINE_PERCPU_SIZE * num_online_cpus();
0277 new_quarantine_size = (total_size < percpu_quarantines) ?
0278 0 : total_size - percpu_quarantines;
0279 WRITE_ONCE(quarantine_max_size, new_quarantine_size);
0280
0281 WRITE_ONCE(quarantine_batch_size, max((size_t)QUARANTINE_PERCPU_SIZE,
0282 2 * total_size / QUARANTINE_BATCHES));
0283
0284 if (likely(quarantine_size > quarantine_max_size)) {
0285 qlist_move_all(&global_quarantine[quarantine_head], &to_free);
0286 WRITE_ONCE(quarantine_size, quarantine_size - to_free.bytes);
0287 quarantine_head++;
0288 if (quarantine_head == QUARANTINE_BATCHES)
0289 quarantine_head = 0;
0290 }
0291
0292 raw_spin_unlock_irqrestore(&quarantine_lock, flags);
0293
0294 qlist_free_all(&to_free, NULL);
0295 srcu_read_unlock(&remove_cache_srcu, srcu_idx);
0296 }
0297
0298 static void qlist_move_cache(struct qlist_head *from,
0299 struct qlist_head *to,
0300 struct kmem_cache *cache)
0301 {
0302 struct qlist_node *curr;
0303
0304 if (unlikely(qlist_empty(from)))
0305 return;
0306
0307 curr = from->head;
0308 qlist_init(from);
0309 while (curr) {
0310 struct qlist_node *next = curr->next;
0311 struct kmem_cache *obj_cache = qlink_to_cache(curr);
0312
0313 if (obj_cache == cache)
0314 qlist_put(to, curr, obj_cache->size);
0315 else
0316 qlist_put(from, curr, obj_cache->size);
0317
0318 curr = next;
0319 }
0320 }
0321
0322 #ifndef CONFIG_PREEMPT_RT
0323 static void __per_cpu_remove_cache(struct qlist_head *q, void *arg)
0324 {
0325 struct kmem_cache *cache = arg;
0326 struct qlist_head to_free = QLIST_INIT;
0327
0328 qlist_move_cache(q, &to_free, cache);
0329 qlist_free_all(&to_free, cache);
0330 }
0331 #else
0332 static void __per_cpu_remove_cache(struct qlist_head *q, void *arg)
0333 {
0334 struct kmem_cache *cache = arg;
0335 unsigned long flags;
0336 struct cpu_shrink_qlist *sq;
0337
0338 sq = this_cpu_ptr(&shrink_qlist);
0339 raw_spin_lock_irqsave(&sq->lock, flags);
0340 qlist_move_cache(q, &sq->qlist, cache);
0341 raw_spin_unlock_irqrestore(&sq->lock, flags);
0342 }
0343 #endif
0344
0345 static void per_cpu_remove_cache(void *arg)
0346 {
0347 struct qlist_head *q;
0348
0349 q = this_cpu_ptr(&cpu_quarantine);
0350
0351
0352
0353
0354
0355 if (READ_ONCE(q->offline))
0356 return;
0357 __per_cpu_remove_cache(q, arg);
0358 }
0359
0360
0361 void kasan_quarantine_remove_cache(struct kmem_cache *cache)
0362 {
0363 unsigned long flags, i;
0364 struct qlist_head to_free = QLIST_INIT;
0365
0366
0367
0368
0369
0370
0371
0372
0373 on_each_cpu(per_cpu_remove_cache, cache, 1);
0374
0375 #ifdef CONFIG_PREEMPT_RT
0376 {
0377 int cpu;
0378 struct cpu_shrink_qlist *sq;
0379
0380 for_each_online_cpu(cpu) {
0381 sq = per_cpu_ptr(&shrink_qlist, cpu);
0382 raw_spin_lock_irqsave(&sq->lock, flags);
0383 qlist_move_cache(&sq->qlist, &to_free, cache);
0384 raw_spin_unlock_irqrestore(&sq->lock, flags);
0385 }
0386 qlist_free_all(&to_free, cache);
0387 }
0388 #endif
0389
0390 raw_spin_lock_irqsave(&quarantine_lock, flags);
0391 for (i = 0; i < QUARANTINE_BATCHES; i++) {
0392 if (qlist_empty(&global_quarantine[i]))
0393 continue;
0394 qlist_move_cache(&global_quarantine[i], &to_free, cache);
0395
0396 raw_spin_unlock_irqrestore(&quarantine_lock, flags);
0397 cond_resched();
0398 raw_spin_lock_irqsave(&quarantine_lock, flags);
0399 }
0400 raw_spin_unlock_irqrestore(&quarantine_lock, flags);
0401
0402 qlist_free_all(&to_free, cache);
0403
0404 synchronize_srcu(&remove_cache_srcu);
0405 }
0406
0407 static int kasan_cpu_online(unsigned int cpu)
0408 {
0409 this_cpu_ptr(&cpu_quarantine)->offline = false;
0410 return 0;
0411 }
0412
0413 static int kasan_cpu_offline(unsigned int cpu)
0414 {
0415 struct qlist_head *q;
0416
0417 q = this_cpu_ptr(&cpu_quarantine);
0418
0419
0420
0421
0422 WRITE_ONCE(q->offline, true);
0423 barrier();
0424 qlist_free_all(q, NULL);
0425 return 0;
0426 }
0427
0428 static int __init kasan_cpu_quarantine_init(void)
0429 {
0430 int ret = 0;
0431
0432 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mm/kasan:online",
0433 kasan_cpu_online, kasan_cpu_offline);
0434 if (ret < 0)
0435 pr_err("kasan cpu quarantine register failed [%d]\n", ret);
0436 return ret;
0437 }
0438 late_initcall(kasan_cpu_quarantine_init);