]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2020 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | #if DEVELOPMENT || DEBUG | |
30 | #if __has_feature(ptrauth_calls) | |
31 | ||
32 | #include <sys/errno.h> | |
33 | #include <sys/sysctl.h> | |
34 | #include <sys/ubc.h> | |
35 | #include <kern/kalloc.h> | |
36 | #include <libkern/libkern.h> | |
37 | #include <pexpert/pexpert.h> | |
38 | ||
39 | ||
40 | #include <mach/task.h> | |
41 | #include <kern/task.h> | |
42 | #include <sys/ubc_internal.h> | |
43 | ||
44 | extern kern_return_t ptrauth_data_tests(void); | |
45 | ||
46 | /* | |
47 | * Given an existing PAC pointer (ptr), its declaration type (decl), the (key) | |
48 | * used to sign it and the string discriminator (discr), extract the raw pointer | |
49 | * along with the signature and compare it with one computed on the fly | |
50 | * via ptrauth_sign_unauthenticated(). | |
51 | * | |
52 | * If the two mismatch, return an error and fail the test. | |
53 | */ | |
54 | #define VALIDATE_PTR(decl, ptr, key, discr) { \ | |
55 | decl raw = *(decl *)&(ptr); \ | |
56 | decl cmp = ptrauth_sign_unauthenticated(ptr, key, \ | |
57 | ptrauth_blend_discriminator(&ptr, ptrauth_string_discriminator(discr))); \ | |
58 | if (cmp != raw) { \ | |
59 | printf("kern.run_pac_test: %s (%s) (discr=%s) is not signed as expected (%p vs %p)\n", #decl, #ptr, #discr, raw, cmp); \ | |
60 | kr = EINVAL; \ | |
61 | } \ | |
62 | } | |
63 | ||
64 | /* | |
65 | * Allocate the containing structure, and store a pointer to the desired member, | |
66 | * which should be subject to pointer signing. | |
67 | */ | |
68 | #define ALLOC_VALIDATE_DATA_PTR(structure, decl, member, discr) { \ | |
69 | structure *tmp = kheap_alloc(KHEAP_TEMP, sizeof(structure), Z_WAITOK | Z_ZERO); \ | |
70 | if (!tmp) return ENOMEM; \ | |
71 | tmp->member = (void*)0xffffffff41414141; \ | |
72 | VALIDATE_DATA_PTR(decl, tmp->member, discr) \ | |
73 | kheap_free(KHEAP_TEMP, tmp, sizeof(structure)); \ | |
74 | } | |
75 | ||
76 | #define VALIDATE_DATA_PTR(decl, ptr, discr) VALIDATE_PTR(decl, ptr, ptrauth_key_process_independent_data, discr) | |
77 | ||
78 | /* | |
79 | * Validate that a pointer that is supposed to be signed, is, and that the signature | |
80 | * matches based on signing key, location and discriminator | |
81 | */ | |
82 | static int | |
83 | sysctl_run_ptrauth_data_tests SYSCTL_HANDLER_ARGS | |
84 | { | |
85 | #pragma unused(arg1, arg2, oidp) | |
86 | ||
87 | unsigned int dummy; | |
88 | int error, changed, kr; | |
89 | error = sysctl_io_number(req, 0, sizeof(dummy), &dummy, &changed); | |
90 | if (error || !changed) { | |
91 | return error; | |
92 | } | |
93 | ||
94 | /* proc_t */ | |
95 | ALLOC_VALIDATE_DATA_PTR(struct proc, void *, task, "proc.task"); | |
96 | ALLOC_VALIDATE_DATA_PTR(struct proc, struct proc *, p_pptr, "proc.p_pptr"); | |
97 | ALLOC_VALIDATE_DATA_PTR(struct proc, struct vnode *, p_textvp, "proc.p_textvp"); | |
98 | ALLOC_VALIDATE_DATA_PTR(struct proc, struct pgrp *, p_pgrp, "proc.p_pgrp"); | |
99 | ||
100 | /* cs_blob */ | |
101 | ALLOC_VALIDATE_DATA_PTR(struct cs_blob, struct cs_blob *, csb_next, "cs_blob.csb_next"); | |
102 | ALLOC_VALIDATE_DATA_PTR(struct cs_blob, const CS_CodeDirectory *, csb_cd, "cs_blob.csb_cd"); | |
103 | ALLOC_VALIDATE_DATA_PTR(struct cs_blob, const char *, csb_teamid, "cs_blob.csb_teamid"); | |
104 | ALLOC_VALIDATE_DATA_PTR(struct cs_blob, const CS_GenericBlob *, csb_entitlements_blob, "cs_blob.csb_entitlements_blob"); | |
105 | ALLOC_VALIDATE_DATA_PTR(struct cs_blob, void *, csb_entitlements, "cs_blob.csb_entitlements"); | |
106 | ||
107 | /* The rest of the tests live in osfmk/ */ | |
108 | kr = ptrauth_data_tests(); | |
109 | ||
110 | if (error == 0) { | |
111 | error = mach_to_bsd_errno(kr); | |
112 | } | |
113 | ||
114 | return kr; | |
115 | } | |
116 | ||
117 | SYSCTL_PROC(_kern, OID_AUTO, run_ptrauth_data_tests, | |
118 | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED | CTLFLAG_MASKED, | |
119 | 0, 0, sysctl_run_ptrauth_data_tests, "I", ""); | |
120 | ||
121 | #endif /* __has_feature(ptrauth_calls) */ | |
122 | #endif /* DEVELOPMENT || DEBUG */ |