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

Subversion リポジトリの参照

Annotation of /trunk/akari/probe.c

Parent Directory Parent Directory | Revision Log Revision Log


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


1 kumaneko 442 /*
2     * probe.c
3     *
4     * Copyright (C) 2010-2013 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5 kumaneko 444 *
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 kumaneko 442 */
18    
19     #include "probe.h"
20    
21 kumaneko 564 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 kumaneko 664 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
43 kumaneko 442
44     /**
45 kumaneko 593 * my_kernel_read - Wrapper for kernel_read().
46 kumaneko 442 *
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 kumaneko 606 static inline int my_kernel_read(struct file *file, unsigned long offset,
55     char *addr, unsigned long count)
56 kumaneko 442 {
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 kumaneko 564
66 kumaneko 442 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 kumaneko 561 #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
74     return kernel_read(file, offset, addr, count);
75 kumaneko 664 #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
76 kumaneko 561 loff_t pos = offset;
77 kumaneko 564
78 kumaneko 561 return kernel_read(file, addr, count, &pos);
79 kumaneko 664 #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 kumaneko 442 #endif
89     }
90    
91     /**
92 kumaneko 446 * probe_find_symbol - Find function's address from /proc/kallsyms .
93 kumaneko 442 *
94     * @keyline: Function to find.
95     *
96     * Returns address of specified function on success, NULL otherwise.
97     */
98 kumaneko 446 static void *__init probe_find_symbol(const char *keyline)
99 kumaneko 442 {
100 kumaneko 628 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0)
101 kumaneko 606 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 kumaneko 442 struct file *file = NULL;
111     char *buf;
112     unsigned long entry = 0;
113 kumaneko 564
114 kumaneko 442 {
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 kumaneko 564
128 kumaneko 442 /*
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 kumaneko 526 #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 kumaneko 442 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 kumaneko 555 struct path path = { .mnt = mnt, .dentry = dentry };
155 kumaneko 564
156 kumaneko 442 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 kumaneko 564
173 kumaneko 593 while ((len = my_kernel_read(file, offset, buf,
174     PAGE_SIZE - 1)) > 0) {
175 kumaneko 442 char *cp;
176 kumaneko 564
177 kumaneko 442 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 kumaneko 606 #endif
198 kumaneko 442 }
199    
200     #endif
201    
202 kumaneko 496 #if defined(LSM_HOOK_INIT)
203 kumaneko 442
204     /*
205     * Dummy variable for finding location of
206 kumaneko 496 * "struct security_hook_heads security_hook_heads".
207 kumaneko 442 */
208 kumaneko 496 struct security_hook_heads probe_dummy_security_hook_heads;
209 kumaneko 442
210     /**
211 kumaneko 446 * probe_security_bprm_committed_creds - Dummy function which does identical to security_bprm_committed_creds() in security/security.c.
212 kumaneko 442 *
213     * @bprm: Pointer to "struct linux_binprm".
214     *
215     * Returns nothing.
216     */
217 kumaneko 446 void probe_security_bprm_committed_creds(struct linux_binprm *bprm)
218 kumaneko 442 {
219     do {
220 kumaneko 496 struct security_hook_list *p;
221 kumaneko 564
222 kumaneko 592 #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 kumaneko 496 list_for_each_entry(p, &probe_dummy_security_hook_heads.
228     bprm_committed_creds, list)
229     p->hook.bprm_committed_creds(bprm);
230 kumaneko 592 #endif
231 kumaneko 442 } while (0);
232     }
233    
234 kumaneko 562 #if defined(CONFIG_ARM64)
235    
236     /**
237 kumaneko 655 * probe_security_hook_heads_on_arm64 - Find security_hook_heads on ARM64.
238 kumaneko 562 *
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 kumaneko 564
254 kumaneko 562 /*
255     * Find
256     * adrp Xd, #imm21
257     * add Xd, Xn, #uimm12
258     * sequence.
259     */
260 kumaneko 585 if ((*ip & 0x9F000000) != 0x90000000 ||
261 kumaneko 562 (*(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 kumaneko 585 /*
272     * Find
273 kumaneko 655 * ldr Xt, [Xn, #uimm12]
274 kumaneko 585 * 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 kumaneko 562 tmp += offset;
281 kumaneko 585 ip4ret = (unsigned int *) tmp;
282     return &ip4ret;
283 kumaneko 562 }
284 kumaneko 585 break;
285 kumaneko 562 }
286 kumaneko 655 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 kumaneko 562 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 kumaneko 564
341 kumaneko 562 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 kumaneko 442 #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 kumaneko 446 static struct security_operations *probe_dummy_security_ops;
361 kumaneko 442
362     /**
363 kumaneko 446 * probe_security_file_alloc - Dummy function which does identical to security_file_alloc() in security/security.c.
364 kumaneko 442 *
365     * @file: Pointer to "struct file".
366     *
367     * Returns return value from security_file_alloc().
368     */
369 kumaneko 446 static int probe_security_file_alloc(struct file *file)
370 kumaneko 442 {
371 kumaneko 446 return probe_dummy_security_ops->file_alloc_security(file);
372 kumaneko 442 }
373    
374     #if defined(CONFIG_ARM)
375    
376     /**
377 kumaneko 446 * probe_security_ops_on_arm - Find security_ops on ARM.
378 kumaneko 442 *
379     * @base: Address of security_file_alloc().
380     *
381     * Returns address of security_ops on success, NULL otherwise.
382     */
383 kumaneko 446 static void * __init probe_security_ops_on_arm(unsigned int *base)
384 kumaneko 442 {
385     static unsigned int *ip4ret;
386     int i;
387 kumaneko 446 const unsigned long addr = (unsigned long) &probe_dummy_security_ops;
388     unsigned int *ip = (unsigned int *) probe_security_file_alloc;
389 kumaneko 564
390 kumaneko 442 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 kumaneko 446 ip = (unsigned int *) probe_security_file_alloc;
398 kumaneko 442 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 kumaneko 446 * probe_find_vfsmount_lock_on_arm - Find vfsmount_lock spinlock on ARM.
427 kumaneko 442 *
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 kumaneko 446 static void * __init probe_find_vfsmount_lock_on_arm(unsigned int *ip,
435     unsigned long addr,
436     unsigned int *base)
437 kumaneko 442 {
438     int i;
439 kumaneko 564
440 kumaneko 442 for (i = 0; i < 32; ip++, i++) {
441     static unsigned int *ip4ret;
442 kumaneko 564
443 kumaneko 442 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 kumaneko 446 * probe_find_variable - Find variable's address using dummy.
455 kumaneko 442 *
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 kumaneko 446 static void * __init probe_find_variable(void *function, unsigned long addr,
468     const char *symbol)
469 kumaneko 442 {
470     int i;
471     u8 *base;
472     u8 *cp = function;
473 kumaneko 564
474 kumaneko 442 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
475     if (*symbol == ' ')
476 kumaneko 446 base = probe_find_symbol(symbol);
477 kumaneko 442 else
478     #endif
479     base = __symbol_get(symbol);
480     if (!base)
481     return NULL;
482 kumaneko 562 #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 kumaneko 496 #if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(LSM_HOOK_INIT)
491 kumaneko 446 if (function == probe_security_file_alloc)
492     return probe_security_ops_on_arm((unsigned int *) base);
493 kumaneko 442 #endif
494     #if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
495 kumaneko 446 return probe_find_vfsmount_lock_on_arm(function, addr,
496     (unsigned int *) base);
497 kumaneko 442 #endif
498 kumaneko 666 /* First, assume absolute addressing mode is used. */
499 kumaneko 442 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 kumaneko 463 #if defined(CONFIG_S390)
506 kumaneko 442 cp = function;
507     for (i = 0; i < 128; i++) {
508 kumaneko 463 if ((unsigned long) (cp + (*(int *) cp) * 2 - 2) == addr) {
509     static void *cp4ret;
510 kumaneko 564
511 kumaneko 463 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 kumaneko 442 if ((unsigned long) (cp + sizeof(int) + *(int *) cp) == addr) {
522     static void *cp4ret;
523 kumaneko 564
524 kumaneko 442 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 kumaneko 564
536 kumaneko 442 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 kumaneko 643 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
547 kumaneko 442
548     /**
549 kumaneko 496 * probe_security_hook_heads - Find address of "struct security_hook_heads security_hook_heads".
550 kumaneko 442 *
551 kumaneko 496 * Returns pointer to "struct security_hook_heads" on success, NULL otherwise.
552 kumaneko 442 */
553 kumaneko 496 struct security_hook_heads * __init probe_security_hook_heads(void)
554 kumaneko 442 {
555 kumaneko 496 const unsigned int offset = offsetof(struct security_hook_heads,
556     bprm_committed_creds);
557 kumaneko 442 void *cp;
558 kumaneko 564 struct security_hook_heads *shh;
559     struct security_hook_list *entry;
560 kumaneko 643 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 kumaneko 683 #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 kumaneko 643 #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 kumaneko 564 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 kumaneko 496 /* Guess "struct security_hook_heads security_hook_heads;". */
647 kumaneko 446 cp = probe_find_variable(probe_security_bprm_committed_creds,
648 kumaneko 496 ((unsigned long)
649     &probe_dummy_security_hook_heads) + offset,
650 kumaneko 446 " security_bprm_committed_creds\n");
651 kumaneko 442 if (!cp) {
652     printk(KERN_ERR
653     "Can't resolve security_bprm_committed_creds().\n");
654 kumaneko 496 return NULL;
655 kumaneko 442 }
656 kumaneko 496 /* This should be "struct security_hook_heads security_hook_heads;". */
657 kumaneko 564 shh = ((void *) (*(unsigned long *) cp)) - offset;
658 kumaneko 592 #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 kumaneko 564 list_for_each_entry(entry, &shh->bprm_set_creds, list)
664     if (entry->hook.bprm_set_creds == cap)
665     return shh;
666 kumaneko 592 #endif
667 kumaneko 564 printk(KERN_ERR "Guessed security_hook_heads is 0x%lx\n",
668     (unsigned long) shh);
669     return NULL;
670 kumaneko 442 }
671    
672     #else
673    
674     /**
675 kumaneko 446 * probe_security_ops - Find address of "struct security_operations *security_ops".
676 kumaneko 442 *
677     * Returns pointer to "struct security_operations" on success, NULL otherwise.
678     */
679 kumaneko 446 struct security_operations * __init probe_security_ops(void)
680 kumaneko 442 {
681     struct security_operations **ptr;
682     struct security_operations *ops;
683     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
684     void *cp;
685 kumaneko 564
686 kumaneko 442 /* Guess "struct security_operations *security_ops;". */
687 kumaneko 446 cp = probe_find_variable(probe_security_file_alloc, (unsigned long)
688     &probe_dummy_security_ops,
689     " security_file_alloc\n");
690 kumaneko 442 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 kumaneko 446 * probe_find_task_by_vpid - Find address of find_task_by_vpid().
718 kumaneko 442 *
719     * Returns address of find_task_by_vpid() on success, NULL otherwise.
720     */
721 kumaneko 446 void * __init probe_find_task_by_vpid(void)
722 kumaneko 442 {
723     void *ptr;
724 kumaneko 564
725 kumaneko 442 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
726 kumaneko 446 ptr = probe_find_symbol(" find_task_by_vpid\n");
727 kumaneko 442 #else
728     ptr = __symbol_get("find_task_by_vpid");
729     #endif
730 kumaneko 564 return check_function_address(ptr, "find_task_by_vpid");
731 kumaneko 442 }
732    
733     /**
734 kumaneko 446 * probe_find_task_by_pid_ns - Find address of find_task_by_pid().
735 kumaneko 442 *
736     * Returns address of find_task_by_pid_ns() on success, NULL otherwise.
737     */
738 kumaneko 446 void * __init probe_find_task_by_pid_ns(void)
739 kumaneko 442 {
740     void *ptr;
741 kumaneko 564
742 kumaneko 442 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
743 kumaneko 446 ptr = probe_find_symbol(" find_task_by_pid_ns\n");
744 kumaneko 442 #else
745     ptr = __symbol_get("find_task_by_pid_ns");
746     #endif
747 kumaneko 564 return check_function_address(ptr, "find_task_by_pid_ns");
748 kumaneko 442 }
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 kumaneko 447 static spinlock_t probe_dummy_vfsmount_lock __cacheline_aligned_in_smp =
760 kumaneko 446 SPIN_LOCK_UNLOCKED;
761 kumaneko 442
762 kumaneko 446 static struct list_head *probe_mount_hashtable;
763     static int probe_hash_mask, probe_hash_bits;
764 kumaneko 442
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 kumaneko 564
777 kumaneko 442 tmp += ((unsigned long) dentry / L1_CACHE_BYTES);
778 kumaneko 446 tmp = tmp + (tmp >> probe_hash_bits);
779     return tmp & probe_hash_mask;
780 kumaneko 442 }
781    
782     /**
783 kumaneko 446 * probe_lookup_mnt - Dummy function which does identical to lookup_mnt() in fs/namespace.c.
784 kumaneko 442 *
785     * @mnt: Pointer to "struct vfsmount".
786     * @dentry: Pointer to "struct dentry".
787     *
788     * Returns pointer to "struct vfsmount".
789     */
790 kumaneko 446 static struct vfsmount *probe_lookup_mnt(struct vfsmount *mnt,
791     struct dentry *dentry)
792 kumaneko 442 {
793 kumaneko 446 struct list_head *head = probe_mount_hashtable + hash(mnt, dentry);
794 kumaneko 442 struct list_head *tmp = head;
795     struct vfsmount *p, *found = NULL;
796    
797 kumaneko 447 spin_lock(&probe_dummy_vfsmount_lock);
798 kumaneko 442 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 kumaneko 447 spin_unlock(&probe_dummy_vfsmount_lock);
810 kumaneko 442 return found;
811     }
812    
813     /**
814 kumaneko 446 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
815 kumaneko 442 *
816     * Returns address of vfsmount_lock on success, NULL otherwise.
817     */
818 kumaneko 446 void * __init probe_vfsmount_lock(void)
819 kumaneko 442 {
820     void *cp;
821     spinlock_t *ptr;
822 kumaneko 564
823 kumaneko 442 /* Guess "spinlock_t vfsmount_lock;". */
824 kumaneko 446 cp = probe_find_variable(probe_lookup_mnt, (unsigned long)
825 kumaneko 447 &probe_dummy_vfsmount_lock, " lookup_mnt\n");
826 kumaneko 442 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 kumaneko 447 static spinlock_t probe_dummy_vfsmount_lock;
843 kumaneko 442
844     /**
845 kumaneko 446 * probe_follow_up - Dummy function which does identical to follow_up() in fs/namei.c.
846 kumaneko 442 *
847     * @mnt: Pointer to "struct vfsmount *".
848     * @dentry: Pointer to "struct dentry *".
849     *
850 kumaneko 666 * Returns 1 if followed up, 0 otherwise.
851 kumaneko 442 */
852 kumaneko 446 static int probe_follow_up(struct vfsmount **mnt, struct dentry **dentry)
853 kumaneko 442 {
854     struct vfsmount *parent;
855     struct dentry *mountpoint;
856 kumaneko 564
857 kumaneko 447 spin_lock(&probe_dummy_vfsmount_lock);
858 kumaneko 442 parent = (*mnt)->mnt_parent;
859     if (parent == *mnt) {
860 kumaneko 447 spin_unlock(&probe_dummy_vfsmount_lock);
861 kumaneko 442 return 0;
862     }
863     mntget(parent);
864     mountpoint = dget((*mnt)->mnt_mountpoint);
865 kumaneko 447 spin_unlock(&probe_dummy_vfsmount_lock);
866 kumaneko 442 dput(*dentry);
867     *dentry = mountpoint;
868     mntput(*mnt);
869     *mnt = parent;
870     return 1;
871     }
872    
873     /**
874 kumaneko 446 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
875 kumaneko 442 *
876     * Returns address of vfsmount_lock on success, NULL otherwise.
877     */
878 kumaneko 446 void * __init probe_vfsmount_lock(void)
879 kumaneko 442 {
880     void *cp;
881     spinlock_t *ptr;
882 kumaneko 564
883 kumaneko 442 /* Guess "spinlock_t vfsmount_lock;". */
884 kumaneko 446 cp = probe_find_variable(probe_follow_up, (unsigned long)
885 kumaneko 447 &probe_dummy_vfsmount_lock, "follow_up");
886 kumaneko 442 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 kumaneko 447 static spinlock_t probe_dummy_vfsmount_lock;
903 kumaneko 442
904     /**
905 kumaneko 446 * probe_mnt_pin - Dummy function which does identical to mnt_pin() in fs/namespace.c.
906 kumaneko 442 *
907     * @mnt: Pointer to "struct vfsmount".
908     *
909     * Returns nothing.
910     */
911 kumaneko 446 static void probe_mnt_pin(struct vfsmount *mnt)
912 kumaneko 442 {
913 kumaneko 447 spin_lock(&probe_dummy_vfsmount_lock);
914 kumaneko 442 mnt->mnt_pinned++;
915 kumaneko 447 spin_unlock(&probe_dummy_vfsmount_lock);
916 kumaneko 442 }
917    
918     /**
919 kumaneko 446 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
920 kumaneko 442 *
921     * Returns address of vfsmount_lock on success, NULL otherwise.
922     */
923 kumaneko 446 void * __init probe_vfsmount_lock(void)
924 kumaneko 442 {
925     void *cp;
926     spinlock_t *ptr;
927 kumaneko 564
928 kumaneko 442 /* Guess "spinlock_t vfsmount_lock;". */
929 kumaneko 446 cp = probe_find_variable(probe_mnt_pin, (unsigned long)
930 kumaneko 447 &probe_dummy_vfsmount_lock, "mnt_pin");
931 kumaneko 442 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 kumaneko 446 * by caller of probe_find_vfsmount_lock().
951 kumaneko 442 */
952 kumaneko 447 static spinlock_t probe_dummy_vfsmount_lock;
953 kumaneko 442
954     /**
955 kumaneko 446 * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
956 kumaneko 442 *
957     * Returns address of vfsmount_lock.
958     */
959 kumaneko 446 void * __init probe_vfsmount_lock(void)
960 kumaneko 442 {
961 kumaneko 447 return &probe_dummy_vfsmount_lock;
962 kumaneko 442 }
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 kumaneko 446 * probe___d_path - Find address of "__d_path()".
972 kumaneko 442 *
973     * Returns address of __d_path() on success, NULL otherwise.
974     */
975 kumaneko 446 void * __init probe___d_path(void)
976 kumaneko 442 {
977 kumaneko 446 void *ptr = probe_find_symbol(" __d_path\n");
978 kumaneko 564
979     return check_function_address(ptr, "__d_path");
980 kumaneko 442 }
981    
982     #endif
983    
984     #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
985    
986     /**
987 kumaneko 446 * probe_d_absolute_path - Find address of "d_absolute_path()".
988 kumaneko 442 *
989     * Returns address of d_absolute_path() on success, NULL otherwise.
990     */
991 kumaneko 446 void * __init probe_d_absolute_path(void)
992 kumaneko 442 {
993 kumaneko 446 void *ptr = probe_find_symbol(" d_absolute_path\n");
994 kumaneko 564
995     return check_function_address(ptr, "d_absolute_path");
996 kumaneko 442 }
997    
998     #endif
999 kumaneko 688
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