• R/O
  • SSH
  • HTTPS

caitsith: コミット


コミットメタ情報

リビジョン81 (tree)
日時2013-02-09 20:03:54
作者kumaneko

ログメッセージ

(メッセージはありません)

変更サマリ

差分

--- trunk/caitsith-patch/caitsith/caitsith_test.c (revision 80)
+++ trunk/caitsith-patch/caitsith/caitsith_test.c (nonexistent)
@@ -1,670 +0,0 @@
1-/*
2- * caitsith_test.c
3- *
4- * Copyright (C) 2010-2012 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5- */
6-#include <linux/version.h>
7-#include <linux/module.h>
8-#include <linux/init.h>
9-#include <linux/slab.h>
10-#include <linux/security.h>
11-#include <linux/namei.h>
12-#include <linux/mount.h>
13-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
14-#include <linux/fs.h>
15-#include <linux/sched.h>
16-#endif
17-
18-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
19-#error This module supports only 2.6.27 and later kernels.
20-#endif
21-#ifndef CONFIG_SECURITY
22-#error You must choose CONFIG_SECURITY=y for building this module.
23-#endif
24-#ifndef CONFIG_KALLSYMS
25-#error You must choose CONFIG_KALLSYMS=y for building this module.
26-#endif
27-#ifndef CONFIG_PROC_FS
28-#error You must choose CONFIG_PROC_FS=y for building this module.
29-#endif
30-#ifndef CONFIG_MODULES
31-#error You must choose CONFIG_MODULES=y for building this module.
32-#endif
33-
34-#ifndef bool
35-#define bool _Bool
36-#endif
37-#ifndef false
38-#define false 0
39-#endif
40-#ifndef true
41-#define true 1
42-#endif
43-
44-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
45-
46-#include <linux/mount.h>
47-#include <linux/fs_struct.h>
48-
49-/**
50- * cs_kernel_read - Wrapper for kernel_read().
51- *
52- * @file: Pointer to "struct file".
53- * @offset: Starting position.
54- * @addr: Buffer.
55- * @count: Size of @addr.
56- *
57- * Returns return value from kernel_read().
58- */
59-static int __init cs_kernel_read(struct file *file, unsigned long offset,
60- char *addr, unsigned long count)
61-{
62-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
63- /*
64- * I can't use kernel_read() because seq_read() returns -EPIPE
65- * if &pos != &file->f_pos .
66- */
67- mm_segment_t old_fs;
68- unsigned long pos = file->f_pos;
69- int result;
70- file->f_pos = offset;
71- old_fs = get_fs();
72- set_fs(get_ds());
73- result = vfs_read(file, (void __user *)addr, count, &file->f_pos);
74- set_fs(old_fs);
75- file->f_pos = pos;
76- return result;
77-#else
78- return kernel_read(file, offset, addr, count);
79-#endif
80-}
81-
82-/**
83- * cs_find_symbol - Find function's address from /proc/kallsyms .
84- *
85- * @keyline: Function to find.
86- *
87- * Returns address of specified function on success, NULL otherwise.
88- */
89-static void *__init cs_find_symbol(const char *keyline)
90-{
91- struct file *file = NULL;
92- char *buf;
93- unsigned long entry = 0;
94- {
95-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
96- struct file_system_type *fstype = get_fs_type("proc");
97- struct vfsmount *mnt = vfs_kern_mount(fstype, 0, "proc", NULL);
98-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
99- struct file_system_type *fstype = NULL;
100- struct vfsmount *mnt = do_kern_mount("proc", 0, "proc", NULL);
101-#else
102- struct file_system_type *fstype = get_fs_type("proc");
103- struct vfsmount *mnt = kern_mount(fstype);
104-#endif
105- struct dentry *root;
106- struct dentry *dentry;
107- /*
108- * We embed put_filesystem() here because it is not exported.
109- */
110- if (fstype)
111- module_put(fstype->owner);
112- if (IS_ERR(mnt))
113- goto out;
114- root = dget(mnt->mnt_root);
115-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
116- mutex_lock(&root->d_inode->i_mutex);
117- dentry = lookup_one_len("kallsyms", root, 8);
118- mutex_unlock(&root->d_inode->i_mutex);
119-#else
120- down(&root->d_inode->i_sem);
121- dentry = lookup_one_len("kallsyms", root, 8);
122- up(&root->d_inode->i_sem);
123-#endif
124- dput(root);
125- if (IS_ERR(dentry))
126- mntput(mnt);
127- else {
128-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
129- struct path path = { mnt, dentry };
130- file = dentry_open(&path, O_RDONLY, current_cred());
131-#else
132- file = dentry_open(dentry, mnt, O_RDONLY
133-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
134- , current_cred()
135-#endif
136- );
137-#endif
138- }
139- }
140- if (IS_ERR(file) || !file)
141- goto out;
142- buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
143- if (buf) {
144- int len;
145- int offset = 0;
146- while ((len = cs_kernel_read(file, offset, buf,
147- PAGE_SIZE - 1)) > 0) {
148- char *cp;
149- buf[len] = '\0';
150- cp = strrchr(buf, '\n');
151- if (!cp)
152- break;
153- *(cp + 1) = '\0';
154- offset += strlen(buf);
155- cp = strstr(buf, keyline);
156- if (!cp)
157- continue;
158- *cp = '\0';
159- while (cp > buf && *(cp - 1) != '\n')
160- cp--;
161- entry = simple_strtoul(cp, NULL, 16);
162- break;
163- }
164- kfree(buf);
165- }
166- filp_close(file, NULL);
167-out:
168- return (void *) entry;
169-}
170-
171-#endif
172-
173-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
174-static int lsm_addr_calculator(struct file *file);
175-static void * __init cs_find_security_ops_on_arm(unsigned int *base);
176-#endif
177-
178-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
179-/**
180- * cs_find_vfsmount_lock_on_arm - Find vfsmount_lock spinlock on ARM.
181- *
182- * @ip: Address of dummy function's entry point.
183- * @addr: Address of the variable which is used within @function.
184- * @base: Address of function's entry point.
185- *
186- * Returns address of vfsmount_lock on success, NULL otherwise.
187- */
188-static void * __init cs_find_vfsmount_lock_on_arm(unsigned int *ip,
189- unsigned long addr,
190- unsigned int *base)
191-{
192- int i;
193- for (i = 0; i < 32; ip++, i++) {
194- static unsigned int *ip4ret;
195- if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
196- continue;
197- ip = base + i;
198- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
199- return &ip4ret;
200- }
201- return NULL;
202-}
203-#endif
204-
205-/**
206- * cs_find_variable - Find variable's address using dummy.
207- *
208- * @function: Pointer to dummy function's entry point.
209- * @addr: Address of the variable which is used within @function.
210- * @symbol: Name of symbol to resolve.
211- *
212- * This trick depends on below assumptions.
213- *
214- * (1) @addr is found within 128 bytes from @function, even if additional
215- * code (e.g. debug symbols) is added.
216- * (2) It is safe to read 128 bytes from @function.
217- * (3) @addr != Byte code except @addr.
218- */
219-static void * __init cs_find_variable(void *function, unsigned long addr,
220- const char *symbol)
221-{
222- int i;
223- u8 *base;
224- u8 *cp = function;
225-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
226- if (*symbol == ' ')
227- base = cs_find_symbol(symbol);
228- else
229-#endif
230- base = __symbol_get(symbol);
231- if (!base)
232- return NULL;
233-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
234- if (function == lsm_addr_calculator)
235- return cs_find_security_ops_on_arm((unsigned int *) base);
236-#endif
237-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
238- return cs_find_vfsmount_lock_on_arm(function, addr,
239- (unsigned int *) base);
240-#endif
241- /* First, assume absolute adressing mode is used. */
242- for (i = 0; i < 128; i++) {
243- if (*(unsigned long *) cp == addr)
244- return base + i;
245- cp++;
246- }
247- /* Next, assume PC-relative addressing mode is used. */
248- cp = function;
249- for (i = 0; i < 128; i++) {
250- if ((unsigned long) (cp + sizeof(int) + *(int *) cp) == addr) {
251- static void *cp4ret;
252- cp = base + i;
253- cp += sizeof(int) + *(int *) cp;
254- cp4ret = cp;
255- return &cp4ret;
256- }
257- cp++;
258- }
259- cp = function;
260- for (i = 0; i < 128; i++) {
261- if ((unsigned long) (long) (*(int *) cp) == addr) {
262- static void *cp4ret;
263- cp = base + i;
264- cp = (void *) (long) (*(int *) cp);
265- cp4ret = cp;
266- return &cp4ret;
267- }
268- cp++;
269- }
270- return NULL;
271-}
272-
273-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
274-
275-/* Never mark this variable as __initdata . */
276-static struct security_operations *cs_security_ops;
277-
278-/**
279- * lsm_addr_calculator - Dummy function which does identical to security_file_alloc() in security/security.c.
280- *
281- * @file: Pointer to "struct file".
282- *
283- * Returns return value from security_file_alloc().
284- *
285- * Never mark this function as __init in order to make sure that compiler
286- * generates identical code for security_file_alloc() and this function.
287- */
288-static int lsm_addr_calculator(struct file *file)
289-{
290- return cs_security_ops->file_alloc_security(file);
291-}
292-
293-#ifdef CONFIG_ARM
294-/**
295- * cs_find_security_ops_on_arm - Find security_ops on ARM.
296- *
297- * @base: Address of security_file_alloc().
298- *
299- * Returns address of security_ops on success, NULL otherwise.
300- */
301-static void * __init cs_find_security_ops_on_arm(unsigned int *base)
302-{
303- static unsigned int *ip4ret;
304- int i;
305- const unsigned long addr = (unsigned long) &cs_security_ops;
306- unsigned int *ip = (unsigned int *) lsm_addr_calculator;
307- for (i = 0; i < 32; ip++, i++) {
308- if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
309- continue;
310- ip = base + i;
311- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
312- return &ip4ret;
313- }
314- ip = (unsigned int *) lsm_addr_calculator;
315- for (i = 0; i < 32; ip++, i++) {
316- /*
317- * Find
318- * ldr r3, [pc, #offset1]
319- * ldr r3, [r3, #offset2]
320- * sequence.
321- */
322- if ((*ip & 0xFFFFF000) != 0xE59F3000 ||
323- (*(ip + 1) & 0xFFFFF000) != 0xE5933000)
324- continue;
325- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
326- ip4ret += (*(ip + 1) & 0xFFF) >> 2;
327- if ((unsigned long) ip4ret != addr)
328- continue;
329- ip = base + i;
330- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
331- ip4ret += (*(ip + 1) & 0xFFF) >> 2;
332- return &ip4ret;
333- }
334- return NULL;
335-}
336-#endif
337-#endif
338-
339-/**
340- * cs_find_find_security_ops - Find address of "struct security_operations *security_ops".
341- *
342- * Returns pointer to "struct security_operations" on success, NULL otherwise.
343- */
344-static struct security_operations * __init cs_find_security_ops(void)
345-{
346- struct security_operations **ptr;
347- struct security_operations *ops;
348-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
349- void *cp;
350- /* Guess "struct security_operations *security_ops;". */
351- cp = cs_find_variable(lsm_addr_calculator, (unsigned long)
352- &cs_security_ops, " security_file_alloc\n");
353- if (!cp) {
354- printk(KERN_ERR "Can't resolve security_file_alloc().\n");
355- goto out;
356- }
357- /* This should be "struct security_operations *security_ops;". */
358- ptr = *(struct security_operations ***) cp;
359-#else
360- /* This is "struct security_operations *security_ops;". */
361- ptr = (struct security_operations **) __symbol_get("security_ops");
362-#endif
363- if (!ptr) {
364- printk(KERN_ERR "Can't resolve security_ops structure.\n");
365- goto out;
366- }
367- printk(KERN_INFO "security_ops=%p\n", ptr);
368- ops = *ptr;
369- if (!ops) {
370- printk(KERN_ERR "No security_operations registered.\n");
371- goto out;
372- }
373- return ops;
374-out:
375- return NULL;
376-}
377-
378-/**
379- * cs_find_find_task_by_pid - Find address of find_task_by_pid().
380- *
381- * Returns true on success, false otherwise.
382- */
383-static bool __init cs_find_find_task_by_pid(void)
384-{
385-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
386- void *ptr;
387-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
388- ptr = cs_find_symbol(" find_task_by_vpid\n");
389-#else
390- ptr = __symbol_get("find_task_by_vpid");
391-#endif
392- if (!ptr) {
393- printk(KERN_ERR "Can't resolve find_task_by_vpid().\n");
394- goto out;
395- }
396- printk(KERN_INFO "find_task_by_vpid=%p\n", ptr);
397-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
398- ptr = cs_find_symbol(" find_task_by_pid_ns\n");
399-#else
400- ptr = __symbol_get("find_task_by_pid_ns");
401-#endif
402- if (!ptr) {
403- printk(KERN_ERR "Can't resolve find_task_by_pid_ns().\n");
404- goto out;
405- }
406- printk(KERN_INFO "find_task_by_pid_ns=%p\n", ptr);
407- return true;
408-out:
409- return false;
410-#else
411- return true;
412-#endif
413-}
414-
415-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
416-
417-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
418-
419-/* Never mark this variable as __initdata . */
420-static spinlock_t cs_vfsmount_lock __cacheline_aligned_in_smp =
421- SPIN_LOCK_UNLOCKED;
422-
423-static struct list_head *mount_hashtable;
424-static int hash_mask, hash_bits;
425-
426-/**
427- * hash - Copy of hash() in fs/namespace.c.
428- *
429- * @mnt: Pointer to "struct vfsmount".
430- * @dentry: Pointer to "struct dentry".
431- *
432- * Returns hash value.
433- */
434-static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
435-{
436- unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
437- tmp += ((unsigned long) dentry / L1_CACHE_BYTES);
438- tmp = tmp + (tmp >> hash_bits);
439- return tmp & hash_mask;
440-}
441-
442-/**
443- * lsm_lu_mnt - Dummy function which does identical to lookup_mnt() in fs/namespace.c.
444- *
445- * @mnt: Pointer to "struct vfsmount".
446- * @dentry: Pointer to "struct dentry".
447- *
448- * Returns pointer to "struct vfsmount".
449- *
450- * Never mark this function as __init in order to make sure that compiler
451- * generates identical code for lookup_mnt() and this function.
452- */
453-static struct vfsmount *lsm_lu_mnt(struct vfsmount *mnt, struct dentry *dentry)
454-{
455- struct list_head *head = mount_hashtable + hash(mnt, dentry);
456- struct list_head *tmp = head;
457- struct vfsmount *p, *found = NULL;
458-
459- spin_lock(&cs_vfsmount_lock);
460- for (;;) {
461- tmp = tmp->next;
462- p = NULL;
463- if (tmp == head)
464- break;
465- p = list_entry(tmp, struct vfsmount, mnt_hash);
466- if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
467- found = mntget(p);
468- break;
469- }
470- }
471- spin_unlock(&cs_vfsmount_lock);
472- return found;
473-}
474-
475-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
476-
477-/* Never mark this variable as __initdata . */
478-static spinlock_t cs_vfsmount_lock;
479-
480-/**
481- * lsm_flwup - Dummy function which does identical to follow_up() in fs/namei.c.
482- *
483- * @mnt: Pointer to "struct vfsmount *".
484- * @dentry: Pointer to "struct dentry *".
485- *
486- * Returns 1 if followed up, 0 otehrwise.
487- *
488- * Never mark this function as __init in order to make sure that compiler
489- * generates identical code for follow_up() and this function.
490- */
491-static int lsm_flwup(struct vfsmount **mnt, struct dentry **dentry)
492-{
493- struct vfsmount *parent;
494- struct dentry *mountpoint;
495- spin_lock(&cs_vfsmount_lock);
496- parent = (*mnt)->mnt_parent;
497- if (parent == *mnt) {
498- spin_unlock(&cs_vfsmount_lock);
499- return 0;
500- }
501- mntget(parent);
502- mountpoint = dget((*mnt)->mnt_mountpoint);
503- spin_unlock(&cs_vfsmount_lock);
504- dput(*dentry);
505- *dentry = mountpoint;
506- mntput(*mnt);
507- *mnt = parent;
508- return 1;
509-}
510-
511-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
512-
513-/* Never mark this variable as __initdata . */
514-static spinlock_t cs_vfsmount_lock;
515-
516-/**
517- * lsm_pin - Dummy function which does identical to mnt_pin() in fs/namespace.c.
518- *
519- * @mnt: Pointer to "struct vfsmount".
520- *
521- * Returns nothing.
522- *
523- * Never mark this function as __init in order to make sure that compiler
524- * generates identical code for mnt_pin() and this function.
525- */
526-static void lsm_pin(struct vfsmount *mnt)
527-{
528- spin_lock(&cs_vfsmount_lock);
529- mnt->mnt_pinned++;
530- spin_unlock(&cs_vfsmount_lock);
531-}
532-
533-#endif
534-
535-/**
536- * cs_find_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
537- *
538- * Returns true on success, false otherwise.
539- */
540-static bool __init cs_find_vfsmount_lock(void)
541-{
542-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
543- void *cp;
544- spinlock_t *ptr;
545- /* Guess "spinlock_t vfsmount_lock;". */
546- cp = cs_find_variable(lsm_lu_mnt, (unsigned long) &cs_vfsmount_lock,
547- " lookup_mnt\n");
548- if (!cp) {
549- printk(KERN_ERR "Can't resolve lookup_mnt().\n");
550- goto out;
551- }
552- /* This should be "spinlock_t *vfsmount_lock;". */
553- ptr = *(spinlock_t **) cp;
554- if (!ptr) {
555- printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
556- goto out;
557- }
558- printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
559- return true;
560-out:
561- return false;
562-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
563- void *cp;
564- spinlock_t *ptr;
565- /* Guess "spinlock_t vfsmount_lock;". */
566- cp = cs_find_variable(lsm_flwup, (unsigned long) &cs_vfsmount_lock,
567- "follow_up");
568- if (!cp) {
569- printk(KERN_ERR "Can't resolve follow_up().\n");
570- goto out;
571- }
572- /* This should be "spinlock_t *vfsmount_lock;". */
573- ptr = *(spinlock_t **) cp;
574- if (!ptr) {
575- printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
576- goto out;
577- }
578- printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
579- return true;
580-out:
581- return false;
582-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
583- void *cp;
584- spinlock_t *ptr;
585- /* Guess "spinlock_t vfsmount_lock;". */
586- cp = cs_find_variable(lsm_pin, (unsigned long) &cs_vfsmount_lock,
587- "mnt_pin");
588- if (!cp) {
589- printk(KERN_ERR "Can't resolve mnt_pin().\n");
590- goto out;
591- }
592- /* This should be "spinlock_t *vfsmount_lock;". */
593- ptr = *(spinlock_t **) cp;
594- if (!ptr) {
595- printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
596- goto out;
597- }
598- printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
599- return true;
600-out:
601- return false;
602-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
603- void *ptr = cs_find_symbol(" __d_path\n");
604- if (!ptr) {
605- printk(KERN_ERR "Can't resolve __d_path().\n");
606- return false;
607- }
608- printk(KERN_INFO "__d_path=%p\n", ptr);
609- return true;
610-#else
611- void *ptr = cs_find_symbol(" d_absolute_path\n");
612- if (!ptr) {
613- printk(KERN_ERR "Can't resolve d_absolute_path().\n");
614- return false;
615- }
616- printk(KERN_INFO "d_absolute_path=%p\n", ptr);
617- return true;
618-#endif
619-}
620-
621-#else
622-
623-/**
624- * cs_find_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
625- *
626- * Returns true on success, false otherwise.
627- */
628-static bool __init cs_find_vfsmount_lock(void)
629-{
630- return true;
631-}
632-
633-#endif
634-
635-/**
636- * cs_init - Initialize this module.
637- *
638- * Returns 0 on success, -EINVAL otherwise.
639- */
640-static int __init cs_init(void)
641-{
642- if (!cs_find_security_ops() || !cs_find_find_task_by_pid() ||
643- !cs_find_vfsmount_lock()) {
644- printk(KERN_INFO "Sorry, I couldn't guess dependent "
645- "symbols.\n");
646- printk(KERN_INFO "I need some changes for supporting your "
647- "environment.\n");
648- printk(KERN_INFO "Please contact the author.\n");
649- return -EINVAL;
650- }
651- printk(KERN_INFO "All dependent symbols have been guessed.\n");
652- printk(KERN_INFO "Please verify these addresses using System.map for "
653- "this kernel (e.g. /boot/System.map-`uname -r` ).\n");
654- printk(KERN_INFO "If these addresses are correct, you can try loading "
655- "CaitSith module on this kernel.\n");
656- return 0;
657-}
658-
659-/**
660- * cs_exit - Exit this module.
661- *
662- * Returns nothing.
663- */
664-static void cs_exit(void)
665-{
666-}
667-
668-module_init(cs_init);
669-module_exit(cs_exit);
670-MODULE_LICENSE("GPL");
--- trunk/caitsith-patch/caitsith/test.c (nonexistent)
+++ trunk/caitsith-patch/caitsith/test.c (revision 81)
@@ -0,0 +1,63 @@
1+/*
2+ * test.c
3+ *
4+ * Copyright (C) 2010-2013 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+ */
6+#include "probe.h"
7+
8+/**
9+ * cs_init - Initialize this module.
10+ *
11+ * Returns 0 on success, -EINVAL otherwise.
12+ */
13+static int __init cs_init(void)
14+{
15+#ifdef CONFIG_SECURITY_COMPOSER_MAX
16+ if (!probe_lsm_hooks_list())
17+ goto out;
18+#else
19+ if (!probe_security_ops())
20+ goto out;
21+#endif
22+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
23+ if (!probe_find_task_by_vpid())
24+ goto out;
25+ if (!probe_find_task_by_pid_ns())
26+ goto out;
27+#endif
28+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
29+ if (!probe_vfsmount_lock())
30+ goto out;
31+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
32+ if (!probe___d_path())
33+ goto out;
34+#else
35+ if (!probe_d_absolute_path())
36+ goto out;
37+#endif
38+ printk(KERN_INFO "All dependent symbols have been guessed.\n");
39+ printk(KERN_INFO "Please verify these addresses using System.map for "
40+ "this kernel (e.g. /boot/System.map-`uname -r` ).\n");
41+ printk(KERN_INFO "If these addresses are correct, you can try loading "
42+ "CaitSith module on this kernel.\n");
43+ return 0;
44+out:
45+ printk(KERN_INFO "Sorry, I couldn't guess dependent symbols.\n");
46+ printk(KERN_INFO "I need some changes for supporting your "
47+ "environment.\n");
48+ printk(KERN_INFO "Please contact the author.\n");
49+ return -EINVAL;
50+}
51+
52+/**
53+ * cs_exit - Exit this module.
54+ *
55+ * Returns nothing.
56+ */
57+static void cs_exit(void)
58+{
59+}
60+
61+module_init(cs_init);
62+module_exit(cs_exit);
63+MODULE_LICENSE("GPL");
--- trunk/caitsith-patch/caitsith/probe.c (nonexistent)
+++ trunk/caitsith-patch/caitsith/probe.c (revision 81)
@@ -0,0 +1,712 @@
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+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
22+
23+/**
24+ * probe_kernel_read - Wrapper for kernel_read().
25+ *
26+ * @file: Pointer to "struct file".
27+ * @offset: Starting position.
28+ * @addr: Buffer.
29+ * @count: Size of @addr.
30+ *
31+ * Returns return value from kernel_read().
32+ */
33+static int __init probe_kernel_read(struct file *file, unsigned long offset,
34+ char *addr, unsigned long count)
35+{
36+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
37+ /*
38+ * I can't use kernel_read() because seq_read() returns -EPIPE
39+ * if &pos != &file->f_pos .
40+ */
41+ mm_segment_t old_fs;
42+ unsigned long pos = file->f_pos;
43+ int result;
44+ file->f_pos = offset;
45+ old_fs = get_fs();
46+ set_fs(get_ds());
47+ result = vfs_read(file, (void __user *)addr, count, &file->f_pos);
48+ set_fs(old_fs);
49+ file->f_pos = pos;
50+ return result;
51+#else
52+ return kernel_read(file, offset, addr, count);
53+#endif
54+}
55+
56+/**
57+ * probe_find_symbol - Find function's address from /proc/kallsyms .
58+ *
59+ * @keyline: Function to find.
60+ *
61+ * Returns address of specified function on success, NULL otherwise.
62+ */
63+static void *__init probe_find_symbol(const char *keyline)
64+{
65+ struct file *file = NULL;
66+ char *buf;
67+ unsigned long entry = 0;
68+ {
69+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
70+ struct file_system_type *fstype = get_fs_type("proc");
71+ struct vfsmount *mnt = vfs_kern_mount(fstype, 0, "proc", NULL);
72+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
73+ struct file_system_type *fstype = NULL;
74+ struct vfsmount *mnt = do_kern_mount("proc", 0, "proc", NULL);
75+#else
76+ struct file_system_type *fstype = get_fs_type("proc");
77+ struct vfsmount *mnt = kern_mount(fstype);
78+#endif
79+ struct dentry *root;
80+ struct dentry *dentry;
81+ /*
82+ * We embed put_filesystem() here because it is not exported.
83+ */
84+ if (fstype)
85+ module_put(fstype->owner);
86+ if (IS_ERR(mnt))
87+ goto out;
88+ root = dget(mnt->mnt_root);
89+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
90+ mutex_lock(&root->d_inode->i_mutex);
91+ dentry = lookup_one_len("kallsyms", root, 8);
92+ mutex_unlock(&root->d_inode->i_mutex);
93+#else
94+ down(&root->d_inode->i_sem);
95+ dentry = lookup_one_len("kallsyms", root, 8);
96+ up(&root->d_inode->i_sem);
97+#endif
98+ dput(root);
99+ if (IS_ERR(dentry))
100+ mntput(mnt);
101+ else {
102+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
103+ struct path path = { mnt, dentry };
104+ file = dentry_open(&path, O_RDONLY, current_cred());
105+#else
106+ file = dentry_open(dentry, mnt, O_RDONLY
107+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
108+ , current_cred()
109+#endif
110+ );
111+#endif
112+ }
113+ }
114+ if (IS_ERR(file) || !file)
115+ goto out;
116+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
117+ if (buf) {
118+ int len;
119+ int offset = 0;
120+ while ((len = probe_kernel_read(file, offset, buf,
121+ PAGE_SIZE - 1)) > 0) {
122+ char *cp;
123+ buf[len] = '\0';
124+ cp = strrchr(buf, '\n');
125+ if (!cp)
126+ break;
127+ *(cp + 1) = '\0';
128+ offset += strlen(buf);
129+ cp = strstr(buf, keyline);
130+ if (!cp)
131+ continue;
132+ *cp = '\0';
133+ while (cp > buf && *(cp - 1) != '\n')
134+ cp--;
135+ entry = simple_strtoul(cp, NULL, 16);
136+ break;
137+ }
138+ kfree(buf);
139+ }
140+ filp_close(file, NULL);
141+out:
142+ return (void *) entry;
143+}
144+
145+#endif
146+
147+#if defined(CONFIG_SECURITY_COMPOSER_MAX)
148+
149+/*
150+ * Dummy variable for finding location of
151+ * "struct list_head lsm_hooks[LSM_MAX_HOOKS]".
152+ */
153+struct list_head probe_lsm_hooks[LSM_MAX_HOOKS];
154+
155+/**
156+ * probe_security_bprm_committed_creds - Dummy function which does identical to security_bprm_committed_creds() in security/security.c.
157+ *
158+ * @bprm: Pointer to "struct linux_binprm".
159+ *
160+ * Returns nothing.
161+ */
162+void probe_security_bprm_committed_creds(struct linux_binprm *bprm)
163+{
164+ do {
165+ struct security_operations *sop;
166+
167+ list_for_each_entry(sop,
168+ &probe_lsm_hooks[lsm_bprm_committed_creds],
169+ list[lsm_bprm_committed_creds])
170+ sop->bprm_committed_creds(bprm);
171+ } while (0);
172+}
173+
174+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
175+
176+/*
177+ * Dummy variable for finding address of
178+ * "struct security_operations *security_ops".
179+ */
180+static struct security_operations *probe_dummy_security_ops;
181+
182+/**
183+ * probe_security_file_alloc - Dummy function which does identical to security_file_alloc() in security/security.c.
184+ *
185+ * @file: Pointer to "struct file".
186+ *
187+ * Returns return value from security_file_alloc().
188+ */
189+static int probe_security_file_alloc(struct file *file)
190+{
191+ return probe_dummy_security_ops->file_alloc_security(file);
192+}
193+
194+#if defined(CONFIG_ARM)
195+
196+/**
197+ * probe_security_ops_on_arm - Find security_ops on ARM.
198+ *
199+ * @base: Address of security_file_alloc().
200+ *
201+ * Returns address of security_ops on success, NULL otherwise.
202+ */
203+static void * __init probe_security_ops_on_arm(unsigned int *base)
204+{
205+ static unsigned int *ip4ret;
206+ int i;
207+ const unsigned long addr = (unsigned long) &probe_dummy_security_ops;
208+ unsigned int *ip = (unsigned int *) probe_security_file_alloc;
209+ for (i = 0; i < 32; ip++, i++) {
210+ if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
211+ continue;
212+ ip = base + i;
213+ ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
214+ return &ip4ret;
215+ }
216+ ip = (unsigned int *) probe_security_file_alloc;
217+ for (i = 0; i < 32; ip++, i++) {
218+ /*
219+ * Find
220+ * ldr r3, [pc, #offset1]
221+ * ldr r3, [r3, #offset2]
222+ * sequence.
223+ */
224+ if ((*ip & 0xFFFFF000) != 0xE59F3000 ||
225+ (*(ip + 1) & 0xFFFFF000) != 0xE5933000)
226+ continue;
227+ ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
228+ ip4ret += (*(ip + 1) & 0xFFF) >> 2;
229+ if ((unsigned long) ip4ret != addr)
230+ continue;
231+ ip = base + i;
232+ ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
233+ ip4ret += (*(ip + 1) & 0xFFF) >> 2;
234+ return &ip4ret;
235+ }
236+ return NULL;
237+}
238+
239+#endif
240+
241+#endif
242+
243+#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
244+/**
245+ * probe_find_vfsmount_lock_on_arm - Find vfsmount_lock spinlock on ARM.
246+ *
247+ * @ip: Address of dummy function's entry point.
248+ * @addr: Address of the variable which is used within @function.
249+ * @base: Address of function's entry point.
250+ *
251+ * Returns address of vfsmount_lock on success, NULL otherwise.
252+ */
253+static void * __init probe_find_vfsmount_lock_on_arm(unsigned int *ip,
254+ unsigned long addr,
255+ unsigned int *base)
256+{
257+ int i;
258+ for (i = 0; i < 32; ip++, i++) {
259+ static unsigned int *ip4ret;
260+ if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
261+ continue;
262+ ip = base + i;
263+ ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
264+ return &ip4ret;
265+ }
266+ return NULL;
267+}
268+#endif
269+
270+/**
271+ * probe_find_variable - Find variable's address using dummy.
272+ *
273+ * @function: Pointer to dummy function's entry point.
274+ * @addr: Address of the variable which is used within @function.
275+ * @symbol: Name of symbol to resolve.
276+ *
277+ * This trick depends on below assumptions.
278+ *
279+ * (1) @addr is found within 128 bytes from @function, even if additional
280+ * code (e.g. debug symbols) is added.
281+ * (2) It is safe to read 128 bytes from @function.
282+ * (3) @addr != Byte code except @addr.
283+ */
284+static void * __init probe_find_variable(void *function, unsigned long addr,
285+ const char *symbol)
286+{
287+ int i;
288+ u8 *base;
289+ u8 *cp = function;
290+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
291+ if (*symbol == ' ')
292+ base = probe_find_symbol(symbol);
293+ else
294+#endif
295+ base = __symbol_get(symbol);
296+ if (!base)
297+ return NULL;
298+#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(CONFIG_SECURITY_COMPOSER_MAX)
299+ if (function == probe_security_file_alloc)
300+ return probe_security_ops_on_arm((unsigned int *) base);
301+#endif
302+#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
303+ return probe_find_vfsmount_lock_on_arm(function, addr,
304+ (unsigned int *) base);
305+#endif
306+ /* First, assume absolute adressing mode is used. */
307+ for (i = 0; i < 128; i++) {
308+ if (*(unsigned long *) cp == addr)
309+ return base + i;
310+ cp++;
311+ }
312+ /* Next, assume PC-relative addressing mode is used. */
313+ cp = function;
314+ for (i = 0; i < 128; i++) {
315+ if ((unsigned long) (cp + sizeof(int) + *(int *) cp) == addr) {
316+ static void *cp4ret;
317+ cp = base + i;
318+ cp += sizeof(int) + *(int *) cp;
319+ cp4ret = cp;
320+ return &cp4ret;
321+ }
322+ cp++;
323+ }
324+ cp = function;
325+ for (i = 0; i < 128; i++) {
326+ if ((unsigned long) (long) (*(int *) cp) == addr) {
327+ static void *cp4ret;
328+ cp = base + i;
329+ cp = (void *) (long) (*(int *) cp);
330+ cp4ret = cp;
331+ return &cp4ret;
332+ }
333+ cp++;
334+ }
335+ return NULL;
336+}
337+
338+#if defined(CONFIG_SECURITY_COMPOSER_MAX)
339+
340+static void * __init probe_find_variable(void *function, unsigned long addr,
341+ const char *symbol);
342+
343+/**
344+ * probe_lsm_hooks_list - Find address of "struct list_head lsm_hooks[LSM_MAX_HOOKS]".
345+ *
346+ * Returns pointer to "struct security_operations" on success, NULL otherwise.
347+ */
348+struct list_head * __init probe_lsm_hooks_list(void)
349+{
350+ void *cp;
351+ /* Guess "struct list_head lsm_hooks[LSM_MAX_HOOKS];". */
352+ cp = probe_find_variable(probe_security_bprm_committed_creds,
353+ (unsigned long) probe_lsm_hooks,
354+ " security_bprm_committed_creds\n");
355+ if (!cp) {
356+ printk(KERN_ERR
357+ "Can't resolve security_bprm_committed_creds().\n");
358+ goto out;
359+ }
360+ /* This should be "struct list_head lsm_hooks[LSM_MAX_HOOKS];". */
361+ cp = (struct list_head *) (*(unsigned long *) cp);
362+ if (!cp) {
363+ printk(KERN_ERR "Can't resolve lsm_hooks array.\n");
364+ goto out;
365+ }
366+ printk(KERN_INFO "lsm_hooks=%p\n", cp);
367+ return cp;
368+out:
369+ return NULL;
370+}
371+
372+#else
373+
374+/**
375+ * probe_security_ops - Find address of "struct security_operations *security_ops".
376+ *
377+ * Returns pointer to "struct security_operations" on success, NULL otherwise.
378+ */
379+struct security_operations * __init probe_security_ops(void)
380+{
381+ struct security_operations **ptr;
382+ struct security_operations *ops;
383+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
384+ void *cp;
385+ /* Guess "struct security_operations *security_ops;". */
386+ cp = probe_find_variable(probe_security_file_alloc, (unsigned long)
387+ &probe_dummy_security_ops,
388+ " security_file_alloc\n");
389+ if (!cp) {
390+ printk(KERN_ERR "Can't resolve security_file_alloc().\n");
391+ return NULL;
392+ }
393+ /* This should be "struct security_operations *security_ops;". */
394+ ptr = *(struct security_operations ***) cp;
395+#else
396+ /* This is "struct security_operations *security_ops;". */
397+ ptr = (struct security_operations **) __symbol_get("security_ops");
398+#endif
399+ if (!ptr) {
400+ printk(KERN_ERR "Can't resolve security_ops structure.\n");
401+ return NULL;
402+ }
403+ printk(KERN_INFO "security_ops=%p\n", ptr);
404+ ops = *ptr;
405+ if (!ops) {
406+ printk(KERN_ERR "No security_operations registered.\n");
407+ return NULL;
408+ }
409+ return ops;
410+}
411+
412+#endif
413+
414+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
415+
416+/**
417+ * probe_find_task_by_vpid - Find address of find_task_by_vpid().
418+ *
419+ * Returns address of find_task_by_vpid() on success, NULL otherwise.
420+ */
421+void * __init probe_find_task_by_vpid(void)
422+{
423+ void *ptr;
424+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
425+ ptr = probe_find_symbol(" find_task_by_vpid\n");
426+#else
427+ ptr = __symbol_get("find_task_by_vpid");
428+#endif
429+ if (!ptr) {
430+ printk(KERN_ERR "Can't resolve find_task_by_vpid().\n");
431+ return NULL;
432+ }
433+ printk(KERN_INFO "find_task_by_vpid=%p\n", ptr);
434+ return ptr;
435+}
436+
437+/**
438+ * probe_find_task_by_pid_ns - Find address of find_task_by_pid().
439+ *
440+ * Returns address of find_task_by_pid_ns() on success, NULL otherwise.
441+ */
442+void * __init probe_find_task_by_pid_ns(void)
443+{
444+ void *ptr;
445+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
446+ ptr = probe_find_symbol(" find_task_by_pid_ns\n");
447+#else
448+ ptr = __symbol_get("find_task_by_pid_ns");
449+#endif
450+ if (!ptr) {
451+ printk(KERN_ERR "Can't resolve find_task_by_pid_ns().\n");
452+ return NULL;
453+ }
454+ printk(KERN_INFO "find_task_by_pid_ns=%p\n", ptr);
455+ return ptr;
456+}
457+
458+#endif
459+
460+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
461+
462+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
463+
464+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
465+
466+/* Dummy variable for finding address of "spinlock_t vfsmount_lock". */
467+static spinlock_t probe_vfsmount_lock __cacheline_aligned_in_smp =
468+ SPIN_LOCK_UNLOCKED;
469+
470+static struct list_head *probe_mount_hashtable;
471+static int probe_hash_mask, probe_hash_bits;
472+
473+/**
474+ * hash - Copy of hash() in fs/namespace.c.
475+ *
476+ * @mnt: Pointer to "struct vfsmount".
477+ * @dentry: Pointer to "struct dentry".
478+ *
479+ * Returns hash value.
480+ */
481+static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
482+{
483+ unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
484+ tmp += ((unsigned long) dentry / L1_CACHE_BYTES);
485+ tmp = tmp + (tmp >> probe_hash_bits);
486+ return tmp & probe_hash_mask;
487+}
488+
489+/**
490+ * probe_lookup_mnt - Dummy function which does identical to lookup_mnt() in fs/namespace.c.
491+ *
492+ * @mnt: Pointer to "struct vfsmount".
493+ * @dentry: Pointer to "struct dentry".
494+ *
495+ * Returns pointer to "struct vfsmount".
496+ */
497+static struct vfsmount *probe_lookup_mnt(struct vfsmount *mnt,
498+ struct dentry *dentry)
499+{
500+ struct list_head *head = probe_mount_hashtable + hash(mnt, dentry);
501+ struct list_head *tmp = head;
502+ struct vfsmount *p, *found = NULL;
503+
504+ spin_lock(&probe_vfsmount_lock);
505+ for (;;) {
506+ tmp = tmp->next;
507+ p = NULL;
508+ if (tmp == head)
509+ break;
510+ p = list_entry(tmp, struct vfsmount, mnt_hash);
511+ if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
512+ found = mntget(p);
513+ break;
514+ }
515+ }
516+ spin_unlock(&probe_vfsmount_lock);
517+ return found;
518+}
519+
520+/**
521+ * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
522+ *
523+ * Returns address of vfsmount_lock on success, NULL otherwise.
524+ */
525+void * __init probe_vfsmount_lock(void)
526+{
527+ void *cp;
528+ spinlock_t *ptr;
529+ /* Guess "spinlock_t vfsmount_lock;". */
530+ cp = probe_find_variable(probe_lookup_mnt, (unsigned long)
531+ &probe_vfsmount_lock, " lookup_mnt\n");
532+ if (!cp) {
533+ printk(KERN_ERR "Can't resolve lookup_mnt().\n");
534+ return NULL;
535+ }
536+ /* This should be "spinlock_t *vfsmount_lock;". */
537+ ptr = *(spinlock_t **) cp;
538+ if (!ptr) {
539+ printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
540+ return NULL;
541+ }
542+ printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
543+ return ptr;
544+}
545+
546+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
547+
548+/* Dummy variable for finding address of "spinlock_t vfsmount_lock". */
549+static spinlock_t probe_vfsmount_lock;
550+
551+/**
552+ * probe_follow_up - Dummy function which does identical to follow_up() in fs/namei.c.
553+ *
554+ * @mnt: Pointer to "struct vfsmount *".
555+ * @dentry: Pointer to "struct dentry *".
556+ *
557+ * Returns 1 if followed up, 0 otehrwise.
558+ */
559+static int probe_follow_up(struct vfsmount **mnt, struct dentry **dentry)
560+{
561+ struct vfsmount *parent;
562+ struct dentry *mountpoint;
563+ spin_lock(&probe_vfsmount_lock);
564+ parent = (*mnt)->mnt_parent;
565+ if (parent == *mnt) {
566+ spin_unlock(&probe_vfsmount_lock);
567+ return 0;
568+ }
569+ mntget(parent);
570+ mountpoint = dget((*mnt)->mnt_mountpoint);
571+ spin_unlock(&probe_vfsmount_lock);
572+ dput(*dentry);
573+ *dentry = mountpoint;
574+ mntput(*mnt);
575+ *mnt = parent;
576+ return 1;
577+}
578+
579+/**
580+ * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
581+ *
582+ * Returns address of vfsmount_lock on success, NULL otherwise.
583+ */
584+void * __init probe_vfsmount_lock(void)
585+{
586+ void *cp;
587+ spinlock_t *ptr;
588+ /* Guess "spinlock_t vfsmount_lock;". */
589+ cp = probe_find_variable(probe_follow_up, (unsigned long)
590+ &probe_vfsmount_lock, "follow_up");
591+ if (!cp) {
592+ printk(KERN_ERR "Can't resolve follow_up().\n");
593+ return NULL;
594+ }
595+ /* This should be "spinlock_t *vfsmount_lock;". */
596+ ptr = *(spinlock_t **) cp;
597+ if (!ptr) {
598+ printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
599+ return NULL;
600+ }
601+ printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
602+ return ptr;
603+}
604+
605+#else
606+
607+/* Dummy variable for finding address of "spinlock_t vfsmount_lock". */
608+static spinlock_t probe_vfsmount_lock;
609+
610+/**
611+ * probe_mnt_pin - Dummy function which does identical to mnt_pin() in fs/namespace.c.
612+ *
613+ * @mnt: Pointer to "struct vfsmount".
614+ *
615+ * Returns nothing.
616+ */
617+static void probe_mnt_pin(struct vfsmount *mnt)
618+{
619+ spin_lock(&probe_vfsmount_lock);
620+ mnt->mnt_pinned++;
621+ spin_unlock(&probe_vfsmount_lock);
622+}
623+
624+/**
625+ * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
626+ *
627+ * Returns address of vfsmount_lock on success, NULL otherwise.
628+ */
629+void * __init probe_vfsmount_lock(void)
630+{
631+ void *cp;
632+ spinlock_t *ptr;
633+ /* Guess "spinlock_t vfsmount_lock;". */
634+ cp = probe_find_variable(probe_mnt_pin, (unsigned long)
635+ &probe_vfsmount_lock, "mnt_pin");
636+ if (!cp) {
637+ printk(KERN_ERR "Can't resolve mnt_pin().\n");
638+ return NULL;
639+ }
640+ /* This should be "spinlock_t *vfsmount_lock;". */
641+ ptr = *(spinlock_t **) cp;
642+ if (!ptr) {
643+ printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
644+ return NULL;
645+ }
646+ printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
647+ return ptr;
648+}
649+
650+#endif
651+
652+#else
653+
654+/*
655+ * Never mark this variable as __initdata , for this variable might be accessed
656+ * by caller of probe_find_vfsmount_lock().
657+ */
658+static spinlock_t probe_vfsmount_lock;
659+
660+/**
661+ * probe_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
662+ *
663+ * Returns address of vfsmount_lock.
664+ */
665+void * __init probe_vfsmount_lock(void)
666+{
667+ return &probe_vfsmount_lock;
668+}
669+
670+#endif
671+
672+#endif
673+
674+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
675+
676+/**
677+ * probe___d_path - Find address of "__d_path()".
678+ *
679+ * Returns address of __d_path() on success, NULL otherwise.
680+ */
681+void * __init probe___d_path(void)
682+{
683+ void *ptr = probe_find_symbol(" __d_path\n");
684+ if (!ptr) {
685+ printk(KERN_ERR "Can't resolve __d_path().\n");
686+ return NULL;
687+ }
688+ printk(KERN_INFO "__d_path=%p\n", ptr);
689+ return ptr;
690+}
691+
692+#endif
693+
694+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
695+
696+/**
697+ * probe_d_absolute_path - Find address of "d_absolute_path()".
698+ *
699+ * Returns address of d_absolute_path() on success, NULL otherwise.
700+ */
701+void * __init probe_d_absolute_path(void)
702+{
703+ void *ptr = probe_find_symbol(" d_absolute_path\n");
704+ if (!ptr) {
705+ printk(KERN_ERR "Can't resolve d_absolute_path().\n");
706+ return NULL;
707+ }
708+ printk(KERN_INFO "d_absolute_path=%p\n", ptr);
709+ return ptr;
710+}
711+
712+#endif
--- trunk/caitsith-patch/caitsith/lsm.c (revision 80)
+++ trunk/caitsith-patch/caitsith/lsm.c (revision 81)
@@ -1,12 +1,13 @@
11 /*
22 * lsm.c
33 *
4- * Copyright (C) 2010-2012 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
4+ * Copyright (C) 2010-2013 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
55 *
66 * Version: 0.1.8 2013/01/06
77 */
88
99 #include "caitsith.h"
10+#include "probe.h"
1011 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
1112 #define USE_UMODE_T
1213 #else
@@ -111,9 +112,7 @@
111112 if (!r)
112113 return;
113114 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
114-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
115- security->cs_flags &= ~CS_TASK_STARTED_EXECVE;
116-#else
115+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
117116 /*
118117 * Drop refcount on "struct cred" in "struct linux_binprm" and forget
119118 * it.
@@ -142,11 +141,11 @@
142141 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
143142 /*
144143 * If this security context was associated with "struct pid" and
145- * ptr->cs_flags has CS_TASK_STARTED_EXECVE set, it indicates that a
144+ * ptr->cs_flags has CS_TASK_IS_IN_EXECVE set, it indicates that a
146145 * "struct task_struct" associated with this security context exited
147146 * immediately after do_execve() has failed.
148147 */
149- if (ptr->pid && (ptr->cs_flags & CS_TASK_STARTED_EXECVE)) {
148+ if (ptr->pid && (ptr->cs_flags & CS_TASK_IS_IN_EXECVE)) {
150149 #ifdef CONFIG_CAITSITH_DEBUG
151150 static bool done;
152151 if (!done) {
@@ -203,7 +202,7 @@
203202 static bool done;
204203 if (!done) {
205204 printk(KERN_INFO "CAITSITH: Releasing memory in "
206- "\"struct cs_execve\" because some "
205+ "\"struct cs_request_info\" because some "
207206 "\"struct task_struct\" has exit()ed "
208207 "immediately after do_execve() has failed.\n");
209208 done = true;
@@ -771,9 +770,7 @@
771770 rc = cs_start_execve(bprm, &security->r);
772771 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
773772 if (security->r) {
774-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
775- security->cs_flags |= CS_TASK_STARTED_EXECVE;
776-#else
773+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
777774 /*
778775 * Get refcount on "struct cred" in
779776 * "struct linux_binprm" and remember it.
@@ -2488,608 +2485,6 @@
24882485
24892486 #endif
24902487
2491-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
2492-
2493-#include <linux/mount.h>
2494-#include <linux/fs_struct.h>
2495-
2496-/**
2497- * cs_kernel_read - Wrapper for kernel_read().
2498- *
2499- * @file: Pointer to "struct file".
2500- * @offset: Starting position.
2501- * @addr: Buffer.
2502- * @count: Size of @addr.
2503- *
2504- * Returns return value from kernel_read().
2505- */
2506-static int __init cs_kernel_read(struct file *file, unsigned long offset,
2507- char *addr, unsigned long count)
2508-{
2509-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
2510- /*
2511- * I can't use kernel_read() because seq_read() returns -EPIPE
2512- * if &pos != &file->f_pos .
2513- */
2514- mm_segment_t old_fs;
2515- unsigned long pos = file->f_pos;
2516- int result;
2517- file->f_pos = offset;
2518- old_fs = get_fs();
2519- set_fs(get_ds());
2520- result = vfs_read(file, (void __user *)addr, count, &file->f_pos);
2521- set_fs(old_fs);
2522- file->f_pos = pos;
2523- return result;
2524-#else
2525- return kernel_read(file, offset, addr, count);
2526-#endif
2527-}
2528-
2529-/**
2530- * cs_find_symbol - Find function's address from /proc/kallsyms .
2531- *
2532- * @keyline: Function to find.
2533- *
2534- * Returns address of specified function on success, NULL otherwise.
2535- */
2536-static void *__init cs_find_symbol(const char *keyline)
2537-{
2538- struct file *file = NULL;
2539- char *buf;
2540- unsigned long entry = 0;
2541- {
2542-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
2543- struct file_system_type *fstype = get_fs_type("proc");
2544- struct vfsmount *mnt = vfs_kern_mount(fstype, 0, "proc", NULL);
2545-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
2546- struct file_system_type *fstype = NULL;
2547- struct vfsmount *mnt = do_kern_mount("proc", 0, "proc", NULL);
2548-#else
2549- struct file_system_type *fstype = get_fs_type("proc");
2550- struct vfsmount *mnt = kern_mount(fstype);
2551-#endif
2552- struct dentry *root;
2553- struct dentry *dentry;
2554- /*
2555- * We embed put_filesystem() here because it is not exported.
2556- */
2557- if (fstype)
2558- module_put(fstype->owner);
2559- if (IS_ERR(mnt))
2560- goto out;
2561- root = dget(mnt->mnt_root);
2562-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
2563- mutex_lock(&root->d_inode->i_mutex);
2564- dentry = lookup_one_len("kallsyms", root, 8);
2565- mutex_unlock(&root->d_inode->i_mutex);
2566-#else
2567- down(&root->d_inode->i_sem);
2568- dentry = lookup_one_len("kallsyms", root, 8);
2569- up(&root->d_inode->i_sem);
2570-#endif
2571- dput(root);
2572- if (IS_ERR(dentry))
2573- mntput(mnt);
2574- else {
2575-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
2576- struct path path = { mnt, dentry };
2577- file = dentry_open(&path, O_RDONLY, current_cred());
2578-#else
2579- file = dentry_open(dentry, mnt, O_RDONLY
2580-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
2581- , current_cred()
2582-#endif
2583- );
2584-#endif
2585- }
2586- }
2587- if (IS_ERR(file) || !file)
2588- goto out;
2589- buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
2590- if (buf) {
2591- int len;
2592- int offset = 0;
2593- while ((len = cs_kernel_read(file, offset, buf,
2594- PAGE_SIZE - 1)) > 0) {
2595- char *cp;
2596- buf[len] = '\0';
2597- cp = strrchr(buf, '\n');
2598- if (!cp)
2599- break;
2600- *(cp + 1) = '\0';
2601- offset += strlen(buf);
2602- cp = strstr(buf, keyline);
2603- if (!cp)
2604- continue;
2605- *cp = '\0';
2606- while (cp > buf && *(cp - 1) != '\n')
2607- cp--;
2608- entry = simple_strtoul(cp, NULL, 16);
2609- break;
2610- }
2611- kfree(buf);
2612- }
2613- filp_close(file, NULL);
2614-out:
2615- return (void *) entry;
2616-}
2617-
2618-#endif
2619-
2620-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2621-static int lsm_addr_calculator(struct file *file);
2622-static void * __init cs_find_security_ops_on_arm(unsigned int *base);
2623-#endif
2624-
2625-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
2626-/**
2627- * cs_find_vfsmount_lock_on_arm - Find vfsmount_lock spinlock on ARM.
2628- *
2629- * @ip: Address of dummy function's entry point.
2630- * @addr: Address of the variable which is used within @function.
2631- * @base: Address of function's entry point.
2632- *
2633- * Returns address of vfsmount_lock on success, NULL otherwise.
2634- */
2635-static void * __init cs_find_vfsmount_lock_on_arm(unsigned int *ip,
2636- unsigned long addr,
2637- unsigned int *base)
2638-{
2639- int i;
2640- for (i = 0; i < 32; ip++, i++) {
2641- static unsigned int *ip4ret;
2642- if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
2643- continue;
2644- ip = base + i;
2645- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
2646- return &ip4ret;
2647- }
2648- return NULL;
2649-}
2650-#endif
2651-
2652-/**
2653- * cs_find_variable - Find variable's address using dummy.
2654- *
2655- * @function: Pointer to dummy function's entry point.
2656- * @addr: Address of the variable which is used within @function.
2657- * @symbol: Name of symbol to resolve.
2658- *
2659- * This trick depends on below assumptions.
2660- *
2661- * (1) @addr is found within 128 bytes from @function, even if additional
2662- * code (e.g. debug symbols) is added.
2663- * (2) It is safe to read 128 bytes from @function.
2664- * (3) @addr != Byte code except @addr.
2665- */
2666-static void * __init cs_find_variable(void *function, unsigned long addr,
2667- const char *symbol)
2668-{
2669- int i;
2670- u8 *base;
2671- u8 *cp = function;
2672-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
2673- if (*symbol == ' ')
2674- base = cs_find_symbol(symbol);
2675- else
2676-#endif
2677- base = __symbol_get(symbol);
2678- if (!base)
2679- return NULL;
2680-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2681- if (function == lsm_addr_calculator)
2682- return cs_find_security_ops_on_arm((unsigned int *) base);
2683-#endif
2684-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
2685- return cs_find_vfsmount_lock_on_arm(function, addr,
2686- (unsigned int *) base);
2687-#endif
2688- /* First, assume absolute adressing mode is used. */
2689- for (i = 0; i < 128; i++) {
2690- if (*(unsigned long *) cp == addr)
2691- return base + i;
2692- cp++;
2693- }
2694- /* Next, assume PC-relative addressing mode is used. */
2695- cp = function;
2696- for (i = 0; i < 128; i++) {
2697- if ((unsigned long) (cp + sizeof(int) + *(int *) cp) == addr) {
2698- static void *cp4ret;
2699- cp = base + i;
2700- cp += sizeof(int) + *(int *) cp;
2701- cp4ret = cp;
2702- return &cp4ret;
2703- }
2704- cp++;
2705- }
2706- cp = function;
2707- for (i = 0; i < 128; i++) {
2708- if ((unsigned long) (long) (*(int *) cp) == addr) {
2709- static void *cp4ret;
2710- cp = base + i;
2711- cp = (void *) (long) (*(int *) cp);
2712- cp4ret = cp;
2713- return &cp4ret;
2714- }
2715- cp++;
2716- }
2717- return NULL;
2718-}
2719-
2720-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2721-
2722-/* Never mark this variable as __initdata . */
2723-static struct security_operations *cs_security_ops;
2724-
2725-/**
2726- * lsm_addr_calculator - Dummy function which does identical to security_file_alloc() in security/security.c.
2727- *
2728- * @file: Pointer to "struct file".
2729- *
2730- * Returns return value from security_file_alloc().
2731- *
2732- * Never mark this function as __init in order to make sure that compiler
2733- * generates identical code for security_file_alloc() and this function.
2734- */
2735-static int lsm_addr_calculator(struct file *file)
2736-{
2737- return cs_security_ops->file_alloc_security(file);
2738-}
2739-
2740-#ifdef CONFIG_ARM
2741-/**
2742- * cs_find_security_ops_on_arm - Find security_ops on ARM.
2743- *
2744- * @base: Address of security_file_alloc().
2745- *
2746- * Returns address of security_ops on success, NULL otherwise.
2747- */
2748-static void * __init cs_find_security_ops_on_arm(unsigned int *base)
2749-{
2750- static unsigned int *ip4ret;
2751- int i;
2752- const unsigned long addr = (unsigned long) &cs_security_ops;
2753- unsigned int *ip = (unsigned int *) lsm_addr_calculator;
2754- for (i = 0; i < 32; ip++, i++) {
2755- if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
2756- continue;
2757- ip = base + i;
2758- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
2759- return &ip4ret;
2760- }
2761- ip = (unsigned int *) lsm_addr_calculator;
2762- for (i = 0; i < 32; ip++, i++) {
2763- /*
2764- * Find
2765- * ldr r3, [pc, #offset1]
2766- * ldr r3, [r3, #offset2]
2767- * sequence.
2768- */
2769- if ((*ip & 0xFFFFF000) != 0xE59F3000 ||
2770- (*(ip + 1) & 0xFFFFF000) != 0xE5933000)
2771- continue;
2772- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
2773- ip4ret += (*(ip + 1) & 0xFFF) >> 2;
2774- if ((unsigned long) ip4ret != addr)
2775- continue;
2776- ip = base + i;
2777- ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
2778- ip4ret += (*(ip + 1) & 0xFFF) >> 2;
2779- return &ip4ret;
2780- }
2781- return NULL;
2782-}
2783-#endif
2784-#endif
2785-
2786-/**
2787- * cs_find_security_ops - Find address of "struct security_operations *security_ops".
2788- *
2789- * Returns pointer to "struct security_operations" on success, NULL otherwise.
2790- */
2791-static struct security_operations * __init cs_find_security_ops(void)
2792-{
2793- struct security_operations **ptr;
2794- struct security_operations *ops;
2795-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2796- void *cp;
2797- /* Guess "struct security_operations *security_ops;". */
2798- cp = cs_find_variable(lsm_addr_calculator, (unsigned long)
2799- &cs_security_ops, " security_file_alloc\n");
2800- if (!cp) {
2801- printk(KERN_ERR "Can't resolve security_file_alloc().\n");
2802- goto out;
2803- }
2804- /* This should be "struct security_operations *security_ops;". */
2805- ptr = *(struct security_operations ***) cp;
2806-#else
2807- /* This is "struct security_operations *security_ops;". */
2808- ptr = (struct security_operations **) __symbol_get("security_ops");
2809-#endif
2810- if (!ptr) {
2811- printk(KERN_ERR "Can't resolve security_ops structure.\n");
2812- goto out;
2813- }
2814- printk(KERN_INFO "security_ops=%p\n", ptr);
2815- ops = *ptr;
2816- if (!ops) {
2817- printk(KERN_ERR "No security_operations registered.\n");
2818- goto out;
2819- }
2820- return ops;
2821-out:
2822- return NULL;
2823-}
2824-
2825-/**
2826- * cs_find_find_task_by_pid - Find address of find_task_by_pid().
2827- *
2828- * Returns true on success, false otherwise.
2829- */
2830-static bool __init cs_find_find_task_by_pid(void)
2831-{
2832-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2833- void *ptr;
2834-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
2835- ptr = cs_find_symbol(" find_task_by_vpid\n");
2836-#else
2837- ptr = __symbol_get("find_task_by_vpid");
2838-#endif
2839- if (!ptr) {
2840- printk(KERN_ERR "Can't resolve find_task_by_vpid().\n");
2841- goto out;
2842- }
2843- caitsith_exports.find_task_by_vpid = ptr;
2844- printk(KERN_INFO "find_task_by_vpid=%p\n", ptr);
2845-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
2846- ptr = cs_find_symbol(" find_task_by_pid_ns\n");
2847-#else
2848- ptr = __symbol_get("find_task_by_pid_ns");
2849-#endif
2850- if (!ptr) {
2851- printk(KERN_ERR "Can't resolve find_task_by_pid_ns().\n");
2852- goto out;
2853- }
2854- caitsith_exports.find_task_by_pid_ns = ptr;
2855- printk(KERN_INFO "find_task_by_pid_ns=%p\n", ptr);
2856- return true;
2857-out:
2858- return false;
2859-#else
2860- return true;
2861-#endif
2862-}
2863-
2864-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
2865-
2866-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
2867-
2868-/* Never mark this variable as __initdata . */
2869-static spinlock_t cs_vfsmount_lock __cacheline_aligned_in_smp =
2870- SPIN_LOCK_UNLOCKED;
2871-
2872-static struct list_head *mount_hashtable;
2873-static int hash_mask, hash_bits;
2874-
2875-/**
2876- * hash - Copy of hash() in fs/namespace.c.
2877- *
2878- * @mnt: Pointer to "struct vfsmount".
2879- * @dentry: Pointer to "struct dentry".
2880- *
2881- * Returns hash value.
2882- */
2883-static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
2884-{
2885- unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
2886- tmp += ((unsigned long) dentry / L1_CACHE_BYTES);
2887- tmp = tmp + (tmp >> hash_bits);
2888- return tmp & hash_mask;
2889-}
2890-
2891-/**
2892- * lsm_lu_mnt - Dummy function which does identical to lookup_mnt() in fs/namespace.c.
2893- *
2894- * @mnt: Pointer to "struct vfsmount".
2895- * @dentry: Pointer to "struct dentry".
2896- *
2897- * Returns pointer to "struct vfsmount".
2898- *
2899- * Never mark this function as __init in order to make sure that compiler
2900- * generates identical code for lookup_mnt() and this function.
2901- */
2902-static struct vfsmount *lsm_lu_mnt(struct vfsmount *mnt, struct dentry *dentry)
2903-{
2904- struct list_head *head = mount_hashtable + hash(mnt, dentry);
2905- struct list_head *tmp = head;
2906- struct vfsmount *p, *found = NULL;
2907-
2908- spin_lock(&cs_vfsmount_lock);
2909- for (;;) {
2910- tmp = tmp->next;
2911- p = NULL;
2912- if (tmp == head)
2913- break;
2914- p = list_entry(tmp, struct vfsmount, mnt_hash);
2915- if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
2916- found = mntget(p);
2917- break;
2918- }
2919- }
2920- spin_unlock(&cs_vfsmount_lock);
2921- return found;
2922-}
2923-
2924-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
2925-
2926-/* Never mark this variable as __initdata . */
2927-static spinlock_t cs_vfsmount_lock;
2928-
2929-/**
2930- * lsm_flwup - Dummy function which does identical to follow_up() in fs/namei.c.
2931- *
2932- * @mnt: Pointer to "struct vfsmount *".
2933- * @dentry: Pointer to "struct dentry *".
2934- *
2935- * Returns 1 if followed up, 0 otehrwise.
2936- *
2937- * Never mark this function as __init in order to make sure that compiler
2938- * generates identical code for follow_up() and this function.
2939- */
2940-static int lsm_flwup(struct vfsmount **mnt, struct dentry **dentry)
2941-{
2942- struct vfsmount *parent;
2943- struct dentry *mountpoint;
2944- spin_lock(&cs_vfsmount_lock);
2945- parent = (*mnt)->mnt_parent;
2946- if (parent == *mnt) {
2947- spin_unlock(&cs_vfsmount_lock);
2948- return 0;
2949- }
2950- mntget(parent);
2951- mountpoint = dget((*mnt)->mnt_mountpoint);
2952- spin_unlock(&cs_vfsmount_lock);
2953- dput(*dentry);
2954- *dentry = mountpoint;
2955- mntput(*mnt);
2956- *mnt = parent;
2957- return 1;
2958-}
2959-
2960-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
2961-
2962-/* Never mark this variable as __initdata . */
2963-static spinlock_t cs_vfsmount_lock;
2964-
2965-/**
2966- * lsm_pin - Dummy function which does identical to mnt_pin() in fs/namespace.c.
2967- *
2968- * @mnt: Pointer to "struct vfsmount".
2969- *
2970- * Returns nothing.
2971- *
2972- * Never mark this function as __init in order to make sure that compiler
2973- * generates identical code for mnt_pin() and this function.
2974- */
2975-static void lsm_pin(struct vfsmount *mnt)
2976-{
2977- spin_lock(&cs_vfsmount_lock);
2978- mnt->mnt_pinned++;
2979- spin_unlock(&cs_vfsmount_lock);
2980-}
2981-
2982-#endif
2983-
2984-/**
2985- * cs_find_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
2986- *
2987- * Returns true on success, false otherwise.
2988- */
2989-static bool __init cs_find_vfsmount_lock(void)
2990-{
2991-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
2992- void *cp;
2993- spinlock_t *ptr;
2994- /* Guess "spinlock_t vfsmount_lock;". */
2995- cp = cs_find_variable(lsm_lu_mnt, (unsigned long) &cs_vfsmount_lock,
2996- " lookup_mnt\n");
2997- if (!cp) {
2998- printk(KERN_ERR "Can't resolve lookup_mnt().\n");
2999- goto out;
3000- }
3001- /* This should be "spinlock_t *vfsmount_lock;". */
3002- ptr = *(spinlock_t **) cp;
3003- if (!ptr) {
3004- printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
3005- goto out;
3006- }
3007- caitsith_exports.vfsmount_lock = ptr;
3008- printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
3009- return true;
3010-out:
3011- return false;
3012-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
3013- void *cp;
3014- spinlock_t *ptr;
3015- /* Guess "spinlock_t vfsmount_lock;". */
3016- cp = cs_find_variable(lsm_flwup, (unsigned long) &cs_vfsmount_lock,
3017- "follow_up");
3018- if (!cp) {
3019- printk(KERN_ERR "Can't resolve follow_up().\n");
3020- goto out;
3021- }
3022- /* This should be "spinlock_t *vfsmount_lock;". */
3023- ptr = *(spinlock_t **) cp;
3024- if (!ptr) {
3025- printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
3026- goto out;
3027- }
3028- caitsith_exports.vfsmount_lock = ptr;
3029- printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
3030- return true;
3031-out:
3032- return false;
3033-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
3034- void *cp;
3035- spinlock_t *ptr;
3036- /* Guess "spinlock_t vfsmount_lock;". */
3037- cp = cs_find_variable(lsm_pin, (unsigned long) &cs_vfsmount_lock,
3038- "mnt_pin");
3039- if (!cp) {
3040- printk(KERN_ERR "Can't resolve mnt_pin().\n");
3041- goto out;
3042- }
3043- /* This should be "spinlock_t *vfsmount_lock;". */
3044- ptr = *(spinlock_t **) cp;
3045- if (!ptr) {
3046- printk(KERN_ERR "Can't resolve vfsmount_lock .\n");
3047- goto out;
3048- }
3049- caitsith_exports.vfsmount_lock = ptr;
3050- printk(KERN_INFO "vfsmount_lock=%p\n", ptr);
3051- return true;
3052-out:
3053- return false;
3054-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
3055- void *ptr = cs_find_symbol(" __d_path\n");
3056- if (!ptr) {
3057- printk(KERN_ERR "Can't resolve __d_path().\n");
3058- return false;
3059- }
3060- caitsith_exports.__d_path = ptr;
3061- printk(KERN_INFO "__d_path=%p\n", ptr);
3062- return true;
3063-#else
3064- void *ptr = cs_find_symbol(" d_absolute_path\n");
3065- if (!ptr) {
3066- printk(KERN_ERR "Can't resolve d_absolute_path().\n");
3067- return false;
3068- }
3069- caitsith_exports.d_absolute_path = ptr;
3070- printk(KERN_INFO "d_absolute_path=%p\n", ptr);
3071- return true;
3072-#endif
3073-}
3074-
3075-#else
3076-
3077-/* Never mark this variable as __initdata . */
3078-static spinlock_t cs_vfsmount_lock;
3079-
3080-/**
3081- * cs_find_vfsmount_lock - Find address of "spinlock_t vfsmount_lock".
3082- *
3083- * Returns true on success, false otherwise.
3084- */
3085-static bool __init cs_find_vfsmount_lock(void)
3086-{
3087- caitsith_exports.vfsmount_lock = &cs_vfsmount_lock;
3088- return true;
3089-}
3090-
3091-#endif
3092-
30932488 /*
30942489 * Why not to copy all operations by "original_security_ops = *ops" ?
30952490 * Because copying byte array is not atomic. Reader checks
@@ -3199,10 +2594,30 @@
31992594 */
32002595 static int __init cs_init(void)
32012596 {
3202- struct security_operations *ops = cs_find_security_ops();
3203- if (!ops || !cs_find_find_task_by_pid() ||
3204- !cs_find_vfsmount_lock())
3205- return -EINVAL;
2597+ struct security_operations *ops = probe_security_ops();
2598+ if (!ops)
2599+ goto out;
2600+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2601+ caitsith_exports.find_task_by_vpid = probe_find_task_by_vpid();
2602+ if (!caitsith_exports.find_task_by_vpid)
2603+ goto out;
2604+ caitsith_exports.find_task_by_pid_ns = probe_find_task_by_pid_ns();
2605+ if (!caitsith_exports.find_task_by_pid_ns)
2606+ goto out;
2607+#endif
2608+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
2609+ caitsith_exports.vfsmount_lock = probe_vfsmount_lock();
2610+ if (!caitsith_exports.vfsmount_lock)
2611+ goto out;
2612+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
2613+ caitsith_exports.__d_path = probe___d_path();
2614+ if (!caitsith_exports.__d_path)
2615+ goto out;
2616+#else
2617+ caitsith_exports.d_absolute_path = probe_d_absolute_path();
2618+ if (!caitsith_exports.d_absolute_path)
2619+ goto out;
2620+#endif
32062621 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
32072622 {
32082623 int idx;
@@ -3221,6 +2636,8 @@
32212636 cs_init_module();
32222637 cs_update_security_ops(ops);
32232638 return 0;
2639+out:
2640+ return -EINVAL;
32242641 }
32252642
32262643 module_init(cs_init);
@@ -3318,11 +2735,11 @@
33182735 * security_prepare_creds().
33192736 *
33202737 * If current->in_execve is not set but ptr->cs_flags has
3321- * CS_TASK_STARTED_EXECVE set, it indicates that do_execve()
2738+ * CS_TASK_IS_IN_EXECVE set, it indicates that do_execve()
33222739 * has failed and reverting domain transition is needed.
33232740 */
33242741 if (task == current &&
3325- (ptr->cs_flags & CS_TASK_STARTED_EXECVE) &&
2742+ (ptr->cs_flags & CS_TASK_IS_IN_EXECVE) &&
33262743 !current->in_execve) {
33272744 #ifdef CONFIG_CAITSITH_DEBUG
33282745 static bool done;
@@ -3480,7 +2897,7 @@
34802897 */
34812898 static void cs_task_security_gc(void)
34822899 {
3483- static DEFINE_MUTEX(lock);
2900+ static DEFINE_SPINLOCK(lock);
34842901 static atomic_t gc_counter = ATOMIC_INIT(0);
34852902 unsigned int idx;
34862903 /*
@@ -3495,7 +2912,7 @@
34952912 atomic_inc_return(&gc_counter) < 1024)
34962913 return;
34972914 atomic_set(&gc_counter, 0);
3498- if (mutex_lock_interruptible(&lock))
2915+ if (!spin_trylock(&lock))
34992916 return;
35002917 rcu_read_lock();
35012918 for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) {
@@ -3508,7 +2925,7 @@
35082925 }
35092926 }
35102927 rcu_read_unlock();
3511- mutex_unlock(&lock);
2928+ spin_unlock(&lock);
35122929 }
35132930
35142931 #endif
--- trunk/caitsith-patch/caitsith/mclsm.c (nonexistent)
+++ trunk/caitsith-patch/caitsith/mclsm.c (revision 81)
@@ -0,0 +1,1571 @@
1+/*
2+ * mclsm.c
3+ *
4+ * Copyright (C) 2010-2013 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+ *
6+ * Version: 0.1.8 2013/01/06
7+ */
8+
9+#include "caitsith.h"
10+#include "probe.h"
11+
12+/* Prototype definition. */
13+static void cs_task_security_gc(void);
14+static int cs_copy_cred_security(const struct cred *new,
15+ const struct cred *old, gfp_t gfp);
16+static struct cs_security *cs_find_cred_security(const struct cred *cred);
17+static DEFINE_SPINLOCK(cs_task_security_list_lock);
18+static atomic_t cs_in_execve_tasks = ATOMIC_INIT(0);
19+/*
20+ * List of "struct cs_security" for "struct pid".
21+ *
22+ * All instances on this list is guaranteed that "struct cs_security"->pid !=
23+ * NULL. Also, instances on this list that are in execve() are guaranteed that
24+ * "struct cs_security"->cred remembers "struct linux_binprm"->cred with a
25+ * refcount on "struct linux_binprm"->cred.
26+ */
27+struct list_head cs_task_security_list[CS_MAX_TASK_SECURITY_HASH];
28+/*
29+ * List of "struct cs_security" for "struct cred".
30+ *
31+ * Since the number of "struct cred" is nearly equals to the number of
32+ * "struct pid", we allocate hash tables like cs_task_security_list.
33+ *
34+ * All instances on this list are guaranteed that "struct cs_security"->pid ==
35+ * NULL and "struct cs_security"->cred != NULL.
36+ */
37+static struct list_head cs_cred_security_list[CS_MAX_TASK_SECURITY_HASH];
38+
39+/* Dummy security context for avoiding NULL pointer dereference. */
40+static struct cs_security cs_oom_security = {
41+ .cs_domain_info = &cs_kernel_domain
42+};
43+
44+/* Dummy security context for avoiding NULL pointer dereference. */
45+static struct cs_security cs_default_security = {
46+ .cs_domain_info = &cs_kernel_domain
47+};
48+
49+/* For exporting variables and functions. */
50+struct caitsith_exports caitsith_exports;
51+
52+/* Original hooks. */
53+static struct security_operations original_security_ops;
54+
55+/**
56+ * cs_clear_execve - Release memory used by do_execve().
57+ *
58+ * @ret: 0 if do_execve() succeeded, negative value otherwise.
59+ * @security: Pointer to "struct cs_security".
60+ *
61+ * Returns nothing.
62+ */
63+static void cs_clear_execve(int ret, struct cs_security *security)
64+{
65+ struct cs_request_info *r;
66+ if (security == &cs_default_security || security == &cs_oom_security)
67+ return;
68+ r = security->r;
69+ security->r = NULL;
70+ if (!r)
71+ return;
72+ atomic_dec(&cs_in_execve_tasks);
73+ cs_finish_execve(ret, r);
74+}
75+
76+/**
77+ * cs_rcu_free - RCU callback for releasing "struct cs_security".
78+ *
79+ * @rcu: Pointer to "struct rcu_head".
80+ *
81+ * Returns nothing.
82+ */
83+static void cs_rcu_free(struct rcu_head *rcu)
84+{
85+ struct cs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
86+ struct cs_request_info *r = ptr->r;
87+ /*
88+ * If this security context was associated with "struct pid" and
89+ * ptr->cs_flags has CS_TASK_IS_IN_EXECVE set, it indicates that a
90+ * "struct task_struct" associated with this security context exited
91+ * immediately after do_execve() has failed.
92+ */
93+ if (ptr->pid && (ptr->cs_flags & CS_TASK_IS_IN_EXECVE)) {
94+#ifdef CONFIG_CAITSITH_DEBUG
95+ static bool done;
96+ if (!done) {
97+ printk(KERN_INFO "CAITSITH: Decrementing "
98+ "cs_in_execve_tasks counter "
99+ "because some \"struct task_struct\" has "
100+ "exit()ed immediately after do_execve() has "
101+ "failed.\n");
102+ done = true;
103+ }
104+#endif
105+ atomic_dec(&cs_in_execve_tasks);
106+ }
107+ /*
108+ * If this security context was associated with "struct pid",
109+ * drop refcount obtained by get_pid() in cs_find_task_security().
110+ */
111+ if (ptr->pid) {
112+#ifdef CONFIG_CAITSITH_DEBUG
113+ static bool done;
114+ if (!done) {
115+ printk(KERN_INFO "CAITSITH: Dropping refcount on "
116+ "\"struct pid\".\n");
117+ done = true;
118+ }
119+#endif
120+ put_pid(ptr->pid);
121+ }
122+ if (r) {
123+#ifdef CONFIG_CAITSITH_DEBUG
124+ static bool done;
125+ if (!done) {
126+ printk(KERN_INFO "CAITSITH: Releasing memory in "
127+ "\"struct cs_execve\" because some "
128+ "\"struct task_struct\" has exit()ed "
129+ "immediately after do_execve() has failed.\n");
130+ done = true;
131+ }
132+#endif
133+ kfree(r->handler_path);
134+ kfree(r);
135+ }
136+ kfree(ptr);
137+}
138+
139+/**
140+ * cs_del_security - Release "struct cs_security".
141+ *
142+ * @ptr: Pointer to "struct cs_security".
143+ *
144+ * Returns nothing.
145+ */
146+static void cs_del_security(struct cs_security *ptr)
147+{
148+ unsigned long flags;
149+ if (ptr == &cs_default_security || ptr == &cs_oom_security)
150+ return;
151+ spin_lock_irqsave(&cs_task_security_list_lock, flags);
152+ list_del_rcu(&ptr->list);
153+ spin_unlock_irqrestore(&cs_task_security_list_lock, flags);
154+ call_rcu(&ptr->rcu, cs_rcu_free);
155+}
156+
157+/**
158+ * cs_add_cred_security - Add "struct cs_security" to list.
159+ *
160+ * @ptr: Pointer to "struct cs_security".
161+ *
162+ * Returns nothing.
163+ */
164+static void cs_add_cred_security(struct cs_security *ptr)
165+{
166+ unsigned long flags;
167+ struct list_head *list = &cs_cred_security_list
168+ [hash_ptr((void *) ptr->cred, CS_TASK_SECURITY_HASH_BITS)];
169+#ifdef CONFIG_CAITSITH_DEBUG
170+ if (ptr->pid)
171+ printk(KERN_INFO "CAITSITH: \"struct cs_security\"->pid != NULL"
172+ "\n");
173+#endif
174+ ptr->pid = NULL;
175+ spin_lock_irqsave(&cs_task_security_list_lock, flags);
176+ list_add_rcu(&ptr->list, list);
177+ spin_unlock_irqrestore(&cs_task_security_list_lock, flags);
178+}
179+
180+/**
181+ * cs_task_create - Make snapshot of security context for new task.
182+ *
183+ * @clone_flags: Flags passed to clone().
184+ *
185+ * Returns 0 on success, negative value otherwise.
186+ */
187+static int cs_task_create(unsigned long clone_flags)
188+{
189+ struct cs_security *old_security;
190+ struct cs_security *new_security;
191+ struct cred *cred = prepare_creds();
192+ if (!cred)
193+ return -ENOMEM;
194+ old_security = cs_find_task_security(current);
195+ new_security = cs_find_cred_security(cred);
196+ new_security->cs_domain_info = old_security->cs_domain_info;
197+ new_security->cs_flags = old_security->cs_flags;
198+ return commit_creds(cred);
199+}
200+
201+/**
202+ * cs_cred_prepare - Allocate memory for new credentials.
203+ *
204+ * @new: Pointer to "struct cred".
205+ * @old: Pointer to "struct cred".
206+ * @gfp: Memory allocation flags.
207+ *
208+ * Returns 0 on success, negative value otherwise.
209+ */
210+static int cs_cred_prepare(struct cred *new, const struct cred *old,
211+ gfp_t gfp)
212+{
213+ int rc1;
214+ /*
215+ * For checking whether reverting domain transition is needed or not.
216+ *
217+ * See cs_find_task_security() for reason.
218+ */
219+ if (gfp == GFP_KERNEL)
220+ cs_find_task_security(current);
221+ rc1 = cs_copy_cred_security(new, old, gfp);
222+ if (gfp == GFP_KERNEL)
223+ cs_task_security_gc();
224+ if (original_security_ops.cred_prepare) {
225+ const int rc2 = original_security_ops.cred_prepare(new, old,
226+ gfp);
227+ if (rc2) {
228+ cs_del_security(cs_find_cred_security(new));
229+ return rc2;
230+ }
231+ }
232+ return rc1;
233+}
234+
235+/**
236+ * cs_cred_free - Release memory used by credentials.
237+ *
238+ * @cred: Pointer to "struct cred".
239+ *
240+ * Returns nothing.
241+ */
242+static void cs_cred_free(struct cred *cred)
243+{
244+ if (original_security_ops.cred_free)
245+ original_security_ops.cred_free(cred);
246+ cs_del_security(cs_find_cred_security(cred));
247+}
248+
249+/**
250+ * cs_alloc_cred_security - Allocate memory for new credentials.
251+ *
252+ * @cred: Pointer to "struct cred".
253+ * @gfp: Memory allocation flags.
254+ *
255+ * Returns 0 on success, negative value otherwise.
256+ */
257+static int cs_alloc_cred_security(const struct cred *cred, gfp_t gfp)
258+{
259+ struct cs_security *new_security = kzalloc(sizeof(*new_security),
260+ gfp);
261+ if (!new_security)
262+ return -ENOMEM;
263+ new_security->cred = cred;
264+ cs_add_cred_security(new_security);
265+ return 0;
266+}
267+
268+/**
269+ * cs_cred_alloc_blank - Allocate memory for new credentials.
270+ *
271+ * @new: Pointer to "struct cred".
272+ * @gfp: Memory allocation flags.
273+ *
274+ * Returns 0 on success, negative value otherwise.
275+ */
276+static int cs_cred_alloc_blank(struct cred *new, gfp_t gfp)
277+{
278+ const int rc1 = cs_alloc_cred_security(new, gfp);
279+ if (original_security_ops.cred_alloc_blank) {
280+ const int rc2 = original_security_ops.cred_alloc_blank(new,
281+ gfp);
282+ if (rc2) {
283+ cs_del_security(cs_find_cred_security(new));
284+ return rc2;
285+ }
286+ }
287+ return rc1;
288+}
289+
290+/**
291+ * cs_cred_transfer - Transfer "struct cs_security" between credentials.
292+ *
293+ * @new: Pointer to "struct cred".
294+ * @old: Pointer to "struct cred".
295+ *
296+ * Returns nothing.
297+ */
298+static void cs_cred_transfer(struct cred *new, const struct cred *old)
299+{
300+ struct cs_security *new_security = cs_find_cred_security(new);
301+ struct cs_security *old_security = cs_find_cred_security(old);
302+ if (new_security == &cs_default_security ||
303+ new_security == &cs_oom_security ||
304+ old_security == &cs_default_security ||
305+ old_security == &cs_oom_security)
306+ return;
307+ new_security->cs_flags = old_security->cs_flags;
308+ new_security->cs_domain_info = old_security->cs_domain_info;
309+}
310+
311+/**
312+ * cs_bprm_committing_creds - A hook which is called when do_execve() succeeded.
313+ *
314+ * @bprm: Pointer to "struct linux_binprm".
315+ *
316+ * Returns nothing.
317+ */
318+static void cs_bprm_committing_creds(struct linux_binprm *bprm)
319+{
320+ struct cs_security *old_security = cs_current_security();
321+ struct cs_security *new_security;
322+ if (old_security == &cs_default_security ||
323+ old_security == &cs_oom_security)
324+ return;
325+ cs_clear_execve(0, old_security);
326+ /* Update current task's cred's domain for future fork(). */
327+ new_security = cs_find_cred_security(bprm->cred);
328+ new_security->cs_flags = old_security->cs_flags;
329+ new_security->cs_domain_info = old_security->cs_domain_info;
330+}
331+
332+#ifndef CONFIG_CAITSITH_OMIT_USERSPACE_LOADER
333+
334+/**
335+ * cs_policy_loader_exists - Check whether /sbin/caitsith-init exists.
336+ *
337+ * Returns true if /sbin/caitsith-init exists, false otherwise.
338+ */
339+static _Bool cs_policy_loader_exists(void)
340+{
341+ struct path path;
342+ if (kern_path(CONFIG_CAITSITH_POLICY_LOADER, LOOKUP_FOLLOW, &path)
343+ == 0) {
344+ path_put(&path);
345+ return 1;
346+ }
347+ printk(KERN_INFO "Not activating CaitSith as %s does not exist.\n",
348+ CONFIG_CAITSITH_POLICY_LOADER);
349+ return 0;
350+}
351+
352+/**
353+ * cs_load_policy - Run external policy loader to load policy.
354+ *
355+ * @filename: The program about to start.
356+ *
357+ * Returns nothing.
358+ *
359+ * This function checks whether @filename is /sbin/init, and if so
360+ * invoke /sbin/caitsith-init and wait for the termination of
361+ * /sbin/caitsith-init and then continues invocation of /sbin/init.
362+ * /sbin/caitsith-init reads policy files in /etc/caitsith/ directory and
363+ * writes to /proc/caitsith/ interfaces.
364+ */
365+static void cs_load_policy(const char *filename)
366+{
367+ static _Bool done;
368+ if (done)
369+ return;
370+ if (strcmp(filename, CONFIG_CAITSITH_ACTIVATION_TRIGGER))
371+ return;
372+ if (!cs_policy_loader_exists())
373+ return;
374+ done = 1;
375+ {
376+ char *argv[2];
377+ char *envp[3];
378+ printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
379+ CONFIG_CAITSITH_POLICY_LOADER);
380+ argv[0] = (char *) CONFIG_CAITSITH_POLICY_LOADER;
381+ argv[1] = NULL;
382+ envp[0] = "HOME=/";
383+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
384+ envp[2] = NULL;
385+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
386+ }
387+ cs_check_profile();
388+}
389+
390+#endif
391+
392+/**
393+ * cs_bprm_check_security - Check permission for execve().
394+ *
395+ * @bprm: Pointer to "struct linux_binprm".
396+ *
397+ * Returns 0 on success, negative value otherwise.
398+ */
399+static int cs_bprm_check_security(struct linux_binprm *bprm)
400+{
401+ struct cs_security *security = cs_current_security();
402+ int rc;
403+ if (security == &cs_default_security || security == &cs_oom_security)
404+ return -ENOMEM;
405+ if (security->r)
406+ return 0;
407+#ifndef CONFIG_CAITSITH_OMIT_USERSPACE_LOADER
408+ if (!cs_policy_loaded)
409+ cs_load_policy(bprm->filename);
410+#endif
411+ rc = cs_start_execve(bprm, &security->r);
412+ if (security->r)
413+ atomic_inc(&cs_in_execve_tasks);
414+ return rc;
415+}
416+
417+/**
418+ * cs_file_open - Check permission for open().
419+ *
420+ * @f: Pointer to "struct file".
421+ * @cred: Pointer to "struct cred".
422+ *
423+ * Returns 0 on success, negative value otherwise.
424+ */
425+static int cs_file_open(struct file *f, const struct cred *cred)
426+{
427+ return cs_open_permission(f);
428+}
429+
430+#ifdef CONFIG_SECURITY_PATH
431+
432+/**
433+ * cs_path_chown - Check permission for chown()/chgrp().
434+ *
435+ * @path: Pointer to "struct path".
436+ * @user: User ID.
437+ * @group: Group ID.
438+ *
439+ * Returns 0 on success, negative value otherwise.
440+ */
441+static int cs_path_chown(struct path *path, kuid_t user, kgid_t group)
442+{
443+ return cs_chown_permission(path->dentry, path->mnt, user, group);
444+}
445+
446+/**
447+ * cs_path_chmod - Check permission for chmod().
448+ *
449+ * @path: Pointer to "struct path".
450+ * @mode: Mode.
451+ *
452+ * Returns 0 on success, negative value otherwise.
453+ */
454+static int cs_path_chmod(struct path *path, umode_t mode)
455+{
456+ return cs_chmod_permission(path->dentry, path->mnt, mode);
457+}
458+
459+/**
460+ * cs_path_chroot - Check permission for chroot().
461+ *
462+ * @path: Pointer to "struct path".
463+ *
464+ * Returns 0 on success, negative value otherwise.
465+ */
466+static int cs_path_chroot(struct path *path)
467+{
468+ return cs_chroot_permission(path);
469+}
470+
471+/**
472+ * cs_path_truncate - Check permission for truncate().
473+ *
474+ * @path: Pointer to "struct path".
475+ *
476+ * Returns 0 on success, negative value otherwise.
477+ */
478+static int cs_path_truncate(struct path *path)
479+{
480+ return cs_truncate_permission(path->dentry, path->mnt);
481+}
482+
483+#else
484+
485+/**
486+ * cs_inode_setattr - Check permission for chown()/chgrp()/chmod()/truncate().
487+ *
488+ * @dentry: Pointer to "struct dentry".
489+ * @attr: Pointer to "struct iattr".
490+ *
491+ * Returns 0 on success, negative value otherwise.
492+ */
493+static int cs_inode_setattr(struct dentry *dentry, struct iattr *attr)
494+{
495+ const int rc1 = (attr->ia_valid & ATTR_UID) ?
496+ cs_chown_permission(dentry, NULL, attr->ia_uid, INVALID_GID) :
497+ 0;
498+ const int rc2 = (attr->ia_valid & ATTR_GID) ?
499+ cs_chown_permission(dentry, NULL, INVALID_UID, attr->ia_gid) :
500+ 0;
501+ const int rc3 = (attr->ia_valid & ATTR_MODE) ?
502+ cs_chmod_permission(dentry, NULL, attr->ia_mode) : 0;
503+ const int rc4 = (attr->ia_valid & ATTR_SIZE) ?
504+ cs_truncate_permission(dentry, NULL) : 0;
505+ if (rc4)
506+ return rc4;
507+ if (rc3)
508+ return rc3;
509+ if (rc2)
510+ return rc2;
511+ return rc1;
512+}
513+
514+#endif
515+
516+/**
517+ * cs_inode_getattr - Check permission for stat().
518+ *
519+ * @mnt: Pointer to "struct vfsmount".
520+ * @dentry: Pointer to "struct dentry".
521+ *
522+ * Returns 0 on success, negative value otherwise.
523+ */
524+static int cs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
525+{
526+ return cs_getattr_permission(mnt, dentry);
527+}
528+
529+#ifdef CONFIG_SECURITY_PATH
530+
531+/**
532+ * cs_path_mknod - Check permission for mknod().
533+ *
534+ * @dir: Pointer to "struct path".
535+ * @dentry: Pointer to "struct dentry".
536+ * @mode: Create mode.
537+ * @dev: Device major/minor number.
538+ *
539+ * Returns 0 on success, negative value otherwise.
540+ */
541+static int cs_path_mknod(struct path *dir, struct dentry *dentry,
542+ umode_t mode, unsigned int dev)
543+{
544+ return cs_mknod_permission(dentry, dir->mnt, mode, dev);
545+}
546+
547+/**
548+ * cs_path_mkdir - Check permission for mkdir().
549+ *
550+ * @dir: Pointer to "struct path".
551+ * @dentry: Pointer to "struct dentry".
552+ * @mode: Create mode.
553+ *
554+ * Returns 0 on success, negative value otherwise.
555+ */
556+static int cs_path_mkdir(struct path *dir, struct dentry *dentry,
557+ umode_t mode)
558+{
559+ return cs_mkdir_permission(dentry, dir->mnt, mode);
560+}
561+
562+/**
563+ * cs_path_rmdir - Check permission for rmdir().
564+ *
565+ * @dir: Pointer to "struct path".
566+ * @dentry: Pointer to "struct dentry".
567+ *
568+ * Returns 0 on success, negative value otherwise.
569+ */
570+static int cs_path_rmdir(struct path *dir, struct dentry *dentry)
571+{
572+ return cs_rmdir_permission(dentry, dir->mnt);
573+}
574+
575+/**
576+ * cs_path_unlink - Check permission for unlink().
577+ *
578+ * @dir: Pointer to "struct path".
579+ * @dentry: Pointer to "struct dentry".
580+ *
581+ * Returns 0 on success, negative value otherwise.
582+ */
583+static int cs_path_unlink(struct path *dir, struct dentry *dentry)
584+{
585+ return cs_unlink_permission(dentry, dir->mnt);
586+}
587+
588+/**
589+ * cs_path_symlink - Check permission for symlink().
590+ *
591+ * @dir: Pointer to "struct path".
592+ * @dentry: Pointer to "struct dentry".
593+ * @old_name: Content of symbolic link.
594+ *
595+ * Returns 0 on success, negative value otherwise.
596+ */
597+static int cs_path_symlink(struct path *dir, struct dentry *dentry,
598+ const char *old_name)
599+{
600+ return cs_symlink_permission(dentry, dir->mnt, old_name);
601+}
602+
603+/**
604+ * cs_path_rename - Check permission for rename().
605+ *
606+ * @old_dir: Pointer to "struct path".
607+ * @old_dentry: Pointer to "struct dentry".
608+ * @new_dir: Pointer to "struct path".
609+ * @new_dentry: Pointer to "struct dentry".
610+ *
611+ * Returns 0 on success, negative value otherwise.
612+ */
613+static int cs_path_rename(struct path *old_dir, struct dentry *old_dentry,
614+ struct path *new_dir, struct dentry *new_dentry)
615+{
616+ return cs_rename_permission(old_dentry, new_dentry, old_dir->mnt);
617+}
618+
619+/**
620+ * cs_path_link - Check permission for link().
621+ *
622+ * @old_dentry: Pointer to "struct dentry".
623+ * @new_dir: Pointer to "struct path".
624+ * @new_dentry: Pointer to "struct dentry".
625+ *
626+ * Returns 0 on success, negative value otherwise.
627+ */
628+static int cs_path_link(struct dentry *old_dentry, struct path *new_dir,
629+ struct dentry *new_dentry)
630+{
631+ return cs_link_permission(old_dentry, new_dentry, new_dir->mnt);
632+}
633+
634+#else
635+
636+/**
637+ * cs_inode_mknod - Check permission for mknod().
638+ *
639+ * @dir: Pointer to "struct inode".
640+ * @dentry: Pointer to "struct dentry".
641+ * @mode: Create mode.
642+ * @dev: Device major/minor number.
643+ *
644+ * Returns 0 on success, negative value otherwise.
645+ */
646+static int cs_inode_mknod(struct inode *dir, struct dentry *dentry,
647+ umode_t mode, dev_t dev)
648+{
649+ return cs_mknod_permission(dentry, NULL, mode, dev);
650+}
651+
652+/**
653+ * cs_inode_mkdir - Check permission for mkdir().
654+ *
655+ * @dir: Pointer to "struct inode".
656+ * @dentry: Pointer to "struct dentry".
657+ * @mode: Create mode.
658+ *
659+ * Returns 0 on success, negative value otherwise.
660+ */
661+static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry,
662+ umode_t mode)
663+{
664+ return cs_mkdir_permission(dentry, NULL, mode);
665+}
666+
667+/**
668+ * cs_inode_rmdir - Check permission for rmdir().
669+ *
670+ * @dir: Pointer to "struct inode".
671+ * @dentry: Pointer to "struct dentry".
672+ *
673+ * Returns 0 on success, negative value otherwise.
674+ */
675+static int cs_inode_rmdir(struct inode *dir, struct dentry *dentry)
676+{
677+ return cs_rmdir_permission(dentry, NULL);
678+}
679+
680+/**
681+ * cs_inode_unlink - Check permission for unlink().
682+ *
683+ * @dir: Pointer to "struct inode".
684+ * @dentry: Pointer to "struct dentry".
685+ *
686+ * Returns 0 on success, negative value otherwise.
687+ */
688+static int cs_inode_unlink(struct inode *dir, struct dentry *dentry)
689+{
690+ return cs_unlink_permission(dentry, NULL);
691+}
692+
693+/**
694+ * cs_inode_symlink - Check permission for symlink().
695+ *
696+ * @dir: Pointer to "struct inode".
697+ * @dentry: Pointer to "struct dentry".
698+ * @old_name: Content of symbolic link.
699+ *
700+ * Returns 0 on success, negative value otherwise.
701+ */
702+static int cs_inode_symlink(struct inode *dir, struct dentry *dentry,
703+ const char *old_name)
704+{
705+ return cs_symlink_permission(dentry, NULL, old_name);
706+}
707+
708+/**
709+ * cs_inode_rename - Check permission for rename().
710+ *
711+ * @old_dir: Pointer to "struct inode".
712+ * @old_dentry: Pointer to "struct dentry".
713+ * @new_dir: Pointer to "struct inode".
714+ * @new_dentry: Pointer to "struct dentry".
715+ *
716+ * Returns 0 on success, negative value otherwise.
717+ */
718+static int cs_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
719+ struct inode *new_dir, struct dentry *new_dentry)
720+{
721+ return cs_rename_permission(old_dentry, new_dentry, NULL);
722+}
723+
724+/**
725+ * cs_inode_link - Check permission for link().
726+ *
727+ * @old_dentry: Pointer to "struct dentry".
728+ * @dir: Pointer to "struct inode".
729+ * @new_dentry: Pointer to "struct dentry".
730+ *
731+ * Returns 0 on success, negative value otherwise.
732+ */
733+static int cs_inode_link(struct dentry *old_dentry, struct inode *dir,
734+ struct dentry *new_dentry)
735+{
736+ return cs_link_permission(old_dentry, new_dentry, NULL);
737+}
738+
739+/**
740+ * cs_inode_create - Check permission for creat().
741+ *
742+ * @dir: Pointer to "struct inode".
743+ * @dentry: Pointer to "struct dentry".
744+ * @mode: Create mode.
745+ *
746+ * Returns 0 on success, negative value otherwise.
747+ */
748+static int cs_inode_create(struct inode *dir, struct dentry *dentry,
749+ umode_t mode)
750+{
751+ return cs_mknod_permission(dentry, NULL, mode, 0);
752+}
753+
754+#endif
755+
756+#ifdef CONFIG_SECURITY_NETWORK
757+
758+#include <net/sock.h>
759+
760+/* Structure for remembering an accept()ed socket's status. */
761+struct cs_socket_tag {
762+ struct list_head list;
763+ struct inode *inode;
764+ int status;
765+ struct rcu_head rcu;
766+};
767+
768+/*
769+ * List for managing accept()ed sockets.
770+ * Since we don't need to keep an accept()ed socket into this list after
771+ * once the permission was granted, the number of entries in this list is
772+ * likely small. Therefore, we don't use hash tables.
773+ */
774+static LIST_HEAD(cs_accepted_socket_list);
775+/* Lock for protecting cs_accepted_socket_list . */
776+static DEFINE_SPINLOCK(cs_accepted_socket_list_lock);
777+
778+/**
779+ * cs_socket_rcu_free - RCU callback for releasing "struct cs_socket_tag".
780+ *
781+ * @rcu: Pointer to "struct rcu_head".
782+ *
783+ * Returns nothing.
784+ */
785+static void cs_socket_rcu_free(struct rcu_head *rcu)
786+{
787+ struct cs_socket_tag *ptr = container_of(rcu, typeof(*ptr), rcu);
788+ kfree(ptr);
789+}
790+
791+/**
792+ * cs_update_socket_tag - Update tag associated with accept()ed sockets.
793+ *
794+ * @inode: Pointer to "struct inode".
795+ * @status: New status.
796+ *
797+ * Returns nothing.
798+ *
799+ * If @status == 0, memory for that socket will be released after RCU grace
800+ * period.
801+ */
802+static void cs_update_socket_tag(struct inode *inode, int status)
803+{
804+ struct cs_socket_tag *ptr;
805+ /*
806+ * Protect whole section because multiple threads may call this
807+ * function with same "sock" via cs_validate_socket().
808+ */
809+ spin_lock(&cs_accepted_socket_list_lock);
810+ rcu_read_lock();
811+ list_for_each_entry_rcu(ptr, &cs_accepted_socket_list, list) {
812+ if (ptr->inode != inode)
813+ continue;
814+ ptr->status = status;
815+ if (status)
816+ break;
817+ list_del_rcu(&ptr->list);
818+ call_rcu(&ptr->rcu, cs_socket_rcu_free);
819+ break;
820+ }
821+ rcu_read_unlock();
822+ spin_unlock(&cs_accepted_socket_list_lock);
823+}
824+
825+/**
826+ * cs_validate_socket - Check post accept() permission if needed.
827+ *
828+ * @sock: Pointer to "struct socket".
829+ *
830+ * Returns 0 on success, negative value otherwise.
831+ */
832+static int cs_validate_socket(struct socket *sock)
833+{
834+ struct inode *inode = SOCK_INODE(sock);
835+ struct cs_socket_tag *ptr;
836+ int ret = 0;
837+ rcu_read_lock();
838+ list_for_each_entry_rcu(ptr, &cs_accepted_socket_list, list) {
839+ if (ptr->inode != inode)
840+ continue;
841+ ret = ptr->status;
842+ break;
843+ }
844+ rcu_read_unlock();
845+ if (ret <= 0)
846+ /*
847+ * This socket is not an accept()ed socket or this socket is
848+ * an accept()ed socket and post accept() permission is done.
849+ */
850+ return ret;
851+ /*
852+ * Check post accept() permission now.
853+ *
854+ * Strictly speaking, we need to pass both listen()ing socket and
855+ * accept()ed socket to __cs_socket_post_accept_permission().
856+ * But since socket's family and type are same for both sockets,
857+ * passing the accept()ed socket in place for the listen()ing socket
858+ * will work.
859+ */
860+ ret = cs_socket_post_accept_permission(sock, sock);
861+ /*
862+ * If permission was granted, we forget that this is an accept()ed
863+ * socket. Otherwise, we remember that this socket needs to return
864+ * error for subsequent socketcalls.
865+ */
866+ cs_update_socket_tag(inode, ret);
867+ return ret;
868+}
869+
870+/**
871+ * cs_socket_accept - Check permission for accept().
872+ *
873+ * @sock: Pointer to "struct socket".
874+ * @newsock: Pointer to "struct socket".
875+ *
876+ * Returns 0 on success, negative value otherwise.
877+ *
878+ * This hook is used for setting up environment for doing post accept()
879+ * permission check. If dereferencing sock->ops->something() were ordered by
880+ * rcu_dereference(), we could replace sock->ops with "a copy of original
881+ * sock->ops with modified sock->ops->accept()" using rcu_assign_pointer()
882+ * in order to do post accept() permission check before returning to userspace.
883+ * If we make the copy in security_socket_post_create(), it would be possible
884+ * to safely replace sock->ops here, but we don't do so because we don't want
885+ * to allocate memory for sockets which do not call sock->ops->accept().
886+ * Therefore, we do post accept() permission check upon next socket syscalls
887+ * rather than between sock->ops->accept() and returning to userspace.
888+ * This means that if a socket was close()d before calling some socket
889+ * syscalls, post accept() permission check will not be done.
890+ */
891+static int cs_socket_accept(struct socket *sock, struct socket *newsock)
892+{
893+ struct cs_socket_tag *ptr;
894+ const int rc = cs_validate_socket(sock);
895+ if (rc < 0)
896+ return rc;
897+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
898+ if (!ptr)
899+ return -ENOMEM;
900+ /*
901+ * Subsequent LSM hooks will receive "newsock". Therefore, I mark
902+ * "newsock" as "an accept()ed socket but post accept() permission
903+ * check is not done yet" by allocating memory using inode of the
904+ * "newsock" as a search key.
905+ */
906+ ptr->inode = SOCK_INODE(newsock);
907+ ptr->status = 1; /* Check post accept() permission later. */
908+ spin_lock(&cs_accepted_socket_list_lock);
909+ list_add_tail_rcu(&ptr->list, &cs_accepted_socket_list);
910+ spin_unlock(&cs_accepted_socket_list_lock);
911+ return 0;
912+}
913+
914+/**
915+ * cs_socket_listen - Check permission for listen().
916+ *
917+ * @sock: Pointer to "struct socket".
918+ * @backlog: Backlog parameter.
919+ *
920+ * Returns 0 on success, negative value otherwise.
921+ */
922+static int cs_socket_listen(struct socket *sock, int backlog)
923+{
924+ const int rc = cs_validate_socket(sock);
925+ if (rc < 0)
926+ return rc;
927+ return cs_socket_listen_permission(sock);
928+}
929+
930+/**
931+ * cs_socket_connect - Check permission for connect().
932+ *
933+ * @sock: Pointer to "struct socket".
934+ * @addr: Pointer to "struct sockaddr".
935+ * @addr_len: Size of @addr.
936+ *
937+ * Returns 0 on success, negative value otherwise.
938+ */
939+static int cs_socket_connect(struct socket *sock, struct sockaddr *addr,
940+ int addr_len)
941+{
942+ const int rc = cs_validate_socket(sock);
943+ if (rc < 0)
944+ return rc;
945+ return cs_socket_connect_permission(sock, addr, addr_len);
946+}
947+
948+/**
949+ * cs_socket_bind - Check permission for bind().
950+ *
951+ * @sock: Pointer to "struct socket".
952+ * @addr: Pointer to "struct sockaddr".
953+ * @addr_len: Size of @addr.
954+ *
955+ * Returns 0 on success, negative value otherwise.
956+ */
957+static int cs_socket_bind(struct socket *sock, struct sockaddr *addr,
958+ int addr_len)
959+{
960+ const int rc = cs_validate_socket(sock);
961+ if (rc < 0)
962+ return rc;
963+ return cs_socket_bind_permission(sock, addr, addr_len);
964+}
965+
966+/**
967+ * cs_socket_sendmsg - Check permission for sendmsg().
968+ *
969+ * @sock: Pointer to "struct socket".
970+ * @msg: Pointer to "struct msghdr".
971+ * @size: Size of message.
972+ *
973+ * Returns 0 on success, negative value otherwise.
974+ */
975+static int cs_socket_sendmsg(struct socket *sock, struct msghdr *msg,
976+ int size)
977+{
978+ const int rc = cs_validate_socket(sock);
979+ if (rc < 0)
980+ return rc;
981+ return cs_socket_sendmsg_permission(sock, msg, size);
982+}
983+
984+/**
985+ * cs_socket_recvmsg - Check permission for recvmsg().
986+ *
987+ * @sock: Pointer to "struct socket".
988+ * @msg: Pointer to "struct msghdr".
989+ * @size: Size of message.
990+ * @flags: Flags.
991+ *
992+ * Returns 0 on success, negative value otherwise.
993+ */
994+static int cs_socket_recvmsg(struct socket *sock, struct msghdr *msg,
995+ int size, int flags)
996+{
997+ return cs_validate_socket(sock);
998+}
999+
1000+/**
1001+ * cs_socket_getsockname - Check permission for getsockname().
1002+ *
1003+ * @sock: Pointer to "struct socket".
1004+ *
1005+ * Returns 0 on success, negative value otherwise.
1006+ */
1007+static int cs_socket_getsockname(struct socket *sock)
1008+{
1009+ return cs_validate_socket(sock);
1010+}
1011+
1012+/**
1013+ * cs_socket_getpeername - Check permission for getpeername().
1014+ *
1015+ * @sock: Pointer to "struct socket".
1016+ *
1017+ * Returns 0 on success, negative value otherwise.
1018+ */
1019+static int cs_socket_getpeername(struct socket *sock)
1020+{
1021+ return cs_validate_socket(sock);
1022+}
1023+
1024+/**
1025+ * cs_socket_getsockopt - Check permission for getsockopt().
1026+ *
1027+ * @sock: Pointer to "struct socket".
1028+ * @level: Level.
1029+ * @optname: Option's name,
1030+ *
1031+ * Returns 0 on success, negative value otherwise.
1032+ */
1033+static int cs_socket_getsockopt(struct socket *sock, int level, int optname)
1034+{
1035+ return cs_validate_socket(sock);
1036+}
1037+
1038+/**
1039+ * cs_socket_setsockopt - Check permission for setsockopt().
1040+ *
1041+ * @sock: Pointer to "struct socket".
1042+ * @level: Level.
1043+ * @optname: Option's name,
1044+ *
1045+ * Returns 0 on success, negative value otherwise.
1046+ */
1047+static int cs_socket_setsockopt(struct socket *sock, int level, int optname)
1048+{
1049+ return cs_validate_socket(sock);
1050+}
1051+
1052+/**
1053+ * cs_socket_shutdown - Check permission for shutdown().
1054+ *
1055+ * @sock: Pointer to "struct socket".
1056+ * @how: Shutdown mode.
1057+ *
1058+ * Returns 0 on success, negative value otherwise.
1059+ */
1060+static int cs_socket_shutdown(struct socket *sock, int how)
1061+{
1062+ return cs_validate_socket(sock);
1063+}
1064+
1065+#define SOCKFS_MAGIC 0x534F434B
1066+
1067+/**
1068+ * cs_inode_free_security - Release memory associated with an inode.
1069+ *
1070+ * @inode: Pointer to "struct inode".
1071+ *
1072+ * Returns nothing.
1073+ *
1074+ * We use this hook for releasing memory associated with an accept()ed socket.
1075+ */
1076+static void cs_inode_free_security(struct inode *inode)
1077+{
1078+ if (inode->i_sb && inode->i_sb->s_magic == SOCKFS_MAGIC)
1079+ cs_update_socket_tag(inode, 0);
1080+}
1081+
1082+#endif
1083+
1084+/**
1085+ * cs_sb_pivotroot - Check permission for pivot_root().
1086+ *
1087+ * @old_path: Pointer to "struct path".
1088+ * @new_path: Pointer to "struct path".
1089+ *
1090+ * Returns 0 on success, negative value otherwise.
1091+ */
1092+static int cs_sb_pivotroot(struct path *old_path, struct path *new_path)
1093+{
1094+ return cs_pivot_root_permission(old_path, new_path);
1095+}
1096+
1097+/**
1098+ * cs_sb_mount - Check permission for mount().
1099+ *
1100+ * @dev_name: Name of device file.
1101+ * @path: Pointer to "struct path".
1102+ * @type: Name of filesystem type. Maybe NULL.
1103+ * @flags: Mount options.
1104+ * @data_page: Optional data. Maybe NULL.
1105+ *
1106+ * Returns 0 on success, negative value otherwise.
1107+ */
1108+static int cs_sb_mount(const char *dev_name, struct path *path,
1109+ const char *type, unsigned long flags, void *data_page)
1110+{
1111+ return cs_mount_permission(dev_name, path, type, flags, data_page);
1112+}
1113+
1114+/**
1115+ * cs_sb_umount - Check permission for umount().
1116+ *
1117+ * @mnt: Pointer to "struct vfsmount".
1118+ * @flags: Unmount flags.
1119+ *
1120+ * Returns 0 on success, negative value otherwise.
1121+ */
1122+static int cs_sb_umount(struct vfsmount *mnt, int flags)
1123+{
1124+ return cs_umount_permission(mnt, flags);
1125+}
1126+
1127+/**
1128+ * cs_file_fcntl - Check permission for fcntl().
1129+ *
1130+ * @file: Pointer to "struct file".
1131+ * @cmd: Command number.
1132+ * @arg: Value for @cmd.
1133+ *
1134+ * Returns 0 on success, negative value otherwise.
1135+ */
1136+static int cs_file_fcntl(struct file *file, unsigned int cmd,
1137+ unsigned long arg)
1138+{
1139+ return cs_fcntl_permission(file, cmd, arg);
1140+}
1141+
1142+/**
1143+ * cs_file_ioctl - Check permission for ioctl().
1144+ *
1145+ * @filp: Pointer to "struct file".
1146+ * @cmd: Command number.
1147+ * @arg: Value for @cmd.
1148+ *
1149+ * Returns 0 on success, negative value otherwise.
1150+ */
1151+static int cs_file_ioctl(struct file *filp, unsigned int cmd,
1152+ unsigned long arg)
1153+{
1154+ return cs_ioctl_permission(filp, cmd, arg);
1155+}
1156+
1157+static struct security_operations caitsith_security_ops = {
1158+ .name = "caitsith",
1159+ .task_create = cs_task_create,
1160+ .cred_prepare = cs_cred_prepare,
1161+ .cred_free = cs_cred_free,
1162+ .cred_alloc_blank = cs_cred_alloc_blank,
1163+ .cred_transfer = cs_cred_transfer,
1164+ .bprm_check_security = cs_bprm_check_security,
1165+ .bprm_committing_creds = cs_bprm_committing_creds,
1166+ .file_open = cs_file_open,
1167+ .file_fcntl = cs_file_fcntl,
1168+ .file_ioctl = cs_file_ioctl,
1169+ .sb_pivotroot = cs_sb_pivotroot,
1170+ .sb_mount = cs_sb_mount,
1171+ .sb_umount = cs_sb_umount,
1172+#ifdef CONFIG_SECURITY_PATH
1173+ .path_mknod = cs_path_mknod,
1174+ .path_mkdir = cs_path_mkdir,
1175+ .path_rmdir = cs_path_rmdir,
1176+ .path_unlink = cs_path_unlink,
1177+ .path_symlink = cs_path_symlink,
1178+ .path_rename = cs_path_rename,
1179+ .path_link = cs_path_link,
1180+ .path_truncate = cs_path_truncate,
1181+ .path_chmod = cs_path_chmod,
1182+ .path_chown = cs_path_chown,
1183+ .path_chroot = cs_path_chroot,
1184+#else
1185+ .inode_mknod = cs_inode_mknod,
1186+ .inode_mkdir = cs_inode_mkdir,
1187+ .inode_rmdir = cs_inode_rmdir,
1188+ .inode_unlink = cs_inode_unlink,
1189+ .inode_symlink = cs_inode_symlink,
1190+ .inode_rename = cs_inode_rename,
1191+ .inode_link = cs_inode_link,
1192+ .inode_create = cs_inode_create,
1193+ .inode_setattr = cs_inode_setattr,
1194+#endif
1195+ .inode_getattr = cs_inode_getattr,
1196+#ifdef CONFIG_SECURITY_NETWORK
1197+ .socket_bind = cs_socket_bind,
1198+ .socket_connect = cs_socket_connect,
1199+ .socket_listen = cs_socket_listen,
1200+ .socket_sendmsg = cs_socket_sendmsg,
1201+ .socket_recvmsg = cs_socket_recvmsg,
1202+ .socket_getsockname = cs_socket_getsockname,
1203+ .socket_getpeername = cs_socket_getpeername,
1204+ .socket_getsockopt = cs_socket_getsockopt,
1205+ .socket_setsockopt = cs_socket_setsockopt,
1206+ .socket_shutdown = cs_socket_shutdown,
1207+ .socket_accept = cs_socket_accept,
1208+ .inode_free_security = cs_inode_free_security,
1209+#endif
1210+};
1211+
1212+#define swap_security_ops(op, lsm_list) \
1213+ do { \
1214+ if (list_empty(&lsm_list[lsm_##op])) \
1215+ add_security_ops(op, lsm_list); \
1216+ else { \
1217+ struct security_operations *ops = \
1218+ container_of(lsm_list, \
1219+ struct security_operations, \
1220+ list[0]); \
1221+ original_security_ops.op = ops->op; \
1222+ smp_wmb(); \
1223+ ops->op = cs_##op; \
1224+ } \
1225+ } while (0)
1226+
1227+#define add_security_ops(op, lsm_list) \
1228+ do { \
1229+ list_add_tail_rcu(&caitsith_security_ops.list[lsm_##op], \
1230+ &lsm_list[lsm_##op]); \
1231+ } while (0)
1232+
1233+/**
1234+ * cs_update_security_ops - Overwrite original "struct security_operations".
1235+ *
1236+ * @lsm_list: Pointer to "struct list_head lsm_hooks[LSM_MAX_HOOKS]".
1237+ *
1238+ * Returns nothing.
1239+ */
1240+static void __init cs_update_security_ops(struct list_head *lsm_list)
1241+{
1242+ /* Security context allocator. */
1243+ swap_security_ops(cred_free, lsm_list);
1244+ swap_security_ops(cred_prepare, lsm_list);
1245+ swap_security_ops(cred_alloc_blank, lsm_list);
1246+ add_security_ops(cred_transfer, lsm_list);
1247+ add_security_ops(task_create, lsm_list);
1248+ /* Security context updater for successful execve(). */
1249+ add_security_ops(bprm_check_security, lsm_list);
1250+ add_security_ops(bprm_committing_creds, lsm_list);
1251+ /* Various permission checker. */
1252+ add_security_ops(file_open, lsm_list);
1253+ add_security_ops(file_fcntl, lsm_list);
1254+ add_security_ops(file_ioctl, lsm_list);
1255+ add_security_ops(sb_pivotroot, lsm_list);
1256+ add_security_ops(sb_mount, lsm_list);
1257+ add_security_ops(sb_umount, lsm_list);
1258+#ifdef CONFIG_SECURITY_PATH
1259+ add_security_ops(path_mknod, lsm_list);
1260+ add_security_ops(path_mkdir, lsm_list);
1261+ add_security_ops(path_rmdir, lsm_list);
1262+ add_security_ops(path_unlink, lsm_list);
1263+ add_security_ops(path_symlink, lsm_list);
1264+ add_security_ops(path_rename, lsm_list);
1265+ add_security_ops(path_link, lsm_list);
1266+ add_security_ops(path_truncate, lsm_list);
1267+ add_security_ops(path_chmod, lsm_list);
1268+ add_security_ops(path_chown, lsm_list);
1269+ add_security_ops(path_chroot, lsm_list);
1270+#else
1271+ add_security_ops(inode_mknod, lsm_list);
1272+ add_security_ops(inode_mkdir, lsm_list);
1273+ add_security_ops(inode_rmdir, lsm_list);
1274+ add_security_ops(inode_unlink, lsm_list);
1275+ add_security_ops(inode_symlink, lsm_list);
1276+ add_security_ops(inode_rename, lsm_list);
1277+ add_security_ops(inode_link, lsm_list);
1278+ add_security_ops(inode_create, lsm_list);
1279+ add_security_ops(inode_setattr, lsm_list);
1280+#endif
1281+ add_security_ops(inode_getattr, lsm_list);
1282+#ifdef CONFIG_SECURITY_NETWORK
1283+ add_security_ops(inode_free_security, lsm_list);
1284+ add_security_ops(socket_bind, lsm_list);
1285+ add_security_ops(socket_connect, lsm_list);
1286+ add_security_ops(socket_listen, lsm_list);
1287+ add_security_ops(socket_sendmsg, lsm_list);
1288+ add_security_ops(socket_recvmsg, lsm_list);
1289+ add_security_ops(socket_getsockname, lsm_list);
1290+ add_security_ops(socket_getpeername, lsm_list);
1291+ add_security_ops(socket_getsockopt, lsm_list);
1292+ add_security_ops(socket_setsockopt, lsm_list);
1293+ add_security_ops(socket_shutdown, lsm_list);
1294+ add_security_ops(socket_accept, lsm_list);
1295+#endif
1296+}
1297+
1298+#undef swap_security_ops
1299+#undef add_security_ops
1300+
1301+/**
1302+ * cs_init - Initialize this module.
1303+ *
1304+ * Returns 0 on success, negative value otherwise.
1305+ */
1306+static int __init cs_init(void)
1307+{
1308+ int idx;
1309+ struct list_head *hooks = probe_lsm_hooks_list();
1310+ if (!hooks)
1311+ goto out;
1312+ caitsith_exports.find_task_by_vpid = probe_find_task_by_vpid();
1313+ if (!caitsith_exports.find_task_by_vpid)
1314+ goto out;
1315+ caitsith_exports.find_task_by_pid_ns = probe_find_task_by_pid_ns();
1316+ if (!caitsith_exports.find_task_by_pid_ns)
1317+ goto out;
1318+ caitsith_exports.d_absolute_path = probe_d_absolute_path();
1319+ if (!caitsith_exports.d_absolute_path)
1320+ goto out;
1321+ for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) {
1322+ INIT_LIST_HEAD(&cs_cred_security_list[idx]);
1323+ INIT_LIST_HEAD(&cs_task_security_list[idx]);
1324+ }
1325+ cs_init_module();
1326+ cs_update_security_ops(hooks);
1327+ printk(KERN_INFO "CAITSITH: 1.0.29 2012/11/04\n");
1328+ printk(KERN_INFO
1329+ "Access Keeping And Regulating Instrument registered.\n");
1330+ return 0;
1331+out:
1332+ return -EINVAL;
1333+}
1334+
1335+module_init(cs_init);
1336+MODULE_LICENSE("GPL");
1337+
1338+/**
1339+ * cs_used_by_cred - Check whether the given domain is in use or not.
1340+ *
1341+ * @domain: Pointer to "struct cs_domain_info".
1342+ *
1343+ * Returns true if @domain is in use, false otherwise.
1344+ *
1345+ * Caller holds rcu_read_lock().
1346+ */
1347+bool cs_used_by_cred(const struct cs_domain_info *domain)
1348+{
1349+ int idx;
1350+ struct cs_security *ptr;
1351+ for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) {
1352+ struct list_head *list = &cs_cred_security_list[idx];
1353+ list_for_each_entry_rcu(ptr, list, list) {
1354+ struct cs_request_info *r = ptr->r;
1355+ if (ptr->cs_domain_info == domain ||
1356+ (r && r->previous_domain == domain)) {
1357+ return true;
1358+ }
1359+ }
1360+ }
1361+ return false;
1362+}
1363+
1364+/**
1365+ * cs_add_task_security - Add "struct cs_security" to list.
1366+ *
1367+ * @ptr: Pointer to "struct cs_security".
1368+ * @list: Pointer to "struct list_head".
1369+ *
1370+ * Returns nothing.
1371+ */
1372+static void cs_add_task_security(struct cs_security *ptr,
1373+ struct list_head *list)
1374+{
1375+ unsigned long flags;
1376+ spin_lock_irqsave(&cs_task_security_list_lock, flags);
1377+ list_add_rcu(&ptr->list, list);
1378+ spin_unlock_irqrestore(&cs_task_security_list_lock, flags);
1379+}
1380+
1381+/**
1382+ * cs_find_task_security - Find "struct cs_security" for given task.
1383+ *
1384+ * @task: Pointer to "struct task_struct".
1385+ *
1386+ * Returns pointer to "struct cs_security" on success, &cs_oom_security on
1387+ * out of memory, &cs_default_security otherwise.
1388+ *
1389+ * If @task is current thread and "struct cs_security" for current thread was
1390+ * not found, I try to allocate it. But if allocation failed, current thread
1391+ * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL
1392+ * won't work.
1393+ */
1394+struct cs_security *cs_find_task_security(const struct task_struct *task)
1395+{
1396+ struct cs_security *ptr;
1397+ struct list_head *list = &cs_task_security_list
1398+ [hash_ptr((void *) task, CS_TASK_SECURITY_HASH_BITS)];
1399+ /* Make sure INIT_LIST_HEAD() in cs_mm_init() takes effect. */
1400+ while (!list->next);
1401+ rcu_read_lock();
1402+ list_for_each_entry_rcu(ptr, list, list) {
1403+ if (ptr->pid != task->pids[PIDTYPE_PID].pid)
1404+ continue;
1405+ rcu_read_unlock();
1406+ /*
1407+ * Current thread needs to transit from old domain to new
1408+ * domain before do_execve() succeeds in order to check
1409+ * permission for interpreters and environment variables using
1410+ * new domain's ACL rules. The domain transition has to be
1411+ * visible from other CPU in order to allow interactive
1412+ * enforcing mode. Also, the domain transition has to be
1413+ * reverted if do_execve() failed. However, an LSM hook for
1414+ * reverting domain transition is missing.
1415+ *
1416+ * security_prepare_creds() is called from prepare_creds() from
1417+ * prepare_bprm_creds() from do_execve() before setting
1418+ * current->in_execve flag, and current->in_execve flag is
1419+ * cleared by the time next do_execve() request starts.
1420+ * This means that we can emulate the missing LSM hook for
1421+ * reverting domain transition, by calling this function from
1422+ * security_prepare_creds().
1423+ *
1424+ * If current->in_execve is not set but ptr->cs_flags has
1425+ * CS_TASK_IS_IN_EXECVE set, it indicates that do_execve()
1426+ * has failed and reverting domain transition is needed.
1427+ */
1428+ if (task == current &&
1429+ (ptr->cs_flags & CS_TASK_IS_IN_EXECVE) &&
1430+ !current->in_execve) {
1431+#ifdef CONFIG_CAITSITH_DEBUG
1432+ static bool done;
1433+ if (!done) {
1434+ printk(KERN_INFO "CAITSITH: Reverting domain "
1435+ "transition because do_execve() has "
1436+ "failed.\n");
1437+ done = true;
1438+ }
1439+#endif
1440+ cs_clear_execve(-1, ptr);
1441+ }
1442+ return ptr;
1443+ }
1444+ rcu_read_unlock();
1445+ if (task != current) {
1446+ /*
1447+ * If a thread does nothing after fork(), caller will reach
1448+ * here because "struct cs_security" for that thread is not
1449+ * yet allocated. But that thread is keeping a snapshot of
1450+ * "struct cs_security" taken as of cs_task_create()
1451+ * associated with that thread's "struct cred".
1452+ *
1453+ * Since that snapshot will be used as initial data when that
1454+ * thread allocates "struct cs_security" for that thread, we
1455+ * can return that snapshot rather than &cs_default_security.
1456+ *
1457+ * Since this function is called by only cs_select_one() and
1458+ * cs_read_pid() (via cs_task_domain() and cs_task_flags()),
1459+ * it is guaranteed that caller has called rcu_read_lock()
1460+ * (via cs_tasklist_lock()) before finding this thread and
1461+ * this thread is valid. Therefore, we can do __task_cred(task)
1462+ * like get_robust_list() does.
1463+ */
1464+ return cs_find_cred_security(__task_cred(task));
1465+ }
1466+ /* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */
1467+ ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC);
1468+ if (!ptr) {
1469+ printk(KERN_WARNING "Unable to allocate memory for pid=%u\n",
1470+ task->pid);
1471+ send_sig(SIGKILL, current, 0);
1472+ return &cs_oom_security;
1473+ }
1474+ *ptr = *cs_find_cred_security(task->cred);
1475+ /* We can shortcut because task == current. */
1476+ ptr->pid = get_pid(((struct task_struct *) task)->
1477+ pids[PIDTYPE_PID].pid);
1478+ ptr->cred = NULL;
1479+ cs_add_task_security(ptr, list);
1480+ return ptr;
1481+}
1482+
1483+/**
1484+ * cs_copy_cred_security - Allocate memory for new credentials.
1485+ *
1486+ * @new: Pointer to "struct cred".
1487+ * @old: Pointer to "struct cred".
1488+ * @gfp: Memory allocation flags.
1489+ *
1490+ * Returns 0 on success, negative value otherwise.
1491+ */
1492+static int cs_copy_cred_security(const struct cred *new,
1493+ const struct cred *old, gfp_t gfp)
1494+{
1495+ struct cs_security *old_security = cs_find_cred_security(old);
1496+ struct cs_security *new_security =
1497+ kzalloc(sizeof(*new_security), gfp);
1498+ if (!new_security)
1499+ return -ENOMEM;
1500+ *new_security = *old_security;
1501+ new_security->cred = new;
1502+ cs_add_cred_security(new_security);
1503+ return 0;
1504+}
1505+
1506+/**
1507+ * cs_find_cred_security - Find "struct cs_security" for given credential.
1508+ *
1509+ * @cred: Pointer to "struct cred".
1510+ *
1511+ * Returns pointer to "struct cs_security" on success, &cs_default_security
1512+ * otherwise.
1513+ */
1514+static struct cs_security *cs_find_cred_security(const struct cred *cred)
1515+{
1516+ struct cs_security *ptr;
1517+ struct list_head *list = &cs_cred_security_list
1518+ [hash_ptr((void *) cred, CS_TASK_SECURITY_HASH_BITS)];
1519+ rcu_read_lock();
1520+ list_for_each_entry_rcu(ptr, list, list) {
1521+ if (ptr->cred != cred)
1522+ continue;
1523+ rcu_read_unlock();
1524+ return ptr;
1525+ }
1526+ rcu_read_unlock();
1527+ return &cs_default_security;
1528+}
1529+
1530+/**
1531+ * cs_task_security_gc - Do garbage collection for "struct task_struct".
1532+ *
1533+ * Returns nothing.
1534+ *
1535+ * Since security_task_free_security() is missing, I can't release memory
1536+ * associated with "struct task_struct" when a task dies. Therefore, I hold
1537+ * a reference on "struct pid" and runs garbage collection when associated
1538+ * "struct task_struct" has gone.
1539+ */
1540+static void cs_task_security_gc(void)
1541+{
1542+ static DEFINE_SPINLOCK(lock);
1543+ static atomic_t gc_counter = ATOMIC_INIT(0);
1544+ unsigned int idx;
1545+ /*
1546+ * If some process is doing execve(), try to garbage collection now.
1547+ * We should kfree() memory associated with "struct cs_security"->r
1548+ * as soon as execve() has completed in order to compensate for lack of
1549+ * security_bprm_free() and security_task_free() hooks.
1550+ *
1551+ * Otherwise, reduce frequency for performance reason.
1552+ */
1553+ if (!atomic_read(&cs_in_execve_tasks) &&
1554+ atomic_inc_return(&gc_counter) < 1024)
1555+ return;
1556+ atomic_set(&gc_counter, 0);
1557+ if (!spin_trylock(&lock))
1558+ return;
1559+ rcu_read_lock();
1560+ for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) {
1561+ struct cs_security *ptr;
1562+ struct list_head *list = &cs_task_security_list[idx];
1563+ list_for_each_entry_rcu(ptr, list, list) {
1564+ if (pid_task(ptr->pid, PIDTYPE_PID))
1565+ continue;
1566+ cs_del_security(ptr);
1567+ }
1568+ }
1569+ rcu_read_unlock();
1570+ spin_unlock(&lock);
1571+}
--- trunk/caitsith-patch/caitsith/Makefile (revision 80)
+++ trunk/caitsith-patch/caitsith/Makefile (revision 81)
@@ -1,4 +1,10 @@
1-caitsith-objs := permission.o gc.o policy_io.o realpath.o lsm.o
1+caitsith-objs := permission.o gc.o policy_io.o realpath.o probe.o
2+ifdef CONFIG_SECURITY_COMPOSER_MAX
3+caitsith-objs += mclsm.o
4+else
5+caitsith-objs += lsm.o
6+endif
7+caitsith_test-objs := test.o probe.o
28 obj-m += caitsith_test.o caitsith.o
39
410 $(obj)/policy/policy.conf:
--- trunk/caitsith-patch/caitsith/probe.h (nonexistent)
+++ trunk/caitsith-patch/caitsith/probe.h (revision 81)
@@ -0,0 +1,45 @@
1+#include <linux/version.h>
2+#include <linux/module.h>
3+#include <linux/sched.h>
4+#include <linux/dcache.h>
5+#include <linux/mount.h>
6+#include <linux/namei.h>
7+#include <linux/fs.h>
8+#include <linux/security.h>
9+
10+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
11+#error This module supports only 2.6.0 and later kernels.
12+#endif
13+#ifndef CONFIG_SECURITY
14+#error You must choose CONFIG_SECURITY=y for building this module.
15+#endif
16+#ifndef CONFIG_KALLSYMS
17+#error You must choose CONFIG_KALLSYMS=y for building this module.
18+#endif
19+#ifndef CONFIG_PROC_FS
20+#error You must choose CONFIG_PROC_FS=y for building this module.
21+#endif
22+#ifndef CONFIG_MODULES
23+#error You must choose CONFIG_MODULES=y for building this module.
24+#endif
25+
26+#if defined(CONFIG_SECURITY_COMPOSER_MAX)
27+struct list_head;
28+struct list_head * __init probe_lsm_hooks_list(void);
29+#else
30+struct security_operations;
31+struct security_operations * __init probe_security_ops(void);
32+#endif
33+
34+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
35+void * __init probe_find_task_by_vpid(void);
36+void * __init probe_find_task_by_pid_ns(void);
37+#endif
38+
39+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
40+void * __init probe_vfsmount_lock(void);
41+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
42+void * __init probe___d_path(void);
43+#else
44+void * __init probe_d_absolute_path(void);
45+#endif
旧リポジトリブラウザで表示