X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8f6c56a50524aa785f7e596d52dddfb331e18961..e2fac8b15b12a7979f72090454d850e612fc5b13:/bsd/kern/kern_acct.c?ds=sidebyside diff --git a/bsd/kern/kern_acct.c b/bsd/kern/kern_acct.c index 275071025..1e378b1db 100644 --- a/bsd/kern/kern_acct.c +++ b/bsd/kern/kern_acct.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2007 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -70,6 +70,12 @@ * Purged old history * New version based on 4.4 */ +/* + * 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 @@ -88,6 +94,9 @@ #include #include #include +#if CONFIG_MACF +#include +#endif /* * The routines implemented in this file are described in: @@ -135,17 +144,16 @@ int acctchkfreq = 15; /* frequency (in seconds) to check space */ * previous implementation done by Mark Tinguely. */ int -acct(struct proc *p, struct acct_args *uap, __unused int *retval) +acct(proc_t p, struct acct_args *uap, __unused int *retval) { struct nameidata nd; int error; - struct vfs_context context; + struct vfs_context *ctx; - context.vc_proc = p; - context.vc_ucred = kauth_cred_get(); + ctx = vfs_context_current(); /* Make sure that the caller is root. */ - if ((error = suser(kauth_cred_get(), &p->p_acflag))) + if ((error = suser(vfs_context_ucred(ctx), &p->p_acflag))) return (error); /* @@ -153,16 +161,31 @@ acct(struct proc *p, struct acct_args *uap, __unused int *retval) * writing and make sure it's a 'normal'. */ if (uap->path != USER_ADDR_NULL) { - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, &context); + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, ctx); if ((error = vn_open(&nd, FWRITE, 0))) return (error); +#if CONFIG_MACF + error = mac_system_check_acct(vfs_context_ucred(ctx), nd.ni_vp); + if (error) { + vnode_put(nd.ni_vp); + vn_close(nd.ni_vp, FWRITE, ctx); + return (error); + } +#endif vnode_put(nd.ni_vp); if (nd.ni_vp->v_type != VREG) { - vn_close(nd.ni_vp, FWRITE, kauth_cred_get(), p); + vn_close(nd.ni_vp, FWRITE, ctx); return (EACCES); } } +#if CONFIG_MACF + else { + error = mac_system_check_acct(vfs_context_ucred(ctx), NULL); + if (error) + return (error); + } +#endif /* * If accounting was previously enabled, kill the old space-watcher, @@ -170,8 +193,8 @@ acct(struct proc *p, struct acct_args *uap, __unused int *retval) */ if (acctp != NULLVP || suspend_acctp != NULLVP) { untimeout(acctwatch_funnel, NULL); - error = vn_close((acctp != NULLVP ? acctp : suspend_acctp), FWRITE, - kauth_cred_get(), p); + error = vn_close((acctp != NULLVP ? acctp : suspend_acctp), + FWRITE, vfs_context_current()); acctp = suspend_acctp = NULLVP; } @@ -194,15 +217,17 @@ acct(struct proc *p, struct acct_args *uap, __unused int *retval) * "acct.h" header file.) */ int -acct_process(p) - struct proc *p; +acct_process(proc_t p) { struct acct an_acct; - struct rusage *r; + struct rusage rup, *r; struct timeval ut, st, tmp; int t; int error; struct vnode *vp; + kauth_cred_t safecred; + struct session * sessp; + boolean_t fstate; /* If accounting isn't enabled, don't bother */ vp = acctp; @@ -222,13 +247,16 @@ acct_process(p) an_acct.ac_stime = encode_comp_t(st.tv_sec, st.tv_usec); /* (3) The elapsed time the commmand ran (and its starting time) */ - an_acct.ac_btime = p->p_stats->p_start.tv_sec; + an_acct.ac_btime = p->p_start.tv_sec; microtime(&tmp); - timevalsub(&tmp, &p->p_stats->p_start); + timevalsub(&tmp, &p->p_start); an_acct.ac_etime = encode_comp_t(tmp.tv_sec, tmp.tv_usec); /* (4) The average amount of memory used */ - r = &p->p_stats->p_ru; + proc_lock(p); + rup = p->p_stats->p_ru; + proc_unlock(p); + r = &rup; tmp = ut; timevaladd(&tmp, &st); t = tmp.tv_sec * hz + tmp.tv_usec / tick; @@ -241,15 +269,24 @@ acct_process(p) an_acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0); /* (6) The UID and GID of the process */ - an_acct.ac_uid = p->p_ucred->cr_ruid; - an_acct.ac_gid = p->p_ucred->cr_rgid; + safecred = kauth_cred_proc_ref(p); + + an_acct.ac_uid = safecred->cr_ruid; + an_acct.ac_gid = safecred->cr_rgid; /* (7) The terminal from which the process was started */ - if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp) - an_acct.ac_tty = p->p_pgrp->pg_session->s_ttyp->t_dev; - else + + sessp = proc_session(p); + if ((p->p_flag & P_CONTROLT) && (sessp != SESSION_NULL) && (sessp->s_ttyp != TTY_NULL)) { + fstate = thread_funnel_set(kernel_flock, TRUE); + an_acct.ac_tty = sessp->s_ttyp->t_dev; + (void) thread_funnel_set(kernel_flock, fstate); + }else an_acct.ac_tty = NODEV; + if (sessp != SESSION_NULL) + session_rele(sessp); + /* (8) The boolean flags that tell how the process terminated, etc. */ an_acct.ac_flag = p->p_acflag; @@ -258,10 +295,12 @@ acct_process(p) */ if ((error = vnode_getwithref(vp)) == 0) { error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&an_acct, sizeof (an_acct), - (off_t)0, UIO_SYSSPACE32, IO_APPEND|IO_UNIT, p->p_ucred, + (off_t)0, UIO_SYSSPACE32, IO_APPEND|IO_UNIT, safecred, (int *)0, p); vnode_put(vp); } + + kauth_cred_unref(&safecred); return (error); } @@ -276,8 +315,7 @@ acct_process(p) #define MAXFRACT ((1 << MANTSIZE) - 1) /* Maximum fractional value. */ comp_t -encode_comp_t(s, us) - u_long s, us; +encode_comp_t(u_long s, u_long us) { int exp, rnd; @@ -305,8 +343,7 @@ encode_comp_t(s, us) } void -acctwatch_funnel(a) - void *a; +acctwatch_funnel(void *a) { thread_funnel_set(kernel_flock, TRUE); acctwatch(a); @@ -324,14 +361,12 @@ acctwatch_funnel(a) void acctwatch(__unused void *a) { - struct vfs_context context; + vfs_context_t ctx = vfs_context_current(); struct vfs_attr va; VFSATTR_INIT(&va); VFSATTR_WANTED(&va, f_blocks); VFSATTR_WANTED(&va, f_bavail); - context.vc_proc = current_proc(); - context.vc_ucred = kauth_cred_get(); if (suspend_acctp != NULLVP) { /* @@ -340,11 +375,11 @@ acctwatch(__unused void *a) * below a low watermark */ if (suspend_acctp->v_type == VBAD) { - (void) vn_close(suspend_acctp, FWRITE, NOCRED, NULL); + (void) vn_close(suspend_acctp, FWRITE, vfs_context_kernel()); suspend_acctp = NULLVP; return; } - (void)vfs_getattr(suspend_acctp->v_mount, &va, &context); + (void)vfs_getattr(suspend_acctp->v_mount, &va, ctx); if (va.f_bavail > acctresume * va.f_blocks / 100) { acctp = suspend_acctp; suspend_acctp = NULLVP; @@ -357,11 +392,11 @@ acctwatch(__unused void *a) * goes over a high watermark */ if (acctp->v_type == VBAD) { - (void) vn_close(acctp, FWRITE, NOCRED, NULL); + (void) vn_close(acctp, FWRITE, vfs_context_kernel()); acctp = NULLVP; return; } - (void)vfs_getattr(acctp->v_mount, &va, &context); + (void)vfs_getattr(acctp->v_mount, &va, ctx); if (va.f_bavail <= acctsuspend * va.f_blocks / 100) { suspend_acctp = acctp; acctp = NULLVP;