kdp_test.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. #include <linux/module.h>
  2. #include <linux/proc_fs.h>
  3. #include <linux/mm.h>
  4. #include <linux/uh.h>
  5. #include <linux/nsproxy.h>
  6. #include <linux/security.h>
  7. #include <../../fs/mount.h>
  8. #include <linux/sched/signal.h>
  9. #include <linux/kdp.h>
  10. /* Never enable this flag*/
  11. //#define CONFIG_KDP_SEC_TEST
  12. struct task_security_struct {
  13. u32 osid; /* SID prior to last execve */
  14. u32 sid; /* current SID */
  15. u32 exec_sid; /* exec SID */
  16. u32 create_sid; /* fscreate SID */
  17. u32 keycreate_sid; /* keycreate SID */
  18. u32 sockcreate_sid; /* fscreate SID */
  19. void *bp_cred;
  20. };
  21. struct test_case {
  22. int (*fn)(void);
  23. char *describe;
  24. };
  25. enum __KDP_TEST {
  26. CMD_ID_CRED = 0,
  27. CMD_ID_SEC_CONTEXT,
  28. CMD_ID_NS,
  29. };
  30. #define KDP_PA_READ 0
  31. #define KDP_PA_WRITE 1
  32. /* BUF define */
  33. #define KDP_BUF_SIZE 8192
  34. #define KDP_LINE_MAX 80
  35. static char kdp_test_buf[KDP_BUF_SIZE];
  36. static unsigned long kdp_test_len;
  37. static DEFINE_RAW_SPINLOCK(par_lock);
  38. static u64 *ha1;
  39. static void kdp_print(const char *fmt, ...)
  40. {
  41. va_list aptr;
  42. if (kdp_test_len > KDP_BUF_SIZE - KDP_LINE_MAX)
  43. return;
  44. va_start(aptr, fmt);
  45. kdp_test_len += vsprintf(kdp_test_buf + kdp_test_len, fmt, aptr);
  46. va_end(aptr);
  47. }
  48. static struct vfsmount *get_vfsmnt(struct task_struct *p)
  49. {
  50. if (!p || !(p->nsproxy) ||
  51. !(p->nsproxy->mnt_ns) ||
  52. !(p->nsproxy->mnt_ns->root))
  53. return NULL;
  54. return ((struct kdp_mount *)p->nsproxy->mnt_ns->root)->mnt;
  55. }
  56. static bool hyp_check_page_ro(u64 va)
  57. {
  58. unsigned long flags;
  59. u64 par = 0;
  60. raw_spin_lock_irqsave(&par_lock, flags);
  61. uh_call(UH_APP_KDP, TEST_GET_PAR, (unsigned long)va, KDP_PA_WRITE, 0, 0);
  62. par = *ha1;
  63. raw_spin_unlock_irqrestore(&par_lock, flags);
  64. return (par & 0x1) ? true : false;
  65. }
  66. static int test_case_kdp_ro(int cmd_id)
  67. {
  68. struct task_struct *p = NULL;
  69. u64 ro = 0, rw = 0, dst;
  70. for_each_process(p) {
  71. switch (cmd_id) {
  72. case CMD_ID_CRED:
  73. /* Here dst points to struct cred */
  74. dst = (u64)__task_cred(p);
  75. break;
  76. case CMD_ID_SEC_CONTEXT:
  77. /* Here dst points to process security context */
  78. dst = (u64)__task_cred(p)->security;
  79. break;
  80. case CMD_ID_NS:
  81. /* Here dst points to process security context */
  82. dst = (u64)get_vfsmnt(p);
  83. break;
  84. }
  85. if (!dst)
  86. continue;
  87. if (hyp_check_page_ro(dst))
  88. ro++;
  89. else
  90. rw++;
  91. }
  92. kdp_print("ro: %llu, rw: %llu\n", ro, rw);
  93. return rw ? 1 : 0;
  94. }
  95. static int cred_match(struct task_struct *p, const struct cred *cred)
  96. {
  97. struct mm_struct *mm = p->mm;
  98. pgd_t *tgt = NULL;
  99. if (((struct cred_kdp *)cred)->bp_task != p) {
  100. kdp_print("KDP_WARN task: #%s# cred: %p, task: %p bp_task: %p\n",
  101. p->comm, cred, p, ((struct cred_kdp *)cred)->bp_task);
  102. return 0;
  103. }
  104. if (!(in_interrupt() || in_softirq()))
  105. return 1;
  106. tgt = mm ? mm->pgd : init_mm.pgd;
  107. if (((struct cred_kdp *)cred)->bp_pgd != tgt) {
  108. kdp_print("KDP_WARN task: #%s# cred: %p, mm: %p, init_mm: %p, pgd: %p, bp_pgd: %p\n",
  109. p->comm, cred, mm, init_mm.pgd, tgt, ((struct cred_kdp *)cred)->bp_pgd);
  110. return 0;
  111. }
  112. return 1;
  113. }
  114. static int sec_context_match(const struct cred *cred)
  115. {
  116. struct task_security_struct *tsec = (struct task_security_struct *)cred->security;
  117. if ((u64)tsec->bp_cred != (u64)cred)
  118. return 0;
  119. return 1;
  120. }
  121. static int test_case_match_bp(int cmd_id)
  122. {
  123. struct task_struct *p = NULL;
  124. u64 match = 0, mismatch = 0, ret = 0;
  125. for_each_process(p) {
  126. switch (cmd_id) {
  127. case CMD_ID_CRED:
  128. /*Here dst points to struct cred*/
  129. ret = cred_match(p, __task_cred(p));
  130. break;
  131. case CMD_ID_SEC_CONTEXT:
  132. /*Here dst points to process security context*/
  133. ret = sec_context_match(__task_cred(p));
  134. break;
  135. }
  136. ret ? match++ : mismatch++;
  137. }
  138. kdp_print("match: %llu, mismatch: %llu\n", match, mismatch);
  139. return mismatch ? 1 : 0;
  140. }
  141. static int test_case_cred_ro(void)
  142. {
  143. kdp_print("CRED PROTECTION ");
  144. return test_case_kdp_ro(CMD_ID_CRED);
  145. }
  146. static int test_case_sec_context_ro(void)
  147. {
  148. kdp_print("SECURITY CONTEXT PROTECTION ");
  149. return test_case_kdp_ro(CMD_ID_SEC_CONTEXT);
  150. }
  151. static int test_case_cred_match_bp(void)
  152. {
  153. kdp_print("CRED Back Poiner check ");
  154. return test_case_match_bp(CMD_ID_CRED);
  155. }
  156. static int test_case_sec_context_match_bp(void)
  157. {
  158. kdp_print("Security Context Back Poiner check ");
  159. return test_case_match_bp(CMD_ID_SEC_CONTEXT);
  160. }
  161. static int test_case_ns_ro(void)
  162. {
  163. kdp_print("NAMESPACE PROTECTION ");
  164. return test_case_kdp_ro(CMD_ID_NS);
  165. }
  166. #ifdef CONFIG_KDP_SEC_TEST
  167. enum {
  168. CMD_ID_COMMIT_CRED,
  169. CMD_ID_OVERRIDE_CRED,
  170. CMD_ID_REVERT_CRED,
  171. };
  172. enum {
  173. CMD_ID_SEC_WRITE_CRED,
  174. CMD_ID_SEC_WRITE_SP,
  175. CMD_ID_SEC_DIRECT_PE,
  176. CMD_ID_SEC_INDIRECT_PE_COMMIT,
  177. CMD_ID_SEC_INDIRECT_PE_OVERRIDE,
  178. CMD_ID_SEC_INDIRECT_PE_REVERT,
  179. };
  180. #define PROCFS_MAX_SIZE 64
  181. void write_ro(u64 *p)
  182. {
  183. memcpy(p, "c", 1);
  184. }
  185. static void sec_test_cred(void)
  186. {
  187. write_ro((u64 *)current_cred());
  188. }
  189. static void sec_test_sp(void)
  190. {
  191. write_ro((u64 *)current_cred()->security);
  192. }
  193. struct cred *get_root_cred(void)
  194. {
  195. struct cred *cred;
  196. cred = prepare_creds();
  197. cred->uid.val = 0;
  198. cred->gid.val = 0;
  199. cred->euid.val = 0;
  200. cred->egid.val = 0;
  201. return cred;
  202. }
  203. static void sec_test_cred_direct_pe(void)
  204. {
  205. struct cred *rcred;
  206. rcred = get_root_cred();
  207. current->cred = rcred;
  208. }
  209. static void sec_test_cred_indirect_pe(int cmd_id)
  210. {
  211. struct cred *rcred;
  212. rcred = get_root_cred();
  213. pr_info("RKP_SEC_TEST #%d# BEFORE current cred uid = %llx euid = %llx gid = %llx egid = %llx Root Cred%llx\n",
  214. cmd_id, current->cred->uid.val, current->cred->euid.val, current->cred->gid.val,
  215. current->cred->egid.val, (u64)rcred);
  216. switch (cmd_id) {
  217. case CMD_ID_COMMIT_CRED:
  218. commit_creds(rcred);
  219. break;
  220. case CMD_ID_OVERRIDE_CRED:
  221. override_creds(rcred);
  222. break;
  223. case CMD_ID_REVERT_CRED:
  224. revert_creds(rcred);
  225. break;
  226. }
  227. pr_info("RKP_SEC_TEST#%d# AFTER current cred uid = %llx euid = %llx gid = %llx egid = %llx Root Cred %llx\n",
  228. cmd_id, current->cred->uid.val, current->cred->euid.val, current->cred->gid.val,
  229. current->cred->egid.val, (u64)rcred);
  230. }
  231. ssize_t kdp_test_write(struct file *filep, const char __user *buffer, size_t len, loff_t *offset)
  232. {
  233. char procfs_buffer[PROCFS_MAX_SIZE];
  234. int buff_size;
  235. int tcase;
  236. buff_size = (len > PROCFS_MAX_SIZE)?PROCFS_MAX_SIZE:len;
  237. if (copy_from_user(procfs_buffer, buffer, buff_size))
  238. return -EFAULT;
  239. sscanf(procfs_buffer, "%d", &tcase);
  240. switch (tcase) {
  241. case CMD_ID_SEC_WRITE_CRED:
  242. sec_test_cred();
  243. break;
  244. case CMD_ID_SEC_WRITE_SP:
  245. sec_test_sp();
  246. break;
  247. case CMD_ID_SEC_DIRECT_PE:
  248. sec_test_cred_direct_pe();
  249. break;
  250. case CMD_ID_SEC_INDIRECT_PE_COMMIT:
  251. sec_test_cred_indirect_pe(CMD_ID_COMMIT_CRED);
  252. break;
  253. case CMD_ID_SEC_INDIRECT_PE_OVERRIDE:
  254. sec_test_cred_indirect_pe(CMD_ID_OVERRIDE_CRED);
  255. break;
  256. case CMD_ID_SEC_INDIRECT_PE_REVERT:
  257. sec_test_cred_indirect_pe(CMD_ID_REVERT_CRED);
  258. break;
  259. }
  260. return len;
  261. }
  262. #endif /* CONFIG_KDP_SEC_TEST*/
  263. ssize_t kdp_test_read(struct file *filep, char __user *buffer, size_t count, loff_t *ppos)
  264. {
  265. int ret = 0, temp_ret = 0, i = 0;
  266. struct test_case tc_funcs[] = {
  267. {test_case_cred_ro, "TEST TASK_CRED_RO"},
  268. {test_case_sec_context_ro, "TEST TASK_SECURITY_CONTEXT_RO"},
  269. {test_case_cred_match_bp, "TEST CRED_MATCH_BACKPOINTERS"},
  270. {test_case_sec_context_match_bp, "TEST TASK_SEC_CONTEXT_BACKPOINTER"},
  271. {test_case_ns_ro, "TEST NAMESPACE_RO"},
  272. };
  273. int tc_num = sizeof(tc_funcs)/sizeof(struct test_case);
  274. static bool done;
  275. if (done)
  276. return 0;
  277. done = true;
  278. for (i = 0; i < tc_num; i++) {
  279. kdp_print("KDP_TEST_CASE %d ===========> RUNNING %s\n", i, tc_funcs[i].describe);
  280. temp_ret = tc_funcs[i].fn();
  281. if (temp_ret) {
  282. kdp_print("KDP_TEST_CASE %d ===========> %s FAILED WITH %d ERRORS\n",
  283. i, tc_funcs[i].describe, temp_ret);
  284. } else {
  285. kdp_print("KDP_TEST_CASE %d ===========> %s PASSED\n", i, tc_funcs[i].describe);
  286. }
  287. ret += temp_ret;
  288. }
  289. if (ret)
  290. kdp_print("KDP_TEST SUMMARY: FAILED WITH %d ERRORS\n", ret);
  291. else
  292. kdp_print("KDP_TEST SUMMARY: PASSED\n");
  293. return simple_read_from_buffer(buffer, count, ppos, kdp_test_buf, kdp_test_len);
  294. }
  295. static const struct proc_ops kdp_proc_ops = {
  296. .proc_read = kdp_test_read,
  297. #ifdef CONFIG_KDP_SEC_TEST
  298. .proc_write = kdp_test_write,
  299. #endif
  300. };
  301. static int __init kdp_test_init(void)
  302. {
  303. u64 va;
  304. #ifndef CONFIG_KDP_SEC_TEST
  305. if (proc_create("kdp_test", 0444, NULL, &kdp_proc_ops) == NULL) {
  306. #else
  307. if (proc_create("kdp_test", 0777, NULL, &kdp_proc_ops) == NULL) {
  308. #endif
  309. pr_err("KDP_TEST: Error creating proc entry");
  310. return -1;
  311. }
  312. va = __get_free_page(GFP_KERNEL | __GFP_ZERO);
  313. if (!va)
  314. return -1;
  315. uh_call(UH_APP_KDP, TEST_INIT, va, 0, 0, 1);
  316. ha1 = (u64 *)va;
  317. return 0;
  318. }
  319. static void __exit kdp_test_exit(void)
  320. {
  321. uh_call(UH_APP_KDP, TEST_EXIT, (u64)ha1, 0, 0, 0);
  322. free_page((unsigned long)ha1);
  323. remove_proc_entry("kdp_test", NULL);
  324. }
  325. module_init(kdp_test_init);
  326. module_exit(kdp_test_exit);