• R/O
  • SSH
  • HTTPS

caitsith: Commit


Commit MetaInfo

Revision239 (tree)
Time2017-05-06 21:26:17
Authorkumaneko

Log Message

Add CONFIG_SECURITY_WRITABLE_HOOKS=n check.

Change Summary

Incremental Difference

--- trunk/caitsith-patch/caitsith/lsm-4.12.c (revision 238)
+++ trunk/caitsith-patch/caitsith/lsm-4.12.c (revision 239)
@@ -1107,6 +1107,71 @@
11071107 }
11081108 }
11091109
1110+#if defined(CONFIG_STRICT_KERNEL_RWX) && !defined(SECURITY_WRITABLE_HOOKS)
1111+#include <linux/uaccess.h> /* probe_kernel_write() */
1112+#define NEED_TO_CHECK_HOOKS_ARE_WRITABLE
1113+
1114+#if defined(CONFIG_X86)
1115+#define MAX_RO_PAGES 1024
1116+static struct page *ro_pages[MAX_RO_PAGES] __initdata;
1117+static unsigned int ro_pages_len __initdata;
1118+
1119+static bool __init lsm_test_page_ro(void *addr)
1120+{
1121+ unsigned int i;
1122+ int unused;
1123+ struct page *page;
1124+
1125+ page = (struct page *) lookup_address((unsigned long) addr, &unused);
1126+ if (!page)
1127+ return false;
1128+ if (test_bit(_PAGE_BIT_RW, &(page->flags)))
1129+ return true;
1130+ for (i = 0; i < ro_pages_len; i++)
1131+ if (page == ro_pages[i])
1132+ return true;
1133+ if (ro_pages_len == MAX_RO_PAGES)
1134+ return false;
1135+ ro_pages[ro_pages_len++] = page;
1136+ return true;
1137+}
1138+
1139+static bool __init check_ro_pages(struct security_hook_heads *hooks)
1140+{
1141+ int i;
1142+ struct list_head *list = (struct list_head *) hooks;
1143+
1144+ if (!probe_kernel_write(&list->next, list->next, sizeof(void *)))
1145+ return true;
1146+ for (i = 0; i < ARRAY_SIZE(caitsith_hooks); i++) {
1147+ const unsigned int idx =
1148+ ((unsigned long) caitsith_hooks[i].head
1149+ - (unsigned long) hooks)
1150+ / sizeof(struct list_head);
1151+ struct list_head *self = &list[idx];
1152+ struct list_head *prev = self->prev;
1153+
1154+ if (!lsm_test_page_ro(&prev->next) ||
1155+ !lsm_test_page_ro(&self->prev))
1156+ return false;
1157+ if (!list_empty(self) &&
1158+ !lsm_test_page_ro(&list_last_entry
1159+ (self, struct security_hook_list,
1160+ list)->hook))
1161+ return false;
1162+ }
1163+ return true;
1164+}
1165+#else
1166+static bool __init check_ro_pages(struct security_hook_heads *hooks)
1167+{
1168+ return !probe_kernel_write(&((struct list_head *) hooks)->next,
1169+ ((struct list_head *) hooks)->next,
1170+ sizeof(void *));
1171+}
1172+#endif
1173+#endif
1174+
11101175 /**
11111176 * cs_init - Initialize this module.
11121177 *
@@ -1123,6 +1188,12 @@
11231188 caitsith_hooks[idx].head = ((void *) hooks)
11241189 + ((unsigned long) caitsith_hooks[idx].head)
11251190 - ((unsigned long) &probe_dummy_security_hook_heads);
1191+#if defined(NEED_TO_CHECK_HOOKS_ARE_WRITABLE)
1192+ if (!check_ro_pages(hooks)) {
1193+ printk(KERN_INFO "Can't update security_hook_heads due to write protected. Retry with rodata=0 kernel command line option added.\n");
1194+ return -EINVAL;
1195+ }
1196+#endif
11261197 caitsith_exports.find_task_by_vpid = probe_find_task_by_vpid();
11271198 if (!caitsith_exports.find_task_by_vpid)
11281199 goto out;
@@ -1135,11 +1206,19 @@
11351206 for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++)
11361207 INIT_LIST_HEAD(&cs_task_security_list[idx]);
11371208 cs_init_module();
1209+#if defined(NEED_TO_CHECK_HOOKS_ARE_WRITABLE) && defined(CONFIG_X86)
1210+ for (idx = 0; idx < ro_pages_len; idx++)
1211+ set_bit(_PAGE_BIT_RW, &(ro_pages[idx]->flags));
1212+#endif
11381213 swap_hook(&caitsith_hooks[0], &original_task_free);
11391214 swap_hook(&caitsith_hooks[1], &original_cred_prepare);
11401215 swap_hook(&caitsith_hooks[2], &original_task_alloc);
11411216 for (idx = 3; idx < ARRAY_SIZE(caitsith_hooks); idx++)
11421217 add_hook(&caitsith_hooks[idx]);
1218+#if defined(NEED_TO_CHECK_HOOKS_ARE_WRITABLE) && defined(CONFIG_X86)
1219+ for (idx = 0; idx < ro_pages_len; idx++)
1220+ clear_bit(_PAGE_BIT_RW, &(ro_pages[idx]->flags));
1221+#endif
11431222 return 0;
11441223 out:
11451224 return -EINVAL;
Show on old repository browser