xref: /xnu-10002.41.9/bsd/sys/ubc_internal.h (revision 699cd48037512bf4380799317ca44ca453c82f57)
1 /*
2  * Copyright (c) 1999-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  *	File:	ubc.h
30  *	Author:	Umesh Vaishampayan [[email protected]]
31  *		05-Aug-1999	umeshv	Created.
32  *
33  *	Header file for Unified Buffer Cache.
34  *
35  */
36 
37 #ifndef _SYS_UBC_INTERNAL_H_
38 #define _SYS_UBC_INTERNAL_H_
39 
40 #include <sys/appleapiopts.h>
41 #include <sys/types.h>
42 #include <sys/kernel_types.h>
43 #include <sys/ucred.h>
44 #include <sys/vnode.h>
45 #include <sys/ubc.h>
46 #include <sys/mman.h>
47 #include <sys/codesign.h>
48 #include <sys/code_signing.h>
49 
50 #include <sys/cdefs.h>
51 
52 #include <kern/locks.h>
53 #include <mach/memory_object_types.h>
54 
55 #include <libkern/ptrauth_utils.h>
56 
57 #define UBC_INFO_NULL   ((struct ubc_info *) 0)
58 
59 
60 extern struct zone      *ubc_info_zone;
61 
62 /*
63  * Maximum number of vfs clusters per vnode
64  */
65 #define MAX_CLUSTERS    CONFIG_MAX_CLUSTERS
66 
67 #define SPARSE_PUSH_LIMIT 4     /* limit on number of concurrent sparse pushes outside of the cl_lockw */
68                                 /* once we reach this limit, we'll hold the lock */
69 
70 struct cl_extent {
71 	daddr64_t       b_addr;
72 	daddr64_t       e_addr;
73 };
74 
75 struct cl_wextent {
76 	daddr64_t       b_addr;
77 	daddr64_t       e_addr;
78 	int             io_flags;
79 };
80 
81 struct cl_readahead {
82 	lck_mtx_t       cl_lockr;
83 	daddr64_t       cl_lastr;                       /* last block read by client */
84 	daddr64_t       cl_maxra;                       /* last block prefetched by the read ahead */
85 	int             cl_ralen;                       /* length of last prefetch */
86 };
87 
88 struct cl_writebehind {
89 	lck_mtx_t       cl_lockw;
90 	void    *       cl_scmap;                       /* pointer to sparse cluster map */
91 	off_t           cl_last_write;                  /* offset of the end of the last write */
92 	off_t           cl_seq_written;                 /* sequentially written bytes */
93 	int             cl_sparse_pushes;               /* number of pushes outside of the cl_lockw in progress */
94 	int             cl_sparse_wait;                 /* synchronous push is in progress */
95 	int             cl_number;                      /* number of packed write behind clusters currently valid */
96 	struct cl_wextent cl_clusters[MAX_CLUSTERS];    /* packed write behind clusters */
97 };
98 
99 struct cs_hash;
100 
101 uint8_t cs_hash_type(struct cs_hash const *);
102 
103 struct cs_blob {
104 	struct cs_blob  *csb_next;
105 	vnode_t         csb_vnode;
106 	void            *csb_ro_addr;
107 	__xnu_struct_group(cs_cpu_info, csb_cpu_info, {
108 		cpu_type_t      csb_cpu_type;
109 		cpu_subtype_t   csb_cpu_subtype;
110 	});
111 	__xnu_struct_group(cs_signer_info, csb_signer_info, {
112 		unsigned int    csb_flags;
113 		unsigned int    csb_signer_type;
114 	});
115 	off_t           csb_base_offset;        /* Offset of Mach-O binary in fat binary */
116 	off_t           csb_start_offset;       /* Blob coverage area start, from csb_base_offset */
117 	off_t           csb_end_offset;         /* Blob coverage area end, from csb_base_offset */
118 	vm_size_t       csb_mem_size;
119 	vm_offset_t     csb_mem_offset;
120 	void            *csb_mem_kaddr;
121 	unsigned char   csb_cdhash[CS_CDHASH_LEN];
122 	const struct cs_hash  *csb_hashtype;
123 #if CONFIG_SUPPLEMENTAL_SIGNATURES
124 	unsigned char   csb_linkage[CS_CDHASH_LEN];
125 	const struct cs_hash  *csb_linkage_hashtype;
126 #endif
127 	int             csb_hash_pageshift;
128 	int             csb_hash_firstlevel_pageshift;   /* First hash this many bytes, then hash the hashes together */
129 	const CS_CodeDirectory *csb_cd;
130 	const char      *csb_teamid;
131 #if CONFIG_SUPPLEMENTAL_SIGNATURES
132 	char            *csb_supplement_teamid;
133 #endif
134 	const CS_GenericBlob *csb_entitlements_blob;    /* raw blob, subrange of csb_mem_kaddr */
135 	const CS_GenericBlob *csb_der_entitlements_blob;    /* raw blob, subrange of csb_mem_kaddr */
136 
137 	/*
138 	 * OSEntitlements pointer setup by AMFI. This is PAC signed in addition to the
139 	 * cs_blob being within RO-memory to prevent modifications on the temporary stack
140 	 * variable used to setup the blob.
141 	 */
142 	void *XNU_PTRAUTH_SIGNED_PTR("cs_blob.csb_entitlements") csb_entitlements;
143 
144 	unsigned int    csb_reconstituted;      /* signature has potentially been modified after validation */
145 	__xnu_struct_group(cs_blob_platform_flags, csb_platform_flags, {
146 		/* The following two will be replaced by the csb_signer_type. */
147 		unsigned int    csb_platform_binary:1;
148 		unsigned int    csb_platform_path:1;
149 	});
150 
151 	/* Validation category used for TLE */
152 	unsigned int    csb_validation_category;
153 
154 #if CODE_SIGNING_MONITOR
155 	void *XNU_PTRAUTH_SIGNED_PTR("cs_blob.csb_csm_obj") csb_csm_obj;
156 	bool csb_csm_managed;
157 #endif
158 };
159 
160 /*
161  *	The following data structure keeps the information to associate
162  *	a vnode to the correspondig VM objects.
163  */
164 struct ubc_info {
165 	memory_object_t         ui_pager;       /* pager */
166 	memory_object_control_t ui_control;     /* VM control for the pager */
167 	vnode_t                 XNU_PTRAUTH_SIGNED_PTR("ubc_info.ui_vnode") ui_vnode;       /* vnode for this ubc_info */
168 	kauth_cred_t            ui_ucred;       /* holds credentials for NFS paging */
169 	off_t                   ui_size;        /* file size for the vnode */
170 	uint32_t                ui_flags;       /* flags */
171 	uint32_t                cs_add_gen;     /* generation count when csblob was validated */
172 
173 	struct  cl_readahead   *cl_rahead;      /* cluster read ahead context */
174 	struct  cl_writebehind *cl_wbehind;     /* cluster write behind context */
175 
176 	struct timespec         cs_mtime;       /* modify time of file when
177 	                                         *   first cs_blob was loaded */
178 	struct  cs_blob         * XNU_PTRAUTH_SIGNED_PTR("ubc_info.cs_blob") cs_blobs; /* for CODE SIGNING */
179 #if CONFIG_SUPPLEMENTAL_SIGNATURES
180 	struct  cs_blob         * cs_blob_supplement;/* supplemental blob (note that there can only be one supplement) */
181 #endif
182 #if CHECK_CS_VALIDATION_BITMAP
183 	void                    * XNU_PTRAUTH_SIGNED_PTR("ubc_info.cs_valid_bitmap") cs_valid_bitmap;     /* right now: used only for signed files on the read-only root volume */
184 	uint64_t                cs_valid_bitmap_size; /* Save original bitmap size in case the file size changes.
185 	                                               * In the future, we may want to reconsider changing the
186 	                                               * underlying bitmap to reflect the new file size changes.
187 	                                               */
188 #endif /* CHECK_CS_VALIDATION_BITMAP */
189 };
190 
191 /* Defines for ui_flags */
192 #define UI_NONE           0x00000000    /* none */
193 #define UI_HASPAGER       0x00000001    /* has a pager associated */
194 #define UI_INITED         0x00000002    /* newly initialized vnode */
195 #define UI_HASOBJREF      0x00000004    /* hold a reference on object */
196 #define UI_WASMAPPED      0x00000008    /* vnode was mapped */
197 #define UI_ISMAPPED       0x00000010    /* vnode is currently mapped */
198 #define UI_MAPBUSY        0x00000020    /* vnode is being mapped or unmapped */
199 #define UI_MAPWAITING     0x00000040    /* someone waiting for UI_MAPBUSY */
200 #define UI_MAPPEDWRITE    0x00000080    /* it's mapped with PROT_WRITE */
201 #define UI_CSBLOBINVALID  0x00000100    /* existing csblobs are invalid */
202 #define UI_WASMAPPEDWRITE 0x00000200    /* was mapped writable at some point */
203 
204 /*
205  * exported primitives for loadable file systems.
206  */
207 
208 __BEGIN_DECLS
209 
210 __private_extern__ int  ubc_umount(mount_t mp);
211 __private_extern__ void ubc_unmountall(void);
212 __private_extern__ memory_object_t ubc_getpager(vnode_t);
213 __private_extern__ void ubc_destroy_named(vnode_t);
214 
215 /* internal only */
216 __private_extern__ void cluster_release(struct ubc_info *);
217 __private_extern__ uint32_t cluster_throttle_io_limit(vnode_t, uint32_t *);
218 
219 
220 /* Flags for ubc_getobject() */
221 #define UBC_FLAGS_NONE          0x0000
222 #define UBC_HOLDOBJECT          0x0001
223 #define UBC_FOR_PAGEOUT         0x0002
224 
225 memory_object_control_t ubc_getobject(vnode_t, int);
226 
227 int     ubc_info_init(vnode_t);
228 int     ubc_info_init_withsize(vnode_t, off_t);
229 void    ubc_info_deallocate(struct ubc_info *);
230 
231 int     ubc_isinuse(vnode_t, int);
232 int     ubc_isinuse_locked(vnode_t, int, int);
233 
234 int     ubc_getcdhash(vnode_t, off_t, unsigned char *);
235 
236 /* code signing */
237 struct cs_blob;
238 void    cs_blob_require(struct cs_blob *, vnode_t);
239 int     ubc_cs_blob_add(vnode_t, uint32_t, cpu_type_t, cpu_subtype_t, off_t, vm_address_t *, vm_size_t, struct image_params *, int, struct cs_blob **);
240 #if CONFIG_SUPPLEMENTAL_SIGNATURES
241 int     ubc_cs_blob_add_supplement(vnode_t, vnode_t, off_t, vm_address_t *, vm_size_t, struct cs_blob **);
242 #endif
243 struct cs_blob *ubc_get_cs_blobs(vnode_t);
244 #if CONFIG_SUPPLEMENTAL_SIGNATURES
245 struct cs_blob *ubc_get_cs_supplement(vnode_t);
246 #endif
247 void    ubc_get_cs_mtime(vnode_t, struct timespec *);
248 int     ubc_cs_getcdhash(vnode_t, off_t, unsigned char *);
249 kern_return_t ubc_cs_blob_allocate(vm_offset_t *, vm_size_t *);
250 void ubc_cs_blob_deallocate(vm_offset_t, vm_size_t);
251 boolean_t ubc_cs_is_range_codesigned(vnode_t, mach_vm_offset_t, mach_vm_size_t);
252 
253 kern_return_t   ubc_cs_validation_bitmap_allocate( vnode_t );
254 void            ubc_cs_validation_bitmap_deallocate( struct ubc_info * );
255 __END_DECLS
256 
257 
258 #endif  /* _SYS_UBC_INTERNAL_H_ */
259