X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6601e61aa18bf4f09af135ff61fc7f4771d23b06..bd504ef0e0b883cdd7917b73b3574eb9ce669905:/bsd/vm/dp_backing_file.c diff --git a/bsd/vm/dp_backing_file.c b/bsd/vm/dp_backing_file.c index 92eb65eb9..9df1b810e 100644 --- a/bsd/vm/dp_backing_file.c +++ b/bsd/vm/dp_backing_file.c @@ -1,23 +1,35 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce + * support for mandatory and extensible security protections. This notice + * is included in support of clause 2.2 (b) of the Apple Public License, + * Version 2.0. */ #include @@ -31,11 +43,15 @@ #include #include #include +#include +#if CONFIG_PROTECT +#include +#endif #include #include -#include +#include #include #include @@ -57,8 +73,9 @@ #include #include #include - -extern thread_t current_act(void); +#if CONFIG_MACF +#include +#endif /* * temporary support for delayed instantiation @@ -141,6 +158,60 @@ backing_store_suspend_return: return(error); } +extern boolean_t backing_store_stop_compaction; + +/* + * Routine: macx_backing_store_compaction + * Function: + * Turn compaction of swap space on or off. This is + * used during shutdown/restart so that the kernel + * doesn't waste time compacting swap files that are + * about to be deleted anyway. Compaction is always + * on by default when the system comes up and is turned + * off when a shutdown/restart is requested. It is + * re-enabled if the shutdown/restart is aborted for any reason. + */ + +int +macx_backing_store_compaction(int flags) +{ + int error; + + if ((error = suser(kauth_cred_get(), 0))) + return error; + + if (flags & SWAP_COMPACT_DISABLE) { + backing_store_stop_compaction = TRUE; + + } else if (flags & SWAP_COMPACT_ENABLE) { + backing_store_stop_compaction = FALSE; + } + + return 0; +} + +/* + * Routine: macx_triggers + * Function: + * Syscall interface to set the call backs for low and + * high water marks. + */ +int +macx_triggers( + struct macx_triggers_args *args) +{ + int error; + + error = suser(kauth_cred_get(), 0); + if (error) + return error; + + return mach_macx_triggers(args); +} + + +extern boolean_t dp_isssd; + /* * Routine: macx_swapon * Function: @@ -153,7 +224,6 @@ macx_swapon( int size = args->size; vnode_t vp = (vnode_t)NULL; struct nameidata nd, *ndp; - struct proc *p = current_proc(); register int error; kern_return_t kr; mach_port_t backing_store; @@ -161,13 +231,13 @@ macx_swapon( int i; boolean_t funnel_state; off_t file_size; - struct vfs_context context; + vfs_context_t ctx = vfs_context_current(); + struct proc *p = current_proc(); + int dp_cluster_size; - context.vc_proc = p; - context.vc_ucred = kauth_cred_get(); AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPON); - AUDIT_ARG(value, args->priority); + AUDIT_ARG(value32, args->priority); funnel_state = thread_funnel_set(kernel_flock, TRUE); ndp = &nd; @@ -175,17 +245,12 @@ macx_swapon( if ((error = suser(kauth_cred_get(), 0))) goto swapon_bailout; - if(default_pager_init_flag == 0) { - start_def_pager(NULL); - default_pager_init_flag = 1; - } - /* * Get a vnode for the paging area. */ - NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, + NDINIT(ndp, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32), - CAST_USER_ADDR_T(args->filename), &context); + (user_addr_t) args->filename, ctx); if ((error = namei(ndp))) goto swapon_bailout; @@ -196,16 +261,37 @@ macx_swapon( error = EINVAL; goto swapon_bailout; } - UBCINFOCHECK("macx_swapon", vp); /* get file size */ - if ((error = vnode_size(vp, &file_size, &context)) != 0) + if ((error = vnode_size(vp, &file_size, ctx)) != 0) + goto swapon_bailout; +#if CONFIG_MACF + vnode_lock(vp); + error = mac_system_check_swapon(vfs_context_ucred(ctx), vp); + vnode_unlock(vp); + if (error) goto swapon_bailout; +#endif /* resize to desired size if it's too small */ - if ((file_size < (off_t)size) && ((error = vnode_setsize(vp, (off_t)size, 0, &context)) != 0)) + if ((file_size < (off_t)size) && ((error = vnode_setsize(vp, (off_t)size, 0, ctx)) != 0)) goto swapon_bailout; +#if CONFIG_PROTECT + { + /* initialize content protection keys manually */ + if ((error = cp_handle_vnop(vp, CP_WRITE_ACCESS, 0)) != 0) { + goto swapon_bailout; + } + } +#endif + + + if (default_pager_init_flag == 0) { + start_def_pager(NULL); + default_pager_init_flag = 1; + } + /* add new backing store to list */ i = 0; while(bs_port_table[i].vp != 0) { @@ -233,9 +319,26 @@ macx_swapon( goto swapon_bailout; } +#if CONFIG_EMBEDDED + dp_cluster_size = 1 * PAGE_SIZE; +#else + if ((dp_isssd = vnode_pager_isSSD(vp)) == TRUE) { + /* + * keep the cluster size small since the + * seek cost is effectively 0 which means + * we don't care much about fragmentation + */ + dp_cluster_size = 2 * PAGE_SIZE; + } else { + /* + * use the default cluster size + */ + dp_cluster_size = 0; + } +#endif kr = default_pager_backing_store_create(default_pager, -1, /* default priority */ - 0, /* default cluster size */ + dp_cluster_size, &backing_store); memory_object_default_deallocate(default_pager); @@ -245,6 +348,11 @@ macx_swapon( goto swapon_bailout; } + /* Mark this vnode as being used for swapfile */ + vnode_lock_spin(vp); + SET(vp->v_flag, VSWAP); + vnode_unlock(vp); + /* * NOTE: we are able to supply PAGE_SIZE here instead of * an actual record size or block number because: @@ -261,14 +369,17 @@ macx_swapon( error = EINVAL; else error = ENOMEM; + + /* This vnode is not to be used for swapfile */ + vnode_lock_spin(vp); + CLR(vp->v_flag, VSWAP); + vnode_unlock(vp); + goto swapon_bailout; } bs_port_table[i].bs = (void *)backing_store; error = 0; - /* Mark this vnode as being used for swapfile */ - SET(vp->v_flag, VSWAP); - ubc_setthreadcred(vp, p, current_thread()); /* @@ -283,6 +394,12 @@ swapon_bailout: } (void) thread_funnel_set(kernel_flock, FALSE); AUDIT_MACH_SYSCALL_EXIT(error); + + if (error) + printf("macx_swapon FAILED - %d\n", error); + else + printf("macx_swapon SUCCESS\n"); + return(error); } @@ -305,10 +422,9 @@ macx_swapoff( int i; int error; boolean_t funnel_state; - struct vfs_context context; - - context.vc_proc = p; - context.vc_ucred = kauth_cred_get(); + vfs_context_t ctx = vfs_context_current(); + struct uthread *ut; + int orig_iopol_disk; AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPOFF); @@ -322,9 +438,9 @@ macx_swapoff( /* * Get the vnode for the paging area. */ - NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, + NDINIT(ndp, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32), - CAST_USER_ADDR_T(args->filename), &context); + (user_addr_t) args->filename, ctx); if ((error = namei(ndp))) goto swapoff_bailout; @@ -335,6 +451,13 @@ macx_swapoff( error = EINVAL; goto swapoff_bailout; } +#if CONFIG_MACF + vnode_lock(vp); + error = mac_system_check_swapoff(vfs_context_ucred(ctx), vp); + vnode_unlock(vp); + if (error) + goto swapoff_bailout; +#endif for(i = 0; i < MAX_BACKING_STORE; i++) { if(bs_port_table[i].vp == vp) { @@ -347,13 +470,23 @@ macx_swapoff( } backing_store = (mach_port_t)bs_port_table[i].bs; + ut = get_bsdthread_info(current_thread()); + + orig_iopol_disk = proc_get_thread_selfdiskacc(); + proc_apply_thread_selfdiskacc(IOPOL_THROTTLE); + kr = default_pager_backing_store_delete(backing_store); + + proc_apply_thread_selfdiskacc(orig_iopol_disk); + switch (kr) { case KERN_SUCCESS: error = 0; bs_port_table[i].vp = 0; /* This vnode is no longer used for swapfile */ + vnode_lock_spin(vp); CLR(vp->v_flag, VSWAP); + vnode_unlock(vp); /* get rid of macx_swapon() "long term" reference */ vnode_rele(vp); @@ -374,6 +507,12 @@ swapoff_bailout: (void) thread_funnel_set(kernel_flock, FALSE); AUDIT_MACH_SYSCALL_EXIT(error); + + if (error) + printf("macx_swapoff FAILED - %d\n", error); + else + printf("macx_swapoff SUCCESS\n"); + return(error); }