1 /**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
10 #define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */
11 #define TRANSLATE_SIZE 256
12 #define MAX_COLLISIONS 2
14 static uint32_t *gator_crc32_table;
15 static uint32_t translate_buffer_mask;
17 static DEFINE_PER_CPU(char *, translate_text);
18 static DEFINE_PER_CPU(uint32_t, cookie_next_key);
19 static DEFINE_PER_CPU(uint64_t *, cookie_keys);
20 static DEFINE_PER_CPU(uint32_t *, cookie_values);
21 static DEFINE_PER_CPU(int, translate_buffer_read);
22 static DEFINE_PER_CPU(int, translate_buffer_write);
23 static DEFINE_PER_CPU(unsigned int *, translate_buffer);
25 static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
26 static void wq_cookie_handler(struct work_struct *unused);
27 DECLARE_WORK(cookie_work, wq_cookie_handler);
28 static struct timer_list app_process_wake_up_timer;
29 static void app_process_wake_up_handler(unsigned long unused_data);
30 static struct timer_list app_process_wake_up_timer;
31 static void app_process_wake_up_handler(unsigned long unused_data);
33 static uint32_t cookiemap_code(uint64_t value64) {
34 uint32_t value = (uint32_t)((value64 >> 32) + value64);
35 uint32_t cookiecode = (value >> 24) & 0xff;
36 cookiecode = cookiecode * 31 + ((value >> 16) & 0xff);
37 cookiecode = cookiecode * 31 + ((value >> 8) & 0xff);
38 cookiecode = cookiecode * 31 + ((value >> 0) & 0xff);
39 cookiecode &= (COOKIEMAP_ENTRIES-1);
40 return cookiecode * MAX_COLLISIONS;
41 }
43 static uint32_t gator_chksum_crc32(char *data)
44 {
45 register unsigned long crc;
46 unsigned char *block = data;
47 int i, length = strlen(data);
49 crc = 0xFFFFFFFF;
50 for (i = 0; i < length; i++) {
51 crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF];
52 }
54 return (crc ^ 0xFFFFFFFF);
55 }
57 /*
58 * Exists
59 * Pre: [0][1][v][3]..[n-1]
60 * Post: [v][0][1][3]..[n-1]
61 */
62 static uint32_t cookiemap_exists(uint64_t key) {
63 unsigned long x, flags, retval = 0;
64 int cpu = smp_processor_id();
65 uint32_t cookiecode = cookiemap_code(key);
66 uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
67 uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
69 // Can be called from interrupt handler or from work queue
70 local_irq_save(flags);
71 for (x = 0; x < MAX_COLLISIONS; x++) {
72 if (keys[x] == key) {
73 uint32_t value = values[x];
74 for (; x > 0; x--) {
75 keys[x] = keys[x-1];
76 values[x] = values[x-1];
77 }
78 keys[0] = key;
79 values[0] = value;
80 retval = value;
81 break;
82 }
83 }
84 local_irq_restore(flags);
86 return retval;
87 }
89 /*
90 * Add
91 * Pre: [0][1][2][3]..[n-1]
92 * Post: [v][0][1][2]..[n-2]
93 */
94 static void cookiemap_add(uint64_t key, uint32_t value) {
95 int cpu = smp_processor_id();
96 int cookiecode = cookiemap_code(key);
97 uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
98 uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
99 int x;
101 for (x = MAX_COLLISIONS-1; x > 0; x--) {
102 keys[x] = keys[x-1];
103 values[x] = values[x-1];
104 }
105 keys[0] = key;
106 values[0] = value;
107 }
109 static void translate_buffer_write_int(int cpu, unsigned int x)
110 {
111 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x;
112 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask;
113 }
115 static unsigned int translate_buffer_read_int(int cpu)
116 {
117 unsigned int value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++];
118 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask;
119 return value;
120 }
122 static void wq_cookie_handler(struct work_struct *unused)
123 {
124 struct task_struct *task;
125 struct vm_area_struct *vma;
126 int cpu = smp_processor_id();
127 unsigned int cookie, commit;
129 mutex_lock(&start_mutex);
131 if (gator_started != 0) {
132 commit = per_cpu(translate_buffer_write, cpu);
133 while (per_cpu(translate_buffer_read, cpu) != commit) {
134 task = (struct task_struct *)translate_buffer_read_int(cpu);
135 vma = (struct vm_area_struct *)translate_buffer_read_int(cpu);
136 cookie = get_cookie(cpu, BACKTRACE_BUF, task, vma, NULL, false);
137 }
138 }
140 mutex_unlock(&start_mutex);
141 }
143 static void app_process_wake_up_handler(unsigned long unused_data)
144 {
145 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
146 schedule_work(&cookie_work);
147 }
149 // Retrieve full name from proc/pid/cmdline for java processes on Android
150 static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt)
151 {
152 void *maddr;
153 unsigned int len;
154 unsigned long addr;
155 struct mm_struct *mm;
156 struct page *page = NULL;
157 struct vm_area_struct *page_vma;
158 int bytes, offset, retval = 0, ptr;
159 char * buf = per_cpu(translate_text, cpu);
161 // Push work into a work queue if in atomic context as the kernel functions below might sleep
162 // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems
163 // inconsistent during a context switch between android/linux versions
164 if (in_interrupt) {
165 // Check if already in buffer
166 ptr = per_cpu(translate_buffer_read, cpu);
167 while (ptr != per_cpu(translate_buffer_write, cpu)) {
168 if (per_cpu(translate_buffer, cpu)[ptr] == (int)task)
169 goto out;
170 ptr = (ptr + 2) & translate_buffer_mask;
171 }
173 translate_buffer_write_int(cpu, (unsigned int)task);
174 translate_buffer_write_int(cpu, (unsigned int)vma);
175 mod_timer(&app_process_wake_up_timer, jiffies + 1);
176 goto out;
177 }
179 mm = get_task_mm(task);
180 if (!mm)
181 goto out;
182 if (!mm->arg_end)
183 goto outmm;
184 addr = mm->arg_start;
185 len = mm->arg_end - mm->arg_start;
187 if (len > TRANSLATE_SIZE)
188 len = TRANSLATE_SIZE;
190 down_read(&mm->mmap_sem);
191 while (len) {
192 if (get_user_pages(task, mm, addr, 1, 0, 1, &page, &page_vma) <= 0)
193 goto outsem;
195 maddr = kmap(page);
196 offset = addr & (PAGE_SIZE-1);
197 bytes = len;
198 if (bytes > PAGE_SIZE - offset)
199 bytes = PAGE_SIZE - offset;
201 copy_from_user_page(page_vma, page, addr, buf, maddr + offset, bytes);
203 kunmap(page); // release page allocated by get_user_pages()
204 page_cache_release(page);
206 len -= bytes;
207 buf += bytes;
208 addr += bytes;
210 *text = per_cpu(translate_text, cpu);
211 retval = 1;
212 }
214 // On app_process startup, /proc/pid/cmdline is initially "zygote" then "<pre-initialized>" but changes after an initial startup period
215 if (strcmp(*text, "zygote") == 0 || strcmp(*text, "<pre-initialized>") == 0)
216 retval = 0;
218 outsem:
219 up_read(&mm->mmap_sem);
220 outmm:
221 mmput(mm);
222 out:
223 return retval;
224 }
226 static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt)
227 {
228 unsigned long flags, cookie;
229 struct path *path;
230 uint64_t key;
231 char *text;
233 if (mod) {
234 text = mod->name;
235 } else {
236 if (!vma || !vma->vm_file) {
237 return INVALID_COOKIE;
238 }
239 path = &vma->vm_file->f_path;
240 if (!path || !path->dentry) {
241 return INVALID_COOKIE;
242 }
244 text = (char*)path->dentry->d_name.name;
245 }
247 key = gator_chksum_crc32(text);
248 key = (key << 32) | (uint32_t)task->tgid;
250 cookie = cookiemap_exists(key);
251 if (cookie) {
252 return cookie;
253 }
255 if (strcmp(text, "app_process") == 0 && !mod) {
256 if (!translate_app_process(&text, cpu, task, vma, in_interrupt))
257 return INVALID_COOKIE;
258 }
260 // Can be called from interrupt handler or from work queue or from scheduler trace
261 local_irq_save(flags);
263 cookie = INVALID_COOKIE;
264 if (marshal_cookie_header(text)) {
265 cookie = per_cpu(cookie_next_key, cpu) += nr_cpu_ids;
266 cookiemap_add(key, cookie);
267 marshal_cookie(cookie, text);
268 }
270 local_irq_restore(flags);
272 return cookie;
273 }
275 static int get_exec_cookie(int cpu, int buftype, struct task_struct *task)
276 {
277 unsigned long cookie = NO_COOKIE;
278 struct mm_struct *mm = task->mm;
279 struct vm_area_struct *vma;
281 // kernel threads have no address space
282 if (!mm)
283 return cookie;
285 for (vma = mm->mmap; vma; vma = vma->vm_next) {
286 if (!vma->vm_file)
287 continue;
288 if (!(vma->vm_flags & VM_EXECUTABLE))
289 continue;
290 cookie = get_cookie(cpu, buftype, task, vma, NULL, true);
291 break;
292 }
294 return cookie;
295 }
297 static unsigned long get_address_cookie(int cpu, int buftype, struct task_struct *task, unsigned long addr, off_t *offset)
298 {
299 unsigned long cookie = NO_COOKIE;
300 struct mm_struct *mm = task->mm;
301 struct vm_area_struct *vma;
303 if (!mm)
304 return cookie;
306 for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
307 if (addr < vma->vm_start || addr >= vma->vm_end)
308 continue;
310 if (vma->vm_file) {
311 cookie = get_cookie(cpu, buftype, task, vma, NULL, true);
312 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
313 } else {
314 /* must be an anonymous map */
315 *offset = addr;
316 }
318 break;
319 }
321 if (!vma)
322 cookie = INVALID_COOKIE;
324 return cookie;
325 }
327 static int cookies_initialize(void)
328 {
329 uint32_t crc, poly;
330 int i, j, cpu, size, err = 0;
332 int translate_buffer_size = 512; // must be a power of 2
333 translate_buffer_mask = translate_buffer_size / sizeof(per_cpu(translate_buffer, 0)[0]) - 1;
335 for_each_present_cpu(cpu) {
336 per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu;
338 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t);
339 per_cpu(cookie_keys, cpu) = (uint64_t*)kmalloc(size, GFP_KERNEL);
340 if (!per_cpu(cookie_keys, cpu)) {
341 err = -ENOMEM;
342 goto cookie_setup_error;
343 }
344 memset(per_cpu(cookie_keys, cpu), 0, size);
346 size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t);
347 per_cpu(cookie_values, cpu) = (uint32_t*)kmalloc(size, GFP_KERNEL);
348 if (!per_cpu(cookie_values, cpu)) {
349 err = -ENOMEM;
350 goto cookie_setup_error;
351 }
352 memset(per_cpu(cookie_values, cpu), 0, size);
354 per_cpu(translate_buffer, cpu) = (unsigned int *)kmalloc(translate_buffer_size, GFP_KERNEL);
355 if (!per_cpu(translate_buffer, cpu)) {
356 err = -ENOMEM;
357 goto cookie_setup_error;
358 }
360 per_cpu(translate_buffer_write, cpu) = 0;
361 per_cpu(translate_buffer_read, cpu) = 0;
363 per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_SIZE, GFP_KERNEL);
364 if (!per_cpu(translate_text, cpu)) {
365 err = -ENOMEM;
366 goto cookie_setup_error;
367 }
368 }
370 // build CRC32 table
371 poly = 0x04c11db7;
372 gator_crc32_table = (uint32_t*)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL);
373 for (i = 0; i < 256; i++) {
374 crc = i;
375 for (j = 8; j > 0; j--) {
376 if (crc & 1) {
377 crc = (crc >> 1) ^ poly;
378 } else {
379 crc >>= 1;
380 }
381 }
382 gator_crc32_table[i] = crc;
383 }
385 setup_timer(&app_process_wake_up_timer, app_process_wake_up_handler, 0);
387 cookie_setup_error:
388 return err;
389 }
391 static void cookies_release(void)
392 {
393 int cpu;
395 for_each_present_cpu(cpu) {
396 kfree(per_cpu(cookie_keys, cpu));
397 per_cpu(cookie_keys, cpu) = NULL;
399 kfree(per_cpu(cookie_values, cpu));
400 per_cpu(cookie_values, cpu) = NULL;
402 kfree(per_cpu(translate_buffer, cpu));
403 per_cpu(translate_buffer, cpu) = NULL;
404 per_cpu(translate_buffer_read, cpu) = 0;
405 per_cpu(translate_buffer_write, cpu) = 0;
407 kfree(per_cpu(translate_text, cpu));
408 per_cpu(translate_text, cpu) = NULL;
409 }
411 del_timer_sync(&app_process_wake_up_timer);
412 kfree(gator_crc32_table);
413 gator_crc32_table = NULL;
414 }