オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/akari/probe.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 688 - (show annotations) (download) (as text)
Fri Sep 9 15:24:05 2022 UTC (19 months, 2 weeks ago) by kumaneko
File MIME type: text/x-csrc
File size: 26970 byte(s)


1 /*
2 * probe.c
3 *
4 * Copyright (C) 2010-2013 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5 *
6 * Functions in this file are doing runtime address resolution based on byte
7 * code comparison in order to allow LKM-based LSM modules to access built-in
8 * functions and variables which are not exported to LKMs.
9 * Since functions in this file are assuming that using identical source code,
10 * identical kernel config and identical compiler generates identical byte code
11 * output, functions in this file may not work on some architectures and/or
12 * environments.
13 *
14 * This file is used by AKARI and CaitSith. This file will become unnecessary
15 * when LKM-based LSM module comes back and TOMOYO 2.x becomes a LKM-based LSM
16 * module.
17 */
18
19 #include "probe.h"
20
21 static void *__init check_function_address(void *ptr, char *symbol)
22 {
23 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
24 static char buf[KSYM_SYMBOL_LEN];
25 const int len = strlen(symbol);
26 #endif
27
28 if (!ptr) {
29 printk(KERN_ERR "Can't resolve %s().\n", symbol);
30 return NULL;
31 }
32 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
33 snprintf(buf, sizeof(buf), "%pS", ptr);
34 if (strncmp(buf, symbol, len) || strncmp(buf + len, "+0x0/", 5)) {
35 printk(KERN_ERR "Guessed %s is %s\n", symbol, buf);
36 return NULL;
37 }
38 #endif
39 return ptr;
40 }
41
42 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
43
44 /**
45 * my_kernel_read - Wrapper for kernel_read().
46 *
47 * @file: Pointer to "struct file".
48 * @offset: Starting position.
49 * @addr: Buffer.
50 * @count: Size of @addr.
51 *
52 * Returns return value from kernel_read().
53 */
54 static inline int my_kernel_read(struct file *file, unsigned long offset,
55 char *addr, unsigned long count)
56 {
57 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
58 /*
59 * I can't use kernel_read() because seq_read() returns -EPIPE
60 * if &pos != &file->f_pos .
61 */
62 mm_segment_t old_fs;
63 unsigned long pos = file->f_pos;
64 int result;
65
66 file->f_pos = offset;
67 old_fs = get_fs();
68 set_fs(get_ds());
69 result = vfs_read(file, (void __user *)addr, count, &file->f_pos);
70 set_fs(old_fs);
71 file->f_pos = pos;
72 return result;
73 #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
74 return kernel_read(file, offset, addr, count);
75 #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
76 loff_t pos = offset;
77
78 return kernel_read(file, addr, count, &pos);
79 #else
80 struct kvec iov = { .iov_base = addr, .iov_len = count };
81 struct kiocb kiocb;
82 struct iov_iter iter;
83
84 init_sync_kiocb(&kiocb, file);
85 iov_iter_kvec(&iter, READ, &iov, 1, count);
86 kiocb.ki_pos = offset;
87 return seq_read_iter(&kiocb, &iter);
88 #endif
89 }
90
91 /**
92 * probe_find_symbol - Find function's address from /proc/kallsyms .
93 *
94 * @keyline: Function to find.
95 *
96 * Returns address of specified function on success, NULL otherwise.
97 */
98 static void *__init probe_find_symbol(const char *keyline)
99 {
100 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0)
101 char buf[128] = { };
102 char *cp;
103
104 strncpy(buf, keyline + 1, sizeof(buf) - 1);
105 cp = strchr(buf, '\n');
106 if (cp)
107 *cp = '\0';
108 return (void *) kallsyms_lookup_name(buf);
109 #else
110 struct file *file = NULL;
111 char *buf;
112 unsigned long entry = 0;
113
114 {
115 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
116 struct file_system_type *fstype = get_fs_type("proc");
117 struct vfsmount *mnt = vfs_kern_mount(fstype, 0, "proc", NULL);
118 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
119 struct file_system_type *fstype = NULL;
120 struct vfsmount *mnt = do_kern_mount("proc", 0, "proc", NULL);
121 #else
122 struct file_system_type *fstype = get_fs_type("proc");
123 struct vfsmount *mnt = kern_mount(fstype);
124 #endif
125 struct dentry *root;
126 struct dentry *dentry;
127
128 /*
129 * We embed put_filesystem() here because it is not exported.
130 */
131 if (fstype)
132 module_put(fstype->owner);
133 if (IS_ERR(mnt))
134 goto out;
135 root = dget(mnt->mnt_root);
136 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
137 inode_lock(root->d_inode);
138 dentry = lookup_one_len("kallsyms", root, 8);
139 inode_unlock(root->d_inode);
140 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
141 mutex_lock(&root->d_inode->i_mutex);
142 dentry = lookup_one_len("kallsyms", root, 8);
143 mutex_unlock(&root->d_inode->i_mutex);
144 #else
145 down(&root->d_inode->i_sem);
146 dentry = lookup_one_len("kallsyms", root, 8);
147 up(&root->d_inode->i_sem);
148 #endif
149 dput(root);
150 if (IS_ERR(dentry))
151 mntput(mnt);
152 else {
153 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
154 struct path path = { .mnt = mnt, .dentry = dentry };
155
156 file = dentry_open(&path, O_RDONLY, current_cred());
157 #else
158 file = dentry_open(dentry, mnt, O_RDONLY
159 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
160 , current_cred()
161 #endif
162 );
163 #endif
164 }
165 }
166 if (IS_ERR(file) || !file)
167 goto out;
168 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
169 if (buf) {
170 int len;
171 int offset = 0;
172
173 while ((len = my_kernel_read(file, offset, buf,
174 PAGE_SIZE - 1)) > 0) {
175 char *cp;
176
177 buf[len] = '\0';
178 cp = strrchr(buf, '\n');
179 if (!cp)
180 break;
181 *(cp + 1) = '\0';
182 offset += strlen(buf);
183 cp = strstr(buf, keyline);
184 if (!cp)
185 continue;
186 *cp = '\0';
187 while (cp > buf && *(cp - 1) != '\n')
188 cp--;
189 entry = simple_strtoul(cp, NULL, 16);
190 break;
191 }
192 kfree(buf);
193 }
194 filp_close(file, NULL);
195 out:
196 return (void *) entry;
197 #endif
198 }
199
200 #endif
201
202 #if defined(LSM_HOOK_INIT)
203
204 /*
205 * Dummy variable for finding location of
206 * "struct security_hook_heads security_hook_heads".
207 */
208 struct security_hook_heads probe_dummy_security_hook_heads;
209
210 /**
211 * probe_security_bprm_committed_creds - Dummy function which does identical to security_bprm_committed_creds() in security/security.c.
212 *
213 * @bprm: Pointer to "struct linux_binprm".
214 *
215 * Returns nothing.
216 */
217 void probe_security_bprm_committed_creds(struct linux_binprm *bprm)
218 {
219 do {
220 struct security_hook_list *p;
221
222 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
223 hlist_for_each_entry(p, &probe_dummy_security_hook_heads.
224 bprm_committed_creds, list)
225 p->hook.bprm_committed_creds(bprm);
226 #else
227 list_for_each_entry(p, &probe_dummy_security_hook_heads.
228 bprm_committed_creds, list)
229 p->hook.bprm_committed_creds(bprm);
230 #endif
231 } while (0);
232 }
233
234 #if defined(CONFIG_ARM64)
235
236 /**
237 * probe_security_hook_heads_on_arm64 - Find security_hook_heads on ARM64.
238 *
239 * @base: Address of security_bprm_committed_creds().
240 *
241 * Returns address of security_hook_heads.bprm_committed_creds on success,
242 * NULL otherwise.
243 */
244 static void * __init probe_security_hook_heads_on_arm64(unsigned int *base)
245 {
246 static unsigned int *ip4ret;
247 int i;
248 unsigned int *ip = (unsigned int *) base;
249
250 for (i = 0; i < 32; ip++, i++) {
251 unsigned long tmp;
252 unsigned long offset;
253
254 /*
255 * Find
256 * adrp Xd, #imm21
257 * add Xd, Xn, #uimm12
258 * sequence.
259 */
260 if ((*ip & 0x9F000000) != 0x90000000 ||
261 (*(ip + 1) & 0xFFC00000) != 0x91000000)
262 continue;
263 tmp = ((unsigned long) ip) & ~0xFFFUL;
264 offset = (unsigned long) (((((*ip >> 5) & 0x007FFFF) << 2) |
265 ((*ip >> 29) & 0x3))) << 12;
266 if (offset & 0x100000000UL)
267 offset |= 0xFFFFFFFF00000000UL;
268 tmp += offset;
269 offset = (*(ip + 1) >> 10) & 0xFFF;
270 tmp += offset;
271 /*
272 * Find
273 * ldr Xt, [Xn, #uimm12]
274 * sequence.
275 */
276 for (ip += 2; i < 32 - 2; ip++, i++) {
277 if ((*ip & 0xFFC00000) != 0xF9400000)
278 continue;
279 offset = ((*ip >> 10) & 0xFFF) << 3;
280 tmp += offset;
281 ip4ret = (unsigned int *) tmp;
282 return &ip4ret;
283 }
284 break;
285 }
286 for (i = 0; i < 32; ip++, i++) {
287 unsigned long tmp;
288 unsigned long offset;
289
290 /*
291 * Find
292 * adrp Xd, #imm21
293 * sequence.
294 */
295 if ((*ip & 0x9F000000) != 0x90000000)
296 continue;
297 tmp = ((unsigned long) ip) & ~0xFFFUL;
298 offset = (unsigned long) (((((*ip >> 5) & 0x007FFFF) << 2) |
299 ((*ip >> 29) & 0x3))) << 12;
300 if (offset & 0x100000000UL)
301 offset |= 0xFFFFFFFF00000000UL;
302 tmp += offset;
303 /*
304 * Find
305 * ldr Xt, [Xn, #uimm12]
306 * sequence.
307 */
308 for (ip += 1; i < 32 - 1; ip++, i++) {
309 if ((*ip & 0xFFC00000) != 0xF9400000)
310 continue;
311 offset = ((*ip >> 10) & 0xFFF) << 3;
312 tmp += offset;
313 ip4ret = (unsigned int *) tmp;
314 return &ip4ret;
315 }
316 break;
317 }
318 return NULL;
319 }
320
321 #endif
322
323 #if defined(CONFIG_ARM)
324
325 /**
326 * probe_security_hook_heads_on_arm - Find security_hook_heads on ARM.
327 *
328 * @base: Address of security_bprm_committed_creds().
329 *
330 * Returns address of security_hook_heads.bprm_committed_creds on success,
331 * NULL otherwise.
332 */
333 static void * __init probe_security_hook_heads_on_arm(unsigned int *base)
334 {
335 static unsigned int *ip4ret;
336 int i;
337 const unsigned long addr = (unsigned long) &probe_dummy_security_hook_heads;
338 const unsigned long offset = (unsigned long) &probe_dummy_security_hook_heads.bprm_committed_creds - addr;
339 unsigned int *ip = (unsigned int *) probe_security_bprm_committed_creds;
340
341 for (i = 0; i < 32; ip++, i++) {
342 if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
343 continue;
344 ip = base + i;
345 ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
346 ip4ret += offset >> 2;
347 return &ip4ret;
348 }
349 return NULL;
350 }
351
352 #endif
353
354 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
355
356 /*
357 * Dummy variable for finding address of
358 * "struct security_operations *security_ops".
359 */
360 static struct security_operations *probe_dummy_security_ops;
361
362 /**
363 * probe_security_file_alloc - Dummy function which does identical to security_file_alloc() in security/security.c.
364 *
365 * @file: Pointer to "struct file".
366 *
367 * Returns return value from security_file_alloc().
368 */
369 static int probe_security_file_alloc(struct file *file)
370 {
371 return probe_dummy_security_ops->file_alloc_security(file);
372 }
373
374 #if defined(CONFIG_ARM)
375
376 /**
377 * probe_security_ops_on_arm - Find security_ops on ARM.
378 *
379 * @base: Address of security_file_alloc().
380 *
381 * Returns address of security_ops on success, NULL otherwise.
382 */
383 static void * __init probe_security_ops_on_arm(unsigned int *base)
384 {
385 static unsigned int *ip4ret;
386 int i;
387 const unsigned long addr = (unsigned long) &probe_dummy_security_ops;
388 unsigned int *ip = (unsigned int *) probe_security_file_alloc;
389
390 for (i = 0; i < 32; ip++, i++) {
391 if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
392 continue;
393 ip = base + i;
394 ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
395 return &ip4ret;
396 }
397 ip = (unsigned int *) probe_security_file_alloc;
398 for (i = 0; i < 32; ip++, i++) {
399 /*
400 * Find
401 * ldr r3, [pc, #offset1]
402 * ldr r3, [r3, #offset2]
403 * sequence.
404 */
405 if ((*ip & 0xFFFFF000) != 0xE59F3000 ||
406 (*(ip + 1) & 0xFFFFF000) != 0xE5933000)
407 continue;
408 ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
409 ip4ret += (*(ip + 1) & 0xFFF) >> 2;
410 if ((unsigned long) ip4ret != addr)
411 continue;
412 ip = base + i;
413 ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
414 ip4ret += (*(ip + 1) & 0xFFF) >> 2;
415 return &ip4ret;
416 }
417 return NULL;
418 }
419
420 #endif
421
422 #endif
423
424 #if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
425 /**
426 * probe_find_vfsmount_lock_on_arm - Find vfsmount_lock spinlock on ARM.
427 *
428 * @ip: Address of dummy function's entry point.
429 * @addr: Address of the variable which is used within @function.
430 * @base: Address of function's entry point.
431 *
432 * Returns address of vfsmount_lock on success, NULL otherwise.
433 */
434 static void * __init probe_find_vfsmount_lock_on_arm(unsigned int *ip,
435 unsigned long addr,
436 unsigned int *base)
437 {
438 int i;
439
440 for (i = 0; i < 32; ip++, i++) {
441 static unsigned int *ip4ret;
442
443 if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
444 continue;
445 ip = base + i;
446 ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
447 return &ip4ret;
448 }
449 return NULL;
450 }
451 #endif
452
453 /**
454 * probe_find_variable - Find variable's address using dummy.
455 *
456 * @function: Pointer to dummy function's entry point.
457 * @addr: Address of the variable which is used within @function.
458 * @symbol: Name of symbol to resolve.
459 *
460 * This trick depends on below assumptions.
461 *
462 * (1) @addr is found within 128 bytes from @function, even if additional
463 * code (e.g. debug symbols) is added.
464 * (2) It is safe to read 128 bytes from @function.
465 * (3) @addr != Byte code except @addr.
466 */
467 static void * __init probe_find_variable(void *function, unsigned long addr,
468 const char *symbol)
469 {
470 int i;
471 u8 *base;
472 u8 *cp = function;
473
474 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
475 if (*symbol == ' ')
476 base = probe_find_symbol(symbol);
477 else
478 #endif
479 base = __symbol_get(symbol);
480 if (!base)
481 return NULL;
482 #if defined(CONFIG_ARM64) && defined(LSM_HOOK_INIT)
483 if (function == probe_security_bprm_committed_creds)
484 return probe_security_hook_heads_on_arm64((unsigned int *) base);
485 #endif
486 #if defined(CONFIG_ARM) && defined(LSM_HOOK_INIT)
487 if (function == probe_security_bprm_committed_creds)
488 return probe_security_hook_heads_on_arm((unsigned int *) base);
489 #endif
490 #if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(LSM_HOOK_INIT)
491 if (function == probe_security_file_alloc)
492 return probe_security_ops_on_arm((unsigned int *) base);
493 #endif
494 #if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
495 return probe_find_vfsmount_lock_on_arm(function, addr,
496 (unsigned int *) base);
497 #endif
498 /* First, assume absolute addressing mode is used. */
499 for (i = 0; i < 128; i++) {
500 if (*(unsigned long *) cp == addr)
501 return base + i;
502 cp++;
503 }
504 /* Next, assume PC-relative addressing mode is used. */
505 #if defined(CONFIG_S390)
506 cp = function;
507 for (i = 0; i < 128; i++) {
508 if ((unsigned long) (cp + (*(int *) cp) * 2 - 2) == addr) {
509 static void *cp4ret;
510
511 cp = base + i;
512 cp += (*(int *) cp) * 2 - 2;
513 cp4ret = cp;
514 return &cp4ret;
515 }
516 cp++;
517 }
518 #endif
519 cp = function;
520 for (i = 0; i < 128; i++) {
521 if ((unsigned long) (cp + sizeof(int) + *(int *) cp) == addr) {
522 static void *cp4ret;
523
524 cp = base + i;
525 cp += sizeof(int) + *(int *) cp;
526 cp4ret = cp;
527 return &cp4ret;
528 }
529 cp++;
530 }
531 cp = function;
532 for (i = 0; i < 128; i++) {
533 if ((unsigned long) (long) (*(int *) cp) == addr) {
534 static void *cp4ret;
535
536 cp = base + i;
537 cp = (void *) (long) (*(int *) cp);
538 cp4ret = cp;
539 return &cp4ret;
540 }
541 cp++;
542 }
543 return NULL;
544 }
545
546 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
547
548 /**
549 * probe_security_hook_heads - Find address of "struct security_hook_heads security_hook_heads".
550 *
551 * Returns pointer to "struct security_hook_heads" on success, NULL otherwise.
552 */
553 struct security_hook_heads * __init probe_security_hook_heads(void)
554 {
555 const unsigned int offset = offsetof(struct security_hook_heads,
556 bprm_committed_creds);
557 void *cp;
558 struct security_hook_heads *shh;
559 struct security_hook_list *entry;
560 void *cap = probe_find_symbol(" cap_bprm_creds_from_file\n");
561
562 /* Get location of cap_bprm_set_creds(). */
563 cap = check_function_address(cap, "cap_bprm_creds_from_file");
564 if (!cap)
565 return NULL;
566 /* Guess "struct security_hook_heads security_hook_heads;". */
567 cp = probe_find_variable(probe_security_bprm_committed_creds,
568 ((unsigned long)
569 &probe_dummy_security_hook_heads) + offset,
570 " security_bprm_committed_creds\n");
571 if (!cp) {
572 printk(KERN_ERR
573 "Can't resolve security_bprm_committed_creds().\n");
574 return NULL;
575 }
576 /* This should be "struct security_hook_heads security_hook_heads;". */
577 shh = ((void *) (*(unsigned long *) cp)) - offset;
578 hlist_for_each_entry(entry, &shh->bprm_creds_from_file, list)
579 if (entry->hook.bprm_creds_from_file == cap)
580 return shh;
581 printk(KERN_ERR "Guessed security_hook_heads is 0x%lx\n",
582 (unsigned long) shh);
583 return NULL;
584 }
585
586 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 8 && defined(RHEL_MINOR) && RHEL_MINOR >= 6
587
588 /**
589 * probe_security_hook_heads - Find address of "struct security_hook_heads security_hook_heads".
590 *
591 * Returns pointer to "struct security_hook_heads" on success, NULL otherwise.
592 */
593 struct security_hook_heads * __init probe_security_hook_heads(void)
594 {
595 const unsigned int offset = offsetof(struct security_hook_heads,
596 bprm_committed_creds);
597 void *cp;
598 struct security_hook_heads *shh;
599 struct security_hook_list *entry;
600 void *cap = probe_find_symbol(" cap_bprm_repopulate_creds\n");
601
602 /* Get location of cap_bprm_repopulate_creds(). */
603 cap = check_function_address(cap, "cap_bprm_repopulate_creds");
604 if (!cap)
605 return NULL;
606 /* Guess "struct security_hook_heads security_hook_heads;". */
607 cp = probe_find_variable(probe_security_bprm_committed_creds,
608 ((unsigned long)
609 &probe_dummy_security_hook_heads) + offset,
610 " security_bprm_committed_creds\n");
611 if (!cp) {
612 printk(KERN_ERR
613 "Can't resolve security_bprm_committed_creds().\n");
614 return NULL;
615 }
616 /* This should be "struct security_hook_heads security_hook_heads;". */
617 shh = ((void *) (*(unsigned long *) cp)) - offset;
618 hlist_for_each_entry(entry, &shh->bprm_repopulate_creds, list)
619 if (entry->hook.bprm_repopulate_creds == cap)
620 return shh;
621 printk(KERN_ERR "Guessed security_hook_heads is 0x%lx\n",
622 (unsigned long) shh);
623 return NULL;
624 }
625
626 #elif defined(LSM_HOOK_INIT)
627
628 /**
629 * probe_security_hook_heads - Find address of "struct security_hook_heads security_hook_heads".
630 *
631 * Returns pointer to "struct security_hook_heads" on success, NULL otherwise.
632 */
633 struct security_hook_heads * __init probe_security_hook_heads(void)
634 {
635 const unsigned int offset = offsetof(struct security_hook_heads,
636 bprm_committed_creds);
637 void *cp;
638 struct security_hook_heads *shh;
639 struct security_hook_list *entry;
640 void *cap = probe_find_symbol(" cap_bprm_set_creds\n");
641
642 /* Get location of cap_bprm_set_creds(). */
643 cap = check_function_address(cap, "cap_bprm_set_creds");
644 if (!cap)
645 return NULL;
646 /* Guess "struct security_hook_heads security_hook_heads;". */
647 cp = probe_find_variable(probe_security_bprm_committed_creds,
648 ((unsigned long)
649 &probe_dummy_security_hook_heads) + offset,
650 " security_bprm_committed_creds\n");
651 if (!cp) {
652 printk(KERN_ERR
653 "Can't resolve security_bprm_committed_creds().\n");
654 return NULL;
655 }
656 /* This should be "struct security_hook_heads security_hook_heads;". */
657 shh = ((void *) (*(unsigned long *) cp)) - offset;
658 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
659 hlist_for_each_entry(entry, &shh->bprm_set_creds, list)
660 if (entry->hook.bprm_set_creds == cap)
661 return shh;
662 #else
663 list_for_each_entry(entry, &shh->bprm_set_creds, list)
664 if (entry->hook.bprm_set_creds == cap)
665 return shh;
666 #endif
667 printk(KERN_ERR "Guessed security_hook_heads is 0x%lx\n",
668 (unsigned long) shh);
669 return NULL;
670 }
671
672 #else
673
674 /**
675 * probe_security_ops - Find address of "struct security_operations *security_ops".
676 *
677 * Returns pointer to "struct security_operations" on success, NULL otherwise.
678 */
679 struct security_operations * __init probe_security_ops(void)
680 {
681 struct security_operations **ptr;
682 struct security_operations *ops;
683 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
684 void *cp;
685
686 /* Guess "struct security_operations *security_ops;". */
687 cp = probe_find_variable(probe_security_file_alloc, (unsigned long)
688 &probe_dummy_security_ops,
689 " security_file_alloc\n");
690 if (!cp) {
691 printk(KERN_ERR "Can't resolve security_file_alloc().\n");
692 return NULL;
693 }
694 /* This should be "struct security_operations *security_ops;". */
695 ptr = *(struct security_operations ***) cp;
696 #else
697 /* This is "struct security_operations *security_ops;". */
698 ptr = (struct security_operations **) __symbol_get("security_ops");
699 #endif
700 if (!ptr) {
701 printk(KERN_ERR "Can't resolve security_ops structure.\n");
702 return NULL;
703 }
704 ops = *ptr;
705 if (!ops) {
706 printk(KERN_ERR "No security_operations registered.\n");
707 return NULL;
708 }
709 return ops;
710 }
711
712 #endif
713
714 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
715
716 /**
717 * probe_find_task_by_vpid - Find address of find_task_by_vpid().
718 *
719 * Returns address of find_task_by_vpid() on success, NULL otherwise.
720 */
721 void * __init probe_find_task_by_vpid(void)
722 {
723 void *ptr;
724
725 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
726 ptr = probe_find_symbol(" find_task_by_vpid\n");
727 #else
728 ptr = __symbol_get("find_task_by_vpid");
729 #endif
730 return check_function_address(ptr, "find_task_by_vpid");
731 }
732
733 /**
734 * probe_find_task_by_pid_ns - Find address of find_task_by_pid().
735 *
736 * Returns address of find_task_by_pid_ns() on success, NULL otherwise.
737 */
738 void * __init probe_find_task_by_pid_ns(void)
739 {
740 void *ptr;
741
742 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
743 ptr = probe_find_symbol(" find_task_by_pid_ns\n");
744 #else
745 ptr = __symbol_get("find_task_by_pid_ns");
746 #endif
747 return check_function_address(ptr, "find_task_by_pid_ns");
748 }
749
750 #endif
751
752 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
753
754 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
755
756 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
757
758 /* Dummy variable for finding address of "spinlock_t vfsmount_lock". */
759 static spinlock_t probe_dummy_vfsmount_lock __cacheline_aligned_in_smp =
760 SPIN_LOCK_UNLOCKED;
761
762 static struct list_head *probe_mount_hashtable;
763 static int probe_hash_mask, probe_hash_bits;
764
765 /**
766 * hash - Copy of hash() in fs/namespace.c.
767 *
768 * @mnt: Pointer to "struct vfsmount".
769 * @dentry: Pointer to "struct dentry".
770 *
771 * Returns hash value.
772 */
773 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
774 {
775 unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
776
777 tmp += ((unsigned long) dentry / L1_CACHE_BYTES);
778 tmp = tmp + (tmp >> probe_hash_bits);
779 return tmp & probe_hash_mask;
780 }
781
782 /**
783 * probe_lookup_mnt - Dummy function which does identical to lookup_mnt() in fs/namespace.c.
784 *
785 * @mnt: Pointer to "struct vfsmount".
786 * @dentry: Pointer to "struct dentry".
787 *
788 * Returns pointer to "struct vfsmount".
789 */
790 static struct vfsmount *probe_lookup_mnt(struct vfsmount *mnt,
791 struct dentry *dentry)
792 {
793 struct list_head *head = probe_mount_hashtable + hash(mnt, dentry);
794 struct list_head *tmp = head;
795 struct vfsmount *p, *found = NULL;
796
797 spin_lock(&probe_dummy_vfsmount_lock);
798 for (;;) {
799 tmp = tmp->next;
800 p = NULL;
801 if (tmp == head)
802 break;
803 p = list_entry(tmp, struct vfsmount, mnt_hash);
804 if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
805 found = mntget(p);
806 break;
807 }
808 }
809 spin_unlock(&probe_dummy_vfsmount_lock);
810 return found;
811 }
812
813 /**
814 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
815 *
816 * Returns address of vfsmount_lock on success, NULL otherwise.
817 */
818 void * __init probe_vfsmount_lock(void)
819 {
820 void *cp;
821 spinlock_t *ptr;
822
823 /* Guess "spinlock_t vfsmount_lock;". */
824 cp = probe_find_variable(probe_lookup_mnt, (unsigned long)
825 &probe_dummy_vfsmount_lock, " lookup_mnt\n");
826 if (!cp) {
827 printk(KERN_ERR "Can't resolve lookup_mnt().\n");
828 return NULL;
829 }
830 /* This should be "spinlock_t *vfsmount_lock;". */
831 ptr = *(spinlock_t **) cp;
832 if (!ptr) {
833 printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
834 return NULL;
835 }
836 return ptr;
837 }
838
839 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
840
841 /* Dummy variable for finding address of "spinlock_t vfsmount_lock". */
842 static spinlock_t probe_dummy_vfsmount_lock;
843
844 /**
845 * probe_follow_up - Dummy function which does identical to follow_up() in fs/namei.c.
846 *
847 * @mnt: Pointer to "struct vfsmount *".
848 * @dentry: Pointer to "struct dentry *".
849 *
850 * Returns 1 if followed up, 0 otherwise.
851 */
852 static int probe_follow_up(struct vfsmount **mnt, struct dentry **dentry)
853 {
854 struct vfsmount *parent;
855 struct dentry *mountpoint;
856
857 spin_lock(&probe_dummy_vfsmount_lock);
858 parent = (*mnt)->mnt_parent;
859 if (parent == *mnt) {
860 spin_unlock(&probe_dummy_vfsmount_lock);
861 return 0;
862 }
863 mntget(parent);
864 mountpoint = dget((*mnt)->mnt_mountpoint);
865 spin_unlock(&probe_dummy_vfsmount_lock);
866 dput(*dentry);
867 *dentry = mountpoint;
868 mntput(*mnt);
869 *mnt = parent;
870 return 1;
871 }
872
873 /**
874 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
875 *
876 * Returns address of vfsmount_lock on success, NULL otherwise.
877 */
878 void * __init probe_vfsmount_lock(void)
879 {
880 void *cp;
881 spinlock_t *ptr;
882
883 /* Guess "spinlock_t vfsmount_lock;". */
884 cp = probe_find_variable(probe_follow_up, (unsigned long)
885 &probe_dummy_vfsmount_lock, "follow_up");
886 if (!cp) {
887 printk(KERN_ERR "Can't resolve follow_up().\n");
888 return NULL;
889 }
890 /* This should be "spinlock_t *vfsmount_lock;". */
891 ptr = *(spinlock_t **) cp;
892 if (!ptr) {
893 printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
894 return NULL;
895 }
896 return ptr;
897 }
898
899 #else
900
901 /* Dummy variable for finding address of "spinlock_t vfsmount_lock". */
902 static spinlock_t probe_dummy_vfsmount_lock;
903
904 /**
905 * probe_mnt_pin - Dummy function which does identical to mnt_pin() in fs/namespace.c.
906 *
907 * @mnt: Pointer to "struct vfsmount".
908 *
909 * Returns nothing.
910 */
911 static void probe_mnt_pin(struct vfsmount *mnt)
912 {
913 spin_lock(&probe_dummy_vfsmount_lock);
914 mnt->mnt_pinned++;
915 spin_unlock(&probe_dummy_vfsmount_lock);
916 }
917
918 /**
919 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
920 *
921 * Returns address of vfsmount_lock on success, NULL otherwise.
922 */
923 void * __init probe_vfsmount_lock(void)
924 {
925 void *cp;
926 spinlock_t *ptr;
927
928 /* Guess "spinlock_t vfsmount_lock;". */
929 cp = probe_find_variable(probe_mnt_pin, (unsigned long)
930 &probe_dummy_vfsmount_lock, "mnt_pin");
931 if (!cp) {
932 printk(KERN_ERR "Can't resolve mnt_pin().\n");
933 return NULL;
934 }
935 /* This should be "spinlock_t *vfsmount_lock;". */
936 ptr = *(spinlock_t **) cp;
937 if (!ptr) {
938 printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
939 return NULL;
940 }
941 return ptr;
942 }
943
944 #endif
945
946 #else
947
948 /*
949 * Never mark this variable as __initdata , for this variable might be accessed
950 * by caller of probe_find_vfsmount_lock().
951 */
952 static spinlock_t probe_dummy_vfsmount_lock;
953
954 /**
955 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
956 *
957 * Returns address of vfsmount_lock.
958 */
959 void * __init probe_vfsmount_lock(void)
960 {
961 return &probe_dummy_vfsmount_lock;
962 }
963
964 #endif
965
966 #endif
967
968 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
969
970 /**
971 * probe___d_path - Find address of "__d_path()".
972 *
973 * Returns address of __d_path() on success, NULL otherwise.
974 */
975 void * __init probe___d_path(void)
976 {
977 void *ptr = probe_find_symbol(" __d_path\n");
978
979 return check_function_address(ptr, "__d_path");
980 }
981
982 #endif
983
984 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
985
986 /**
987 * probe_d_absolute_path - Find address of "d_absolute_path()".
988 *
989 * Returns address of d_absolute_path() on success, NULL otherwise.
990 */
991 void * __init probe_d_absolute_path(void)
992 {
993 void *ptr = probe_find_symbol(" d_absolute_path\n");
994
995 return check_function_address(ptr, "d_absolute_path");
996 }
997
998 #endif
999
1000 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
1001
1002 /**
1003 * probe_copy_to_kernel_nofault - Find address of "copy_to_kernel_nofault()".
1004 *
1005 * Returns address of copy_to_kernel_nofault() on success, NULL otherwise.
1006 */
1007 void * __init probe_copy_to_kernel_nofault(void)
1008 {
1009 void *ptr = probe_find_symbol(" copy_to_kernel_nofault\n");
1010
1011 return check_function_address(ptr, "copy_to_kernel_nofault");
1012 }
1013
1014 #endif

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26