• R/O
  • SSH
  • HTTPS

akari: Commit


Commit MetaInfo

Revision567 (tree)
Time2018-03-05 19:28:42
Authorkumaneko

Log Message

Update tasktracker

Change Summary

Incremental Difference

--- branches/tasktracker/README (revision 566)
+++ branches/tasktracker/README (revision 567)
@@ -102,7 +102,7 @@
102102 Version 0.1 2014/04/15 Initial backport.
103103
104104 Backported the version posted to Linux Security Module ML (readable
105- at http://lwn.net/Articles/575044/ ) as a loadable kernel module.
105+ at https://lwn.net/Articles/575044/ ) as a loadable kernel module.
106106
107107 Version 0.2 2014/04/20 Bug fix.
108108
--- branches/tasktracker/probe.c (revision 566)
+++ branches/tasktracker/probe.c (revision 567)
@@ -18,6 +18,29 @@
1818
1919 #include "probe.h"
2020
21+static void *__init check_function_address(void *ptr, char *symbol)
22+{
23+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
24+ static char buf[KSYM_SYMBOL_LEN];
25+ const int len = strlen(symbol);
26+#endif
27+
28+ if (!ptr) {
29+ printk(KERN_ERR "Can't resolve %s().\n", symbol);
30+ return NULL;
31+ }
32+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
33+ snprintf(buf, sizeof(buf), "%pS", ptr);
34+ if (strncmp(buf, symbol, len) || strncmp(buf + len, "+0x0/", 5)) {
35+ printk(KERN_ERR "Guessed %s is %s\n", symbol, buf);
36+ return NULL;
37+ }
38+#else
39+ printk(KERN_INFO "%s=%p\n", symbol, ptr);
40+#endif
41+ return ptr;
42+}
43+
2144 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
2245
2346 /**
@@ -41,6 +64,7 @@
4164 mm_segment_t old_fs;
4265 unsigned long pos = file->f_pos;
4366 int result;
67+
4468 file->f_pos = offset;
4569 old_fs = get_fs();
4670 set_fs(get_ds());
@@ -48,8 +72,12 @@
4872 set_fs(old_fs);
4973 file->f_pos = pos;
5074 return result;
75+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
76+ return kernel_read(file, offset, addr, count);
5177 #else
52- return kernel_read(file, offset, addr, count);
78+ loff_t pos = offset;
79+
80+ return kernel_read(file, addr, count, &pos);
5381 #endif
5482 }
5583
@@ -65,6 +93,7 @@
6593 struct file *file = NULL;
6694 char *buf;
6795 unsigned long entry = 0;
96+
6897 {
6998 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
7099 struct file_system_type *fstype = get_fs_type("proc");
@@ -78,6 +107,7 @@
78107 #endif
79108 struct dentry *root;
80109 struct dentry *dentry;
110+
81111 /*
82112 * We embed put_filesystem() here because it is not exported.
83113 */
@@ -86,7 +116,11 @@
86116 if (IS_ERR(mnt))
87117 goto out;
88118 root = dget(mnt->mnt_root);
89-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
119+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
120+ inode_lock(root->d_inode);
121+ dentry = lookup_one_len("kallsyms", root, 8);
122+ inode_unlock(root->d_inode);
123+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
90124 mutex_lock(&root->d_inode->i_mutex);
91125 dentry = lookup_one_len("kallsyms", root, 8);
92126 mutex_unlock(&root->d_inode->i_mutex);
@@ -100,7 +134,8 @@
100134 mntput(mnt);
101135 else {
102136 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
103- struct path path = { mnt, dentry };
137+ struct path path = { .mnt = mnt, .dentry = dentry };
138+
104139 file = dentry_open(&path, O_RDONLY, current_cred());
105140 #else
106141 file = dentry_open(dentry, mnt, O_RDONLY
@@ -117,9 +152,11 @@
117152 if (buf) {
118153 int len;
119154 int offset = 0;
155+
120156 while ((len = probe_kernel_read(file, offset, buf,
121157 PAGE_SIZE - 1)) > 0) {
122158 char *cp;
159+
123160 buf[len] = '\0';
124161 cp = strrchr(buf, '\n');
125162 if (!cp)
@@ -144,13 +181,13 @@
144181
145182 #endif
146183
147-#if defined(CONFIG_SECURITY_COMPOSER_MAX)
184+#if defined(LSM_HOOK_INIT)
148185
149186 /*
150187 * Dummy variable for finding location of
151- * "struct list_head lsm_hooks[LSM_MAX_HOOKS]".
188+ * "struct security_hook_heads security_hook_heads".
152189 */
153-struct list_head probe_lsm_hooks[LSM_MAX_HOOKS];
190+struct security_hook_heads probe_dummy_security_hook_heads;
154191
155192 /**
156193 * probe_security_bprm_committed_creds - Dummy function which does identical to security_bprm_committed_creds() in security/security.c.
@@ -162,15 +199,96 @@
162199 void probe_security_bprm_committed_creds(struct linux_binprm *bprm)
163200 {
164201 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);
202+ struct security_hook_list *p;
203+
204+ list_for_each_entry(p, &probe_dummy_security_hook_heads.
205+ bprm_committed_creds, list)
206+ p->hook.bprm_committed_creds(bprm);
171207 } while (0);
172208 }
173209
210+#if defined(CONFIG_ARM64)
211+
212+/**
213+ * probe_security_hook_heads_on_arm - Find security_hook_heads on ARM64.
214+ *
215+ * @base: Address of security_bprm_committed_creds().
216+ *
217+ * Returns address of security_hook_heads.bprm_committed_creds on success,
218+ * NULL otherwise.
219+ */
220+static void * __init probe_security_hook_heads_on_arm64(unsigned int *base)
221+{
222+ static unsigned int *ip4ret;
223+ int i;
224+ unsigned int *ip = (unsigned int *) base;
225+
226+ for (i = 0; i < 32; ip++, i++) {
227+ unsigned long tmp;
228+ unsigned long offset;
229+
230+ /*
231+ * Find
232+ * adrp Xd, #imm21
233+ * add Xd, Xn, #uimm12
234+ * add Xd, Xn, #uimm12
235+ * sequence.
236+ * But don't mandate the last one in case it was optimized.
237+ */
238+ if ((*ip & 0x98000000) != 0x90000000 ||
239+ (*(ip + 1) & 0xFFC00000) != 0x91000000)
240+ continue;
241+ tmp = ((unsigned long) ip) & ~0xFFFUL;
242+ offset = (unsigned long) (((((*ip >> 5) & 0x007FFFF) << 2) |
243+ ((*ip >> 29) & 0x3))) << 12;
244+ if (offset & 0x100000000UL)
245+ offset |= 0xFFFFFFFF00000000UL;
246+ tmp += offset;
247+ offset = (*(ip + 1) >> 10) & 0xFFF;
248+ tmp += offset;
249+ if ((*(ip + 2) & 0xFFC00000) == 0x91000000) {
250+ offset = (*(ip + 2) >> 10) & 0xFFF;
251+ tmp += offset;
252+ }
253+ ip4ret = (unsigned int *) tmp;
254+ return &ip4ret;
255+ }
256+ return NULL;
257+}
258+
259+#endif
260+
261+#if defined(CONFIG_ARM)
262+
263+/**
264+ * probe_security_hook_heads_on_arm - Find security_hook_heads on ARM.
265+ *
266+ * @base: Address of security_bprm_committed_creds().
267+ *
268+ * Returns address of security_hook_heads.bprm_committed_creds on success,
269+ * NULL otherwise.
270+ */
271+static void * __init probe_security_hook_heads_on_arm(unsigned int *base)
272+{
273+ static unsigned int *ip4ret;
274+ int i;
275+ const unsigned long addr = (unsigned long) &probe_dummy_security_hook_heads;
276+ const unsigned long offset = (unsigned long) &probe_dummy_security_hook_heads.bprm_committed_creds - addr;
277+ unsigned int *ip = (unsigned int *) probe_security_bprm_committed_creds;
278+
279+ for (i = 0; i < 32; ip++, i++) {
280+ if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
281+ continue;
282+ ip = base + i;
283+ ip4ret = (unsigned int *) (*(ip + 2 + ((*ip & 0xFFF) >> 2)));
284+ ip4ret += offset >> 2;
285+ return &ip4ret;
286+ }
287+ return NULL;
288+}
289+
290+#endif
291+
174292 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
175293
176294 /*
@@ -206,6 +324,7 @@
206324 int i;
207325 const unsigned long addr = (unsigned long) &probe_dummy_security_ops;
208326 unsigned int *ip = (unsigned int *) probe_security_file_alloc;
327+
209328 for (i = 0; i < 32; ip++, i++) {
210329 if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
211330 continue;
@@ -255,8 +374,10 @@
255374 unsigned int *base)
256375 {
257376 int i;
377+
258378 for (i = 0; i < 32; ip++, i++) {
259379 static unsigned int *ip4ret;
380+
260381 if (*(ip + 2 + ((*ip & 0xFFF) >> 2)) != addr)
261382 continue;
262383 ip = base + i;
@@ -287,6 +408,7 @@
287408 int i;
288409 u8 *base;
289410 u8 *cp = function;
411+
290412 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)
291413 if (*symbol == ' ')
292414 base = probe_find_symbol(symbol);
@@ -295,7 +417,15 @@
295417 base = __symbol_get(symbol);
296418 if (!base)
297419 return NULL;
298-#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(CONFIG_SECURITY_COMPOSER_MAX)
420+#if defined(CONFIG_ARM64) && defined(LSM_HOOK_INIT)
421+ if (function == probe_security_bprm_committed_creds)
422+ return probe_security_hook_heads_on_arm64((unsigned int *) base);
423+#endif
424+#if defined(CONFIG_ARM) && defined(LSM_HOOK_INIT)
425+ if (function == probe_security_bprm_committed_creds)
426+ return probe_security_hook_heads_on_arm((unsigned int *) base);
427+#endif
428+#if defined(CONFIG_ARM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && !defined(LSM_HOOK_INIT)
299429 if (function == probe_security_file_alloc)
300430 return probe_security_ops_on_arm((unsigned int *) base);
301431 #endif
@@ -315,6 +445,7 @@
315445 for (i = 0; i < 128; i++) {
316446 if ((unsigned long) (cp + (*(int *) cp) * 2 - 2) == addr) {
317447 static void *cp4ret;
448+
318449 cp = base + i;
319450 cp += (*(int *) cp) * 2 - 2;
320451 cp4ret = cp;
@@ -327,6 +458,7 @@
327458 for (i = 0; i < 128; i++) {
328459 if ((unsigned long) (cp + sizeof(int) + *(int *) cp) == addr) {
329460 static void *cp4ret;
461+
330462 cp = base + i;
331463 cp += sizeof(int) + *(int *) cp;
332464 cp4ret = cp;
@@ -338,6 +470,7 @@
338470 for (i = 0; i < 128; i++) {
339471 if ((unsigned long) (long) (*(int *) cp) == addr) {
340472 static void *cp4ret;
473+
341474 cp = base + i;
342475 cp = (void *) (long) (*(int *) cp);
343476 cp4ret = cp;
@@ -348,47 +481,43 @@
348481 return NULL;
349482 }
350483
351-#if defined(CONFIG_SECURITY_COMPOSER_MAX)
484+#if defined(LSM_HOOK_INIT)
352485
353486 /**
354- * probe_lsm_hooks_list - Find address of "struct list_head lsm_hooks[LSM_MAX_HOOKS]".
487+ * probe_security_hook_heads - Find address of "struct security_hook_heads security_hook_heads".
355488 *
356- * Returns pointer to "struct security_operations" on success, NULL otherwise.
489+ * Returns pointer to "struct security_hook_heads" on success, NULL otherwise.
357490 */
358-struct list_head * __init probe_lsm_hooks_list(void)
491+struct security_hook_heads * __init probe_security_hook_heads(void)
359492 {
360- unsigned int offset = 0;
493+ const unsigned int offset = offsetof(struct security_hook_heads,
494+ bprm_committed_creds);
361495 void *cp;
362- /* Guess "struct list_head lsm_hooks[LSM_MAX_HOOKS];". */
363- /* Try without offset. GCC 4.x seems to use this one. */
496+ struct security_hook_heads *shh;
497+ struct security_hook_list *entry;
498+ void *cap = probe_find_symbol(" cap_bprm_set_creds\n");
499+
500+ /* Get location of cap_bprm_set_creds(). */
501+ cap = check_function_address(cap, "cap_bprm_set_creds");
502+ if (!cap)
503+ return NULL;
504+ /* Guess "struct security_hook_heads security_hook_heads;". */
364505 cp = probe_find_variable(probe_security_bprm_committed_creds,
365- (unsigned long) probe_lsm_hooks,
506+ ((unsigned long)
507+ &probe_dummy_security_hook_heads) + offset,
366508 " security_bprm_committed_creds\n");
367509 if (!cp) {
368- /* Retry with offset. GCC 3.x seems to use this one. */
369- offset = offsetof(struct security_operations,
370- list[lsm_bprm_committed_creds]);
371- cp = probe_find_variable(probe_security_bprm_committed_creds,
372- ((unsigned long) probe_lsm_hooks)
373- + offset,
374- " security_bprm_committed_creds\n");
375- }
376- if (!cp) {
377510 printk(KERN_ERR
378511 "Can't resolve security_bprm_committed_creds().\n");
379- goto out;
512+ return NULL;
380513 }
381- /* This should be "struct list_head lsm_hooks[LSM_MAX_HOOKS];". */
382- cp = (struct list_head *) (*(unsigned long *) cp);
383- if (!cp) {
384- printk(KERN_ERR "Can't resolve lsm_hooks array.\n");
385- goto out;
386- }
387- /* Adjust if offset is used. */
388- cp -= offset;
389- printk(KERN_INFO "lsm_hooks=%p\n", cp);
390- return cp;
391-out:
514+ /* This should be "struct security_hook_heads security_hook_heads;". */
515+ shh = ((void *) (*(unsigned long *) cp)) - offset;
516+ list_for_each_entry(entry, &shh->bprm_set_creds, list)
517+ if (entry->hook.bprm_set_creds == cap)
518+ return shh;
519+ printk(KERN_ERR "Guessed security_hook_heads is 0x%lx\n",
520+ (unsigned long) shh);
392521 return NULL;
393522 }
394523
@@ -405,6 +534,7 @@
405534 struct security_operations *ops;
406535 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
407536 void *cp;
537+
408538 /* Guess "struct security_operations *security_ops;". */
409539 cp = probe_find_variable(probe_security_file_alloc, (unsigned long)
410540 &probe_dummy_security_ops,
@@ -444,17 +574,13 @@
444574 void * __init probe_find_task_by_vpid(void)
445575 {
446576 void *ptr;
577+
447578 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
448579 ptr = probe_find_symbol(" find_task_by_vpid\n");
449580 #else
450581 ptr = __symbol_get("find_task_by_vpid");
451582 #endif
452- if (!ptr) {
453- printk(KERN_ERR "Can't resolve find_task_by_vpid().\n");
454- return NULL;
455- }
456- printk(KERN_INFO "find_task_by_vpid=%p\n", ptr);
457- return ptr;
583+ return check_function_address(ptr, "find_task_by_vpid");
458584 }
459585
460586 /**
@@ -465,17 +591,13 @@
465591 void * __init probe_find_task_by_pid_ns(void)
466592 {
467593 void *ptr;
594+
468595 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
469596 ptr = probe_find_symbol(" find_task_by_pid_ns\n");
470597 #else
471598 ptr = __symbol_get("find_task_by_pid_ns");
472599 #endif
473- if (!ptr) {
474- printk(KERN_ERR "Can't resolve find_task_by_pid_ns().\n");
475- return NULL;
476- }
477- printk(KERN_INFO "find_task_by_pid_ns=%p\n", ptr);
478- return ptr;
600+ return check_function_address(ptr, "find_task_by_pid_ns");
479601 }
480602
481603 #endif
@@ -504,6 +626,7 @@
504626 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
505627 {
506628 unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
629+
507630 tmp += ((unsigned long) dentry / L1_CACHE_BYTES);
508631 tmp = tmp + (tmp >> probe_hash_bits);
509632 return tmp & probe_hash_mask;
@@ -549,6 +672,7 @@
549672 {
550673 void *cp;
551674 spinlock_t *ptr;
675+
552676 /* Guess "spinlock_t vfsmount_lock;". */
553677 cp = probe_find_variable(probe_lookup_mnt, (unsigned long)
554678 &probe_dummy_vfsmount_lock, " lookup_mnt\n");
@@ -583,6 +707,7 @@
583707 {
584708 struct vfsmount *parent;
585709 struct dentry *mountpoint;
710+
586711 spin_lock(&probe_dummy_vfsmount_lock);
587712 parent = (*mnt)->mnt_parent;
588713 if (parent == *mnt) {
@@ -608,6 +733,7 @@
608733 {
609734 void *cp;
610735 spinlock_t *ptr;
736+
611737 /* Guess "spinlock_t vfsmount_lock;". */
612738 cp = probe_find_variable(probe_follow_up, (unsigned long)
613739 &probe_dummy_vfsmount_lock, "follow_up");
@@ -653,6 +779,7 @@
653779 {
654780 void *cp;
655781 spinlock_t *ptr;
782+
656783 /* Guess "spinlock_t vfsmount_lock;". */
657784 cp = probe_find_variable(probe_mnt_pin, (unsigned long)
658785 &probe_dummy_vfsmount_lock, "mnt_pin");
@@ -704,12 +831,8 @@
704831 void * __init probe___d_path(void)
705832 {
706833 void *ptr = probe_find_symbol(" __d_path\n");
707- if (!ptr) {
708- printk(KERN_ERR "Can't resolve __d_path().\n");
709- return NULL;
710- }
711- printk(KERN_INFO "__d_path=%p\n", ptr);
712- return ptr;
834+
835+ return check_function_address(ptr, "__d_path");
713836 }
714837
715838 #endif
@@ -724,12 +847,8 @@
724847 void * __init probe_d_absolute_path(void)
725848 {
726849 void *ptr = probe_find_symbol(" d_absolute_path\n");
727- if (!ptr) {
728- printk(KERN_ERR "Can't resolve d_absolute_path().\n");
729- return NULL;
730- }
731- printk(KERN_INFO "d_absolute_path=%p\n", ptr);
732- return ptr;
850+
851+ return check_function_address(ptr, "d_absolute_path");
733852 }
734853
735854 #endif
--- branches/tasktracker/probe.h (revision 566)
+++ branches/tasktracker/probe.h (revision 567)
@@ -9,6 +9,9 @@
99 #ifndef __init
1010 #include <linux/init.h>
1111 #endif
12+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
13+#include <linux/cred.h>
14+#endif
1215
1316 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
1417 #error This module supports only 2.6.0 and later kernels.
@@ -25,10 +28,14 @@
2528 #ifndef CONFIG_MODULES
2629 #error You must choose CONFIG_MODULES=y for building this module.
2730 #endif
31+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
32+#include <linux/kallsyms.h>
33+#endif
2834
29-#if defined(CONFIG_SECURITY_COMPOSER_MAX)
30-struct list_head;
31-struct list_head * __init probe_lsm_hooks_list(void);
35+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) && !defined(SECURITY_NAME_MAX)
36+#include <linux/lsm_hooks.h>
37+extern struct security_hook_heads probe_dummy_security_hook_heads;
38+struct security_hook_heads * __init probe_security_hook_heads(void);
3239 #else
3340 struct security_operations;
3441 struct security_operations * __init probe_security_ops(void);
--- branches/tasktracker/tt.c (revision 566)
+++ branches/tasktracker/tt.c (revision 567)
@@ -32,8 +32,17 @@
3232 static DEFINE_SPINLOCK(tt_record_list_lock);
3333 /* List of "struct tt_record" for "struct cred". */
3434 static struct list_head tt_record_list[TT_MAX_RECORD_HASH];
35+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
3536 /* Function pointers originally registered by register_security(). */
3637 static struct security_operations original_security_ops /* = *security_ops; */;
38+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
39+/* Original hooks. */
40+static union security_list_options original_cred_prepare;
41+static union security_list_options original_cred_alloc_blank;
42+#else
43+/* Original hooks. */
44+static union security_list_options original_task_alloc;
45+#endif
3746
3847 /* Structure for representing YYYY/MM/DD hh/mm/ss. */
3948 struct tt_time {
@@ -70,10 +79,10 @@
7079 time /= 60;
7180 stamp->hour = time % 24;
7281 time /= 24;
73- if (time >= 16436) {
74- /* Start from 2015/01/01 rather than 1970/01/01. */
75- time -= 16436;
76- y += 45;
82+ if (time >= 17532) {
83+ /* Start from 2018/01/01 rather than 1970/01/01. */
84+ time -= 17532;
85+ y += 48;
7786 }
7887 while (1) {
7988 const unsigned short days = (y & 3) ? 365 : 366;
@@ -222,7 +231,7 @@
222231 return NULL;
223232 record->key = key;
224233 tt_update_record(record);
225-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
234+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
226235 /*
227236 * Special handling is needed because "struct cred" might be shared
228237 * between multiple threads. We need to allocate history only once for
@@ -288,7 +297,7 @@
288297 call_rcu(&ptr->rcu, tt_rcu_free);
289298 }
290299
291-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
300+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
292301
293302 /**
294303 * tt_cred_prepare - Allocate memory for new credentials.
@@ -312,8 +321,16 @@
312321 new_record->key = new;
313322 strcpy(new_record->history, old_record->history);
314323 tt_add_record(new_record);
315- while (!original_security_ops.cred_prepare);
324+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
325+ while (!original_security_ops.cred_prepare)
326+ smp_rmb();
316327 rc = original_security_ops.cred_prepare(new, old, gfp);
328+#else
329+ if (original_cred_prepare.cred_prepare)
330+ rc = original_cred_prepare.cred_prepare(new, old, gfp);
331+ else
332+ rc = 0;
333+#endif
317334 if (rc)
318335 tt_del_record(new_record);
319336 return rc;
@@ -328,8 +345,11 @@
328345 */
329346 static void tt_cred_free(struct cred *cred)
330347 {
331- while (!original_security_ops.cred_free);
348+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
349+ while (!original_security_ops.cred_free)
350+ smp_rmb();
332351 original_security_ops.cred_free(cred);
352+#endif
333353 tt_del_record(tt_find_record(cred));
334354 }
335355
@@ -351,8 +371,16 @@
351371 return -ENOMEM;
352372 record->key = new;
353373 tt_add_record(record);
354- while (!original_security_ops.cred_alloc_blank);
374+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
375+ while (!original_security_ops.cred_alloc_blank)
376+ smp_rmb();
355377 rc = original_security_ops.cred_alloc_blank(new, gfp);
378+#else
379+ if (original_cred_alloc_blank.cred_alloc_blank)
380+ rc = original_cred_alloc_blank.cred_alloc_blank(new, gfp);
381+ else
382+ rc = 0;
383+#endif
356384 if (rc)
357385 tt_del_record(record);
358386 return rc;
@@ -370,8 +398,11 @@
370398 {
371399 struct tt_record *new_record;
372400 struct tt_record *old_record;
373- while (!original_security_ops.cred_transfer);
401+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
402+ while (!original_security_ops.cred_transfer)
403+ smp_rmb();
374404 original_security_ops.cred_transfer(new, old);
405+#endif
375406 new_record = tt_find_record(new);
376407 old_record = tt_find_record(old);
377408 if (new_record && old_record)
@@ -382,6 +413,7 @@
382413
383414 #else
384415
416+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
385417 /**
386418 * tt_task_alloc_security - Allocate memory for new tasks.
387419 *
@@ -401,12 +433,43 @@
401433 new->key = p;
402434 strcpy(new->history, old->history);
403435 tt_add_record(new);
404- while (!original_security_ops.task_alloc_security);
436+ while (!original_security_ops.task_alloc_security)
437+ smp_rmb();
405438 rc = original_security_ops.task_alloc_security(p);
406439 if (rc)
407440 tt_del_record(new);
408441 return rc;
409442 }
443+#else
444+/**
445+ * tt_task_alloc_security - Allocate memory for new tasks.
446+ *
447+ * @p: Pointer to "struct task_struct".
448+ * @clone_flags: Flags passed to clone().
449+ *
450+ * Returns 0 on success, negative value otherwise.
451+ */
452+static int tt_task_alloc_security(struct task_struct *p, unsigned long clone_flags)
453+{
454+ int rc;
455+ struct tt_record *old = tt_current_record(current, GFP_KERNEL);
456+ struct tt_record *new = kzalloc(sizeof(*new), GFP_KERNEL);
457+ if (!old || !new) {
458+ kfree(new);
459+ return -ENOMEM;
460+ }
461+ new->key = p;
462+ strcpy(new->history, old->history);
463+ tt_add_record(new);
464+ if (original_task_alloc.task_alloc)
465+ rc = original_task_alloc.task_alloc(p, clone_flags);
466+ else
467+ rc = 0;
468+ if (rc)
469+ tt_del_record(new);
470+ return rc;
471+}
472+#endif
410473
411474 /**
412475 * tt_task_free_security - Release memory for "struct task_struct".
@@ -417,8 +480,11 @@
417480 */
418481 static void tt_task_free_security(struct task_struct *p)
419482 {
420- while (!original_security_ops.task_free_security);
483+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
484+ while (!original_security_ops.task_free_security)
485+ smp_rmb();
421486 original_security_ops.task_free_security(p);
487+#endif
422488 tt_del_record(tt_find_record(p));
423489 }
424490
@@ -436,7 +502,8 @@
436502 */
437503 static void tt_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
438504 {
439- while (!original_security_ops.bprm_apply_creds);
505+ while (!original_security_ops.bprm_apply_creds)
506+ smp_rmb();
440507 original_security_ops.bprm_apply_creds(bprm, unsafe);
441508 tt_update_record(tt_find_record(current));
442509 }
@@ -452,9 +519,16 @@
452519 */
453520 static void tt_bprm_committing_creds(struct linux_binprm *bprm)
454521 {
455- while (!original_security_ops.bprm_committing_creds);
522+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
523+ while (!original_security_ops.bprm_committing_creds)
524+ smp_rmb();
456525 original_security_ops.bprm_committing_creds(bprm);
457526 tt_update_record(tt_find_record(bprm->cred));
527+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
528+ tt_update_record(tt_find_record(bprm->cred));
529+#else
530+ tt_update_record(tt_find_record(current));
531+#endif
458532 }
459533
460534 #endif
@@ -492,7 +566,7 @@
492566 * tt_current_record() is called and tt_current_record() failed to
493567 * allocate memory for current thread's record.
494568 */
495-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
569+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
496570 record = tt_current_record(current->real_cred, GFP_ATOMIC);
497571 #else
498572 record = tt_current_record(current, GFP_ATOMIC);
@@ -510,6 +584,115 @@
510584 return 0;
511585 }
512586
587+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
588+
589+#define MY_HOOK_INIT(HEAD, HOOK) \
590+ { .head = &probe_dummy_security_hook_heads.HEAD, \
591+ .hook = { .HEAD = HOOK } }
592+
593+static struct security_hook_list tt_hooks[] = {
594+ MY_HOOK_INIT(bprm_committing_creds, tt_bprm_committing_creds),
595+ MY_HOOK_INIT(secid_to_secctx, tt_secid_to_secctx),
596+ MY_HOOK_INIT(task_getsecid, tt_task_getsecid),
597+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
598+ MY_HOOK_INIT(task_free, tt_task_free_security),
599+ MY_HOOK_INIT(task_alloc, tt_task_alloc_security),
600+#else
601+ MY_HOOK_INIT(cred_free, tt_cred_free),
602+ MY_HOOK_INIT(cred_transfer, tt_cred_transfer),
603+ MY_HOOK_INIT(cred_prepare, tt_cred_prepare),
604+ MY_HOOK_INIT(cred_alloc_blank, tt_cred_alloc_blank),
605+#endif
606+};
607+
608+static inline void add_hook(struct security_hook_list *hook)
609+{
610+ list_add_tail_rcu(&hook->list, hook->head);
611+}
612+
613+static void __init swap_hook(struct security_hook_list *hook,
614+ union security_list_options *original)
615+{
616+ struct list_head *list = hook->head;
617+ if (list_empty(list)) {
618+ add_hook(hook);
619+ } else {
620+ struct security_hook_list *shp =
621+ list_last_entry(list, struct security_hook_list, list);
622+ *original = shp->hook;
623+ smp_wmb();
624+ shp->hook = hook->hook;
625+ }
626+}
627+
628+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
629+#if defined(CONFIG_STRICT_KERNEL_RWX) && !defined(SECURITY_WRITABLE_HOOKS)
630+#include <linux/uaccess.h> /* probe_kernel_write() */
631+#define NEED_TO_CHECK_HOOKS_ARE_WRITABLE
632+
633+#if defined(CONFIG_X86)
634+#define MAX_RO_PAGES 1024
635+static struct page *ro_pages[MAX_RO_PAGES] __initdata;
636+static unsigned int ro_pages_len __initdata;
637+
638+static bool __init lsm_test_page_ro(void *addr)
639+{
640+ unsigned int i;
641+ int unused;
642+ struct page *page;
643+
644+ page = (struct page *) lookup_address((unsigned long) addr, &unused);
645+ if (!page)
646+ return false;
647+ if (test_bit(_PAGE_BIT_RW, &(page->flags)))
648+ return true;
649+ for (i = 0; i < ro_pages_len; i++)
650+ if (page == ro_pages[i])
651+ return true;
652+ if (ro_pages_len == MAX_RO_PAGES)
653+ return false;
654+ ro_pages[ro_pages_len++] = page;
655+ return true;
656+}
657+
658+static bool __init check_ro_pages(struct security_hook_heads *hooks)
659+{
660+ int i;
661+ struct list_head *list = (struct list_head *) hooks;
662+
663+ if (!probe_kernel_write(&list->next, list->next, sizeof(void *)))
664+ return true;
665+ for (i = 0; i < ARRAY_SIZE(tt_hooks); i++) {
666+ const unsigned int idx =
667+ ((unsigned long) tt_hooks[i].head
668+ - (unsigned long) hooks)
669+ / sizeof(struct list_head);
670+ struct list_head *self = &list[idx];
671+ struct list_head *prev = self->prev;
672+
673+ if (!lsm_test_page_ro(&prev->next) ||
674+ !lsm_test_page_ro(&self->prev))
675+ return false;
676+ if (!list_empty(self) &&
677+ !lsm_test_page_ro(&list_last_entry
678+ (self, struct security_hook_list,
679+ list)->hook))
680+ return false;
681+ }
682+ return true;
683+}
684+#else
685+static bool __init check_ro_pages(struct security_hook_heads *hooks)
686+{
687+ return !probe_kernel_write(&((struct list_head *) hooks)->next,
688+ ((struct list_head *) hooks)->next,
689+ sizeof(void *));
690+}
691+#endif
692+#endif
693+#endif
694+
695+#else
513696 /**
514697 * tt_update_security_ops - Overwrite original "struct security_operations".
515698 *
@@ -556,6 +739,7 @@
556739 ops->bprm_committing_creds = tt_bprm_committing_creds;
557740 #endif
558741 }
742+#endif
559743
560744 /**
561745 * tt_init - Initialize this module.
@@ -565,6 +749,21 @@
565749 static int __init tt_init(void)
566750 {
567751 int idx;
752+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
753+ struct security_hook_heads *hooks = probe_security_hook_heads();
754+ if (!hooks)
755+ return -EINVAL;
756+ for (idx = 0; idx < ARRAY_SIZE(tt_hooks); idx++)
757+ tt_hooks[idx].head = ((void *) hooks)
758+ + ((unsigned long) tt_hooks[idx].head)
759+ - ((unsigned long) &probe_dummy_security_hook_heads);
760+#if defined(NEED_TO_CHECK_HOOKS_ARE_WRITABLE)
761+ if (!check_ro_pages(hooks)) {
762+ printk(KERN_INFO "Can't update security_hook_heads due to write protected. Retry with rodata=0 kernel command line option added.\n");
763+ return -EINVAL;
764+ }
765+#endif
766+#else
568767 struct security_operations *ops = probe_security_ops();
569768 if (!ops)
570769 return -EINVAL;
@@ -574,9 +773,30 @@
574773 "command line option.\n", ops->name);
575774 return -EINVAL;
576775 }
776+#endif
577777 for (idx = 0; idx < TT_MAX_RECORD_HASH; idx++)
578778 INIT_LIST_HEAD(&tt_record_list[idx]);
779+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
780+#if defined(NEED_TO_CHECK_HOOKS_ARE_WRITABLE) && defined(CONFIG_X86)
781+ for (idx = 0; idx < ro_pages_len; idx++)
782+ set_bit(_PAGE_BIT_RW, &(ro_pages[idx]->flags));
783+#endif
784+ for (idx = 0; idx < 4; idx++)
785+ add_hook(&tt_hooks[idx]);
786+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
787+ swap_hook(&tt_hooks[4], &original_task_alloc);
788+#else
789+ add_hook(&tt_hooks[4]);
790+ swap_hook(&tt_hooks[5], &original_cred_prepare);
791+ swap_hook(&tt_hooks[6], &original_cred_alloc_blank);
792+#endif
793+#if defined(NEED_TO_CHECK_HOOKS_ARE_WRITABLE) && defined(CONFIG_X86)
794+ for (idx = 0; idx < ro_pages_len; idx++)
795+ clear_bit(_PAGE_BIT_RW, &(ro_pages[idx]->flags));
796+#endif
797+#else
579798 tt_update_security_ops(ops);
799+#endif
580800 printk(KERN_INFO "TaskTracker: 0.3 2015/01/11\n");
581801 return 0;
582802 }
Show on old repository browser