]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/ubc_subr.c
xnu-1504.15.3.tar.gz
[apple/xnu.git] / bsd / kern / ubc_subr.c
CommitLineData
1c79356b 1/*
cf7d32b8 2 * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * File: ubc_subr.c
30 * Author: Umesh Vaishampayan [umeshv@apple.com]
31 * 05-Aug-1999 umeshv Created.
32 *
33 * Functions related to Unified Buffer cache.
34 *
0b4e3aa0
A
35 * Caller of UBC functions MUST have a valid reference on the vnode.
36 *
1c79356b
A
37 */
38
1c79356b
A
39#include <sys/types.h>
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/lock.h>
91447636
A
43#include <sys/mman.h>
44#include <sys/mount_internal.h>
45#include <sys/vnode_internal.h>
46#include <sys/ubc_internal.h>
1c79356b 47#include <sys/ucred.h>
91447636
A
48#include <sys/proc_internal.h>
49#include <sys/kauth.h>
1c79356b 50#include <sys/buf.h>
13fec989 51#include <sys/user.h>
2d21ac55 52#include <sys/codesign.h>
1c79356b
A
53
54#include <mach/mach_types.h>
55#include <mach/memory_object_types.h>
91447636
A
56#include <mach/memory_object_control.h>
57#include <mach/vm_map.h>
b0d623f7 58#include <mach/mach_vm.h>
91447636 59#include <mach/upl.h>
1c79356b 60
91447636 61#include <kern/kern_types.h>
2d21ac55 62#include <kern/kalloc.h>
1c79356b 63#include <kern/zalloc.h>
13fec989 64#include <kern/thread.h>
91447636
A
65#include <vm/vm_kern.h>
66#include <vm/vm_protos.h> /* last */
1c79356b 67
2d21ac55
A
68#include <libkern/crypto/sha1.h>
69
593a1d5f
A
70#include <security/mac_framework.h>
71
2d21ac55
A
72/* XXX These should be in a BSD accessible Mach header, but aren't. */
73extern kern_return_t memory_object_pages_resident(memory_object_control_t,
74 boolean_t *);
75extern kern_return_t memory_object_signed(memory_object_control_t control,
76 boolean_t is_signed);
77extern void Debugger(const char *message);
78
79
80/* XXX no one uses this interface! */
81kern_return_t ubc_page_op_with_control(
82 memory_object_control_t control,
83 off_t f_offset,
84 int ops,
85 ppnum_t *phys_entryp,
86 int *flagsp);
87
88
1c79356b
A
89#if DIAGNOSTIC
90#if defined(assert)
b0d623f7 91#undef assert
1c79356b
A
92#endif
93#define assert(cond) \
2d21ac55 94 ((void) ((cond) ? 0 : panic("Assert failed: %s", # cond)))
1c79356b
A
95#else
96#include <kern/assert.h>
97#endif /* DIAGNOSTIC */
98
2d21ac55 99static int ubc_info_init_internal(struct vnode *vp, int withfsize, off_t filesize);
0c530ab8 100static int ubc_umcallback(vnode_t, void *);
0c530ab8 101static int ubc_msync_internal(vnode_t, off_t, off_t, off_t *, int, int *);
2d21ac55 102static void ubc_cs_free(struct ubc_info *uip);
b4c24cb9 103
91447636 104struct zone *ubc_info_zone;
b4c24cb9 105
2d21ac55
A
106
107/*
108 * CODESIGNING
109 * Routines to navigate code signing data structures in the kernel...
110 */
b0d623f7
A
111
112extern int cs_debug;
113
2d21ac55
A
114static boolean_t
115cs_valid_range(
116 const void *start,
117 const void *end,
118 const void *lower_bound,
119 const void *upper_bound)
120{
121 if (upper_bound < lower_bound ||
122 end < start) {
123 return FALSE;
124 }
125
126 if (start < lower_bound ||
127 end > upper_bound) {
128 return FALSE;
129 }
130
131 return TRUE;
132}
133
134/*
135 * Magic numbers used by Code Signing
136 */
137enum {
138 CSMAGIC_REQUIREMENT = 0xfade0c00, /* single Requirement blob */
139 CSMAGIC_REQUIREMENTS = 0xfade0c01, /* Requirements vector (internal requirements) */
140 CSMAGIC_CODEDIRECTORY = 0xfade0c02, /* CodeDirectory blob */
141 CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, /* embedded form of signature data */
142 CSMAGIC_EMBEDDED_SIGNATURE_OLD = 0xfade0b02, /* XXX */
143 CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, /* multi-arch collection of embedded signatures */
144
145 CSSLOT_CODEDIRECTORY = 0, /* slot index for CodeDirectory */
146};
147
b0d623f7 148static const uint32_t supportsScatter = 0x20100; // first version to support scatter option
2d21ac55
A
149
150/*
151 * Structure of an embedded-signature SuperBlob
152 */
153typedef struct __BlobIndex {
154 uint32_t type; /* type of entry */
155 uint32_t offset; /* offset of entry */
156} CS_BlobIndex;
157
158typedef struct __SuperBlob {
159 uint32_t magic; /* magic number */
160 uint32_t length; /* total length of SuperBlob */
161 uint32_t count; /* number of index entries following */
162 CS_BlobIndex index[]; /* (count) entries */
163 /* followed by Blobs in no particular order as indicated by offsets in index */
164} CS_SuperBlob;
165
b0d623f7
A
166struct Scatter {
167 uint32_t count; // number of pages; zero for sentinel (only)
168 uint32_t base; // first page number
169 uint64_t targetOffset; // offset in target
170 uint64_t spare; // reserved
171};
2d21ac55
A
172
173/*
174 * C form of a CodeDirectory.
175 */
176typedef struct __CodeDirectory {
177 uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */
178 uint32_t length; /* total length of CodeDirectory blob */
179 uint32_t version; /* compatibility version */
180 uint32_t flags; /* setup and mode flags */
181 uint32_t hashOffset; /* offset of hash slot element at index zero */
182 uint32_t identOffset; /* offset of identifier string */
183 uint32_t nSpecialSlots; /* number of special hash slots */
184 uint32_t nCodeSlots; /* number of ordinary (code) hash slots */
185 uint32_t codeLimit; /* limit to main image signature range */
186 uint8_t hashSize; /* size of each hash in bytes */
187 uint8_t hashType; /* type of hash (cdHashType* constants) */
188 uint8_t spare1; /* unused (must be zero) */
189 uint8_t pageSize; /* log2(page size in bytes); 0 => infinite */
190 uint32_t spare2; /* unused (must be zero) */
b0d623f7
A
191 /* Version 0x20100 */
192 uint32_t scatterOffset; /* offset of optional scatter vector */
2d21ac55
A
193 /* followed by dynamic content as located by offset fields above */
194} CS_CodeDirectory;
195
196
197/*
198 * Locate the CodeDirectory from an embedded signature blob
199 */
200static const
201CS_CodeDirectory *findCodeDirectory(
202 const CS_SuperBlob *embedded,
203 char *lower_bound,
204 char *upper_bound)
205{
206 const CS_CodeDirectory *cd = NULL;
207
208 if (embedded &&
209 cs_valid_range(embedded, embedded + 1, lower_bound, upper_bound) &&
210 ntohl(embedded->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
211 const CS_BlobIndex *limit;
212 const CS_BlobIndex *p;
213
214 limit = &embedded->index[ntohl(embedded->count)];
215 if (!cs_valid_range(&embedded->index[0], limit,
216 lower_bound, upper_bound)) {
217 return NULL;
218 }
219 for (p = embedded->index; p < limit; ++p) {
220 if (ntohl(p->type) == CSSLOT_CODEDIRECTORY) {
221 const unsigned char *base;
222
223 base = (const unsigned char *)embedded;
224 cd = (const CS_CodeDirectory *)(base + ntohl(p->offset));
225 break;
226 }
227 }
228 } else {
229 /*
230 * Detached signatures come as a bare CS_CodeDirectory,
231 * without a blob.
232 */
233 cd = (const CS_CodeDirectory *) embedded;
234 }
b0d623f7 235
2d21ac55
A
236 if (cd &&
237 cs_valid_range(cd, cd + 1, lower_bound, upper_bound) &&
238 cs_valid_range(cd, (const char *) cd + ntohl(cd->length),
239 lower_bound, upper_bound) &&
cf7d32b8
A
240 cs_valid_range(cd, (const char *) cd + ntohl(cd->hashOffset),
241 lower_bound, upper_bound) &&
242 cs_valid_range(cd, (const char *) cd +
243 ntohl(cd->hashOffset) +
244 (ntohl(cd->nCodeSlots) * SHA1_RESULTLEN),
245 lower_bound, upper_bound) &&
246
2d21ac55
A
247 ntohl(cd->magic) == CSMAGIC_CODEDIRECTORY) {
248 return cd;
249 }
250
251 // not found or not a valid code directory
252 return NULL;
253}
254
255
256/*
257 * Locating a page hash
258 */
259static const unsigned char *
260hashes(
261 const CS_CodeDirectory *cd,
262 unsigned page,
263 char *lower_bound,
264 char *upper_bound)
265{
266 const unsigned char *base, *top, *hash;
b0d623f7 267 uint32_t nCodeSlots = ntohl(cd->nCodeSlots);
2d21ac55
A
268
269 assert(cs_valid_range(cd, cd + 1, lower_bound, upper_bound));
270
b0d623f7
A
271 if((ntohl(cd->version) >= supportsScatter) && (ntohl(cd->scatterOffset))) {
272 /* Get first scatter struct */
273 const struct Scatter *scatter = (const struct Scatter*)
274 ((const char*)cd + ntohl(cd->scatterOffset));
275 uint32_t hashindex=0, scount, sbase=0;
276 /* iterate all scatter structs */
277 do {
278 if((const char*)scatter > (const char*)cd + ntohl(cd->length)) {
279 if(cs_debug) {
280 printf("CODE SIGNING: Scatter extends past Code Directory\n");
281 }
282 return NULL;
283 }
284
285 scount = ntohl(scatter->count);
286 uint32_t new_base = ntohl(scatter->base);
287
288 /* last scatter? */
289 if (scount == 0) {
290 return NULL;
291 }
292
293 if((hashindex > 0) && (new_base <= sbase)) {
294 if(cs_debug) {
295 printf("CODE SIGNING: unordered Scatter, prev base %d, cur base %d\n",
296 sbase, new_base);
297 }
298 return NULL; /* unordered scatter array */
299 }
300 sbase = new_base;
301
302 /* this scatter beyond page we're looking for? */
303 if (sbase > page) {
304 return NULL;
305 }
306
307 if (sbase+scount >= page) {
308 /* Found the scatter struct that is
309 * referencing our page */
310
311 /* base = address of first hash covered by scatter */
312 base = (const unsigned char *)cd + ntohl(cd->hashOffset) +
313 hashindex * SHA1_RESULTLEN;
314 /* top = address of first hash after this scatter */
315 top = base + scount * SHA1_RESULTLEN;
316 if (!cs_valid_range(base, top, lower_bound,
317 upper_bound) ||
318 hashindex > nCodeSlots) {
319 return NULL;
320 }
321
322 break;
323 }
324
325 /* this scatter struct is before the page we're looking
326 * for. Iterate. */
327 hashindex+=scount;
328 scatter++;
329 } while(1);
330
331 hash = base + (page - sbase) * SHA1_RESULTLEN;
332 } else {
333 base = (const unsigned char *)cd + ntohl(cd->hashOffset);
334 top = base + nCodeSlots * SHA1_RESULTLEN;
335 if (!cs_valid_range(base, top, lower_bound, upper_bound) ||
336 page > nCodeSlots) {
337 return NULL;
338 }
339 assert(page < nCodeSlots);
2d21ac55 340
b0d623f7
A
341 hash = base + page * SHA1_RESULTLEN;
342 }
343
2d21ac55
A
344 if (!cs_valid_range(hash, hash + SHA1_RESULTLEN,
345 lower_bound, upper_bound)) {
346 hash = NULL;
347 }
348
349 return hash;
350}
351/*
352 * CODESIGNING
353 * End of routines to navigate code signing data structures in the kernel.
354 */
355
356
1c79356b 357/*
2d21ac55
A
358 * ubc_init
359 *
360 * Initialization of the zone for Unified Buffer Cache.
361 *
362 * Parameters: (void)
363 *
364 * Returns: (void)
365 *
366 * Implicit returns:
367 * ubc_info_zone(global) initialized for subsequent allocations
1c79356b 368 */
0b4e3aa0 369__private_extern__ void
2d21ac55 370ubc_init(void)
1c79356b
A
371{
372 int i;
373
374 i = (vm_size_t) sizeof (struct ubc_info);
2d21ac55 375
1c79356b 376 ubc_info_zone = zinit (i, 10000*i, 8192, "ubc_info zone");
0b4c1975
A
377
378 zone_change(ubc_info_zone, Z_NOENCRYPT, TRUE);
1c79356b
A
379}
380
2d21ac55 381
1c79356b 382/*
2d21ac55
A
383 * ubc_info_init
384 *
385 * Allocate and attach an empty ubc_info structure to a vnode
386 *
387 * Parameters: vp Pointer to the vnode
388 *
389 * Returns: 0 Success
390 * vnode_size:ENOMEM Not enough space
391 * vnode_size:??? Other error from vnode_getattr
392 *
1c79356b
A
393 */
394int
395ubc_info_init(struct vnode *vp)
91447636
A
396{
397 return(ubc_info_init_internal(vp, 0, 0));
398}
2d21ac55
A
399
400
401/*
402 * ubc_info_init_withsize
403 *
404 * Allocate and attach a sized ubc_info structure to a vnode
405 *
406 * Parameters: vp Pointer to the vnode
407 * filesize The size of the file
408 *
409 * Returns: 0 Success
410 * vnode_size:ENOMEM Not enough space
411 * vnode_size:??? Other error from vnode_getattr
412 */
91447636
A
413int
414ubc_info_init_withsize(struct vnode *vp, off_t filesize)
415{
416 return(ubc_info_init_internal(vp, 1, filesize));
417}
418
2d21ac55
A
419
420/*
421 * ubc_info_init_internal
422 *
423 * Allocate and attach a ubc_info structure to a vnode
424 *
425 * Parameters: vp Pointer to the vnode
426 * withfsize{0,1} Zero if the size should be obtained
427 * from the vnode; otherwise, use filesize
428 * filesize The size of the file, if withfsize == 1
429 *
430 * Returns: 0 Success
431 * vnode_size:ENOMEM Not enough space
432 * vnode_size:??? Other error from vnode_getattr
433 *
434 * Notes: We call a blocking zalloc(), and the zone was created as an
435 * expandable and collectable zone, so if no memory is available,
436 * it is possible for zalloc() to block indefinitely. zalloc()
437 * may also panic if the zone of zones is exhausted, since it's
438 * NOT expandable.
439 *
440 * We unconditionally call vnode_pager_setup(), even if this is
441 * a reuse of a ubc_info; in that case, we should probably assert
442 * that it does not already have a pager association, but do not.
443 *
444 * Since memory_object_create_named() can only fail from receiving
445 * an invalid pager argument, the explicit check and panic is
446 * merely precautionary.
447 */
448static int
449ubc_info_init_internal(vnode_t vp, int withfsize, off_t filesize)
1c79356b
A
450{
451 register struct ubc_info *uip;
452 void * pager;
1c79356b
A
453 int error = 0;
454 kern_return_t kret;
0b4e3aa0 455 memory_object_control_t control;
1c79356b 456
91447636 457 uip = vp->v_ubcinfo;
1c79356b 458
2d21ac55
A
459 /*
460 * If there is not already a ubc_info attached to the vnode, we
461 * attach one; otherwise, we will reuse the one that's there.
462 */
91447636 463 if (uip == UBC_INFO_NULL) {
1c79356b 464
1c79356b 465 uip = (struct ubc_info *) zalloc(ubc_info_zone);
91447636
A
466 bzero((char *)uip, sizeof(struct ubc_info));
467
1c79356b 468 uip->ui_vnode = vp;
91447636 469 uip->ui_flags = UI_INITED;
1c79356b
A
470 uip->ui_ucred = NOCRED;
471 }
1c79356b
A
472 assert(uip->ui_flags != UI_NONE);
473 assert(uip->ui_vnode == vp);
474
1c79356b
A
475 /* now set this ubc_info in the vnode */
476 vp->v_ubcinfo = uip;
91447636 477
2d21ac55
A
478 /*
479 * Allocate a pager object for this vnode
480 *
481 * XXX The value of the pager parameter is currently ignored.
482 * XXX Presumably, this API changed to avoid the race between
483 * XXX setting the pager and the UI_HASPAGER flag.
484 */
1c79356b
A
485 pager = (void *)vnode_pager_setup(vp, uip->ui_pager);
486 assert(pager);
91447636 487
2d21ac55
A
488 /*
489 * Explicitly set the pager into the ubc_info, after setting the
490 * UI_HASPAGER flag.
491 */
91447636
A
492 SET(uip->ui_flags, UI_HASPAGER);
493 uip->ui_pager = pager;
1c79356b
A
494
495 /*
91447636 496 * Note: We can not use VNOP_GETATTR() to get accurate
2d21ac55
A
497 * value of ui_size because this may be an NFS vnode, and
498 * nfs_getattr() can call vinvalbuf(); if this happens,
499 * ubc_info is not set up to deal with that event.
1c79356b
A
500 * So use bogus size.
501 */
502
1c79356b 503 /*
0b4e3aa0
A
504 * create a vnode - vm_object association
505 * memory_object_create_named() creates a "named" reference on the
506 * memory object we hold this reference as long as the vnode is
507 * "alive." Since memory_object_create_named() took its own reference
508 * on the vnode pager we passed it, we can drop the reference
509 * vnode_pager_setup() returned here.
1c79356b 510 */
0b4e3aa0
A
511 kret = memory_object_create_named(pager,
512 (memory_object_size_t)uip->ui_size, &control);
513 vnode_pager_deallocate(pager);
514 if (kret != KERN_SUCCESS)
515 panic("ubc_info_init: memory_object_create_named returned %d", kret);
1c79356b 516
0b4e3aa0
A
517 assert(control);
518 uip->ui_control = control; /* cache the value of the mo control */
519 SET(uip->ui_flags, UI_HASOBJREF); /* with a named reference */
2d21ac55 520
91447636 521 if (withfsize == 0) {
91447636 522 /* initialize the size */
2d21ac55 523 error = vnode_size(vp, &uip->ui_size, vfs_context_current());
91447636
A
524 if (error)
525 uip->ui_size = 0;
526 } else {
527 uip->ui_size = filesize;
528 }
2d21ac55 529 vp->v_lflag |= VNAMED_UBC; /* vnode has a named ubc reference */
1c79356b 530
0b4e3aa0 531 return (error);
1c79356b
A
532}
533
2d21ac55
A
534
535/*
536 * ubc_info_free
537 *
538 * Free a ubc_info structure
539 *
540 * Parameters: uip A pointer to the ubc_info to free
541 *
542 * Returns: (void)
543 *
544 * Notes: If there is a credential that has subsequently been associated
545 * with the ubc_info via a call to ubc_setcred(), the reference
546 * to the credential is dropped.
547 *
548 * It's actually impossible for a ubc_info.ui_control to take the
549 * value MEMORY_OBJECT_CONTROL_NULL.
550 */
0b4e3aa0
A
551static void
552ubc_info_free(struct ubc_info *uip)
1c79356b 553{
0c530ab8
A
554 if (IS_VALID_CRED(uip->ui_ucred)) {
555 kauth_cred_unref(&uip->ui_ucred);
1c79356b 556 }
0b4e3aa0
A
557
558 if (uip->ui_control != MEMORY_OBJECT_CONTROL_NULL)
559 memory_object_control_deallocate(uip->ui_control);
91447636
A
560
561 cluster_release(uip);
2d21ac55 562 ubc_cs_free(uip);
0b4e3aa0 563
2d21ac55 564 zfree(ubc_info_zone, uip);
1c79356b
A
565 return;
566}
567
2d21ac55 568
0b4e3aa0
A
569void
570ubc_info_deallocate(struct ubc_info *uip)
571{
91447636 572 ubc_info_free(uip);
0b4e3aa0
A
573}
574
2d21ac55 575
1c79356b 576/*
2d21ac55
A
577 * ubc_setsize
578 *
579 * Tell the VM that the the size of the file represented by the vnode has
580 * changed
581 *
582 * Parameters: vp The vp whose backing file size is
583 * being changed
584 * nsize The new size of the backing file
585 *
586 * Returns: 1 Success
587 * 0 Failure
588 *
589 * Notes: This function will indicate failure if the new size that's
590 * being attempted to be set is negative.
591 *
592 * This function will fail if there is no ubc_info currently
593 * associated with the vnode.
594 *
595 * This function will indicate success it the new size is the
596 * same or larger than the old size (in this case, the remainder
597 * of the file will require modification or use of an existing upl
598 * to access successfully).
599 *
600 * This function will fail if the new file size is smaller, and
601 * the memory region being invalidated was unable to actually be
602 * invalidated and/or the last page could not be flushed, if the
603 * new size is not aligned to a page boundary. This is usually
604 * indicative of an I/O error.
1c79356b
A
605 */
606int
607ubc_setsize(struct vnode *vp, off_t nsize)
608{
609 off_t osize; /* ui_size before change */
610 off_t lastpg, olastpgend, lastoff;
611 struct ubc_info *uip;
0b4e3aa0 612 memory_object_control_t control;
2d21ac55 613 kern_return_t kret = KERN_SUCCESS;
1c79356b 614
55e303ae
A
615 if (nsize < (off_t)0)
616 return (0);
1c79356b 617
1c79356b 618 if (!UBCINFOEXISTS(vp))
0b4e3aa0 619 return (0);
1c79356b
A
620
621 uip = vp->v_ubcinfo;
2d21ac55
A
622 osize = uip->ui_size;
623 /*
624 * Update the size before flushing the VM
625 */
1c79356b
A
626 uip->ui_size = nsize;
627
b0d623f7
A
628 if (nsize >= osize) { /* Nothing more to do */
629 lock_vnode_and_post(vp, NOTE_EXTEND);
0b4e3aa0 630 return (1); /* return success */
b0d623f7 631 }
1c79356b
A
632
633 /*
634 * When the file shrinks, invalidate the pages beyond the
635 * new size. Also get rid of garbage beyond nsize on the
2d21ac55
A
636 * last page. The ui_size already has the nsize, so any
637 * subsequent page-in will zero-fill the tail properly
1c79356b 638 */
1c79356b
A
639 lastpg = trunc_page_64(nsize);
640 olastpgend = round_page_64(osize);
0b4e3aa0
A
641 control = uip->ui_control;
642 assert(control);
1c79356b
A
643 lastoff = (nsize & PAGE_MASK_64);
644
2d21ac55
A
645 if (lastoff) {
646 upl_t upl;
647 upl_page_info_t *pl;
648
649
650 /*
651 * new EOF ends up in the middle of a page
652 * zero the tail of this page if its currently
653 * present in the cache
654 */
655 kret = ubc_create_upl(vp, lastpg, PAGE_SIZE, &upl, &pl, UPL_SET_LITE);
656
1c79356b 657 if (kret != KERN_SUCCESS)
2d21ac55
A
658 panic("ubc_setsize: ubc_create_upl (error = %d)\n", kret);
659
660 if (upl_valid_page(pl, 0))
661 cluster_zero(upl, (uint32_t)lastoff, PAGE_SIZE - (uint32_t)lastoff, NULL);
662
663 ubc_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY);
1c79356b 664
2d21ac55
A
665 lastpg += PAGE_SIZE_64;
666 }
667 if (olastpgend > lastpg) {
b0d623f7
A
668 int flags;
669
670 if (lastpg == 0)
671 flags = MEMORY_OBJECT_DATA_FLUSH_ALL;
672 else
673 flags = MEMORY_OBJECT_DATA_FLUSH;
2d21ac55
A
674 /*
675 * invalidate the pages beyond the new EOF page
676 *
677 */
678 kret = memory_object_lock_request(control,
679 (memory_object_offset_t)lastpg,
680 (memory_object_size_t)(olastpgend - lastpg), NULL, NULL,
b0d623f7 681 MEMORY_OBJECT_RETURN_NONE, flags, VM_PROT_NO_CHANGE);
2d21ac55
A
682 if (kret != KERN_SUCCESS)
683 printf("ubc_setsize: invalidate failed (error = %d)\n", kret);
684 }
1c79356b
A
685 return ((kret == KERN_SUCCESS) ? 1 : 0);
686}
687
2d21ac55 688
1c79356b 689/*
2d21ac55
A
690 * ubc_getsize
691 *
692 * Get the size of the file assocated with the specified vnode
693 *
694 * Parameters: vp The vnode whose size is of interest
695 *
696 * Returns: 0 There is no ubc_info associated with
697 * this vnode, or the size is zero
698 * !0 The size of the file
699 *
700 * Notes: Using this routine, it is not possible for a caller to
701 * successfully distinguish between a vnode associate with a zero
702 * length file, and a vnode with no associated ubc_info. The
703 * caller therefore needs to not care, or needs to ensure that
704 * they have previously successfully called ubc_info_init() or
705 * ubc_info_init_withsize().
1c79356b
A
706 */
707off_t
708ubc_getsize(struct vnode *vp)
709{
91447636
A
710 /* people depend on the side effect of this working this way
711 * as they call this for directory
1c79356b 712 */
91447636
A
713 if (!UBCINFOEXISTS(vp))
714 return ((off_t)0);
715 return (vp->v_ubcinfo->ui_size);
1c79356b
A
716}
717
2d21ac55 718
1c79356b 719/*
2d21ac55
A
720 * ubc_umount
721 *
722 * Call ubc_sync_range(vp, 0, EOF, UBC_PUSHALL) on all the vnodes for this
723 * mount point
724 *
725 * Parameters: mp The mount point
726 *
727 * Returns: 0 Success
728 *
729 * Notes: There is no failure indication for this function.
730 *
731 * This function is used in the unmount path; since it may block
732 * I/O indefinitely, it should not be used in the forced unmount
733 * path, since a device unavailability could also block that
734 * indefinitely.
735 *
736 * Because there is no device ejection interlock on USB, FireWire,
737 * or similar devices, it's possible that an ejection that begins
738 * subsequent to the vnode_iterate() completing, either on one of
739 * those devices, or a network mount for which the server quits
740 * responding, etc., may cause the caller to block indefinitely.
1c79356b 741 */
0b4e3aa0 742__private_extern__ int
1c79356b
A
743ubc_umount(struct mount *mp)
744{
91447636
A
745 vnode_iterate(mp, 0, ubc_umcallback, 0);
746 return(0);
1c79356b
A
747}
748
2d21ac55
A
749
750/*
751 * ubc_umcallback
752 *
753 * Used by ubc_umount() as an internal implementation detail; see ubc_umount()
754 * and vnode_iterate() for details of implementation.
755 */
91447636
A
756static int
757ubc_umcallback(vnode_t vp, __unused void * args)
1c79356b 758{
1c79356b 759
91447636
A
760 if (UBCINFOEXISTS(vp)) {
761
91447636 762 (void) ubc_msync(vp, (off_t)0, ubc_getsize(vp), NULL, UBC_PUSHALL);
1c79356b 763 }
91447636 764 return (VNODE_RETURNED);
1c79356b
A
765}
766
91447636 767
2d21ac55
A
768/*
769 * ubc_getcred
770 *
771 * Get the credentials currently active for the ubc_info associated with the
772 * vnode.
773 *
774 * Parameters: vp The vnode whose ubc_info credentials
775 * are to be retrieved
776 *
777 * Returns: !NOCRED The credentials
778 * NOCRED If there is no ubc_info for the vnode,
779 * or if there is one, but it has not had
780 * any credentials associated with it via
781 * a call to ubc_setcred()
782 */
91447636 783kauth_cred_t
1c79356b
A
784ubc_getcred(struct vnode *vp)
785{
91447636
A
786 if (UBCINFOEXISTS(vp))
787 return (vp->v_ubcinfo->ui_ucred);
1c79356b 788
91447636 789 return (NOCRED);
1c79356b
A
790}
791
2d21ac55
A
792
793/*
794 * ubc_setthreadcred
795 *
796 * If they are not already set, set the credentials of the ubc_info structure
797 * associated with the vnode to those of the supplied thread; otherwise leave
798 * them alone.
799 *
800 * Parameters: vp The vnode whose ubc_info creds are to
801 * be set
802 * p The process whose credentials are to
803 * be used, if not running on an assumed
804 * credential
805 * thread The thread whose credentials are to
806 * be used
807 *
808 * Returns: 1 This vnode has no associated ubc_info
809 * 0 Success
810 *
811 * Notes: This function takes a proc parameter to account for bootstrap
812 * issues where a task or thread may call this routine, either
813 * before credentials have been initialized by bsd_init(), or if
814 * there is no BSD info asscoiate with a mach thread yet. This
815 * is known to happen in both the initial swap and memory mapping
816 * calls.
817 *
818 * This function is generally used only in the following cases:
819 *
820 * o a memory mapped file via the mmap() system call
821 * o a memory mapped file via the deprecated map_fd() call
822 * o a swap store backing file
823 * o subsequent to a successful write via vn_write()
824 *
825 * The information is then used by the NFS client in order to
826 * cons up a wire message in either the page-in or page-out path.
827 *
828 * There are two potential problems with the use of this API:
829 *
830 * o Because the write path only set it on a successful
831 * write, there is a race window between setting the
832 * credential and its use to evict the pages to the
833 * remote file server
834 *
835 * o Because a page-in may occur prior to a write, the
836 * credential may not be set at this time, if the page-in
837 * is not the result of a mapping established via mmap()
838 * or map_fd().
839 *
840 * In both these cases, this will be triggered from the paging
841 * path, which will instead use the credential of the current
842 * process, which in this case is either the dynamic_pager or
843 * the kernel task, both of which utilize "root" credentials.
844 *
845 * This may potentially permit operations to occur which should
846 * be denied, or it may cause to be denied operations which
847 * should be permitted, depending on the configuration of the NFS
848 * server.
849 */
13fec989 850int
2d21ac55 851ubc_setthreadcred(struct vnode *vp, proc_t p, thread_t thread)
13fec989
A
852{
853 struct ubc_info *uip;
854 kauth_cred_t credp;
2d21ac55 855 struct uthread *uthread = get_bsdthread_info(thread);
13fec989
A
856
857 if (!UBCINFOEXISTS(vp))
2d21ac55 858 return (1);
13fec989
A
859
860 vnode_lock(vp);
861
862 uip = vp->v_ubcinfo;
863 credp = uip->ui_ucred;
864
0c530ab8 865 if (!IS_VALID_CRED(credp)) {
13fec989
A
866 /* use per-thread cred, if assumed identity, else proc cred */
867 if (uthread == NULL || (uthread->uu_flag & UT_SETUID) == 0) {
868 uip->ui_ucred = kauth_cred_proc_ref(p);
869 } else {
870 uip->ui_ucred = uthread->uu_ucred;
871 kauth_cred_ref(uip->ui_ucred);
872 }
2d21ac55 873 }
13fec989
A
874 vnode_unlock(vp);
875
876 return (0);
877}
878
2d21ac55 879
1c79356b 880/*
2d21ac55
A
881 * ubc_setcred
882 *
883 * If they are not already set, set the credentials of the ubc_info structure
884 * associated with the vnode to those of the process; otherwise leave them
885 * alone.
886 *
887 * Parameters: vp The vnode whose ubc_info creds are to
888 * be set
889 * p The process whose credentials are to
890 * be used
891 *
892 * Returns: 0 This vnode has no associated ubc_info
893 * 1 Success
894 *
895 * Notes: The return values for this function are inverted from nearly
896 * all other uses in the kernel.
897 *
898 * See also ubc_setthreadcred(), above.
899 *
900 * This function is considered deprecated, and generally should
901 * not be used, as it is incompatible with per-thread credentials;
902 * it exists for legacy KPI reasons.
903 *
904 * DEPRECATION: ubc_setcred() is being deprecated. Please use
905 * ubc_setthreadcred() instead.
1c79356b 906 */
1c79356b 907int
2d21ac55 908ubc_setcred(struct vnode *vp, proc_t p)
1c79356b
A
909{
910 struct ubc_info *uip;
91447636 911 kauth_cred_t credp;
1c79356b 912
2d21ac55
A
913 /* If there is no ubc_info, deny the operation */
914 if ( !UBCINFOEXISTS(vp))
1c79356b 915 return (0);
1c79356b 916
2d21ac55
A
917 /*
918 * Check to see if there is already a credential reference in the
919 * ubc_info; if there is not, take one on the supplied credential.
920 */
91447636 921 vnode_lock(vp);
91447636 922 uip = vp->v_ubcinfo;
1c79356b 923 credp = uip->ui_ucred;
0c530ab8 924 if (!IS_VALID_CRED(credp)) {
91447636 925 uip->ui_ucred = kauth_cred_proc_ref(p);
1c79356b 926 }
91447636 927 vnode_unlock(vp);
1c79356b
A
928
929 return (1);
930}
931
2d21ac55
A
932/*
933 * ubc_getpager
934 *
935 * Get the pager associated with the ubc_info associated with the vnode.
936 *
937 * Parameters: vp The vnode to obtain the pager from
938 *
939 * Returns: !VNODE_PAGER_NULL The memory_object_t for the pager
940 * VNODE_PAGER_NULL There is no ubc_info for this vnode
941 *
942 * Notes: For each vnode that has a ubc_info associated with it, that
943 * ubc_info SHALL have a pager associated with it, so in the
944 * normal case, it's impossible to return VNODE_PAGER_NULL for
945 * a vnode with an associated ubc_info.
946 */
0b4e3aa0 947__private_extern__ memory_object_t
1c79356b
A
948ubc_getpager(struct vnode *vp)
949{
91447636
A
950 if (UBCINFOEXISTS(vp))
951 return (vp->v_ubcinfo->ui_pager);
1c79356b 952
91447636 953 return (0);
1c79356b
A
954}
955
2d21ac55 956
1c79356b 957/*
2d21ac55
A
958 * ubc_getobject
959 *
960 * Get the memory object control associated with the ubc_info associated with
961 * the vnode
962 *
963 * Parameters: vp The vnode to obtain the memory object
964 * from
965 * flags DEPRECATED
966 *
967 * Returns: !MEMORY_OBJECT_CONTROL_NULL
968 * MEMORY_OBJECT_CONTROL_NULL
969 *
970 * Notes: Historically, if the flags were not "do not reactivate", this
971 * function would look up the memory object using the pager if
972 * it did not exist (this could be the case if the vnode had
973 * been previously reactivated). The flags would also permit a
974 * hold to be requested, which would have created an object
975 * reference, if one had not already existed. This usage is
976 * deprecated, as it would permit a race between finding and
977 * taking the reference vs. a single reference being dropped in
978 * another thread.
1c79356b 979 */
0b4e3aa0 980memory_object_control_t
91447636 981ubc_getobject(struct vnode *vp, __unused int flags)
1c79356b 982{
91447636
A
983 if (UBCINFOEXISTS(vp))
984 return((vp->v_ubcinfo->ui_control));
1c79356b 985
2d21ac55 986 return (MEMORY_OBJECT_CONTROL_NULL);
1c79356b
A
987}
988
1c79356b 989
2d21ac55
A
990/*
991 * ubc_blktooff
992 *
993 * Convert a given block number to a memory backing object (file) offset for a
994 * given vnode
995 *
996 * Parameters: vp The vnode in which the block is located
997 * blkno The block number to convert
998 *
999 * Returns: !-1 The offset into the backing object
1000 * -1 There is no ubc_info associated with
1001 * the vnode
1002 * -1 An error occurred in the underlying VFS
1003 * while translating the block to an
1004 * offset; the most likely cause is that
1005 * the caller specified a block past the
1006 * end of the file, but this could also be
1007 * any other error from VNOP_BLKTOOFF().
1008 *
1009 * Note: Representing the error in band loses some information, but does
1010 * not occlude a valid offset, since an off_t of -1 is normally
1011 * used to represent EOF. If we had a more reliable constant in
1012 * our header files for it (i.e. explicitly cast to an off_t), we
1013 * would use it here instead.
1014 */
1c79356b 1015off_t
91447636 1016ubc_blktooff(vnode_t vp, daddr64_t blkno)
1c79356b 1017{
2d21ac55 1018 off_t file_offset = -1;
1c79356b
A
1019 int error;
1020
2d21ac55
A
1021 if (UBCINFOEXISTS(vp)) {
1022 error = VNOP_BLKTOOFF(vp, blkno, &file_offset);
1023 if (error)
1024 file_offset = -1;
1025 }
1c79356b
A
1026
1027 return (file_offset);
1028}
0b4e3aa0 1029
2d21ac55
A
1030
1031/*
1032 * ubc_offtoblk
1033 *
1034 * Convert a given offset in a memory backing object into a block number for a
1035 * given vnode
1036 *
1037 * Parameters: vp The vnode in which the offset is
1038 * located
1039 * offset The offset into the backing object
1040 *
1041 * Returns: !-1 The returned block number
1042 * -1 There is no ubc_info associated with
1043 * the vnode
1044 * -1 An error occurred in the underlying VFS
1045 * while translating the block to an
1046 * offset; the most likely cause is that
1047 * the caller specified a block past the
1048 * end of the file, but this could also be
1049 * any other error from VNOP_OFFTOBLK().
1050 *
1051 * Note: Representing the error in band loses some information, but does
1052 * not occlude a valid block number, since block numbers exceed
1053 * the valid range for offsets, due to their relative sizes. If
1054 * we had a more reliable constant than -1 in our header files
1055 * for it (i.e. explicitly cast to an daddr64_t), we would use it
1056 * here instead.
1057 */
91447636
A
1058daddr64_t
1059ubc_offtoblk(vnode_t vp, off_t offset)
1c79356b 1060{
2d21ac55 1061 daddr64_t blkno = -1;
0b4e3aa0 1062 int error = 0;
1c79356b 1063
2d21ac55
A
1064 if (UBCINFOEXISTS(vp)) {
1065 error = VNOP_OFFTOBLK(vp, offset, &blkno);
1066 if (error)
1067 blkno = -1;
1068 }
1c79356b
A
1069
1070 return (blkno);
1071}
1072
2d21ac55
A
1073
1074/*
1075 * ubc_pages_resident
1076 *
1077 * Determine whether or not a given vnode has pages resident via the memory
1078 * object control associated with the ubc_info associated with the vnode
1079 *
1080 * Parameters: vp The vnode we want to know about
1081 *
1082 * Returns: 1 Yes
1083 * 0 No
1084 */
1c79356b 1085int
91447636 1086ubc_pages_resident(vnode_t vp)
1c79356b 1087{
91447636
A
1088 kern_return_t kret;
1089 boolean_t has_pages_resident;
1090
2d21ac55 1091 if (!UBCINFOEXISTS(vp))
0b4e3aa0 1092 return (0);
91447636 1093
2d21ac55
A
1094 /*
1095 * The following call may fail if an invalid ui_control is specified,
1096 * or if there is no VM object associated with the control object. In
1097 * either case, reacting to it as if there were no pages resident will
1098 * result in correct behavior.
1099 */
91447636
A
1100 kret = memory_object_pages_resident(vp->v_ubcinfo->ui_control, &has_pages_resident);
1101
1102 if (kret != KERN_SUCCESS)
0b4e3aa0 1103 return (0);
91447636
A
1104
1105 if (has_pages_resident == TRUE)
1106 return (1);
1107
1108 return (0);
1109}
1c79356b 1110
1c79356b 1111
1c79356b 1112/*
2d21ac55
A
1113 * ubc_sync_range
1114 *
1115 * Clean and/or invalidate a range in the memory object that backs this vnode
1116 *
1117 * Parameters: vp The vnode whose associated ubc_info's
1118 * associated memory object is to have a
1119 * range invalidated within it
1120 * beg_off The start of the range, as an offset
1121 * end_off The end of the range, as an offset
1122 * flags See ubc_msync_internal()
91447636 1123 *
2d21ac55
A
1124 * Returns: 1 Success
1125 * 0 Failure
91447636 1126 *
2d21ac55
A
1127 * Notes: see ubc_msync_internal() for more detailed information.
1128 *
1129 * DEPRECATED: This interface is obsolete due to a failure to return error
1130 * information needed in order to correct failures. The currently
1131 * recommended interface is ubc_msync().
1c79356b
A
1132 */
1133int
91447636 1134ubc_sync_range(vnode_t vp, off_t beg_off, off_t end_off, int flags)
1c79356b 1135{
91447636 1136 return (ubc_msync_internal(vp, beg_off, end_off, NULL, flags, NULL));
0b4e3aa0
A
1137}
1138
91447636 1139
0b4e3aa0 1140/*
2d21ac55
A
1141 * ubc_msync
1142 *
1143 * Clean and/or invalidate a range in the memory object that backs this vnode
1144 *
1145 * Parameters: vp The vnode whose associated ubc_info's
1146 * associated memory object is to have a
1147 * range invalidated within it
1148 * beg_off The start of the range, as an offset
1149 * end_off The end of the range, as an offset
1150 * resid_off The address of an off_t supplied by the
1151 * caller; may be set to NULL to ignore
1152 * flags See ubc_msync_internal()
1153 *
1154 * Returns: 0 Success
1155 * !0 Failure; an errno is returned
1156 *
1157 * Implicit Returns:
1158 * *resid_off, modified If non-NULL, the contents are ALWAYS
1159 * modified; they are initialized to the
1160 * beg_off, and in case of an I/O error,
1161 * the difference between beg_off and the
1162 * current value will reflect what was
1163 * able to be written before the error
1164 * occurred. If no error is returned, the
1165 * value of the resid_off is undefined; do
1166 * NOT use it in place of end_off if you
1167 * intend to increment from the end of the
1168 * last call and call iteratively.
1169 *
1170 * Notes: see ubc_msync_internal() for more detailed information.
1171 *
0b4e3aa0 1172 */
91447636
A
1173errno_t
1174ubc_msync(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags)
0b4e3aa0 1175{
91447636
A
1176 int retval;
1177 int io_errno = 0;
1178
1179 if (resid_off)
1180 *resid_off = beg_off;
0b4e3aa0 1181
91447636 1182 retval = ubc_msync_internal(vp, beg_off, end_off, resid_off, flags, &io_errno);
0b4e3aa0 1183
91447636
A
1184 if (retval == 0 && io_errno == 0)
1185 return (EINVAL);
1186 return (io_errno);
1187}
0b4e3aa0 1188
1c79356b 1189
1c79356b 1190/*
2d21ac55
A
1191 * Clean and/or invalidate a range in the memory object that backs this vnode
1192 *
1193 * Parameters: vp The vnode whose associated ubc_info's
1194 * associated memory object is to have a
1195 * range invalidated within it
1196 * beg_off The start of the range, as an offset
1197 * end_off The end of the range, as an offset
1198 * resid_off The address of an off_t supplied by the
1199 * caller; may be set to NULL to ignore
1200 * flags MUST contain at least one of the flags
1201 * UBC_INVALIDATE, UBC_PUSHDIRTY, or
1202 * UBC_PUSHALL; if UBC_PUSHDIRTY is used,
1203 * UBC_SYNC may also be specified to cause
1204 * this function to block until the
1205 * operation is complete. The behavior
1206 * of UBC_SYNC is otherwise undefined.
1207 * io_errno The address of an int to contain the
1208 * errno from a failed I/O operation, if
1209 * one occurs; may be set to NULL to
1210 * ignore
1211 *
1212 * Returns: 1 Success
1213 * 0 Failure
1214 *
1215 * Implicit Returns:
1216 * *resid_off, modified The contents of this offset MAY be
1217 * modified; in case of an I/O error, the
1218 * difference between beg_off and the
1219 * current value will reflect what was
1220 * able to be written before the error
1221 * occurred.
1222 * *io_errno, modified The contents of this offset are set to
1223 * an errno, if an error occurs; if the
1224 * caller supplies an io_errno parameter,
1225 * they should be careful to initialize it
1226 * to 0 before calling this function to
1227 * enable them to distinguish an error
1228 * with a valid *resid_off from an invalid
1229 * one, and to avoid potentially falsely
1230 * reporting an error, depending on use.
1231 *
1232 * Notes: If there is no ubc_info associated with the vnode supplied,
1233 * this function immediately returns success.
1234 *
1235 * If the value of end_off is less than or equal to beg_off, this
1236 * function immediately returns success; that is, end_off is NOT
1237 * inclusive.
1238 *
1239 * IMPORTANT: one of the flags UBC_INVALIDATE, UBC_PUSHDIRTY, or
1240 * UBC_PUSHALL MUST be specified; that is, it is NOT possible to
1241 * attempt to block on in-progress I/O by calling this function
1242 * with UBC_PUSHDIRTY, and then later call it with just UBC_SYNC
1243 * in order to block pending on the I/O already in progress.
1244 *
1245 * The start offset is truncated to the page boundary and the
1246 * size is adjusted to include the last page in the range; that
1247 * is, end_off on exactly a page boundary will not change if it
1248 * is rounded, and the range of bytes written will be from the
1249 * truncate beg_off to the rounded (end_off - 1).
1c79356b 1250 */
91447636
A
1251static int
1252ubc_msync_internal(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags, int *io_errno)
1c79356b 1253{
91447636
A
1254 memory_object_size_t tsize;
1255 kern_return_t kret;
1256 int request_flags = 0;
1257 int flush_flags = MEMORY_OBJECT_RETURN_NONE;
1258
1259 if ( !UBCINFOEXISTS(vp))
1260 return (0);
91447636
A
1261 if ((flags & (UBC_INVALIDATE | UBC_PUSHDIRTY | UBC_PUSHALL)) == 0)
1262 return (0);
2d21ac55
A
1263 if (end_off <= beg_off)
1264 return (1);
91447636
A
1265
1266 if (flags & UBC_INVALIDATE)
1267 /*
1268 * discard the resident pages
1269 */
1270 request_flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE);
1c79356b 1271
91447636
A
1272 if (flags & UBC_SYNC)
1273 /*
1274 * wait for all the I/O to complete before returning
55e303ae 1275 */
91447636 1276 request_flags |= MEMORY_OBJECT_IO_SYNC;
55e303ae 1277
91447636
A
1278 if (flags & UBC_PUSHDIRTY)
1279 /*
1280 * we only return the dirty pages in the range
1281 */
1282 flush_flags = MEMORY_OBJECT_RETURN_DIRTY;
0b4e3aa0 1283
91447636
A
1284 if (flags & UBC_PUSHALL)
1285 /*
2d21ac55
A
1286 * then return all the interesting pages in the range (both
1287 * dirty and precious) to the pager
91447636
A
1288 */
1289 flush_flags = MEMORY_OBJECT_RETURN_ALL;
0b4e3aa0 1290
91447636
A
1291 beg_off = trunc_page_64(beg_off);
1292 end_off = round_page_64(end_off);
1293 tsize = (memory_object_size_t)end_off - beg_off;
b4c24cb9 1294
91447636
A
1295 /* flush and/or invalidate pages in the range requested */
1296 kret = memory_object_lock_request(vp->v_ubcinfo->ui_control,
2d21ac55
A
1297 beg_off, tsize,
1298 (memory_object_offset_t *)resid_off,
1299 io_errno, flush_flags, request_flags,
1300 VM_PROT_NO_CHANGE);
91447636
A
1301
1302 return ((kret == KERN_SUCCESS) ? 1 : 0);
1c79356b
A
1303}
1304
1c79356b
A
1305
1306/*
2d21ac55
A
1307 * ubc_msync_internal
1308 *
1309 * Explicitly map a vnode that has an associate ubc_info, and add a reference
1310 * to it for the ubc system, if there isn't one already, so it will not be
1311 * recycled while it's in use, and set flags on the ubc_info to indicate that
1312 * we have done this
1313 *
1314 * Parameters: vp The vnode to map
1315 * flags The mapping flags for the vnode; this
1316 * will be a combination of one or more of
1317 * PROT_READ, PROT_WRITE, and PROT_EXEC
1318 *
1319 * Returns: 0 Success
1320 * EPERM Permission was denied
1321 *
1322 * Notes: An I/O reference on the vnode must already be held on entry
1323 *
1324 * If there is no ubc_info associated with the vnode, this function
1325 * will return success.
1326 *
1327 * If a permission error occurs, this function will return
1328 * failure; all other failures will cause this function to return
1329 * success.
1330 *
1331 * IMPORTANT: This is an internal use function, and its symbols
1332 * are not exported, hence its error checking is not very robust.
1333 * It is primarily used by:
1334 *
1335 * o mmap(), when mapping a file
1336 * o The deprecated map_fd() interface, when mapping a file
1337 * o When mapping a shared file (a shared library in the
1338 * shared segment region)
1339 * o When loading a program image during the exec process
1340 *
1341 * ...all of these uses ignore the return code, and any fault that
1342 * results later because of a failure is handled in the fix-up path
1343 * of the fault handler. The interface exists primarily as a
1344 * performance hint.
1345 *
1346 * Given that third party implementation of the type of interfaces
1347 * that would use this function, such as alternative executable
1348 * formats, etc., are unsupported, this function is not exported
1349 * for general use.
1350 *
1351 * The extra reference is held until the VM system unmaps the
1352 * vnode from its own context to maintain a vnode reference in
1353 * cases like open()/mmap()/close(), which leave the backing
1354 * object referenced by a mapped memory region in a process
1355 * address space.
1c79356b 1356 */
91447636
A
1357__private_extern__ int
1358ubc_map(vnode_t vp, int flags)
1c79356b
A
1359{
1360 struct ubc_info *uip;
91447636
A
1361 int error = 0;
1362 int need_ref = 0;
2d21ac55 1363 int need_wakeup = 0;
1c79356b 1364
91447636 1365 if (UBCINFOEXISTS(vp)) {
1c79356b 1366
2d21ac55
A
1367 vnode_lock(vp);
1368 uip = vp->v_ubcinfo;
1369
1370 while (ISSET(uip->ui_flags, UI_MAPBUSY)) {
1371 SET(uip->ui_flags, UI_MAPWAITING);
1372 (void) msleep(&uip->ui_flags, &vp->v_lock,
1373 PRIBIO, "ubc_map", NULL);
1374 }
1375 SET(uip->ui_flags, UI_MAPBUSY);
1376 vnode_unlock(vp);
1377
1378 error = VNOP_MMAP(vp, flags, vfs_context_current());
1c79356b 1379
91447636
A
1380 if (error != EPERM)
1381 error = 0;
1c79356b 1382
2d21ac55 1383 vnode_lock_spin(vp);
1c79356b 1384
2d21ac55 1385 if (error == 0) {
91447636
A
1386 if ( !ISSET(uip->ui_flags, UI_ISMAPPED))
1387 need_ref = 1;
1388 SET(uip->ui_flags, (UI_WASMAPPED | UI_ISMAPPED));
2d21ac55
A
1389 }
1390 CLR(uip->ui_flags, UI_MAPBUSY);
55e303ae 1391
2d21ac55
A
1392 if (ISSET(uip->ui_flags, UI_MAPWAITING)) {
1393 CLR(uip->ui_flags, UI_MAPWAITING);
1394 need_wakeup = 1;
55e303ae 1395 }
2d21ac55 1396 vnode_unlock(vp);
b4c24cb9 1397
2d21ac55
A
1398 if (need_wakeup)
1399 wakeup(&uip->ui_flags);
1400
1401 if (need_ref)
1402 vnode_ref(vp);
1403 }
91447636 1404 return (error);
0b4e3aa0
A
1405}
1406
2d21ac55 1407
0b4e3aa0 1408/*
2d21ac55
A
1409 * ubc_destroy_named
1410 *
1411 * Destroy the named memory object associated with the ubc_info control object
1412 * associated with the designated vnode, if there is a ubc_info associated
1413 * with the vnode, and a control object is associated with it
1414 *
1415 * Parameters: vp The designated vnode
1416 *
1417 * Returns: (void)
1418 *
1419 * Notes: This function is called on vnode termination for all vnodes,
1420 * and must therefore not assume that there is a ubc_info that is
1421 * associated with the vnode, nor that there is a control object
1422 * associated with the ubc_info.
1423 *
1424 * If all the conditions necessary are present, this function
1425 * calls memory_object_destory(), which will in turn end up
1426 * calling ubc_unmap() to release any vnode references that were
1427 * established via ubc_map().
1428 *
1429 * IMPORTANT: This is an internal use function that is used
1430 * exclusively by the internal use function vclean().
0b4e3aa0 1431 */
2d21ac55
A
1432__private_extern__ void
1433ubc_destroy_named(vnode_t vp)
0b4e3aa0
A
1434{
1435 memory_object_control_t control;
0b4e3aa0
A
1436 struct ubc_info *uip;
1437 kern_return_t kret;
1438
2d21ac55
A
1439 if (UBCINFOEXISTS(vp)) {
1440 uip = vp->v_ubcinfo;
1441
1442 /* Terminate the memory object */
1443 control = ubc_getobject(vp, UBC_HOLDOBJECT);
1444 if (control != MEMORY_OBJECT_CONTROL_NULL) {
1445 kret = memory_object_destroy(control, 0);
1446 if (kret != KERN_SUCCESS)
1447 panic("ubc_destroy_named: memory_object_destroy failed");
0b4e3aa0
A
1448 }
1449 }
1c79356b
A
1450}
1451
0b4e3aa0 1452
1c79356b 1453/*
2d21ac55
A
1454 * ubc_isinuse
1455 *
1456 * Determine whether or not a vnode is currently in use by ubc at a level in
1457 * excess of the requested busycount
1458 *
1459 * Parameters: vp The vnode to check
1460 * busycount The threshold busy count, used to bias
1461 * the count usually already held by the
1462 * caller to avoid races
1463 *
1464 * Returns: 1 The vnode is in use over the threshold
1465 * 0 The vnode is not in use over the
1466 * threshold
1467 *
1468 * Notes: Because the vnode is only held locked while actually asking
1469 * the use count, this function only represents a snapshot of the
1470 * current state of the vnode. If more accurate information is
1471 * required, an additional busycount should be held by the caller
1472 * and a non-zero busycount used.
1473 *
1474 * If there is no ubc_info associated with the vnode, this
1475 * function will report that the vnode is not in use by ubc.
1c79356b
A
1476 */
1477int
91447636 1478ubc_isinuse(struct vnode *vp, int busycount)
1c79356b 1479{
91447636 1480 if ( !UBCINFOEXISTS(vp))
0b4e3aa0 1481 return (0);
91447636 1482 return(ubc_isinuse_locked(vp, busycount, 0));
1c79356b
A
1483}
1484
91447636 1485
2d21ac55
A
1486/*
1487 * ubc_isinuse_locked
1488 *
1489 * Determine whether or not a vnode is currently in use by ubc at a level in
1490 * excess of the requested busycount
1491 *
1492 * Parameters: vp The vnode to check
1493 * busycount The threshold busy count, used to bias
1494 * the count usually already held by the
1495 * caller to avoid races
1496 * locked True if the vnode is already locked by
1497 * the caller
1498 *
1499 * Returns: 1 The vnode is in use over the threshold
1500 * 0 The vnode is not in use over the
1501 * threshold
1502 *
1503 * Notes: If the vnode is not locked on entry, it is locked while
1504 * actually asking the use count. If this is the case, this
1505 * function only represents a snapshot of the current state of
1506 * the vnode. If more accurate information is required, the
1507 * vnode lock should be held by the caller, otherwise an
1508 * additional busycount should be held by the caller and a
1509 * non-zero busycount used.
1510 *
1511 * If there is no ubc_info associated with the vnode, this
1512 * function will report that the vnode is not in use by ubc.
1513 */
1c79356b 1514int
91447636 1515ubc_isinuse_locked(struct vnode *vp, int busycount, int locked)
1c79356b 1516{
91447636 1517 int retval = 0;
1c79356b 1518
9bccf70c 1519
91447636 1520 if (!locked)
b0d623f7 1521 vnode_lock_spin(vp);
1c79356b 1522
91447636
A
1523 if ((vp->v_usecount - vp->v_kusecount) > busycount)
1524 retval = 1;
1525
1526 if (!locked)
1527 vnode_unlock(vp);
1528 return (retval);
1c79356b
A
1529}
1530
91447636 1531
1c79356b 1532/*
2d21ac55
A
1533 * ubc_unmap
1534 *
1535 * Reverse the effects of a ubc_map() call for a given vnode
1536 *
1537 * Parameters: vp vnode to unmap from ubc
1538 *
1539 * Returns: (void)
1540 *
1541 * Notes: This is an internal use function used by vnode_pager_unmap().
1542 * It will attempt to obtain a reference on the supplied vnode,
1543 * and if it can do so, and there is an associated ubc_info, and
1544 * the flags indicate that it was mapped via ubc_map(), then the
1545 * flag is cleared, the mapping removed, and the reference taken
1546 * by ubc_map() is released.
1547 *
1548 * IMPORTANT: This MUST only be called by the VM
1549 * to prevent race conditions.
1c79356b 1550 */
0b4e3aa0 1551__private_extern__ void
1c79356b
A
1552ubc_unmap(struct vnode *vp)
1553{
1554 struct ubc_info *uip;
91447636 1555 int need_rele = 0;
2d21ac55 1556 int need_wakeup = 0;
b0d623f7 1557
91447636
A
1558 if (vnode_getwithref(vp))
1559 return;
1c79356b 1560
91447636
A
1561 if (UBCINFOEXISTS(vp)) {
1562 vnode_lock(vp);
91447636 1563 uip = vp->v_ubcinfo;
2d21ac55
A
1564
1565 while (ISSET(uip->ui_flags, UI_MAPBUSY)) {
1566 SET(uip->ui_flags, UI_MAPWAITING);
1567 (void) msleep(&uip->ui_flags, &vp->v_lock,
1568 PRIBIO, "ubc_unmap", NULL);
1569 }
1570 SET(uip->ui_flags, UI_MAPBUSY);
1571
91447636 1572 if (ISSET(uip->ui_flags, UI_ISMAPPED)) {
b0d623f7 1573 CLR(uip->ui_flags, UI_ISMAPPED);
91447636
A
1574 need_rele = 1;
1575 }
1576 vnode_unlock(vp);
b0d623f7 1577
91447636 1578 if (need_rele) {
b0d623f7
A
1579 (void)VNOP_MNOMAP(vp, vfs_context_current());
1580 vnode_rele(vp);
91447636 1581 }
2d21ac55
A
1582
1583 vnode_lock_spin(vp);
1584
1585 CLR(uip->ui_flags, UI_MAPBUSY);
1586 if (ISSET(uip->ui_flags, UI_MAPWAITING)) {
1587 CLR(uip->ui_flags, UI_MAPWAITING);
1588 need_wakeup = 1;
1589 }
1590 vnode_unlock(vp);
1591
1592 if (need_wakeup)
b0d623f7 1593 wakeup(&uip->ui_flags);
2d21ac55 1594
91447636
A
1595 }
1596 /*
1597 * the drop of the vnode ref will cleanup
1598 */
1599 vnode_put(vp);
0b4e3aa0
A
1600}
1601
2d21ac55
A
1602
1603/*
1604 * ubc_page_op
1605 *
1606 * Manipulate individual page state for a vnode with an associated ubc_info
1607 * with an associated memory object control.
1608 *
1609 * Parameters: vp The vnode backing the page
1610 * f_offset A file offset interior to the page
1611 * ops The operations to perform, as a bitmap
1612 * (see below for more information)
1613 * phys_entryp The address of a ppnum_t; may be NULL
1614 * to ignore
1615 * flagsp A pointer to an int to contain flags;
1616 * may be NULL to ignore
1617 *
1618 * Returns: KERN_SUCCESS Success
1619 * KERN_INVALID_ARGUMENT If the memory object control has no VM
1620 * object associated
1621 * KERN_INVALID_OBJECT If UPL_POP_PHYSICAL and the object is
1622 * not physically contiguous
1623 * KERN_INVALID_OBJECT If !UPL_POP_PHYSICAL and the object is
1624 * physically contiguous
1625 * KERN_FAILURE If the page cannot be looked up
1626 *
1627 * Implicit Returns:
1628 * *phys_entryp (modified) If phys_entryp is non-NULL and
1629 * UPL_POP_PHYSICAL
1630 * *flagsp (modified) If flagsp is non-NULL and there was
1631 * !UPL_POP_PHYSICAL and a KERN_SUCCESS
1632 *
1633 * Notes: For object boundaries, it is considerably more efficient to
1634 * ensure that f_offset is in fact on a page boundary, as this
1635 * will avoid internal use of the hash table to identify the
1636 * page, and would therefore skip a number of early optimizations.
1637 * Since this is a page operation anyway, the caller should try
1638 * to pass only a page aligned offset because of this.
1639 *
1640 * *flagsp may be modified even if this function fails. If it is
1641 * modified, it will contain the condition of the page before the
1642 * requested operation was attempted; these will only include the
1643 * bitmap flags, and not the PL_POP_PHYSICAL, UPL_POP_DUMP,
1644 * UPL_POP_SET, or UPL_POP_CLR bits.
1645 *
1646 * The flags field may contain a specific operation, such as
1647 * UPL_POP_PHYSICAL or UPL_POP_DUMP:
1648 *
1649 * o UPL_POP_PHYSICAL Fail if not contiguous; if
1650 * *phys_entryp and successful, set
1651 * *phys_entryp
1652 * o UPL_POP_DUMP Dump the specified page
1653 *
1654 * Otherwise, it is treated as a bitmap of one or more page
1655 * operations to perform on the final memory object; allowable
1656 * bit values are:
1657 *
1658 * o UPL_POP_DIRTY The page is dirty
1659 * o UPL_POP_PAGEOUT The page is paged out
1660 * o UPL_POP_PRECIOUS The page is precious
1661 * o UPL_POP_ABSENT The page is absent
1662 * o UPL_POP_BUSY The page is busy
1663 *
1664 * If the page status is only being queried and not modified, then
1665 * not other bits should be specified. However, if it is being
1666 * modified, exactly ONE of the following bits should be set:
1667 *
1668 * o UPL_POP_SET Set the current bitmap bits
1669 * o UPL_POP_CLR Clear the current bitmap bits
1670 *
1671 * Thus to effect a combination of setting an clearing, it may be
1672 * necessary to call this function twice. If this is done, the
1673 * set should be used before the clear, since clearing may trigger
1674 * a wakeup on the destination page, and if the page is backed by
1675 * an encrypted swap file, setting will trigger the decryption
1676 * needed before the wakeup occurs.
1677 */
0b4e3aa0
A
1678kern_return_t
1679ubc_page_op(
1680 struct vnode *vp,
1681 off_t f_offset,
1682 int ops,
55e303ae 1683 ppnum_t *phys_entryp,
0b4e3aa0
A
1684 int *flagsp)
1685{
1686 memory_object_control_t control;
1687
1688 control = ubc_getobject(vp, UBC_FLAGS_NONE);
1689 if (control == MEMORY_OBJECT_CONTROL_NULL)
1690 return KERN_INVALID_ARGUMENT;
1691
1692 return (memory_object_page_op(control,
1693 (memory_object_offset_t)f_offset,
1694 ops,
1695 phys_entryp,
1696 flagsp));
1697}
2d21ac55
A
1698
1699
1700/*
1701 * ubc_range_op
1702 *
1703 * Manipulate page state for a range of memory for a vnode with an associated
1704 * ubc_info with an associated memory object control, when page level state is
1705 * not required to be returned from the call (i.e. there are no phys_entryp or
1706 * flagsp parameters to this call, and it takes a range which may contain
1707 * multiple pages, rather than an offset interior to a single page).
1708 *
1709 * Parameters: vp The vnode backing the page
1710 * f_offset_beg A file offset interior to the start page
1711 * f_offset_end A file offset interior to the end page
1712 * ops The operations to perform, as a bitmap
1713 * (see below for more information)
1714 * range The address of an int; may be NULL to
1715 * ignore
1716 *
1717 * Returns: KERN_SUCCESS Success
1718 * KERN_INVALID_ARGUMENT If the memory object control has no VM
1719 * object associated
1720 * KERN_INVALID_OBJECT If the object is physically contiguous
1721 *
1722 * Implicit Returns:
1723 * *range (modified) If range is non-NULL, its contents will
1724 * be modified to contain the number of
1725 * bytes successfully operated upon.
1726 *
1727 * Notes: IMPORTANT: This function cannot be used on a range that
1728 * consists of physically contiguous pages.
1729 *
1730 * For object boundaries, it is considerably more efficient to
1731 * ensure that f_offset_beg and f_offset_end are in fact on page
1732 * boundaries, as this will avoid internal use of the hash table
1733 * to identify the page, and would therefore skip a number of
1734 * early optimizations. Since this is an operation on a set of
1735 * pages anyway, the caller should try to pass only a page aligned
1736 * offsets because of this.
1737 *
1738 * *range will be modified only if this function succeeds.
1739 *
1740 * The flags field MUST contain a specific operation; allowable
1741 * values are:
1742 *
1743 * o UPL_ROP_ABSENT Returns the extent of the range
1744 * presented which is absent, starting
1745 * with the start address presented
1746 *
1747 * o UPL_ROP_PRESENT Returns the extent of the range
1748 * presented which is present (resident),
1749 * starting with the start address
1750 * presented
1751 * o UPL_ROP_DUMP Dump the pages which are found in the
1752 * target object for the target range.
1753 *
1754 * IMPORTANT: For UPL_ROP_ABSENT and UPL_ROP_PRESENT; if there are
1755 * multiple regions in the range, only the first matching region
1756 * is returned.
1757 */
55e303ae
A
1758kern_return_t
1759ubc_range_op(
1760 struct vnode *vp,
1761 off_t f_offset_beg,
1762 off_t f_offset_end,
1763 int ops,
1764 int *range)
1765{
1766 memory_object_control_t control;
1767
1768 control = ubc_getobject(vp, UBC_FLAGS_NONE);
1769 if (control == MEMORY_OBJECT_CONTROL_NULL)
1770 return KERN_INVALID_ARGUMENT;
1771
1772 return (memory_object_range_op(control,
1773 (memory_object_offset_t)f_offset_beg,
1774 (memory_object_offset_t)f_offset_end,
1775 ops,
1776 range));
1777}
2d21ac55
A
1778
1779
1780/*
1781 * ubc_create_upl
1782 *
1783 * Given a vnode, cause the population of a portion of the vm_object; based on
1784 * the nature of the request, the pages returned may contain valid data, or
1785 * they may be uninitialized.
1786 *
1787 * Parameters: vp The vnode from which to create the upl
1788 * f_offset The start offset into the backing store
1789 * represented by the vnode
1790 * bufsize The size of the upl to create
1791 * uplp Pointer to the upl_t to receive the
1792 * created upl; MUST NOT be NULL
1793 * plp Pointer to receive the internal page
1794 * list for the created upl; MAY be NULL
1795 * to ignore
1796 *
1797 * Returns: KERN_SUCCESS The requested upl has been created
1798 * KERN_INVALID_ARGUMENT The bufsize argument is not an even
1799 * multiple of the page size
1800 * KERN_INVALID_ARGUMENT There is no ubc_info associated with
1801 * the vnode, or there is no memory object
1802 * control associated with the ubc_info
1803 * memory_object_upl_request:KERN_INVALID_VALUE
1804 * The supplied upl_flags argument is
1805 * invalid
1806 * Implicit Returns:
1807 * *uplp (modified)
1808 * *plp (modified) If non-NULL, the value of *plp will be
1809 * modified to point to the internal page
1810 * list; this modification may occur even
1811 * if this function is unsuccessful, in
1812 * which case the contents may be invalid
1813 *
1814 * Note: If successful, the returned *uplp MUST subsequently be freed
1815 * via a call to ubc_upl_commit(), ubc_upl_commit_range(),
1816 * ubc_upl_abort(), or ubc_upl_abort_range().
1817 */
0b4e3aa0
A
1818kern_return_t
1819ubc_create_upl(
1820 struct vnode *vp,
2d21ac55 1821 off_t f_offset,
b0d623f7 1822 int bufsize,
2d21ac55 1823 upl_t *uplp,
0b4e3aa0 1824 upl_page_info_t **plp,
2d21ac55 1825 int uplflags)
0b4e3aa0
A
1826{
1827 memory_object_control_t control;
55e303ae 1828 kern_return_t kr;
b0d623f7
A
1829
1830 if (plp != NULL)
1831 *plp = NULL;
1832 *uplp = NULL;
0b4e3aa0
A
1833
1834 if (bufsize & 0xfff)
1835 return KERN_INVALID_ARGUMENT;
1836
b0d623f7
A
1837 if (uplflags & (UPL_UBC_MSYNC | UPL_UBC_PAGEOUT | UPL_UBC_PAGEIN)) {
1838
1839 if (uplflags & UPL_UBC_MSYNC) {
1840 uplflags &= UPL_RET_ONLY_DIRTY;
1841
1842 uplflags |= UPL_COPYOUT_FROM | UPL_CLEAN_IN_PLACE |
1843 UPL_SET_INTERNAL | UPL_SET_LITE;
1844
1845 } else if (uplflags & UPL_UBC_PAGEOUT) {
1846 uplflags &= UPL_RET_ONLY_DIRTY;
1847
1848 if (uplflags & UPL_RET_ONLY_DIRTY)
1849 uplflags |= UPL_NOBLOCK;
1850
1851 uplflags |= UPL_FOR_PAGEOUT | UPL_CLEAN_IN_PLACE |
1852 UPL_COPYOUT_FROM | UPL_SET_INTERNAL | UPL_SET_LITE;
1853 } else {
1854 uplflags |= UPL_RET_ONLY_ABSENT | UPL_NOBLOCK |
1855 UPL_NO_SYNC | UPL_CLEAN_IN_PLACE |
1856 UPL_SET_INTERNAL | UPL_SET_LITE;
1857 }
1858 } else {
55e303ae 1859 uplflags &= ~UPL_FOR_PAGEOUT;
55e303ae 1860
b0d623f7
A
1861 if (uplflags & UPL_WILL_BE_DUMPED) {
1862 uplflags &= ~UPL_WILL_BE_DUMPED;
1863 uplflags |= (UPL_NO_SYNC|UPL_SET_INTERNAL);
1864 } else
1865 uplflags |= (UPL_NO_SYNC|UPL_CLEAN_IN_PLACE|UPL_SET_INTERNAL);
1866 }
1867 control = ubc_getobject(vp, UBC_FLAGS_NONE);
0b4e3aa0
A
1868 if (control == MEMORY_OBJECT_CONTROL_NULL)
1869 return KERN_INVALID_ARGUMENT;
1870
b0d623f7
A
1871 kr = memory_object_upl_request(control, f_offset, bufsize, uplp, NULL, NULL, uplflags);
1872 if (kr == KERN_SUCCESS && plp != NULL)
1873 *plp = UPL_GET_INTERNAL_PAGE_LIST(*uplp);
0b4e3aa0
A
1874 return kr;
1875}
2d21ac55
A
1876
1877
1878/*
1879 * ubc_upl_maxbufsize
1880 *
1881 * Return the maximum bufsize ubc_create_upl( ) will take.
1882 *
1883 * Parameters: none
1884 *
1885 * Returns: maximum size buffer (in bytes) ubc_create_upl( ) will take.
1886 */
1887upl_size_t
1888ubc_upl_maxbufsize(
1889 void)
1890{
cf7d32b8 1891 return(MAX_UPL_SIZE * PAGE_SIZE);
2d21ac55 1892}
0b4e3aa0 1893
2d21ac55
A
1894/*
1895 * ubc_upl_map
1896 *
1897 * Map the page list assocated with the supplied upl into the kernel virtual
1898 * address space at the virtual address indicated by the dst_addr argument;
1899 * the entire upl is mapped
1900 *
1901 * Parameters: upl The upl to map
1902 * dst_addr The address at which to map the upl
1903 *
1904 * Returns: KERN_SUCCESS The upl has been mapped
1905 * KERN_INVALID_ARGUMENT The upl is UPL_NULL
1906 * KERN_FAILURE The upl is already mapped
1907 * vm_map_enter:KERN_INVALID_ARGUMENT
1908 * A failure code from vm_map_enter() due
1909 * to an invalid argument
1910 */
0b4e3aa0
A
1911kern_return_t
1912ubc_upl_map(
1913 upl_t upl,
1914 vm_offset_t *dst_addr)
1915{
1916 return (vm_upl_map(kernel_map, upl, dst_addr));
1917}
1918
1919
2d21ac55
A
1920/*
1921 * ubc_upl_unmap
1922 *
1923 * Unmap the page list assocated with the supplied upl from the kernel virtual
1924 * address space; the entire upl is unmapped.
1925 *
1926 * Parameters: upl The upl to unmap
1927 *
1928 * Returns: KERN_SUCCESS The upl has been unmapped
1929 * KERN_FAILURE The upl is not currently mapped
1930 * KERN_INVALID_ARGUMENT If the upl is UPL_NULL
1931 */
0b4e3aa0
A
1932kern_return_t
1933ubc_upl_unmap(
1934 upl_t upl)
1935{
1936 return(vm_upl_unmap(kernel_map, upl));
1937}
1938
2d21ac55
A
1939
1940/*
1941 * ubc_upl_commit
1942 *
1943 * Commit the contents of the upl to the backing store
1944 *
1945 * Parameters: upl The upl to commit
1946 *
1947 * Returns: KERN_SUCCESS The upl has been committed
1948 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
1949 * KERN_FAILURE The supplied upl does not represent
1950 * device memory, and the offset plus the
1951 * size would exceed the actual size of
1952 * the upl
1953 *
1954 * Notes: In practice, the only return value for this function should be
1955 * KERN_SUCCESS, unless there has been data structure corruption;
1956 * since the upl is deallocated regardless of success or failure,
1957 * there's really nothing to do about this other than panic.
1958 *
1959 * IMPORTANT: Use of this function should not be mixed with use of
1960 * ubc_upl_commit_range(), due to the unconditional deallocation
1961 * by this function.
1962 */
0b4e3aa0
A
1963kern_return_t
1964ubc_upl_commit(
1965 upl_t upl)
1966{
1967 upl_page_info_t *pl;
1968 kern_return_t kr;
1969
1970 pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
cf7d32b8 1971 kr = upl_commit(upl, pl, MAX_UPL_SIZE);
0b4e3aa0
A
1972 upl_deallocate(upl);
1973 return kr;
1c79356b
A
1974}
1975
0b4e3aa0 1976
2d21ac55
A
1977/*
1978 * ubc_upl_commit
1979 *
1980 * Commit the contents of the specified range of the upl to the backing store
1981 *
1982 * Parameters: upl The upl to commit
1983 * offset The offset into the upl
1984 * size The size of the region to be committed,
1985 * starting at the specified offset
1986 * flags commit type (see below)
1987 *
1988 * Returns: KERN_SUCCESS The range has been committed
1989 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
1990 * KERN_FAILURE The supplied upl does not represent
1991 * device memory, and the offset plus the
1992 * size would exceed the actual size of
1993 * the upl
1994 *
1995 * Notes: IMPORTANT: If the commit is successful, and the object is now
1996 * empty, the upl will be deallocated. Since the caller cannot
1997 * check that this is the case, the UPL_COMMIT_FREE_ON_EMPTY flag
1998 * should generally only be used when the offset is 0 and the size
1999 * is equal to the upl size.
2000 *
2001 * The flags argument is a bitmap of flags on the rage of pages in
2002 * the upl to be committed; allowable flags are:
2003 *
2004 * o UPL_COMMIT_FREE_ON_EMPTY Free the upl when it is
2005 * both empty and has been
2006 * successfully committed
2007 * o UPL_COMMIT_CLEAR_DIRTY Clear each pages dirty
2008 * bit; will prevent a
2009 * later pageout
2010 * o UPL_COMMIT_SET_DIRTY Set each pages dirty
2011 * bit; will cause a later
2012 * pageout
2013 * o UPL_COMMIT_INACTIVATE Clear each pages
2014 * reference bit; the page
2015 * will not be accessed
2016 * o UPL_COMMIT_ALLOW_ACCESS Unbusy each page; pages
2017 * become busy when an
2018 * IOMemoryDescriptor is
2019 * mapped or redirected,
2020 * and we have to wait for
2021 * an IOKit driver
2022 *
2023 * The flag UPL_COMMIT_NOTIFY_EMPTY is used internally, and should
2024 * not be specified by the caller.
2025 *
2026 * The UPL_COMMIT_CLEAR_DIRTY and UPL_COMMIT_SET_DIRTY flags are
2027 * mutually exclusive, and should not be combined.
2028 */
0b4e3aa0
A
2029kern_return_t
2030ubc_upl_commit_range(
2031 upl_t upl,
b0d623f7
A
2032 upl_offset_t offset,
2033 upl_size_t size,
0b4e3aa0
A
2034 int flags)
2035{
2036 upl_page_info_t *pl;
2037 boolean_t empty;
2038 kern_return_t kr;
2039
2040 if (flags & UPL_COMMIT_FREE_ON_EMPTY)
2041 flags |= UPL_COMMIT_NOTIFY_EMPTY;
2042
593a1d5f
A
2043 if (flags & UPL_COMMIT_KERNEL_ONLY_FLAGS) {
2044 return KERN_INVALID_ARGUMENT;
2045 }
2046
0b4e3aa0
A
2047 pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
2048
2049 kr = upl_commit_range(upl, offset, size, flags,
cf7d32b8 2050 pl, MAX_UPL_SIZE, &empty);
0b4e3aa0
A
2051
2052 if((flags & UPL_COMMIT_FREE_ON_EMPTY) && empty)
2053 upl_deallocate(upl);
2054
2055 return kr;
2056}
2d21ac55
A
2057
2058
2059/*
2060 * ubc_upl_abort_range
2061 *
2062 * Abort the contents of the specified range of the specified upl
2063 *
2064 * Parameters: upl The upl to abort
2065 * offset The offset into the upl
2066 * size The size of the region to be aborted,
2067 * starting at the specified offset
2068 * abort_flags abort type (see below)
2069 *
2070 * Returns: KERN_SUCCESS The range has been aborted
2071 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2072 * KERN_FAILURE The supplied upl does not represent
2073 * device memory, and the offset plus the
2074 * size would exceed the actual size of
2075 * the upl
2076 *
2077 * Notes: IMPORTANT: If the abort is successful, and the object is now
2078 * empty, the upl will be deallocated. Since the caller cannot
2079 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2080 * should generally only be used when the offset is 0 and the size
2081 * is equal to the upl size.
2082 *
2083 * The abort_flags argument is a bitmap of flags on the range of
2084 * pages in the upl to be aborted; allowable flags are:
2085 *
2086 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both
2087 * empty and has been successfully
2088 * aborted
2089 * o UPL_ABORT_RESTART The operation must be restarted
2090 * o UPL_ABORT_UNAVAILABLE The pages are unavailable
2091 * o UPL_ABORT_ERROR An I/O error occurred
2092 * o UPL_ABORT_DUMP_PAGES Just free the pages
2093 * o UPL_ABORT_NOTIFY_EMPTY RESERVED
2094 * o UPL_ABORT_ALLOW_ACCESS RESERVED
2095 *
2096 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2097 * not be specified by the caller. It is intended to fulfill the
2098 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2099 * ubc_upl_commit_range(), but is never referenced internally.
2100 *
2101 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2102 * referenced; do not use it.
2103 */
0b4e3aa0
A
2104kern_return_t
2105ubc_upl_abort_range(
2106 upl_t upl,
b0d623f7
A
2107 upl_offset_t offset,
2108 upl_size_t size,
0b4e3aa0
A
2109 int abort_flags)
2110{
2111 kern_return_t kr;
2112 boolean_t empty = FALSE;
2113
2114 if (abort_flags & UPL_ABORT_FREE_ON_EMPTY)
2115 abort_flags |= UPL_ABORT_NOTIFY_EMPTY;
2116
2117 kr = upl_abort_range(upl, offset, size, abort_flags, &empty);
2118
2119 if((abort_flags & UPL_ABORT_FREE_ON_EMPTY) && empty)
2120 upl_deallocate(upl);
2121
2122 return kr;
2123}
2124
2d21ac55
A
2125
2126/*
2127 * ubc_upl_abort
2128 *
2129 * Abort the contents of the specified upl
2130 *
2131 * Parameters: upl The upl to abort
2132 * abort_type abort type (see below)
2133 *
2134 * Returns: KERN_SUCCESS The range has been aborted
2135 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2136 * KERN_FAILURE The supplied upl does not represent
2137 * device memory, and the offset plus the
2138 * size would exceed the actual size of
2139 * the upl
2140 *
2141 * Notes: IMPORTANT: If the abort is successful, and the object is now
2142 * empty, the upl will be deallocated. Since the caller cannot
2143 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2144 * should generally only be used when the offset is 0 and the size
2145 * is equal to the upl size.
2146 *
2147 * The abort_type is a bitmap of flags on the range of
2148 * pages in the upl to be aborted; allowable flags are:
2149 *
2150 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both
2151 * empty and has been successfully
2152 * aborted
2153 * o UPL_ABORT_RESTART The operation must be restarted
2154 * o UPL_ABORT_UNAVAILABLE The pages are unavailable
2155 * o UPL_ABORT_ERROR An I/O error occurred
2156 * o UPL_ABORT_DUMP_PAGES Just free the pages
2157 * o UPL_ABORT_NOTIFY_EMPTY RESERVED
2158 * o UPL_ABORT_ALLOW_ACCESS RESERVED
2159 *
2160 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2161 * not be specified by the caller. It is intended to fulfill the
2162 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2163 * ubc_upl_commit_range(), but is never referenced internally.
2164 *
2165 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2166 * referenced; do not use it.
2167 */
0b4e3aa0
A
2168kern_return_t
2169ubc_upl_abort(
2170 upl_t upl,
2171 int abort_type)
2172{
2173 kern_return_t kr;
2174
2175 kr = upl_abort(upl, abort_type);
2176 upl_deallocate(upl);
2177 return kr;
2178}
2179
2d21ac55
A
2180
2181/*
2182 * ubc_upl_pageinfo
2183 *
2184 * Retrieve the internal page list for the specified upl
2185 *
2186 * Parameters: upl The upl to obtain the page list from
2187 *
2188 * Returns: !NULL The (upl_page_info_t *) for the page
2189 * list internal to the upl
2190 * NULL Error/no page list associated
2191 *
2192 * Notes: IMPORTANT: The function is only valid on internal objects
2193 * where the list request was made with the UPL_INTERNAL flag.
2194 *
2195 * This function is a utility helper function, since some callers
2196 * may not have direct access to the header defining the macro,
2197 * due to abstraction layering constraints.
2198 */
0b4e3aa0
A
2199upl_page_info_t *
2200ubc_upl_pageinfo(
2201 upl_t upl)
2202{
2203 return (UPL_GET_INTERNAL_PAGE_LIST(upl));
2204}
91447636 2205
91447636
A
2206
2207int
2d21ac55 2208UBCINFOEXISTS(struct vnode * vp)
91447636 2209{
2d21ac55 2210 return((vp) && ((vp)->v_type == VREG) && ((vp)->v_ubcinfo != UBC_INFO_NULL));
91447636
A
2211}
2212
2d21ac55
A
2213
2214/*
2215 * CODE SIGNING
2216 */
593a1d5f 2217#define CS_BLOB_PAGEABLE 0
2d21ac55
A
2218static volatile SInt32 cs_blob_size = 0;
2219static volatile SInt32 cs_blob_count = 0;
2220static SInt32 cs_blob_size_peak = 0;
2221static UInt32 cs_blob_size_max = 0;
2222static SInt32 cs_blob_count_peak = 0;
2d21ac55
A
2223
2224int cs_validation = 1;
2225
2226SYSCTL_INT(_vm, OID_AUTO, cs_validation, CTLFLAG_RW, &cs_validation, 0, "Do validate code signatures");
2227SYSCTL_INT(_vm, OID_AUTO, cs_blob_count, CTLFLAG_RD, &cs_blob_count, 0, "Current number of code signature blobs");
2228SYSCTL_INT(_vm, OID_AUTO, cs_blob_size, CTLFLAG_RD, &cs_blob_size, 0, "Current size of all code signature blobs");
2229SYSCTL_INT(_vm, OID_AUTO, cs_blob_count_peak, CTLFLAG_RD, &cs_blob_count_peak, 0, "Peak number of code signature blobs");
2230SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_peak, CTLFLAG_RD, &cs_blob_size_peak, 0, "Peak size of code signature blobs");
2231SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_max, CTLFLAG_RD, &cs_blob_size_max, 0, "Size of biggest code signature blob");
2232
593a1d5f
A
2233kern_return_t
2234ubc_cs_blob_allocate(
2235 vm_offset_t *blob_addr_p,
2236 vm_size_t *blob_size_p)
2237{
2238 kern_return_t kr;
2239
2240#if CS_BLOB_PAGEABLE
2241 *blob_size_p = round_page(*blob_size_p);
2242 kr = kmem_alloc(kernel_map, blob_addr_p, *blob_size_p);
2243#else /* CS_BLOB_PAGEABLE */
2244 *blob_addr_p = (vm_offset_t) kalloc(*blob_size_p);
2245 if (*blob_addr_p == 0) {
2246 kr = KERN_NO_SPACE;
2247 } else {
2248 kr = KERN_SUCCESS;
2249 }
2250#endif /* CS_BLOB_PAGEABLE */
2251 return kr;
2252}
2253
2254void
2255ubc_cs_blob_deallocate(
2256 vm_offset_t blob_addr,
2257 vm_size_t blob_size)
2258{
2259#if CS_BLOB_PAGEABLE
2260 kmem_free(kernel_map, blob_addr, blob_size);
2261#else /* CS_BLOB_PAGEABLE */
2262 kfree((void *) blob_addr, blob_size);
2263#endif /* CS_BLOB_PAGEABLE */
2264}
2265
2d21ac55
A
2266int
2267ubc_cs_blob_add(
2268 struct vnode *vp,
2269 cpu_type_t cputype,
2270 off_t base_offset,
2271 vm_address_t addr,
2272 vm_size_t size)
91447636 2273{
2d21ac55
A
2274 kern_return_t kr;
2275 struct ubc_info *uip;
2276 struct cs_blob *blob, *oblob;
2277 int error;
2278 ipc_port_t blob_handle;
2279 memory_object_size_t blob_size;
2280 const CS_CodeDirectory *cd;
2281 off_t blob_start_offset, blob_end_offset;
2282 SHA1_CTX sha1ctxt;
2283
2284 blob_handle = IPC_PORT_NULL;
2285
2286 blob = (struct cs_blob *) kalloc(sizeof (struct cs_blob));
2287 if (blob == NULL) {
2288 return ENOMEM;
2289 }
2290
593a1d5f 2291#if CS_BLOB_PAGEABLE
2d21ac55
A
2292 /* get a memory entry on the blob */
2293 blob_size = (memory_object_size_t) size;
2294 kr = mach_make_memory_entry_64(kernel_map,
2295 &blob_size,
2296 addr,
2297 VM_PROT_READ,
2298 &blob_handle,
2299 IPC_PORT_NULL);
2300 if (kr != KERN_SUCCESS) {
2301 error = ENOMEM;
2302 goto out;
2303 }
2304 if (memory_object_round_page(blob_size) !=
2305 (memory_object_size_t) round_page(size)) {
b0d623f7
A
2306 printf("ubc_cs_blob_add: size mismatch 0x%llx 0x%lx !?\n",
2307 blob_size, (size_t)size);
2308 panic("XXX FBDP size mismatch 0x%llx 0x%lx\n", blob_size, (size_t)size);
2d21ac55
A
2309 error = EINVAL;
2310 goto out;
2311 }
593a1d5f
A
2312#else
2313 blob_size = (memory_object_size_t) size;
2314 blob_handle = IPC_PORT_NULL;
2315#endif
2d21ac55
A
2316
2317 /* fill in the new blob */
2318 blob->csb_cpu_type = cputype;
2319 blob->csb_base_offset = base_offset;
2320 blob->csb_mem_size = size;
2321 blob->csb_mem_offset = 0;
2322 blob->csb_mem_handle = blob_handle;
2323 blob->csb_mem_kaddr = addr;
2d21ac55
A
2324
2325 /*
2326 * Validate the blob's contents
2327 */
2328 cd = findCodeDirectory(
2329 (const CS_SuperBlob *) addr,
2330 (char *) addr,
2331 (char *) addr + blob->csb_mem_size);
2332 if (cd == NULL) {
2333 /* no code directory => useless blob ! */
2334 blob->csb_flags = 0;
2335 blob->csb_start_offset = 0;
2336 blob->csb_end_offset = 0;
2337 } else {
2338 unsigned char *sha1_base;
2339 int sha1_size;
2340
2341 blob->csb_flags = ntohl(cd->flags) | CS_VALID;
2342 blob->csb_end_offset = round_page(ntohl(cd->codeLimit));
b0d623f7
A
2343 if((ntohl(cd->version) >= supportsScatter) && (ntohl(cd->scatterOffset))) {
2344 const struct Scatter *scatter = (const struct Scatter*)
2345 ((const char*)cd + ntohl(cd->scatterOffset));
2346 blob->csb_start_offset = ntohl(scatter->base) * PAGE_SIZE;
2347 } else {
2348 blob->csb_start_offset = (blob->csb_end_offset -
2349 (ntohl(cd->nCodeSlots) * PAGE_SIZE));
2350 }
2d21ac55
A
2351 /* compute the blob's SHA1 hash */
2352 sha1_base = (const unsigned char *) cd;
2353 sha1_size = ntohl(cd->length);
2354 SHA1Init(&sha1ctxt);
2355 SHA1Update(&sha1ctxt, sha1_base, sha1_size);
2356 SHA1Final(blob->csb_sha1, &sha1ctxt);
2357 }
2358
593a1d5f
A
2359 /*
2360 * Let policy module check whether the blob's signature is accepted.
2361 */
2362#if CONFIG_MACF
2363 error = mac_vnode_check_signature(vp, blob->csb_sha1, (void*)addr, size);
2364 if (error)
2365 goto out;
2366#endif
2367
2d21ac55
A
2368 /*
2369 * Validate the blob's coverage
2370 */
2371 blob_start_offset = blob->csb_base_offset + blob->csb_start_offset;
2372 blob_end_offset = blob->csb_base_offset + blob->csb_end_offset;
2373
cf7d32b8
A
2374 if (blob_start_offset >= blob_end_offset ||
2375 blob_start_offset < 0 ||
2376 blob_end_offset <= 0) {
2d21ac55
A
2377 /* reject empty or backwards blob */
2378 error = EINVAL;
2379 goto out;
2380 }
2381
2382 vnode_lock(vp);
2383 if (! UBCINFOEXISTS(vp)) {
2384 vnode_unlock(vp);
2385 error = ENOENT;
2386 goto out;
2387 }
2388 uip = vp->v_ubcinfo;
2389
2390 /* check if this new blob overlaps with an existing blob */
2391 for (oblob = uip->cs_blobs;
2392 oblob != NULL;
2393 oblob = oblob->csb_next) {
2394 off_t oblob_start_offset, oblob_end_offset;
2395
2396 oblob_start_offset = (oblob->csb_base_offset +
2397 oblob->csb_start_offset);
2398 oblob_end_offset = (oblob->csb_base_offset +
2399 oblob->csb_end_offset);
2400 if (blob_start_offset >= oblob_end_offset ||
2401 blob_end_offset <= oblob_start_offset) {
2402 /* no conflict with this existing blob */
2403 } else {
2404 /* conflict ! */
2405 if (blob_start_offset == oblob_start_offset &&
2406 blob_end_offset == oblob_end_offset &&
2407 blob->csb_mem_size == oblob->csb_mem_size &&
2408 blob->csb_flags == oblob->csb_flags &&
2409 (blob->csb_cpu_type == CPU_TYPE_ANY ||
2410 oblob->csb_cpu_type == CPU_TYPE_ANY ||
2411 blob->csb_cpu_type == oblob->csb_cpu_type) &&
2412 !bcmp(blob->csb_sha1,
2413 oblob->csb_sha1,
2414 SHA1_RESULTLEN)) {
2415 /*
2416 * We already have this blob:
2417 * we'll return success but
2418 * throw away the new blob.
2419 */
2420 if (oblob->csb_cpu_type == CPU_TYPE_ANY) {
2421 /*
2422 * The old blob matches this one
2423 * but doesn't have any CPU type.
2424 * Update it with whatever the caller
2425 * provided this time.
2426 */
2427 oblob->csb_cpu_type = cputype;
2428 }
2429 vnode_unlock(vp);
2430 error = EAGAIN;
2431 goto out;
2432 } else {
2433 /* different blob: reject the new one */
2434 vnode_unlock(vp);
2435 error = EALREADY;
2436 goto out;
2437 }
2438 }
2439
2440 }
2441
2442
2443 /* mark this vnode's VM object as having "signed pages" */
2444 kr = memory_object_signed(uip->ui_control, TRUE);
2445 if (kr != KERN_SUCCESS) {
2446 vnode_unlock(vp);
2447 error = ENOENT;
2448 goto out;
2449 }
2450
2451 /*
2452 * Add this blob to the list of blobs for this vnode.
2453 * We always add at the front of the list and we never remove a
2454 * blob from the list, so ubc_cs_get_blobs() can return whatever
2455 * the top of the list was and that list will remain valid
2456 * while we validate a page, even after we release the vnode's lock.
2457 */
2458 blob->csb_next = uip->cs_blobs;
2459 uip->cs_blobs = blob;
2460
2461 OSAddAtomic(+1, &cs_blob_count);
2462 if (cs_blob_count > cs_blob_count_peak) {
2463 cs_blob_count_peak = cs_blob_count; /* XXX atomic ? */
2464 }
b0d623f7
A
2465 OSAddAtomic((SInt32) +blob->csb_mem_size, &cs_blob_size);
2466 if ((SInt32) cs_blob_size > cs_blob_size_peak) {
2467 cs_blob_size_peak = (SInt32) cs_blob_size; /* XXX atomic ? */
2d21ac55 2468 }
b0d623f7
A
2469 if ((UInt32) blob->csb_mem_size > cs_blob_size_max) {
2470 cs_blob_size_max = (UInt32) blob->csb_mem_size;
2d21ac55
A
2471 }
2472
c331a0be 2473 if (cs_debug > 1) {
2d21ac55
A
2474 proc_t p;
2475
2476 p = current_proc();
2477 printf("CODE SIGNING: proc %d(%s) "
2478 "loaded %s signatures for file (%s) "
2479 "range 0x%llx:0x%llx flags 0x%x\n",
2480 p->p_pid, p->p_comm,
2481 blob->csb_cpu_type == -1 ? "detached" : "embedded",
2482 vnode_name(vp),
2483 blob->csb_base_offset + blob->csb_start_offset,
2484 blob->csb_base_offset + blob->csb_end_offset,
2485 blob->csb_flags);
2486 }
2487
2d21ac55
A
2488 vnode_unlock(vp);
2489
2490 error = 0; /* success ! */
2491
2492out:
2493 if (error) {
2494 /* we failed; release what we allocated */
2495 if (blob) {
2496 kfree(blob, sizeof (*blob));
2497 blob = NULL;
2498 }
2499 if (blob_handle != IPC_PORT_NULL) {
2500 mach_memory_entry_port_release(blob_handle);
2501 blob_handle = IPC_PORT_NULL;
2502 }
2d21ac55
A
2503 }
2504
2505 if (error == EAGAIN) {
2506 /*
2507 * See above: error is EAGAIN if we were asked
2508 * to add an existing blob again. We cleaned the new
2509 * blob and we want to return success.
2510 */
2511 error = 0;
2512 /*
2513 * Since we're not failing, consume the data we received.
2514 */
593a1d5f 2515 ubc_cs_blob_deallocate(addr, size);
2d21ac55
A
2516 }
2517
2518 return error;
91447636
A
2519}
2520
2521
2d21ac55
A
2522struct cs_blob *
2523ubc_cs_blob_get(
2524 struct vnode *vp,
2525 cpu_type_t cputype,
2526 off_t offset)
91447636 2527{
2d21ac55
A
2528 struct ubc_info *uip;
2529 struct cs_blob *blob;
2530 off_t offset_in_blob;
2531
2532 vnode_lock_spin(vp);
2533
2534 if (! UBCINFOEXISTS(vp)) {
2535 blob = NULL;
2536 goto out;
2537 }
2538
2539 uip = vp->v_ubcinfo;
2540 for (blob = uip->cs_blobs;
2541 blob != NULL;
2542 blob = blob->csb_next) {
2543 if (cputype != -1 && blob->csb_cpu_type == cputype) {
2544 break;
2545 }
2546 if (offset != -1) {
2547 offset_in_blob = offset - blob->csb_base_offset;
2548 if (offset_in_blob >= blob->csb_start_offset &&
2549 offset_in_blob < blob->csb_end_offset) {
2550 /* our offset is covered by this blob */
2551 break;
2552 }
2553 }
2554 }
2555
2556out:
2557 vnode_unlock(vp);
2558
2559 return blob;
91447636 2560}
2d21ac55
A
2561
2562static void
2563ubc_cs_free(
2564 struct ubc_info *uip)
91447636 2565{
2d21ac55
A
2566 struct cs_blob *blob, *next_blob;
2567
2568 for (blob = uip->cs_blobs;
2569 blob != NULL;
2570 blob = next_blob) {
2571 next_blob = blob->csb_next;
2572 if (blob->csb_mem_kaddr != 0) {
593a1d5f
A
2573 ubc_cs_blob_deallocate(blob->csb_mem_kaddr,
2574 blob->csb_mem_size);
2d21ac55
A
2575 blob->csb_mem_kaddr = 0;
2576 }
593a1d5f
A
2577 if (blob->csb_mem_handle != IPC_PORT_NULL) {
2578 mach_memory_entry_port_release(blob->csb_mem_handle);
2579 }
2d21ac55
A
2580 blob->csb_mem_handle = IPC_PORT_NULL;
2581 OSAddAtomic(-1, &cs_blob_count);
b0d623f7 2582 OSAddAtomic((SInt32) -blob->csb_mem_size, &cs_blob_size);
2d21ac55
A
2583 kfree(blob, sizeof (*blob));
2584 }
2585 uip->cs_blobs = NULL;
91447636 2586}
2d21ac55
A
2587
2588struct cs_blob *
2589ubc_get_cs_blobs(
2590 struct vnode *vp)
91447636 2591{
2d21ac55
A
2592 struct ubc_info *uip;
2593 struct cs_blob *blobs;
2594
b0d623f7
A
2595 /*
2596 * No need to take the vnode lock here. The caller must be holding
2597 * a reference on the vnode (via a VM mapping or open file descriptor),
2598 * so the vnode will not go away. The ubc_info stays until the vnode
2599 * goes away. And we only modify "blobs" by adding to the head of the
2600 * list.
2601 * The ubc_info could go away entirely if the vnode gets reclaimed as
2602 * part of a forced unmount. In the case of a code-signature validation
2603 * during a page fault, the "paging_in_progress" reference on the VM
2604 * object guarantess that the vnode pager (and the ubc_info) won't go
2605 * away during the fault.
2606 * Other callers need to protect against vnode reclaim by holding the
2607 * vnode lock, for example.
2608 */
2d21ac55
A
2609
2610 if (! UBCINFOEXISTS(vp)) {
2611 blobs = NULL;
2612 goto out;
2613 }
2614
2615 uip = vp->v_ubcinfo;
2616 blobs = uip->cs_blobs;
2617
2618out:
2d21ac55 2619 return blobs;
91447636 2620}
2d21ac55
A
2621
2622unsigned long cs_validate_page_no_hash = 0;
2623unsigned long cs_validate_page_bad_hash = 0;
2624boolean_t
2625cs_validate_page(
2626 void *_blobs,
2627 memory_object_offset_t page_offset,
2628 const void *data,
2629 boolean_t *tainted)
91447636 2630{
2d21ac55
A
2631 SHA1_CTX sha1ctxt;
2632 unsigned char actual_hash[SHA1_RESULTLEN];
2633 unsigned char expected_hash[SHA1_RESULTLEN];
2634 boolean_t found_hash;
2635 struct cs_blob *blobs, *blob;
2636 const CS_CodeDirectory *cd;
2637 const CS_SuperBlob *embedded;
2d21ac55
A
2638 const unsigned char *hash;
2639 boolean_t validated;
2640 off_t offset; /* page offset in the file */
2641 size_t size;
2642 off_t codeLimit = 0;
2643 char *lower_bound, *upper_bound;
2644 vm_offset_t kaddr, blob_addr;
2645 vm_size_t ksize;
2646 kern_return_t kr;
2647
2648 offset = page_offset;
2649
2650 /* retrieve the expected hash */
2651 found_hash = FALSE;
2652 blobs = (struct cs_blob *) _blobs;
2653
2654 for (blob = blobs;
2655 blob != NULL;
2656 blob = blob->csb_next) {
2657 offset = page_offset - blob->csb_base_offset;
2658 if (offset < blob->csb_start_offset ||
2659 offset >= blob->csb_end_offset) {
2660 /* our page is not covered by this blob */
2661 continue;
2662 }
2663
2664 /* map the blob in the kernel address space */
2665 kaddr = blob->csb_mem_kaddr;
2666 if (kaddr == 0) {
2667 ksize = (vm_size_t) (blob->csb_mem_size +
2668 blob->csb_mem_offset);
2669 kr = vm_map(kernel_map,
2670 &kaddr,
2671 ksize,
2672 0,
2673 VM_FLAGS_ANYWHERE,
2674 blob->csb_mem_handle,
2675 0,
2676 TRUE,
2677 VM_PROT_READ,
2678 VM_PROT_READ,
2679 VM_INHERIT_NONE);
2680 if (kr != KERN_SUCCESS) {
2681 /* XXX FBDP what to do !? */
2682 printf("cs_validate_page: failed to map blob, "
b0d623f7
A
2683 "size=0x%lx kr=0x%x\n",
2684 (size_t)blob->csb_mem_size, kr);
2d21ac55
A
2685 break;
2686 }
2687 }
2688 blob_addr = kaddr + blob->csb_mem_offset;
2689
2690 lower_bound = CAST_DOWN(char *, blob_addr);
2691 upper_bound = lower_bound + blob->csb_mem_size;
2692
2693 embedded = (const CS_SuperBlob *) blob_addr;
2694 cd = findCodeDirectory(embedded, lower_bound, upper_bound);
2695 if (cd != NULL) {
2696 if (cd->pageSize != PAGE_SHIFT ||
2697 cd->hashType != 0x1 ||
2698 cd->hashSize != SHA1_RESULTLEN) {
2699 /* bogus blob ? */
2d21ac55
A
2700 continue;
2701 }
b0d623f7 2702
2d21ac55 2703 offset = page_offset - blob->csb_base_offset;
b0d623f7
A
2704 if (offset < blob->csb_start_offset ||
2705 offset >= blob->csb_end_offset) {
2d21ac55 2706 /* our page is not covered by this blob */
2d21ac55
A
2707 continue;
2708 }
2709
2710 codeLimit = ntohl(cd->codeLimit);
2711 hash = hashes(cd, atop(offset),
2712 lower_bound, upper_bound);
cf7d32b8
A
2713 if (hash != NULL) {
2714 bcopy(hash, expected_hash,
2715 sizeof (expected_hash));
2716 found_hash = TRUE;
2717 }
2d21ac55 2718
2d21ac55
A
2719 break;
2720 }
2721 }
2722
2723 if (found_hash == FALSE) {
2724 /*
2725 * We can't verify this page because there is no signature
2726 * for it (yet). It's possible that this part of the object
2727 * is not signed, or that signatures for that part have not
2728 * been loaded yet.
2729 * Report that the page has not been validated and let the
2730 * caller decide if it wants to accept it or not.
2731 */
2732 cs_validate_page_no_hash++;
2733 if (cs_debug > 1) {
2734 printf("CODE SIGNING: cs_validate_page: "
2735 "off 0x%llx: no hash to validate !?\n",
2736 page_offset);
2737 }
2738 validated = FALSE;
2739 *tainted = FALSE;
2740 } else {
2d21ac55
A
2741
2742 size = PAGE_SIZE;
593a1d5f 2743 const uint32_t *asha1, *esha1;
b0d623f7 2744 if ((off_t)(offset + size) > codeLimit) {
2d21ac55
A
2745 /* partial page at end of segment */
2746 assert(offset < codeLimit);
b0d623f7 2747 size = (size_t) (codeLimit & PAGE_MASK);
2d21ac55
A
2748 }
2749 /* compute the actual page's SHA1 hash */
2750 SHA1Init(&sha1ctxt);
593a1d5f 2751 SHA1UpdateUsePhysicalAddress(&sha1ctxt, data, size);
2d21ac55
A
2752 SHA1Final(actual_hash, &sha1ctxt);
2753
2754 asha1 = (const uint32_t *) actual_hash;
2755 esha1 = (const uint32_t *) expected_hash;
2756
2757 if (bcmp(expected_hash, actual_hash, SHA1_RESULTLEN) != 0) {
2758 if (cs_debug) {
2759 printf("CODE SIGNING: cs_validate_page: "
2760 "off 0x%llx size 0x%lx: "
2761 "actual [0x%x 0x%x 0x%x 0x%x 0x%x] != "
2762 "expected [0x%x 0x%x 0x%x 0x%x 0x%x]\n",
2763 page_offset, size,
2764 asha1[0], asha1[1], asha1[2],
2765 asha1[3], asha1[4],
2766 esha1[0], esha1[1], esha1[2],
2767 esha1[3], esha1[4]);
2768 }
2769 cs_validate_page_bad_hash++;
2770 *tainted = TRUE;
2771 } else {
2772 if (cs_debug > 1) {
2773 printf("CODE SIGNING: cs_validate_page: "
2774 "off 0x%llx size 0x%lx: SHA1 OK\n",
2775 page_offset, size);
2776 }
2777 *tainted = FALSE;
2778 }
2779 validated = TRUE;
2780 }
2781
2782 return validated;
91447636
A
2783}
2784
2d21ac55
A
2785int
2786ubc_cs_getcdhash(
2787 vnode_t vp,
2788 off_t offset,
2789 unsigned char *cdhash)
2790{
b0d623f7
A
2791 struct cs_blob *blobs, *blob;
2792 off_t rel_offset;
2793 int ret;
2794
2795 vnode_lock(vp);
2d21ac55
A
2796
2797 blobs = ubc_get_cs_blobs(vp);
2798 for (blob = blobs;
2799 blob != NULL;
2800 blob = blob->csb_next) {
2801 /* compute offset relative to this blob */
2802 rel_offset = offset - blob->csb_base_offset;
2803 if (rel_offset >= blob->csb_start_offset &&
2804 rel_offset < blob->csb_end_offset) {
2805 /* this blob does cover our "offset" ! */
2806 break;
2807 }
2808 }
2809
2810 if (blob == NULL) {
2811 /* we didn't find a blob covering "offset" */
b0d623f7
A
2812 ret = EBADEXEC; /* XXX any better error ? */
2813 } else {
2814 /* get the SHA1 hash of that blob */
2815 bcopy(blob->csb_sha1, cdhash, sizeof (blob->csb_sha1));
2816 ret = 0;
2d21ac55
A
2817 }
2818
b0d623f7 2819 vnode_unlock(vp);
2d21ac55 2820
b0d623f7 2821 return ret;
2d21ac55 2822}