Example #1
0
/*
 * Call for disabling global system override.
 * This should be called only with the sys_override_lock held.
 */
static void
disable_system_override(uint64_t flags)
{

	if (flags & SYS_OVERRIDE_IO_THROTTLE) {
		assert(io_throttle_assert_cnt > 0);
		io_throttle_assert_cnt--;
		if (io_throttle_assert_cnt == 0) {
			/* Enable I/O Throttling */
			KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_THROTTLE, IO_THROTTLE_DISABLE) | DBG_FUNC_END, current_proc()->p_pid, 0, 0, 0, 0);
			sys_override_io_throttle(THROTTLE_IO_ENABLE);
		}
	}

	if (flags & SYS_OVERRIDE_CPU_THROTTLE) {
		assert(cpu_throttle_assert_cnt > 0);
		cpu_throttle_assert_cnt--;
			if (cpu_throttle_assert_cnt == 0) {
			/* Enable CPU Throttling */
			KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_CPU_THROTTLE_DISABLE) | DBG_FUNC_END, current_proc()->p_pid, 0, 0, 0, 0);
			sys_override_cpu_throttle(CPU_THROTTLE_ENABLE);
		}
	}
}
Example #2
0
void
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
{
	thread_t thread = current_thread();
	x86_saved_state_t *regs;
	user_addr_t pc, sp, fp;
	volatile uint16_t *flags =
	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
	int n;
	boolean_t is64Bit = proc_is64bit(current_proc());

	if (*flags & CPU_DTRACE_FAULT)
		return;

	if (pcstack_limit <= 0)
		return;

	/*
	 * If there's no user context we still need to zero the stack.
	 */
	if (thread == NULL)
		goto zero;

	regs = (x86_saved_state_t *)find_user_regs(thread);
	if (regs == NULL)
		goto zero;
		
	*pcstack++ = (uint64_t)proc_selfpid();
	pcstack_limit--;

	if (pcstack_limit <= 0)
		return;

	if (is64Bit) {
		pc = regs->ss_64.isf.rip;
		sp = regs->ss_64.isf.rsp;
		fp = regs->ss_64.rbp;
	} else {
		pc = regs->ss_32.eip;
		sp = regs->ss_32.uesp;
		fp = regs->ss_32.ebp;
	}

        /*
	 * The return value indicates if we've modified the stack.
	 * Since there is nothing else to fix up in either case,
	 * we can safely ignore it here.
	 */
	(void)dtrace_adjust_stack(&pcstack, &pcstack_limit, &pc, sp);

	if(pcstack_limit <= 0)
	    return;

	/*
	 * Note that unlike ppc, the x86 code does not use
	 * CPU_DTRACE_USTACK_FP. This is because x86 always
	 * traces from the fp, even in syscall/profile/fbt
	 * providers.
	 */
	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp);
	ASSERT(n >= 0);
	ASSERT(n <= pcstack_limit);

	pcstack += n;
	pcstack_limit -= n;

zero:
	while (pcstack_limit-- > 0)
		*pcstack++ = 0;
}
Example #3
0
/*
 *	Routine:	macx_swapoff
 *	Function:
 *		Syscall interface to remove a file from backing store
 */
int
macx_swapoff(
	struct macx_swapoff_args *args)
{
	__unused int	flags = args->flags;
	kern_return_t	kr;
	mach_port_t	backing_store;

	struct vnode		*vp = 0; 
	struct nameidata 	nd, *ndp;
	struct proc		*p =  current_proc();
	int			i;
	int			error;
	boolean_t		funnel_state;
	vfs_context_t ctx = vfs_context_current();

	AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPOFF);

	funnel_state = thread_funnel_set(kernel_flock, TRUE);
	backing_store = NULL;
	ndp = &nd;

	if ((error = suser(kauth_cred_get(), 0)))
		goto swapoff_bailout;

	/*
	 * Get the vnode for the paging area.
	 */
	NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
	       ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
	       CAST_USER_ADDR_T(args->filename), ctx);

	if ((error = namei(ndp)))
		goto swapoff_bailout;
	nameidone(ndp);
	vp = ndp->ni_vp;

	if (vp->v_type != VREG) {
		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) {
			break;
		}
	}
	if (i == MAX_BACKING_STORE) {
		error = EINVAL;
		goto swapoff_bailout;
	}
	backing_store = (mach_port_t)bs_port_table[i].bs;

	kr = default_pager_backing_store_delete(backing_store);
	switch (kr) {
		case KERN_SUCCESS:
			error = 0;
			bs_port_table[i].vp = 0;
			/* This vnode is no longer used for swapfile */
			CLR(vp->v_flag, VSWAP);

			/* get rid of macx_swapon() "long term" reference */
			vnode_rele(vp);

			break;
		case KERN_FAILURE:
			error = EAGAIN;
			break;
		default:
			error = EAGAIN;
			break;
	}

swapoff_bailout:
	/* get rid of macx_swapoff() namei() reference */
	if (vp)
		vnode_put(vp);

	(void) thread_funnel_set(kernel_flock, FALSE);
	AUDIT_MACH_SYSCALL_EXIT(error);
	return(error);
}
Example #4
0
int
afs_UFSRead(register struct vcache *avc, struct uio *auio,
            struct AFS_UCRED *acred, daddr_t albn, struct buf **abpp,
            int noLock)
{
    afs_size_t totalLength;
    afs_size_t transferLength;
    afs_size_t filePos;
    afs_size_t offset, len, tlen;
    afs_int32 trimlen;
    struct dcache *tdc = 0;
    afs_int32 error;
#ifdef AFS_DARWIN80_ENV
    uio_t tuiop=NULL;
#else
    struct uio tuio;
    struct uio *tuiop = &tuio;
    struct iovec *tvec;
#endif
    struct osi_file *tfile;
    afs_int32 code;
    int trybusy = 1;
    struct vrequest treq;

    AFS_STATCNT(afs_UFSRead);
    if (avc && avc->vc_error)
        return EIO;

    AFS_DISCON_LOCK();

    /* check that we have the latest status info in the vnode cache */
    if ((code = afs_InitReq(&treq, acred)))
        return code;
    if (!noLock) {
        if (!avc)
            osi_Panic("null avc in afs_UFSRead");
        else {
            code = afs_VerifyVCache(avc, &treq);
            if (code) {
                code = afs_CheckCode(code, &treq, 11);	/* failed to get it */
                AFS_DISCON_UNLOCK();
                return code;
            }
        }
    }
#ifndef	AFS_VM_RDWR_ENV
    if (AFS_NFSXLATORREQ(acred)) {
        if (!afs_AccessOK
                (avc, PRSFS_READ, &treq,
                 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
            AFS_DISCON_UNLOCK();
            return afs_CheckCode(EACCES, &treq, 12);
        }
    }
#endif

#ifndef AFS_DARWIN80_ENV
    tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
#endif
    totalLength = AFS_UIO_RESID(auio);
    filePos = AFS_UIO_OFFSET(auio);
    afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
               ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
               totalLength, ICL_TYPE_OFFSET,
               ICL_HANDLE_OFFSET(avc->f.m.Length));
    error = 0;
    transferLength = 0;
    if (!noLock)
        ObtainReadLock(&avc->lock);
#if	defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
    if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
        hset(avc->flushDV, avc->f.m.DataVersion);
    }
#endif

    if (filePos >= avc->f.m.Length) {
        if (len > AFS_ZEROS)
            len = sizeof(afs_zeros);	/* and in 0 buffer */
        len = 0;
#ifdef AFS_DARWIN80_ENV
        trimlen = len;
        tuiop = afsio_darwin_partialcopy(auio, trimlen);
#else
        afsio_copy(auio, &tuio, tvec);
        trimlen = len;
        afsio_trim(&tuio, trimlen);
#endif
        AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
    }

    while (avc->f.m.Length > 0 && totalLength > 0) {
        /* read all of the cached info */
        if (filePos >= avc->f.m.Length)
            break;		/* all done */
        if (noLock) {
            if (tdc) {
                ReleaseReadLock(&tdc->lock);
                afs_PutDCache(tdc);
            }
            tdc = afs_FindDCache(avc, filePos);
            if (tdc) {
                ObtainReadLock(&tdc->lock);
                offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
                len = tdc->validPos - filePos;
            }
        } else {
            /* a tricky question: does the presence of the DFFetching flag
             * mean that we're fetching the latest version of the file?  No.
             * The server could update the file as soon as the fetch responsible
             * for the setting of the DFFetching flag completes.
             *
             * However, the presence of the DFFetching flag (visible under
             * a dcache read lock since it is set and cleared only under a
             * dcache write lock) means that we're fetching as good a version
             * as was known to this client at the time of the last call to
             * afs_VerifyVCache, since the latter updates the stat cache's
             * m.DataVersion field under a vcache write lock, and from the
             * time that the DFFetching flag goes on in afs_GetDCache (before
             * the fetch starts), to the time it goes off (after the fetch
             * completes), afs_GetDCache keeps at least a read lock on the
             * vcache entry.
             *
             * This means that if the DFFetching flag is set, we can use that
             * data for any reads that must come from the current version of
             * the file (current == m.DataVersion).
             *
             * Another way of looking at this same point is this: if we're
             * fetching some data and then try do an afs_VerifyVCache, the
             * VerifyVCache operation will not complete until after the
             * DFFetching flag is turned off and the dcache entry's f.versionNo
             * field is updated.
             *
             * Note, by the way, that if DFFetching is set,
             * m.DataVersion > f.versionNo (the latter is not updated until
             * after the fetch completes).
             */
            if (tdc) {
                ReleaseReadLock(&tdc->lock);
                afs_PutDCache(tdc);	/* before reusing tdc */
            }
            tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
#ifdef AFS_DISCON_ENV
            if (!tdc) {
                printf("Network down in afs_read");
                error = ENETDOWN;
                break;
            }
#endif /* AFS_DISCON_ENV */

            ObtainReadLock(&tdc->lock);
            /* now, first try to start transfer, if we'll need the data.  If
             * data already coming, we don't need to do this, obviously.  Type
             * 2 requests never return a null dcache entry, btw. */
            if (!(tdc->dflags & DFFetching)
                    && !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
                /* have cache entry, it is not coming in now, and we'll need new data */
tagain:
                if (trybusy && !afs_BBusy()) {
                    struct brequest *bp;
                    /* daemon is not busy */
                    ObtainSharedLock(&tdc->mflock, 667);
                    if (!(tdc->mflags & DFFetchReq)) {
                        UpgradeSToWLock(&tdc->mflock, 668);
                        tdc->mflags |= DFFetchReq;
                        bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
                                        (afs_size_t) filePos, (afs_size_t) 0,
                                        tdc);
                        if (!bp) {
                            /* Bkg table full; retry deadlocks */
                            tdc->mflags &= ~DFFetchReq;
                            trybusy = 0;	/* Avoid bkg daemon since they're too busy */
                            ReleaseWriteLock(&tdc->mflock);
                            goto tagain;
                        }
                        ConvertWToSLock(&tdc->mflock);
                    }
                    code = 0;
                    ConvertSToRLock(&tdc->mflock);
                    while (!code && tdc->mflags & DFFetchReq) {
                        afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
                                   ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32,
                                   __LINE__, ICL_TYPE_POINTER, tdc,
                                   ICL_TYPE_INT32, tdc->dflags);
                        /* don't need waiting flag on this one */
                        ReleaseReadLock(&tdc->mflock);
                        ReleaseReadLock(&tdc->lock);
                        ReleaseReadLock(&avc->lock);
                        code = afs_osi_SleepSig(&tdc->validPos);
                        ObtainReadLock(&avc->lock);
                        ObtainReadLock(&tdc->lock);
                        ObtainReadLock(&tdc->mflock);
                    }
                    ReleaseReadLock(&tdc->mflock);
                    if (code) {
                        error = code;
                        break;
                    }
                }
            }
            /* now data may have started flowing in (if DFFetching is on).  If
             * data is now streaming in, then wait for some interesting stuff.
             */
            code = 0;
            while (!code && (tdc->dflags & DFFetching)
                    && tdc->validPos <= filePos) {
                /* too early: wait for DFFetching flag to vanish,
                 * or data to appear */
                afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
                           __FILE__, ICL_TYPE_INT32, __LINE__,
                           ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
                           tdc->dflags);
                ReleaseReadLock(&tdc->lock);
                ReleaseReadLock(&avc->lock);
                code = afs_osi_SleepSig(&tdc->validPos);
                ObtainReadLock(&avc->lock);
                ObtainReadLock(&tdc->lock);
            }
            if (code) {
                error = code;
                break;
            }
            /* fetching flag gone, data is here, or we never tried
             * (BBusy for instance) */
            if (tdc->dflags & DFFetching) {
                /* still fetching, some new data is here:
                 * compute length and offset */
                offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
                len = tdc->validPos - filePos;
            } else {
                /* no longer fetching, verify data version (avoid new
                 * GetDCache call) */
                if (hsame(avc->f.m.DataVersion, tdc->f.versionNo)
                        && ((len = tdc->validPos - filePos) > 0)) {
                    offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
                } else {
                    /* don't have current data, so get it below */
                    afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
                               ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
                               ICL_TYPE_HYPER, &avc->f.m.DataVersion,
                               ICL_TYPE_HYPER, &tdc->f.versionNo);
                    ReleaseReadLock(&tdc->lock);
                    afs_PutDCache(tdc);
                    tdc = NULL;
                }
            }

            if (!tdc) {
                /* If we get, it was not possible to start the
                 * background daemon. With flag == 1 afs_GetDCache
                 * does the FetchData rpc synchronously.
                 */
                ReleaseReadLock(&avc->lock);
                tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 1);
                ObtainReadLock(&avc->lock);
                if (tdc)
                    ObtainReadLock(&tdc->lock);
            }
        }

        if (!tdc) {
            error = EIO;
            break;
        }
        len = tdc->validPos - filePos;
        afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, ICL_TYPE_POINTER, tdc,
                   ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset),
                   ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len));
        if (len > totalLength)
            len = totalLength;	/* will read len bytes */
        if (len <= 0) {		/* shouldn't get here if DFFetching is on */
            afs_Trace4(afs_iclSetp, CM_TRACE_VNODEREAD2, ICL_TYPE_POINTER,
                       tdc, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(tdc->validPos),
                       ICL_TYPE_INT32, tdc->f.chunkBytes, ICL_TYPE_INT32,
                       tdc->dflags);
            /* read past the end of a chunk, may not be at next chunk yet, and yet
             * also not at eof, so may have to supply fake zeros */
            len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset;	/* bytes left in chunk addr space */
            if (len > totalLength)
                len = totalLength;	/* and still within xfr request */
            tlen = avc->f.m.Length - offset;	/* and still within file */
            if (len > tlen)
                len = tlen;
            if (len > AFS_ZEROS)
                len = sizeof(afs_zeros);	/* and in 0 buffer */
#ifdef AFS_DARWIN80_ENV
            trimlen = len;
            tuiop = afsio_darwin_partialcopy(auio, trimlen);
#else
            afsio_copy(auio, &tuio, tvec);
            trimlen = len;
            afsio_trim(&tuio, trimlen);
#endif
            AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
            if (code) {
                error = code;
                break;
            }
        } else {
            /* get the data from the file */
#ifdef IHINT
            if (tfile = tdc->ihint) {
                if (tdc->f.inode != tfile->inum) {
                    afs_warn("afs_UFSRead: %x hint mismatch tdc %d inum %d\n",
                             tdc, tdc->f.inode, tfile->inum);
                    osi_UFSClose(tfile);
                    tdc->ihint = tfile = 0;
                    nihints--;
                }
            }
            if (tfile != 0) {
                usedihint++;
            } else
#endif /* IHINT */
#if defined(LINUX_USE_FH)
                tfile = (struct osi_file *)osi_UFSOpen_fh(&tdc->f.fh, tdc->f.fh_type);
#else
                tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
#endif
#ifdef AFS_DARWIN80_ENV
            trimlen = len;
            tuiop = afsio_darwin_partialcopy(auio, trimlen);
            uio_setoffset(tuiop, offset);
#else
            /* mung uio structure to be right for this transfer */
            afsio_copy(auio, &tuio, tvec);
            trimlen = len;
            afsio_trim(&tuio, trimlen);
            tuio.afsio_offset = offset;
#endif

#if defined(AFS_AIX41_ENV)
            AFS_GUNLOCK();
            code =
                VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL,
                          NULL, afs_osi_credp);
            AFS_GLOCK();
#elif defined(AFS_AIX32_ENV)
            code =
                VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL);
            /* Flush all JFS pages now for big performance gain in big file cases
             * If we do something like this, must check to be sure that AFS file
             * isn't mmapped... see afs_gn_map() for why.
             */
            /*
            	  if (tfile->vnode->v_gnode && tfile->vnode->v_gnode->gn_seg) {
             many different ways to do similar things:
               so far, the best performing one is #2, but #1 might match it if we
               straighten out the confusion regarding which pages to flush.  It
               really does matter.
               1.	    vm_flushp(tfile->vnode->v_gnode->gn_seg, 0, len/PAGESIZE - 1);
               2.	    vm_releasep(tfile->vnode->v_gnode->gn_seg, offset/PAGESIZE,
            			(len + PAGESIZE-1)/PAGESIZE);
               3.	    vms_inactive(tfile->vnode->v_gnode->gn_seg) Doesn't work correctly
               4.  	    vms_delete(tfile->vnode->v_gnode->gn_seg) probably also fails
            	    tfile->vnode->v_gnode->gn_seg = NULL;
               5.       deletep
               6.       ipgrlse
               7.       ifreeseg
                      Unfortunately, this seems to cause frequent "cache corruption" episodes.
               	    vm_releasep(tfile->vnode->v_gnode->gn_seg, offset/PAGESIZE,
            			(len + PAGESIZE-1)/PAGESIZE);
            	  }
            */
#elif defined(AFS_AIX_ENV)
            code =
                VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t) & offset,
                          &tuio, NULL, NULL, -1);
#elif defined(AFS_SUN5_ENV)
            AFS_GUNLOCK();
#ifdef AFS_SUN510_ENV
            {
                caller_context_t ct;

                VOP_RWLOCK(tfile->vnode, 0, &ct);
                code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp, &ct);
                VOP_RWUNLOCK(tfile->vnode, 0, &ct);
            }
#else
            VOP_RWLOCK(tfile->vnode, 0);
            code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
            VOP_RWUNLOCK(tfile->vnode, 0);
#endif
            AFS_GLOCK();
#elif defined(AFS_SGI_ENV)
            AFS_GUNLOCK();
            AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_READ);
            AFS_VOP_READ(tfile->vnode, &tuio, IO_ISLOCKED, afs_osi_credp,
                         code);
            AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
            AFS_GLOCK();
#elif defined(AFS_OSF_ENV)
            tuio.uio_rw = UIO_READ;
            AFS_GUNLOCK();
            VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp, code);
            AFS_GLOCK();
#elif defined(AFS_HPUX100_ENV)
            AFS_GUNLOCK();
            code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
            AFS_GLOCK();
#elif defined(AFS_LINUX20_ENV)
            AFS_GUNLOCK();
            code = osi_rdwr(tfile, &tuio, UIO_READ);
            AFS_GLOCK();
#elif defined(AFS_DARWIN80_ENV)
            AFS_GUNLOCK();
            code = VNOP_READ(tfile->vnode, tuiop, 0, afs_osi_ctxtp);
            AFS_GLOCK();
#elif defined(AFS_DARWIN_ENV)
            AFS_GUNLOCK();
            VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
            code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
            VOP_UNLOCK(tfile->vnode, 0, current_proc());
            AFS_GLOCK();
#elif defined(AFS_FBSD80_ENV)
            AFS_GUNLOCK();
            VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
            code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
            VOP_UNLOCK(tfile->vnode, 0);
            AFS_GLOCK();
#elif defined(AFS_FBSD50_ENV)
            AFS_GUNLOCK();
            VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
            code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
            VOP_UNLOCK(tfile->vnode, 0, curthread);
            AFS_GLOCK();
#elif defined(AFS_XBSD_ENV)
            AFS_GUNLOCK();
            VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
            code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
            VOP_UNLOCK(tfile->vnode, 0, curproc);
            AFS_GLOCK();
#else
            code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
#endif

#ifdef IHINT
            if (!tdc->ihint && nihints < maxIHint) {
                tdc->ihint = tfile;
                nihints++;
            } else
#endif /* IHINT */
                osi_UFSClose(tfile);

            if (code) {
                error = code;
                break;
            }
        }
        /* otherwise we've read some, fixup length, etc and continue with next seg */
        len = len - AFS_UIO_RESID(tuiop);	/* compute amount really transferred */
        trimlen = len;
        afsio_skip(auio, trimlen);	/* update input uio structure */
        totalLength -= len;
        transferLength += len;
        filePos += len;
        if (len <= 0)
            break;		/* surprise eof */
#ifdef AFS_DARWIN80_ENV
        if (tuiop) {
            uio_free(tuiop);
            tuiop = 0;
        }
#endif
    }

    /* if we make it here with tdc non-zero, then it is the last chunk we
     * dealt with, and we have to release it when we're done.  We hold on
     * to it in case we need to do a prefetch, obviously.
     */
    if (tdc) {
        ReleaseReadLock(&tdc->lock);
#if !defined(AFS_VM_RDWR_ENV)
        /* try to queue prefetch, if needed */
        if (!noLock) {
            if (!(tdc->mflags & DFNextStarted))
                afs_PrefetchChunk(avc, tdc, acred, &treq);
        }
#endif
        afs_PutDCache(tdc);
    }
    if (!noLock)
        ReleaseReadLock(&avc->lock);

#ifdef AFS_DARWIN80_ENV
    if (tuiop)
        uio_free(tuiop);
#else
    osi_FreeSmallSpace(tvec);
#endif
    AFS_DISCON_UNLOCK();
    error = afs_CheckCode(error, &treq, 13);
    return error;
}
Example #5
0
uint64_t
dtrace_getreg(struct regs *savearea, uint_t reg)
{
	boolean_t is64Bit = proc_is64bit(current_proc());
	x86_saved_state_t *regs = (x86_saved_state_t *)savearea;

	if (is64Bit) {
	    if (reg <= SS) {
		reg = regmap[reg];
	    } else {
		reg -= (SS + 1);
	    }

	    switch (reg) {
	    case REG_RDI:
		return (uint64_t)(regs->ss_64.rdi);
	    case REG_RSI:
		return (uint64_t)(regs->ss_64.rsi);
	    case REG_RDX:
		return (uint64_t)(regs->ss_64.rdx);
	    case REG_RCX:
		return (uint64_t)(regs->ss_64.rcx);
	    case REG_R8:
		return (uint64_t)(regs->ss_64.r8);
	    case REG_R9:
		return (uint64_t)(regs->ss_64.r9);
	    case REG_RAX:
		return (uint64_t)(regs->ss_64.rax);
	    case REG_RBX:
		return (uint64_t)(regs->ss_64.rbx);
	    case REG_RBP:
		return (uint64_t)(regs->ss_64.rbp);
	    case REG_R10:
		return (uint64_t)(regs->ss_64.r10);
	    case REG_R11:
		return (uint64_t)(regs->ss_64.r11);
	    case REG_R12:
		return (uint64_t)(regs->ss_64.r12);
	    case REG_R13:
		return (uint64_t)(regs->ss_64.r13);
	    case REG_R14:
		return (uint64_t)(regs->ss_64.r14);
	    case REG_R15:
		return (uint64_t)(regs->ss_64.r15);
	    case REG_FS:
		return (uint64_t)(regs->ss_64.fs);
	    case REG_GS:
		return (uint64_t)(regs->ss_64.gs);
	    case REG_TRAPNO:
		return (uint64_t)(regs->ss_64.isf.trapno);
	    case REG_ERR:
		return (uint64_t)(regs->ss_64.isf.err);
	    case REG_RIP:
		return (uint64_t)(regs->ss_64.isf.rip);
	    case REG_CS:
		return (uint64_t)(regs->ss_64.isf.cs);
	    case REG_SS:
		return (uint64_t)(regs->ss_64.isf.ss);
	    case REG_RFL:
		return (uint64_t)(regs->ss_64.isf.rflags);
	    case REG_RSP:
		return (uint64_t)(regs->ss_64.isf.rsp);
	    case REG_DS:
	    case REG_ES:
	    default:
		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
		return (0);
	    }
	
	} else {   /* is 32bit user */
		/* beyond register SS */
		if (reg > x86_SAVED_STATE32_COUNT - 1) {
			DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
			return (0);
		}
		return (uint64_t)((unsigned int *)(&(regs->ss_32.gs)))[reg];
	}
}
Example #6
0
/*
 * The file size of a mach-o file is limited to 32 bits; this is because
 * this is the limit on the kalloc() of enough bytes for a mach_header and
 * the contents of its sizeofcmds, which is currently constrained to 32
 * bits in the file format itself.  We read into the kernel buffer the
 * commands section, and then parse it in order to parse the mach-o file
 * format load_command segment(s).  We are only interested in a subset of
 * the total set of possible commands. If "map"==VM_MAP_NULL or
 * "thread"==THREAD_NULL, do not make permament VM modifications,
 * just preflight the parse.
 */
static
load_return_t
parse_machfile(
	struct vnode 		*vp,       
	vm_map_t		map,
	thread_t		thread,
	struct mach_header	*header,
	off_t			file_offset,
	off_t			macho_size,
	int			depth,
	int64_t			aslr_offset,
	int64_t			dyld_aslr_offset,
	load_result_t		*result
)
{
	uint32_t		ncmds;
	struct load_command	*lcp;
	struct dylinker_command	*dlp = 0;
	integer_t		dlarchbits = 0;
	void *			control;
	load_return_t		ret = LOAD_SUCCESS;
	caddr_t			addr;
	void *			kl_addr;
	vm_size_t		size,kl_size;
	size_t			offset;
	size_t			oldoffset;	/* for overflow check */
	int			pass;
	proc_t			p = current_proc();		/* XXXX */
	int			error;
	int resid=0;
	size_t			mach_header_sz = sizeof(struct mach_header);
	boolean_t		abi64;
	boolean_t		got_code_signatures = FALSE;
	int64_t			slide = 0;

	if (header->magic == MH_MAGIC_64 ||
	    header->magic == MH_CIGAM_64) {
	    	mach_header_sz = sizeof(struct mach_header_64);
	}

	/*
	 *	Break infinite recursion
	 */
	if (depth > 6) {
		return(LOAD_FAILURE);
	}

	depth++;

	/*
	 *	Check to see if right machine type.
	 */
	if (((cpu_type_t)(header->cputype & ~CPU_ARCH_MASK) != (cpu_type() & ~CPU_ARCH_MASK)) ||
	    !grade_binary(header->cputype, 
	    	header->cpusubtype & ~CPU_SUBTYPE_MASK))
		return(LOAD_BADARCH);
		
	abi64 = ((header->cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64);
		
	switch (header->filetype) {
	
	case MH_OBJECT:
	case MH_EXECUTE:
	case MH_PRELOAD:
		if (depth != 1) {
			return (LOAD_FAILURE);
		}
		break;
		
	case MH_FVMLIB:
	case MH_DYLIB:
		if (depth == 1) {
			return (LOAD_FAILURE);
		}
		break;

	case MH_DYLINKER:
		if (depth != 2) {
			return (LOAD_FAILURE);
		}
		break;
		
	default:
		return (LOAD_FAILURE);
	}

	/*
	 *	Get the pager for the file.
	 */
	control = ubc_getobject(vp, UBC_FLAGS_NONE);

	/*
	 *	Map portion that must be accessible directly into
	 *	kernel's map.
	 */
	if ((off_t)(mach_header_sz + header->sizeofcmds) > macho_size)
		return(LOAD_BADMACHO);

	/*
	 *	Round size of Mach-O commands up to page boundry.
	 */
	size = round_page(mach_header_sz + header->sizeofcmds);
	if (size <= 0)
		return(LOAD_BADMACHO);

	/*
	 * Map the load commands into kernel memory.
	 */
	addr = 0;
	kl_size = size;
	kl_addr = kalloc(size);
	addr = (caddr_t)kl_addr;
	if (addr == NULL)
		return(LOAD_NOSPACE);

	error = vn_rdwr(UIO_READ, vp, addr, size, file_offset,
	    UIO_SYSSPACE, 0, kauth_cred_get(), &resid, p);
	if (error) {
		if (kl_addr )
			kfree(kl_addr, kl_size);
		return(LOAD_IOERROR);
	}

	/*
	 *	For PIE and dyld, slide everything by the ASLR offset.
	 */
	if ((header->flags & MH_PIE) || (header->filetype == MH_DYLINKER)) {
		slide = aslr_offset;
	}

	 /*
	 *  Scan through the commands, processing each one as necessary.
	 *  We parse in three passes through the headers:
	 *  1: thread state, uuid, code signature
	 *  2: segments
	 *  3: dyld, encryption, check entry point
	 */
	
	for (pass = 1; pass <= 3; pass++) {

		/*
		 * Check that the entry point is contained in an executable segments
		 */ 
		if ((pass == 3) && (result->validentry == 0)) {
			thread_state_initialize(thread);
			ret = LOAD_FAILURE;
			break;
		}

		/*
		 * Loop through each of the load_commands indicated by the
		 * Mach-O header; if an absurd value is provided, we just
		 * run off the end of the reserved section by incrementing
		 * the offset too far, so we are implicitly fail-safe.
		 */
		offset = mach_header_sz;
		ncmds = header->ncmds;

		while (ncmds--) {
			/*
			 *	Get a pointer to the command.
			 */
			lcp = (struct load_command *)(addr + offset);
			oldoffset = offset;
			offset += lcp->cmdsize;

			/*
			 * Perform prevalidation of the struct load_command
			 * before we attempt to use its contents.  Invalid
			 * values are ones which result in an overflow, or
			 * which can not possibly be valid commands, or which
			 * straddle or exist past the reserved section at the
			 * start of the image.
			 */
			if (oldoffset > offset ||
			    lcp->cmdsize < sizeof(struct load_command) ||
			    offset > header->sizeofcmds + mach_header_sz) {
				ret = LOAD_BADMACHO;
				break;
			}

			/*
			 * Act on struct load_command's for which kernel
			 * intervention is required.
			 */
			switch(lcp->cmd) {
			case LC_SEGMENT:
				if (pass != 2)
					break;

				if (abi64) {
					/*
					 * Having an LC_SEGMENT command for the
					 * wrong ABI is invalid <rdar://problem/11021230>
					 */
					ret = LOAD_BADMACHO;
					break;
				}

				ret = load_segment(lcp,
				                   header->filetype,
				                   control,
				                   file_offset,
				                   macho_size,
				                   vp,
				                   map,
				                   slide,
				                   result);
				break;
			case LC_SEGMENT_64:
				if (pass != 2)
					break;

				if (!abi64) {
					/*
					 * Having an LC_SEGMENT_64 command for the
					 * wrong ABI is invalid <rdar://problem/11021230>
					 */
					ret = LOAD_BADMACHO;
					break;
				}

				ret = load_segment(lcp,
				                   header->filetype,
				                   control,
				                   file_offset,
				                   macho_size,
				                   vp,
				                   map,
				                   slide,
				                   result);
				break;
			case LC_UNIXTHREAD:
				if (pass != 1)
					break;
				ret = load_unixthread(
						 (struct thread_command *) lcp,
						 thread,
						 slide,
						 result);
				break;
			case LC_MAIN:
				if (pass != 1)
					break;
				if (depth != 1)
					break;
				ret = load_main(
						 (struct entry_point_command *) lcp,
						 thread,
						 slide,
						 result);
				break;
			case LC_LOAD_DYLINKER:
				if (pass != 3)
					break;
				if ((depth == 1) && (dlp == 0)) {
					dlp = (struct dylinker_command *)lcp;
					dlarchbits = (header->cputype & CPU_ARCH_MASK);
				} else {
					ret = LOAD_FAILURE;
				}
				break;
			case LC_UUID:
				if (pass == 1 && depth == 1) {
					ret = load_uuid((struct uuid_command *) lcp,
							(char *)addr + mach_header_sz + header->sizeofcmds,
							result);
				}
				break;
			case LC_CODE_SIGNATURE:
				/* CODE SIGNING */
				if (pass != 1)
					break;
				/* pager -> uip ->
				   load signatures & store in uip
				   set VM object "signed_pages"
				*/
				ret = load_code_signature(
					(struct linkedit_data_command *) lcp,
					vp,
					file_offset,
					macho_size,
					header->cputype,
					(depth == 1) ? result : NULL);
				if (ret != LOAD_SUCCESS) {
					printf("proc %d: load code signature error %d "
					       "for file \"%s\"\n",
					       p->p_pid, ret, vp->v_name);
					ret = LOAD_SUCCESS; /* ignore error */
				} else {
					got_code_signatures = TRUE;
				}
				break;
#if CONFIG_CODE_DECRYPTION
			case LC_ENCRYPTION_INFO:
			case LC_ENCRYPTION_INFO_64:
				if (pass != 3)
					break;
				ret = set_code_unprotect(
					(struct encryption_info_command *) lcp,
					addr, map, slide, vp,
					header->cputype, header->cpusubtype);
				if (ret != LOAD_SUCCESS) {
					printf("proc %d: set_code_unprotect() error %d "
					       "for file \"%s\"\n",
					       p->p_pid, ret, vp->v_name);
					/* 
					 * Don't let the app run if it's 
					 * encrypted but we failed to set up the
					 * decrypter. If the keys are missing it will
					 * return LOAD_DECRYPTFAIL.
					 */
					 if (ret == LOAD_DECRYPTFAIL) {
						/* failed to load due to missing FP keys */
						proc_lock(p);
						p->p_lflag |= P_LTERM_DECRYPTFAIL;
						proc_unlock(p);
					}
					 psignal(p, SIGKILL);
				}
				break;
#endif
			default:
				/* Other commands are ignored by the kernel */
				ret = LOAD_SUCCESS;
				break;
			}
			if (ret != LOAD_SUCCESS)
				break;
		}
		if (ret != LOAD_SUCCESS)
			break;
	}
	if (ret == LOAD_SUCCESS) { 
	    if (! got_code_signatures) {
		    struct cs_blob *blob;
		    /* no embedded signatures: look for detached ones */
		    blob = ubc_cs_blob_get(vp, -1, file_offset);
		    if (blob != NULL) {
			    /* get flags to be applied to the process */
			    result->csflags |= blob->csb_flags;
		    }
	    }

		/* Make sure if we need dyld, we got it */
		if (result->needs_dynlinker && !dlp) {
			ret = LOAD_FAILURE;
		}

	    if ((ret == LOAD_SUCCESS) && (dlp != 0)) {
		/*
		 * load the dylinker, and slide it by the independent DYLD ASLR
		 * offset regardless of the PIE-ness of the main binary.
		 */

		ret = load_dylinker(dlp, dlarchbits, map, thread, depth,
		                    dyld_aslr_offset, result);
	    }

	    if((ret == LOAD_SUCCESS) && (depth == 1)) {
			if (result->thread_count == 0) {
				ret = LOAD_FAILURE;
			}
	    }
	}

	if (kl_addr )
		kfree(kl_addr, kl_size);

	return(ret);
}
Example #7
0
void
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
{
	thread_t thread = current_thread();
	ppc_saved_state_t *regs;
	user_addr_t pc, sp;
	volatile uint16_t *flags =
	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
	int n;
	boolean_t is64Bit = proc_is64bit(current_proc());

	if (*flags & CPU_DTRACE_FAULT)
		return;

	if (pcstack_limit <= 0)
		return;

	/*
	 * If there's no user context we still need to zero the stack.
	 */
	if (thread == NULL)
		goto zero;

	regs = (ppc_saved_state_t *)find_user_regs(thread);
	if (regs == NULL)
		goto zero;
		
	*pcstack++ = (uint64_t)proc_selfpid();
	pcstack_limit--;

	if (pcstack_limit <= 0)
		return;

	pc = regs->REGPC;
	sp = regs->REGSP;

	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
		*pcstack++ = (uint64_t)pc;
		pcstack_limit--;
		if (pcstack_limit <= 0)
			return;

		pc = regs->save_lr;
	}
	
	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_USTACK_FP)) {
		/*
		 * If the ustack fp flag is set, the stack frame from sp to
		 * fp contains no valid call information. Start with the fp.
		 */
		if (is64Bit)
			sp = dtrace_fuword64(sp);
		else
			sp = (user_addr_t)dtrace_fuword32(sp);
	}

	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
	ASSERT(n >= 0);
	ASSERT(n <= pcstack_limit);

	pcstack += n;
	pcstack_limit -= n;

zero:
	while (pcstack_limit-- > 0)
		*pcstack++ = 0;
}
Example #8
0
static void
fasttrap_return_common(proc_t *p, arm_saved_state_t *regs, user_addr_t pc, user_addr_t new_pc)
{
	pid_t pid = p->p_pid;
	fasttrap_tracepoint_t *tp;
	fasttrap_bucket_t *bucket;
	fasttrap_id_t *id;
	lck_mtx_t *pid_mtx;
	int retire_tp = 1;

	pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;
	lck_mtx_lock(pid_mtx);
	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];

	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
	    	tp->ftt_proc->ftpc_acount != 0)
			break;
	}

	/*
	 * Don't sweat it if we can't find the tracepoint again; unlike
	 * when we're in fasttrap_pid_probe(), finding the tracepoint here
	 * is not essential to the correct execution of the process.
 	 */
	if (tp == NULL) {
		lck_mtx_unlock(pid_mtx);
		return;
	}

	for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
		fasttrap_probe_t *probe = id->fti_probe;
		/*
		 * If there's a branch that could act as a return site, we
		 * need to trace it, and check here if the program counter is
		 * external to the function.
		 */
		if (tp->ftt_type != FASTTRAP_T_LDM_PC &&
		    tp->ftt_type != FASTTRAP_T_POP_PC &&
		    new_pc - probe->ftp_faddr < probe->ftp_fsize)
			continue;

		if (probe->ftp_prov->ftp_provider_type == DTFTP_PROVIDER_ONESHOT) {
			uint8_t already_triggered = atomic_or_8(&probe->ftp_triggered, 1);
			if (already_triggered) {
				continue;
			}
		}
		/*
		 * If we have at least one probe associated that
		 * is not a oneshot probe, don't remove the
		 * tracepoint
		 */
		else {
			retire_tp = 0;
		}
#ifndef CONFIG_EMBEDDED
		if (ISSET(current_proc()->p_lflag, P_LNOATTACH)) {
			dtrace_probe(dtrace_probeid_error, 0 /* state */, id->fti_probe->ftp_id,
				     1 /* ndx */, -1 /* offset */, DTRACEFLT_UPRIV);
#else
		if (FALSE) {
#endif
		} else {
			dtrace_probe(id->fti_probe->ftp_id,
				     pc - id->fti_probe->ftp_faddr,
				     regs->r[0], 0, 0, 0);
		}
	}
	if (retire_tp) {
		fasttrap_tracepoint_retire(p, tp);
	}

	lck_mtx_unlock(pid_mtx);
}

static void
fasttrap_sigsegv(proc_t *p, uthread_t t, user_addr_t addr, arm_saved_state_t *regs)
{
	/* TODO: This function isn't implemented yet. In debug mode, panic the system to
	 * find out why we're hitting this point. In other modes, kill the process.
	 */
#if DEBUG
#pragma unused(p,t,addr,arm_saved_state)
	panic("fasttrap: sigsegv not yet implemented");
#else
#pragma unused(p,t,addr)
	/* Kill the process */
	regs->pc = 0;
#endif

#if 0
	proc_lock(p);

	/* Set fault address and mark signal */
	t->uu_code = addr;
	t->uu_siglist |= sigmask(SIGSEGV);

	/* 
	 * XXX These two line may be redundant; if not, then we need
	 * XXX to potentially set the data address in the machine
	 * XXX specific thread state structure to indicate the address.
	 */         
	t->uu_exception = KERN_INVALID_ADDRESS;         /* SIGSEGV */
	t->uu_subcode = 0;      /* XXX pad */
                
	proc_unlock(p); 
                                     
	/* raise signal */
	signal_setast(t->uu_context.vc_thread);
#endif
}
Example #9
0
int
fasttrap_pid_probe(arm_saved_state_t *regs)
{
	proc_t *p = current_proc();
	user_addr_t new_pc = 0;
	fasttrap_bucket_t *bucket;
	lck_mtx_t *pid_mtx;
	fasttrap_tracepoint_t *tp, tp_local;
	pid_t pid;
	dtrace_icookie_t cookie;
	uint_t is_enabled = 0;
	int instr_size;
	int was_simulated = 1, retire_tp = 1;

	user_addr_t pc = regs->pc;

	uthread_t uthread = (uthread_t) get_bsdthread_info(current_thread());

	/*
	 * It's possible that a user (in a veritable orgy of bad planning)
	 * could redirect this thread's flow of control before it reached the
	 * return probe fasttrap. In this case we need to kill the process
	 * since it's in a unrecoverable state.
	 */
	if (uthread->t_dtrace_step) {
		ASSERT(uthread->t_dtrace_on);
		fasttrap_sigtrap(p, uthread, pc);
		return (0);
	}

	/*
	 * Clear all user tracing flags.
	 */
	uthread->t_dtrace_ft = 0;
	uthread->t_dtrace_pc = 0;
	uthread->t_dtrace_npc = 0;
	uthread->t_dtrace_scrpc = 0;
	uthread->t_dtrace_astpc = 0;

	/*
	 * Treat a child created by a call to vfork(2) as if it were its
	 * parent. We know that there's only one thread of control in such a
	 * process: this one.
	 */
	if (p->p_lflag & P_LINVFORK) {
		proc_list_lock();
		while (p->p_lflag & P_LINVFORK)
			p = p->p_pptr;
		proc_list_unlock();
	}

	pid = p->p_pid;
	pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;
	lck_mtx_lock(pid_mtx);
	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid,pc)];

	/*
	 * Lookup the tracepoint that the process just hit.
	 */
	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
		    tp->ftt_proc->ftpc_acount != 0)
			break;
	}

	/*
	 * If we couldn't find a matching tracepoint, either a tracepoint has
	 * been inserted without using the pid<pid> ioctl interface (see
	 * fasttrap_ioctl), or somehow we have mislaid this tracepoint.
	 */
	if (tp == NULL) {
		lck_mtx_unlock(pid_mtx);
		return (-1);
	}

	/* Default to always execute */
	int condition_code = 0xE;
	if (tp->ftt_thumb) {
		uint32_t itstate = GETITSTATE(regs->cpsr);
		if (itstate != 0) {
			/* In IT block, make sure it's the last statement in the block */
			if (ISLASTINIT(itstate)) {
				condition_code = itstate >> 4;
			} else {
				printf("dtrace: fasttrap: Tried to trace instruction %08x at %08x but not at end of IT block\n",
				    (tp->ftt_thumb && dtrace_instr_size(tp->ftt_instr,tp->ftt_thumb) == 2) ? tp->ftt_instr1 : tp->ftt_instr, pc);

				fasttrap_tracepoint_remove(p, tp);
				lck_mtx_unlock(pid_mtx);
				return (-1);
			}
		}
Example #10
0
/*
 *	Routine:	task_for_pid
 *	Purpose:
 *		Get the task port for another "process", named by its
 *		process ID on the same host as "target_task".
 *
 *		Only permitted to privileged processes, or processes
 *		with the same user ID.
 *
 *		Note: if pid == 0, an error is return no matter who is calling.
 *
 * XXX This should be a BSD system call, not a Mach trap!!!
 */
kern_return_t
task_for_pid(
	struct task_for_pid_args *args)
{
	mach_port_name_t	target_tport = args->target_tport;
	int			pid = args->pid;
	user_addr_t		task_addr = args->t;
	proc_t 			p = PROC_NULL;
	task_t			t1 = TASK_NULL;
	mach_port_name_t	tret = MACH_PORT_NULL;
 	ipc_port_t 		tfpport;
	void * sright;
	int error = 0;

	AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID);
	AUDIT_ARG(pid, pid);
	AUDIT_ARG(mach_port1, target_tport);

	/* Always check if pid == 0 */
	if (pid == 0) {
		(void ) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t));
		AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
		return(KERN_FAILURE);
	}

	t1 = port_name_to_task(target_tport);
	if (t1 == TASK_NULL) {
		(void) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t));
		AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
		return(KERN_FAILURE);
	} 


	p = proc_find(pid);
	if (p == PROC_NULL) {
		error = KERN_FAILURE;
		goto tfpout;
	}

#if CONFIG_AUDIT
	AUDIT_ARG(process, p);
#endif

	if (!(task_for_pid_posix_check(p))) {
		error = KERN_FAILURE;
		goto tfpout;
	}

	if (p->task != TASK_NULL) {
		/* If we aren't root and target's task access port is set... */
		if (!kauth_cred_issuser(kauth_cred_get()) &&
			p != current_proc() &&
			(task_get_task_access_port(p->task, &tfpport) == 0) &&
			(tfpport != IPC_PORT_NULL)) {

			if (tfpport == IPC_PORT_DEAD) {
				error = KERN_PROTECTION_FAILURE;
				goto tfpout;
			}

			/* Call up to the task access server */
			error = check_task_access(tfpport, proc_selfpid(), kauth_getgid(), pid);

			if (error != MACH_MSG_SUCCESS) {
				if (error == MACH_RCV_INTERRUPTED)
					error = KERN_ABORTED;
				else
					error = KERN_FAILURE;
				goto tfpout;
			}
		}
#if CONFIG_MACF
		error = mac_proc_check_get_task(kauth_cred_get(), p);
		if (error) {
			error = KERN_FAILURE;
			goto tfpout;
		}
#endif

		/* Grant task port access */
		task_reference(p->task);
		extmod_statistics_incr_task_for_pid(p->task);

		sright = (void *) convert_task_to_port(p->task);
		tret = ipc_port_copyout_send(
				sright, 
				get_task_ipcspace(current_task()));
	} 
	error = KERN_SUCCESS;

tfpout:
	task_deallocate(t1);
	AUDIT_ARG(mach_port2, tret);
	(void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
	if (p != PROC_NULL)
		proc_rele(p);
	AUDIT_MACH_SYSCALL_EXIT(error);
	return(error);
}
Example #11
0
kern_return_t
task_name_for_pid(
	struct task_name_for_pid_args *args)
{
	mach_port_name_t	target_tport = args->target_tport;
	int			pid = args->pid;
	user_addr_t		task_addr = args->t;
	proc_t		p = PROC_NULL;
	task_t		t1;
	mach_port_name_t	tret;
	void * sright;
	int error = 0, refheld = 0;
	kauth_cred_t target_cred;

	AUDIT_MACH_SYSCALL_ENTER(AUE_TASKNAMEFORPID);
	AUDIT_ARG(pid, pid);
	AUDIT_ARG(mach_port1, target_tport);

	t1 = port_name_to_task(target_tport);
	if (t1 == TASK_NULL) {
		(void) copyout((char *)&t1, task_addr, sizeof(mach_port_name_t));
		AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
		return(KERN_FAILURE);
	} 

	p = proc_find(pid);
	if (p != PROC_NULL) {
		AUDIT_ARG(process, p);
		target_cred = kauth_cred_proc_ref(p);
		refheld = 1;

		if ((p->p_stat != SZOMB)
		    && ((current_proc() == p)
			|| kauth_cred_issuser(kauth_cred_get()) 
			|| ((kauth_cred_getuid(target_cred) == kauth_cred_getuid(kauth_cred_get())) && 
			    ((kauth_cred_getruid(target_cred) == kauth_getruid()))))) {

			if (p->task != TASK_NULL) {
				task_reference(p->task);
#if CONFIG_MACF
				error = mac_proc_check_get_task_name(kauth_cred_get(),  p);
				if (error) {
					task_deallocate(p->task);
					goto noperm;
				}
#endif
				sright = (void *)convert_task_name_to_port(p->task);
				tret = ipc_port_copyout_send(sright, 
						get_task_ipcspace(current_task()));
			} else
				tret  = MACH_PORT_NULL;

			AUDIT_ARG(mach_port2, tret);
			(void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
			task_deallocate(t1);
			error = KERN_SUCCESS;
			goto tnfpout;
		}
	}

#if CONFIG_MACF
noperm:
#endif
    task_deallocate(t1);
	tret = MACH_PORT_NULL;
	(void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
	error = KERN_FAILURE;
tnfpout:
	if (refheld != 0)
		kauth_cred_unref(&target_cred);
	if (p != PROC_NULL)
		proc_rele(p);
	AUDIT_MACH_SYSCALL_EXIT(error);
	return(error);
}
Example #12
0
void
log_stack_execution_failure(addr64_t vaddr, vm_prot_t prot)
{
	printf("Data/Stack execution not permitted: %s[pid %d] at virtual address 0x%qx, protections were %s\n", 
		current_proc()->p_comm, current_proc()->p_pid, vaddr, prot_values[prot & VM_PROT_ALL]);
}
Example #13
0
int xi_lpx_connect(xi_socket_t *oso, struct sockaddr_lpx daddr, struct sockaddr_lpx saddr, int timeoutsec)
{
    xi_socket_t so = NULL;
	errno_t	error;
	struct timeval timeout;
#ifndef __KPI_SOCKET__
	struct sockopt sopt;
	boolean_t funnel_state;
#endif
	
	*oso = NULL;
	
	error = xi_sock_socket(AF_LPX, SOCK_STREAM, 0, NULL, NULL, &so);
	if(error) {
		DebugPrint(1, false, "socreate error %d\n", error);
        goto bad;
	}

	error = xi_sock_bind(so, (struct sockaddr *) &saddr);
	
	if(error) {
		DebugPrint(1, false, "xi_lpx_connect: sobind error\n");
		goto bad;
	}

#if 0
    DebugPrint(4, false, "xi_lpx_connect to ");
    for(i=0; i<6; i++)
        DebugPrint(4, false, "02x ", daddr.slpx_node[i]);
#endif
	
    error = xi_sock_connect(so, (struct sockaddr *)&daddr, 0);
    if(error) {
        DebugPrint(4, false, "soconnect error %d\n", error);
        goto bad;
    }
		
#ifndef __KPI_SOCKET__
	do {
//		struct sockaddr_lpx sin;
		int s;
		
		funnel_state = thread_funnel_set(network_flock, TRUE);
		
		s = splnet();
		while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
			//        IOLog("before sleep\n");
			(void) tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, "xiscsicon", 0);
			//        IOLog("after sleep\n");
			break;
		}
		//    IOLog("so->so_error = %d\n", so->so_error);
		if (so->so_error) {
			error = so->so_error;
			so->so_error = 0;
			splx(s);
			goto bad;
		}
		splx(s);
		
		(void) thread_funnel_set(network_flock, FALSE);
		
	} while(0);
#endif // __KPI_SOCKET__
	
	*oso = so;

	// Set Read Timeout.
	timeout.tv_sec = timeoutsec;
	timeout.tv_usec = 0;
	
#ifdef __KPI_SOCKET__
	error = sock_setsockopt(
							so,
							SOL_SOCKET,
							SO_RCVTIMEO,
							&timeout,
							sizeof(struct timeval)
							); 
#else 
	sopt.sopt_dir = SOPT_SET;
	sopt.sopt_level = SOL_SOCKET;
	sopt.sopt_name = SO_RCVTIMEO;
	sopt.sopt_val = &timeout;
	sopt.sopt_valsize = sizeof(struct timeval);
	sopt.sopt_p = current_proc();
	
	funnel_state = thread_funnel_set(network_flock, TRUE);
	
	error = sosetopt(so, &sopt);

	(void) thread_funnel_set(network_flock, FALSE);
#endif

	if(error) {
        DebugPrint(1, false, "xi_lpx_connect: Can't set Receive Time out. error %d\n", error);
		
		goto bad;	
	}
		
	return 0;
	
bad:

#ifdef __KPI_SOCKET__
#else
	(void) thread_funnel_set(network_flock, FALSE);
#endif
	
    xi_lpx_disconnect(so);
    
	return error;
}
Example #14
0
/* kauth file scope listener 
 * this allows to detect files written to the filesystem
 * arg2 contains a flag KAUTH_FILEOP_CLOSE which is set if a modified file is being closed
 * this way we don't need to trace every close(), only the ones writing to the filesystem
 */
static int
fileop_scope_listener(kauth_cred_t    credential,
                      void *          idata,
                      kauth_action_t  action,
                      uintptr_t       arg0,     /* vnode reference */
                      uintptr_t       arg1,     /* full path to file being closed */
                      uintptr_t       arg2,     /* flags */
                      uintptr_t       arg3)
{
    /* ignore all actions except FILE_CLOSE */
    if (action != KAUTH_FILEOP_CLOSE)
    {
        return KAUTH_RESULT_DEFER;
    }
    
    /* ignore operations with bad data */
    if (credential == NULL || (vnode_t)arg0 == NULL || (char*)arg1 == NULL)
    {
        ERROR_MSG("Arguments contain null pointers!");
        return KAUTH_RESULT_DEFER;
    }
    
    /* ignore closes on folders, character and block devices */
    switch ( vnode_vtype((vnode_t)arg0) )
    {
        case VDIR:
        case VCHR:
        case VBLK:
            return KAUTH_RESULT_DEFER;
        default:
            break;
    }
    
    /* we are only interested when a modified file is being closed */
    if ((int)arg2 != KAUTH_FILEOP_CLOSE_MODIFIED)
    {
        return KAUTH_RESULT_DEFER;
    }
    
    char *file_path = (char*)arg1;
    /* get information from current proc trying to write to the vnode */
    proc_t proc = current_proc();
    pid_t mypid = proc_pid(proc);
    char myprocname[MAXCOMLEN+1] = {0};
    proc_name(mypid, myprocname, sizeof(myprocname));

    /* retrieve the vnode attributes, we can get a lot of vnode information from here */
    struct vnode_attr vap = {0};
    vfs_context_t context = vfs_context_create(NULL);
    /* initialize the structure fields we are interested in
     * reference vn_stat_noauth() xnu/bsd/vfs/vfs_vnops.c
     */
    VATTR_INIT(&vap);
    VATTR_WANTED(&vap, va_mode);
    VATTR_WANTED(&vap, va_type);
    VATTR_WANTED(&vap, va_uid);
    VATTR_WANTED(&vap, va_gid);
    VATTR_WANTED(&vap, va_data_size);
    VATTR_WANTED(&vap, va_flags);
    int attr_ok = 1;
    if ( vnode_getattr((vnode_t)arg0, &vap, context) != 0 )
    {
        /* in case of error permissions and filesize will be bogus */
        ERROR_MSG("failed to vnode_getattr");
        attr_ok = 0;
    }
    /* release the context we created, else kab00m! */
    vfs_context_rele(context);
    
    int error = 0;
    /* make sure we :
     * - were able to read the attributes
     * - file size is at least uint32_t 
     * - path starts with /Users
     */
    if ( attr_ok == 1 &&
         vap.va_data_size >= sizeof(uint32_t) &&
         strprefix(file_path, "/Users/") )
    {
        uint32_t magic = 0;
        /* read target vnode */
        uio_t uio = NULL;
        /* read from offset 0 */
        uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ);
        if (uio == NULL)
        {
            ERROR_MSG("uio_create returned null!");
            return KAUTH_RESULT_DEFER;
        }
        /* we just want to read 4 bytes to match the header */
        if ( (error = uio_addiov(uio, CAST_USER_ADDR_T(&magic), sizeof(uint32_t))) )
        {
            ERROR_MSG("uio_addiov returned error %d!", error);
            return KAUTH_RESULT_DEFER;
        }
        if ( (error = VNOP_READ((vnode_t)arg0, uio, 0, NULL)) )
        {
            ERROR_MSG("VNOP_READ failed %d!", error);
            return KAUTH_RESULT_DEFER;
        }
        else if (uio_resid(uio))
        {
            ERROR_MSG("uio_resid!");
            return KAUTH_RESULT_DEFER;
        }
        
        /* verify if it's a Mach-O file */
        if (magic == MH_MAGIC || magic == MH_MAGIC_64 || magic == FAT_CIGAM)
        {
            char *token = NULL;
            char *string = NULL;
            char *tofree = NULL;
            int library = 0;
            int preferences = 0;
            
            tofree = string = STRDUP(file_path, M_TEMP);
            while ((token = strsep(&string, "/")) != NULL)
            {
                if (strcmp(token, "Library") == 0)
                {
                    library = 1;
                }
                else if (library == 1 && strcmp(token, "Preferences") == 0)
                {
                    preferences = 1;
                }
            }
            _FREE(tofree, M_TEMP);
            /* we got a match into /Users/username/Library/Preferences, warn user about it */
            if (library == 1 && preferences == 1)
            {
                DEBUG_MSG("Found Mach-O written to %s by %s.", file_path, myprocname);
                char alert_msg[1025] = {0};
                snprintf(alert_msg, sizeof(alert_msg), "Process \"%s\" wrote Mach-O binary %s.\n This could be Hacking Team's malware!", myprocname, file_path);
                alert_msg[sizeof(alert_msg)-1] = '\0';
                
                /* log to syslog */
                printf("[WARNING] Process \"%s\" wrote Mach-O binary %s.\n This could be Hacking Team's malware!", myprocname, file_path);
                /* deprecated but still usable to display the alert */
                KUNCUserNotificationDisplayNotice(10,		// Timeout
                                                  0,		// Flags - default is Stop alert level
                                                  NULL,     // iconpath
                                                  NULL,     // soundpath
                                                  NULL,     // localization path
                                                  "Security Alert", // alert header
                                                  alert_msg, // alert message
                                                  "OK");	// button title
            }
        }
    }
    /* don't deny access, we are just here to observe */
    return KAUTH_RESULT_DEFER;
}
kern_return_t
dtrace_user_probe(x86_saved_state_t *regs)
{
    x86_saved_state64_t *regs64;
    x86_saved_state32_t *regs32;
    int trapno;

    /*
     * FIXME!
     *
     * The only call path into this method is always a user trap.
     * We don't need to test for user trap, but should assert it.
     */
    boolean_t user_mode = TRUE;

    if (is_saved_state64(regs) == TRUE) {
        regs64 = saved_state64(regs);
        regs32 = NULL;
        trapno = regs64->isf.trapno;
        user_mode = TRUE; // By default, because xnu is 32 bit only
    } else {
        regs64 = NULL;
        regs32 = saved_state32(regs);
        if (regs32->cs & 0x03) user_mode = TRUE;
        trapno = regs32->trapno;
    }

    lck_rw_t *rwp;
    struct proc *p = current_proc();

    uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
    if (user_mode /*|| (rp->r_ps & PS_VM)*/) {
        /*
         * DTrace accesses t_cred in probe context.  t_cred
         * must always be either NULL, or point to a valid,
         * allocated cred structure.
         */
        kauth_cred_uthread_update(uthread, p);
    }

    if (trapno == T_DTRACE_RET) {
        uint8_t step = uthread->t_dtrace_step;
        uint8_t ret = uthread->t_dtrace_ret;
        user_addr_t npc = uthread->t_dtrace_npc;

        if (uthread->t_dtrace_ast) {
            printf("dtrace_user_probe() should be calling aston()\n");
            // aston(uthread);
            // uthread->t_sig_check = 1;
        }

        /*
         * Clear all user tracing flags.
         */
        uthread->t_dtrace_ft = 0;

        /*
         * If we weren't expecting to take a return probe trap, kill
         * the process as though it had just executed an unassigned
         * trap instruction.
         */
        if (step == 0) {
            /*
             * APPLE NOTE: We're returning KERN_FAILURE, which causes
             * the generic signal handling code to take over, which will effectively
             * deliver a EXC_BAD_INSTRUCTION to the user process.
             */
            return KERN_FAILURE;
        }

        /*
         * If we hit this trap unrelated to a return probe, we're
         * just here to reset the AST flag since we deferred a signal
         * until after we logically single-stepped the instruction we
         * copied out.
         */
        if (ret == 0) {
            if (regs64) {
                regs64->isf.rip = npc;
            } else {
                regs32->eip = npc;
            }
            return KERN_SUCCESS;
        }

        /*
         * We need to wait until after we've called the
         * dtrace_return_probe_ptr function pointer to set %pc.
         */
        rwp = &CPU->cpu_ft_lock;
        lck_rw_lock_shared(rwp);

        if (dtrace_return_probe_ptr != NULL)
            (void) (*dtrace_return_probe_ptr)(regs);
        lck_rw_unlock_shared(rwp);

        if (regs64) {
            regs64->isf.rip = npc;
        } else {
            regs32->eip = npc;
        }

        return KERN_SUCCESS;
    } else if (trapno == T_INT3) {
        uint8_t instr;
        rwp = &CPU->cpu_ft_lock;

        /*
         * The DTrace fasttrap provider uses the breakpoint trap
         * (int 3). We let DTrace take the first crack at handling
         * this trap; if it's not a probe that DTrace knowns about,
         * we call into the trap() routine to handle it like a
         * breakpoint placed by a conventional debugger.
         */

        /*
         * APPLE NOTE: I believe the purpose of the reader/writers lock
         * is thus: There are times which dtrace needs to prevent calling
         * dtrace_pid_probe_ptr(). Sun's original impl grabbed a plain
         * mutex here. However, that serialized all probe calls, and
         * destroyed MP behavior. So now they use a RW lock, with probes
         * as readers, and the top level synchronization as a writer.
         */
        lck_rw_lock_shared(rwp);
        if (dtrace_pid_probe_ptr != NULL &&
                (*dtrace_pid_probe_ptr)(regs) == 0) {
            lck_rw_unlock_shared(rwp);
            return KERN_SUCCESS;
        }
        lck_rw_unlock_shared(rwp);


        /*
         * If the instruction that caused the breakpoint trap doesn't
         * look like an int 3 anymore, it may be that this tracepoint
         * was removed just after the user thread executed it. In
         * that case, return to user land to retry the instuction.
         */
        user_addr_t pc = (regs64) ? regs64->isf.rip : (user_addr_t)regs32->eip;
        if (fuword8(pc - 1, &instr) == 0 && instr != FASTTRAP_INSTR) {
            if (regs64) {
                regs64->isf.rip--;
            } else {
                regs32->eip--;
            }
            return KERN_SUCCESS;
        }

    }

    return KERN_FAILURE;
}
Example #16
0
/*
 * Initialize the aurp pipe -
 * -Create, initialize, and start the aurpd kernel process; we need
 *  a process to permit queueing between the socket and the stream,
 *  which is necessary for orderly access to the socket structure.
 * -The user process (aurpd) is there to 'build' the AURP
 *  stream, act as a 'logging agent' (:-}), and hold open the stream
 *  during its use.
 * -Data and AURP packets from the DDP stream will be fed into the
 *  UDP tunnel (AURPsend())
 * -Data and AURP packets from the UDP tunnel will be fed into the
 *  DDP stream (ip_to_atalk(), via the kernel process).
 */
int
aurpd_start()
{
	register int error;
	register struct socket *so;
	struct mbuf *m;
	int maxbuf;
	struct sockopt sopt;

	if (suser(current_proc()->p_ucred, &current_proc()->p_acflag) != 0 )
		return(EPERM);

	/*
	 * Set up state prior to starting kernel process so we can back out
	 *  (error return) if something goes wrong.
	 */
	bzero((char *)&aurp_global.tunnel, sizeof(aurp_global.tunnel));
	/*lock_alloc(&aurp_global.glock, LOCK_ALLOC_PIN, AURP_EVNT_LOCK, -1);*/
	ATLOCKINIT(aurp_global.glock);
	ATEVENTINIT(aurp_global.event_anchor);

	/* open udp socket */
	if (aurp_global.udp_port == 0)
		aurp_global.udp_port = AURP_SOCKNUM;
	error = socreate(AF_INET, &aurp_global.tunnel, SOCK_DGRAM,
			 IPPROTO_UDP);
	if (error)
	{	dPrintf(D_M_AURP, D_L_FATAL, ("AURP: Can't get socket (%d)\n",
			error));
		return(error);
	}

	so = aurp_global.tunnel;

	if ((error = aurp_bindrp(so)) != 0)
	{	dPrintf(D_M_AURP, D_L_FATAL,
			("AURP: Can't bind to port %d (error %d)\n",
			aurp_global.udp_port, error));
		soclose(so);
		return(error);
	}

	sblock(&so->so_rcv, M_WAIT);
	sblock(&so->so_snd, M_WAIT);

	/*
	 * Set socket Receive buffer size
	 */
	m = m_get(M_WAIT, MT_SOOPTS);
	if (m == NULL) {
		error = ENOBUFS;
		goto out;
	} else {
		maxbuf = M_RCVBUF;
		sopt.sopt_val     = &maxbuf;
		sopt.sopt_valsize = sizeof(maxbuf);
		sopt.sopt_level   = SOL_SOCKET;
		sopt.sopt_name    = SO_RCVBUF;
		sopt.sopt_dir     = SOPT_SET;
		sopt.sopt_p		  = NULL;
		if ((error = sosetopt(so, &sopt)) != 0)
			goto out;
	}

	/*
	 * Set socket Send buffer size
	 */
	m = m_get(M_WAIT, MT_SOOPTS);
	if (m == NULL) {
		error = ENOBUFS;
		goto out;
	} else {

		maxbuf = M_SNDBUF;
		sopt.sopt_val     = &maxbuf;
		sopt.sopt_valsize = sizeof(maxbuf);
		sopt.sopt_level   = SOL_SOCKET;
		sopt.sopt_name    = SO_SNDBUF;
		sopt.sopt_dir     = SOPT_SET;
		sopt.sopt_p		  = NULL;
		if ((error = sosetopt(so, &sopt)) != 0)
			goto out;
	}

	so->so_upcall = aurp_wakeup;
	so->so_upcallarg = (caddr_t)AE_UDPIP; /* Yuck */
	so->so_state |= SS_NBIO;
	so->so_rcv.sb_flags |=(SB_SEL|SB_NOINTR);
	so->so_snd.sb_flags |=(SB_SEL|SB_NOINTR);

out:
	sbunlock(&so->so_snd);
	sbunlock(&so->so_rcv);

	return(error);
}
Example #17
0
load_return_t
load_machfile(
	struct image_params	*imgp,
	struct mach_header	*header,
	thread_t 		thread,
	vm_map_t 		new_map,
	load_result_t		*result
)
{
	struct vnode		*vp = imgp->ip_vp;
	off_t			file_offset = imgp->ip_arch_offset;
	off_t			macho_size = imgp->ip_arch_size;
	off_t			file_size = imgp->ip_vattr->va_data_size;
	
	pmap_t			pmap = 0;	/* protected by create_map */
	vm_map_t		map;
	vm_map_t		old_map;
	task_t			old_task = TASK_NULL; /* protected by create_map */
	load_result_t		myresult;
	load_return_t		lret;
	boolean_t create_map = FALSE;
	int spawn = (imgp->ip_flags & IMGPF_SPAWN);
	task_t task = current_task();
	proc_t p = current_proc();
	mach_vm_offset_t	aslr_offset = 0;
	mach_vm_offset_t	dyld_aslr_offset = 0;
	kern_return_t 		kret;

	if (macho_size > file_size) {
		return(LOAD_BADMACHO);
	}

	if (new_map == VM_MAP_NULL) {
		create_map = TRUE;
		old_task = current_task();
	}

	/*
	 * If we are spawning, we have created backing objects for the process
	 * already, which include non-lazily creating the task map.  So we
	 * are going to switch out the task map with one appropriate for the
	 * bitness of the image being loaded.
	 */
	if (spawn) {
		create_map = TRUE;
		old_task = get_threadtask(thread);
	}

	if (create_map) {
		pmap = pmap_create(get_task_ledger(task), (vm_map_size_t) 0,
				(imgp->ip_flags & IMGPF_IS_64BIT));
		pal_switch_pmap(thread, pmap, imgp->ip_flags & IMGPF_IS_64BIT);
		map = vm_map_create(pmap,
				0,
				vm_compute_max_offset((imgp->ip_flags & IMGPF_IS_64BIT)),
				TRUE);
	} else
		map = new_map;

#ifndef	CONFIG_ENFORCE_SIGNED_CODE
	/* This turns off faulting for executable pages, which allows
	 * to circumvent Code Signing Enforcement. The per process
	 * flag (CS_ENFORCEMENT) is not set yet, but we can use the
	 * global flag.
	 */
	if ( !cs_enforcement(NULL) && (header->flags & MH_ALLOW_STACK_EXECUTION) )
	        vm_map_disable_NX(map);
#endif

	/* Forcibly disallow execution from data pages on even if the arch
	 * normally permits it. */
	if ((header->flags & MH_NO_HEAP_EXECUTION) && !(imgp->ip_flags & IMGPF_ALLOW_DATA_EXEC))
		vm_map_disallow_data_exec(map);
	
	/*
	 * Compute a random offset for ASLR, and an independent random offset for dyld.
	 */
	if (!(imgp->ip_flags & IMGPF_DISABLE_ASLR)) {
		uint64_t max_slide_pages;

		max_slide_pages = vm_map_get_max_aslr_slide_pages(map);

		aslr_offset = random();
		aslr_offset %= max_slide_pages;
		aslr_offset <<= vm_map_page_shift(map);

		dyld_aslr_offset = random();
		dyld_aslr_offset %= max_slide_pages;
		dyld_aslr_offset <<= vm_map_page_shift(map);
	}
	
	if (!result)
		result = &myresult;

	*result = load_result_null;

	lret = parse_machfile(vp, map, thread, header, file_offset, macho_size,
	                      0, (int64_t)aslr_offset, (int64_t)dyld_aslr_offset, result);

	if (lret != LOAD_SUCCESS) {
		if (create_map) {
			vm_map_deallocate(map);	/* will lose pmap reference too */
		}
		return(lret);
	}

	/*
	 * For 64-bit users, check for presence of a 4GB page zero
	 * which will enable the kernel to share the user's address space
	 * and hence avoid TLB flushes on kernel entry/exit
	 */ 

	if ((imgp->ip_flags & IMGPF_IS_64BIT) &&
	     vm_map_has_4GB_pagezero(map)) {
		vm_map_set_4GB_pagezero(map);
	}
	/*
	 *	Commit to new map.
	 *
	 *	Swap the new map for the old, which  consumes our new map
	 *	reference but each leaves us responsible for the old_map reference.
	 *	That lets us get off the pmap associated with it, and
	 *	then we can release it.
	 */

	 if (create_map) {
		/*
		 * If this is an exec, then we are going to destroy the old
		 * task, and it's correct to halt it; if it's spawn, the
		 * task is not yet running, and it makes no sense.
		 */
	 	if (!spawn) {
			/*
			 * Mark the task as halting and start the other
			 * threads towards terminating themselves.  Then
			 * make sure any threads waiting for a process
			 * transition get informed that we are committed to
			 * this transition, and then finally complete the
			 * task halting (wait for threads and then cleanup
			 * task resources).
			 *
			 * NOTE: task_start_halt() makes sure that no new
			 * threads are created in the task during the transition.
			 * We need to mark the workqueue as exiting before we
			 * wait for threads to terminate (at the end of which
			 * we no longer have a prohibition on thread creation).
			 * 
			 * Finally, clean up any lingering workqueue data structures
			 * that may have been left behind by the workqueue threads
			 * as they exited (and then clean up the work queue itself).
			 */
			kret = task_start_halt(task);
			if (kret != KERN_SUCCESS) {
				return(kret);		
			}
			proc_transcommit(p, 0);
			workqueue_mark_exiting(p);
			task_complete_halt(task);
			workqueue_exit(p);
		}
		old_map = swap_task_map(old_task, thread, map, !spawn);
		vm_map_clear_4GB_pagezero(old_map);
		vm_map_deallocate(old_map);
	}
	return(LOAD_SUCCESS);
}
Example #18
0
int
libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
{
        struct socket      *so;
        struct ifreq       ifr;
        int                nob;
        int                rc;
        __u32              val;
        CFS_DECL_FUNNEL_DATA;

        CFS_NET_IN;
        rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
        CFS_NET_EX;
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return (-rc);
        }
        nob = strnlen(name, IFNAMSIZ);
        if (nob == IFNAMSIZ) {
                CERROR("Interface name %s too long\n", name);
                rc = -EINVAL;
                goto out;
        }

        CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
        strcpy(ifr.ifr_name, name);
        CFS_NET_IN;
        rc = ifioctl(so, SIOCGIFFLAGS, (caddr_t)&ifr, current_proc());
        CFS_NET_EX;

        if (rc != 0) {
                CERROR("Can't get flags for interface %s\n", name);
                goto out;
        }
        if ((ifr.ifr_flags & IFF_UP) == 0) {
                CDEBUG(D_NET, "Interface %s down\n", name);
                *up = 0;
                *ip = *mask = 0;
                goto out;
        }
       
        *up = 1;
        strcpy(ifr.ifr_name, name);
        *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
        CFS_NET_IN;
        rc = ifioctl(so, SIOCGIFADDR, (caddr_t)&ifr, current_proc());
        CFS_NET_EX;

        if (rc != 0) {
                CERROR("Can't get IP address for interface %s\n", name);
                goto out;
        }

        val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
        *ip = ntohl(val);

        strcpy(ifr.ifr_name, name);
        *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
        CFS_NET_IN;
        rc = ifioctl(so, SIOCGIFNETMASK, (caddr_t)&ifr, current_proc());
        CFS_NET_EX;

        if (rc != 0) {
                CERROR("Can't get netmask for interface %s\n", name);
                goto out;
        }

        val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
        *mask = ntohl(val);
out:
        CFS_NET_IN;
        soclose(so);
        CFS_NET_EX;
        return -rc;
}
Example #19
0
kern_return_t
dtrace_user_probe(arm_saved_state_t *regs, unsigned int instr)
{
	/*
	 * FIXME
	 *
	 * The only call path into this method is always a user trap.
	 * We don't need to test for user trap, but should assert it.
	 */

	lck_rw_t *rwp;
	struct proc *p = current_proc();

	uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());

	kauth_cred_uthread_update(uthread, p);

	if (((regs->cpsr & PSR_TF) && ((uint16_t) instr) == FASTTRAP_THUMB_RET_INSTR) ||
	    ((uint32_t) instr == FASTTRAP_ARM_RET_INSTR)) {
		uint8_t step = uthread->t_dtrace_step;
		uint8_t ret = uthread->t_dtrace_ret;
		user_addr_t npc = uthread->t_dtrace_npc;

		if (uthread->t_dtrace_ast) {
			printf("dtrace_user_probe() should be calling aston()\n");
			// aston(thread);
			// uthread->t_sig_check = 1;
		}

		/*
		 * Clear all user tracing flags.
		 */
		uthread->t_dtrace_ft = 0;

		/*
		 * If we weren't expecting to take a return probe trap, kill
		 * the process as though it had just executed an unassigned
		 * trap instruction.
		 */
		if (step == 0) {
			/*
			 * APPLE NOTE: We're returning KERN_FAILURE, which causes 
			 * the generic signal handling code to take over, which will effectively
			 * deliver a EXC_BAD_INSTRUCTION to the user process.
			 */
			return KERN_FAILURE;
		} 

		/*
		 * If we hit this trap unrelated to a return probe, we're
		 * just here to reset the AST flag since we deferred a signal
		 * until after we logically single-stepped the instruction we
		 * copied out.
		 */
		if (ret == 0) {
			regs->pc = npc;
			return KERN_SUCCESS;
		}

		/*
		 * We need to wait until after we've called the
		 * dtrace_return_probe_ptr function pointer to step the pc.
		 */
		rwp = &CPU->cpu_ft_lock;
		lck_rw_lock_shared(rwp);

		if (dtrace_return_probe_ptr != NULL)
			(void) (*dtrace_return_probe_ptr)(regs);
		lck_rw_unlock_shared(rwp);

		regs->pc = npc;

		return KERN_SUCCESS;
	} else {
		rwp = &CPU->cpu_ft_lock;

		/*
		 * The DTrace fasttrap provider uses a trap,
		 * FASTTRAP_{ARM,THUMB}_INSTR. We let
		 * DTrace take the first crack at handling
		 * this trap; if it's not a probe that DTrace knows about,
		 * we call into the trap() routine to handle it like a
		 * breakpoint placed by a conventional debugger.
		 */

		/*
		 * APPLE NOTE: I believe the purpose of the reader/writers lock
		 * is thus: There are times which dtrace needs to prevent calling
		 * dtrace_pid_probe_ptr(). Sun's original impl grabbed a plain
		 * mutex here. However, that serialized all probe calls, and
		 * destroyed MP behavior. So now they use a RW lock, with probes
		 * as readers, and the top level synchronization as a writer.
		 */
		lck_rw_lock_shared(rwp);
		if (dtrace_pid_probe_ptr != NULL &&
		    (*dtrace_pid_probe_ptr)(regs) == 0) {
			lck_rw_unlock_shared(rwp);
			return KERN_SUCCESS;
		}
		lck_rw_unlock_shared(rwp);

		/*
		 * If the instruction that caused the breakpoint trap doesn't
		 * look like our trap anymore, it may be that this tracepoint
		 * was removed just after the user thread executed it. In
		 * that case, return to user land to retry the instuction.
		 *
		 * Note that the PC points to the instruction that caused the fault.
		 */
		if (regs->cpsr & PSR_TF) {
			uint16_t instr_check;
			if (fuword16(regs->pc, &instr_check) == 0 && instr_check != FASTTRAP_THUMB_INSTR) {
				return KERN_SUCCESS;
			}
		} else {
			uint32_t instr_check;
			if (fuword32(regs->pc, &instr_check) == 0 && instr_check != FASTTRAP_ARM_INSTR) {
				return KERN_SUCCESS;
			}
		}
	}

	return KERN_FAILURE;
}
Example #20
0
int
libcfs_ipif_enumerate (char ***namesp)
{
        /* Allocate and fill in 'names', returning # interfaces/error */
        char           **names;
        int             toobig;
        int             nalloc;
        int             nfound;
        struct socket  *so;
        struct ifreq   *ifr;
        struct ifconf   ifc;
        int             rc;
        int             nob;
        int             i;
        CFS_DECL_FUNNEL_DATA;

        CFS_NET_IN;
        rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
        CFS_NET_EX;
        if (rc != 0) {
                CERROR ("Can't create socket: %d\n", rc);
                return (-rc);
        }

        nalloc = 16;    /* first guess at max interfaces */
        toobig = 0;
        for (;;) {
		if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) {
                        toobig = 1;
			nalloc = PAGE_CACHE_SIZE/sizeof(*ifr);
                        CWARN("Too many interfaces: only enumerating first %d\n",
                              nalloc);
                }

                LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
                if (ifr == NULL) {
                        CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
                                rc = -ENOMEM;
                        goto out0;
                }
                                
                ifc.ifc_buf = (char *)ifr;
                ifc.ifc_len = nalloc * sizeof(*ifr);
                                        
                CFS_NET_IN;
                rc = -ifioctl(so, SIOCGIFCONF, (caddr_t)&ifc, current_proc());
                CFS_NET_EX;
                                
                if (rc < 0) {
                        CERROR ("Error %d enumerating interfaces\n", rc);
                        goto out1;
                }

                nfound = ifc.ifc_len/sizeof(*ifr);
                LASSERT (nfound <= nalloc);

                if (nfound < nalloc || toobig)
                        break;

                LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
                nalloc *= 2;
        }
        if (nfound == 0)
                goto out1;

        LIBCFS_ALLOC(names, nfound * sizeof(*names));
        if (names == NULL) {
                rc = -ENOMEM;
                goto out1;
        }
        /* NULL out all names[i] */
        memset (names, 0, nfound * sizeof(*names));

        for (i = 0; i < nfound; i++) {

                nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
                if (nob == IFNAMSIZ) {
                        /* no space for terminating NULL */
                        CERROR("interface name %.*s too long (%d max)\n",
                               nob, ifr[i].ifr_name, IFNAMSIZ);
                        rc = -ENAMETOOLONG;
                        goto out2;
                }

                LIBCFS_ALLOC(names[i], IFNAMSIZ);
                if (names[i] == NULL) {
                        rc = -ENOMEM;
                        goto out2;
                }

                memcpy(names[i], ifr[i].ifr_name, nob);
                names[i][nob] = 0;
        }

        *namesp = names;
        rc = nfound;

out2:
        if (rc < 0)
                libcfs_ipif_free_enumeration(names, nfound);
out1:
        LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
out0:
        CFS_NET_IN;
        soclose(so);
        CFS_NET_EX;
        return rc;
}
Example #21
0
void
dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
{
	thread_t thread = current_thread();
	ppc_saved_state_t *regs;
	user_addr_t pc, sp;
	volatile uint16_t *flags =
	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
#if 0
	uintptr_t oldcontext;
	size_t s1, s2;
#endif
	boolean_t is64Bit = proc_is64bit(current_proc());

	if (*flags & CPU_DTRACE_FAULT)
		return;

	if (pcstack_limit <= 0)
		return;

	/*
	 * If there's no user context we still need to zero the stack.
	 */
	if (thread == NULL)
		goto zero;

	regs = (ppc_saved_state_t *)find_user_regs(thread);
	if (regs == NULL)
		goto zero;
		
	*pcstack++ = (uint64_t)proc_selfpid();
	pcstack_limit--;

	if (pcstack_limit <= 0)
		return;

	pc = regs->REGPC;
	sp = regs->REGSP;
	
#if 0 /* XXX signal stack crawl*/
	oldcontext = lwp->lwp_oldcontext;

	if (p->p_model == DATAMODEL_NATIVE) {
		s1 = sizeof (struct frame) + 2 * sizeof (long);
		s2 = s1 + sizeof (siginfo_t);
	} else {
		s1 = sizeof (struct frame32) + 3 * sizeof (int);
		s2 = s1 + sizeof (siginfo32_t);
	}
#endif

	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
		*pcstack++ = (uint64_t)pc;
		*fpstack++ = 0;
		pcstack_limit--;
		if (pcstack_limit <= 0)
			return;

		/*
		 * XXX This is wrong, but we do not yet support stack helpers.
		 */
		if (is64Bit)
			pc = dtrace_fuword64(sp);
		else
			pc = dtrace_fuword32(sp);
	}

	while (pc != 0) {
		*pcstack++ = (uint64_t)pc;
		*fpstack++ = sp;
		pcstack_limit--;
		if (pcstack_limit <= 0)
			break;

		if (sp == 0)
			break;

#if 0 /* XXX signal stack crawl*/
		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
			if (p->p_model == DATAMODEL_NATIVE) {
				ucontext_t *ucp = (ucontext_t *)oldcontext;
				greg_t *gregs = ucp->uc_mcontext.gregs;

				sp = dtrace_fulword(&gregs[REG_FP]);
				pc = dtrace_fulword(&gregs[REG_PC]);

				oldcontext = dtrace_fulword(&ucp->uc_link);
			} else {
				ucontext_t *ucp = (ucontext_t *)oldcontext;
				greg_t *gregs = ucp->uc_mcontext.gregs;

				sp = dtrace_fuword32(&gregs[EBP]);
				pc = dtrace_fuword32(&gregs[EIP]);

				oldcontext = dtrace_fuword32(&ucp->uc_link);
			}
		} 
		else
#endif
		{
			if (is64Bit) {
				pc = dtrace_fuword64((sp + RETURN_OFFSET64));
				sp = dtrace_fuword64(sp);
			} else {
				pc = dtrace_fuword32((sp + RETURN_OFFSET));
				sp = dtrace_fuword32(sp);
			}
		}
	}

zero:
	while (pcstack_limit-- > 0)
		*pcstack++ = 0;
}
Example #22
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
int ppp_comp_setcompressor(struct ppp_if *wan, struct ppp_option_data *odp)
{
    int 			error = 0;
	u_int32_t		nb;
    struct ppp_comp *cp;
    u_char 			ccp_option[CCP_MAX_OPTION_LENGTH];
    user_addr_t		ptr;
    int				transmit;
    
    if (proc_is64bit(current_proc())) {
        struct ppp_option_data64 *odp64 = (struct ppp_option_data64 *)odp;

        nb = odp64->length;
        ptr = odp64->ptr;
        transmit = odp64->transmit;
    } else {
        struct ppp_option_data32 *odp32 = (struct ppp_option_data32 *)odp;

        nb = odp32->length;
        ptr = CAST_USER_ADDR_T(odp32->ptr);
        transmit = odp32->transmit;
    }
    
    if (nb > sizeof(ccp_option))
        nb = sizeof(ccp_option);

    if (error = copyin(ptr, ccp_option, nb))
        return (error);

    if (ccp_option[1] < 2)	/* preliminary check on the length byte */
        return (EINVAL);

    cp = ppp_comp_find(ccp_option[0]);
    if (cp == 0) {
        LOGDBG(wan->net, ("ppp%d: no compressor for [%x %x %x], %x\n",
                ifnet_unit(wan->net), ccp_option[0], ccp_option[1],
                ccp_option[2], nb));

        return EINVAL;	/* no handler found */
    }

    if (transmit) {
        if (wan->xc_state)
            (*wan->xcomp->comp_free)(wan->xc_state);
        wan->xcomp = cp;
        wan->xc_state = cp->comp_alloc(ccp_option, nb);
        if (!wan->xc_state) {
            error = ENOMEM;
            LOGDBG(wan->net, ("ppp%d: comp_alloc failed\n", ifnet_unit(wan->net)));
        }
        wan->sc_flags &= ~SC_COMP_RUN;
    }
    else {
        if (wan->rc_state)
            (*wan->rcomp->decomp_free)(wan->rc_state);
        wan->rcomp = cp;
        wan->rc_state = cp->decomp_alloc(ccp_option, nb);
        if (!wan->rc_state) {
            error = ENOMEM;
            LOGDBG(wan->net, ("ppp%d: decomp_alloc failed\n", ifnet_unit(wan->net)));
        }
        wan->sc_flags &= ~SC_DECOMP_RUN;
    }
    
    return error;
}
Example #23
0
int
ptrace(struct proc *p, struct ptrace_args *uap, int32_t *retval)
{
	struct proc *t = current_proc();	/* target process */
	task_t		task;
	thread_t	th_act;
	struct uthread 	*ut;
	int tr_sigexc = 0;
	int error = 0;
	int stopped = 0;

	AUDIT_ARG(cmd, uap->req);
	AUDIT_ARG(pid, uap->pid);
	AUDIT_ARG(addr, uap->addr);
	AUDIT_ARG(value32, uap->data);

	if (uap->req == PT_DENY_ATTACH) {
		proc_lock(p);
		if (ISSET(p->p_lflag, P_LTRACED)) {
			proc_unlock(p);
			KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_FRCEXIT) | DBG_FUNC_NONE,
					      p->p_pid, W_EXITCODE(ENOTSUP, 0), 4, 0, 0);
			exit1(p, W_EXITCODE(ENOTSUP, 0), retval);

			thread_exception_return();
			/* NOTREACHED */
		}
		SET(p->p_lflag, P_LNOATTACH);
		proc_unlock(p);

		return(0);
	}

	if (uap->req == PT_FORCEQUOTA) {
		if (kauth_cred_issuser(kauth_cred_get())) {
			OSBitOrAtomic(P_FORCEQUOTA, &t->p_flag);
			return (0);
		} else
			return (EPERM);
	}

	/*
	 *	Intercept and deal with "please trace me" request.
	 */	 
	if (uap->req == PT_TRACE_ME) {
retry_trace_me:;
		proc_t pproc = proc_parent(p);
		if (pproc == NULL)
			return (EINVAL);
#if CONFIG_MACF
		/*
		 * NB: Cannot call kauth_authorize_process(..., KAUTH_PROCESS_CANTRACE, ...)
		 *     since that assumes the process being checked is the current process
		 *     when, in this case, it is the current process's parent.
		 *     Most of the other checks in cantrace() don't apply either.
		 */
		if ((error = mac_proc_check_debug(pproc, p)) == 0) {
#endif
			proc_lock(p);
			/* Make sure the process wasn't re-parented. */
			if (p->p_ppid != pproc->p_pid) {
				proc_unlock(p);
				proc_rele(pproc);
				goto retry_trace_me;
			}
			SET(p->p_lflag, P_LTRACED);
			/* Non-attached case, our tracer is our parent. */
			p->p_oppid = p->p_ppid;
			proc_unlock(p);
			/* Child and parent will have to be able to run modified code. */
			cs_allow_invalid(p);
			cs_allow_invalid(pproc);
#if CONFIG_MACF
		}
#endif
		proc_rele(pproc);
		return (error);
	}
	if (uap->req == PT_SIGEXC) {
		proc_lock(p);
		if (ISSET(p->p_lflag, P_LTRACED)) {
			SET(p->p_lflag, P_LSIGEXC);
			proc_unlock(p);
			return(0);
		} else {
			proc_unlock(p);
			return(EINVAL);
		}
	}

	/* 
	 * We do not want ptrace to do anything with kernel or launchd 
	 */
	if (uap->pid < 2) {
		return(EPERM);
	}

	/*
	 *	Locate victim, and make sure it is traceable.
	 */
	if ((t = proc_find(uap->pid)) == NULL)
			return (ESRCH);

	AUDIT_ARG(process, t);

	task = t->task;
	if (uap->req == PT_ATTACHEXC) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
		uap->req = PT_ATTACH;
		tr_sigexc = 1;
	}
	if (uap->req == PT_ATTACH) {
#pragma clang diagnostic pop
		int		err;


		if ( kauth_authorize_process(proc_ucred(p), KAUTH_PROCESS_CANTRACE, 
									 t, (uintptr_t)&err, 0, 0) == 0 ) {
			/* it's OK to attach */
			proc_lock(t);
			SET(t->p_lflag, P_LTRACED);
			if (tr_sigexc) 
				SET(t->p_lflag, P_LSIGEXC);
	
			t->p_oppid = t->p_ppid;
			/* Check whether child and parent are allowed to run modified
			 * code (they'll have to) */
			proc_unlock(t);
			cs_allow_invalid(t);
			cs_allow_invalid(p);
			if (t->p_pptr != p)
				proc_reparentlocked(t, p, 1, 0);
	
			proc_lock(t);
			if (get_task_userstop(task) > 0 ) {
				stopped = 1;
			}
			t->p_xstat = 0;
			proc_unlock(t);
			psignal(t, SIGSTOP);
			/*
			 * If the process was stopped, wake up and run through
			 * issignal() again to properly connect to the tracing
			 * process.
			 */
			if (stopped)
				task_resume(task);       
			error = 0;
			goto out;
		}
		else {
			/* not allowed to attach, proper error code returned by kauth_authorize_process */
			if (ISSET(t->p_lflag, P_LNOATTACH)) {
				psignal(p, SIGSEGV);
			}
			
			error = err;
			goto out;
		}
	}

	/*
	 * You can't do what you want to the process if:
	 *	(1) It's not being traced at all,
	 */
	proc_lock(t);
	if (!ISSET(t->p_lflag, P_LTRACED)) {
		proc_unlock(t);
		error = EPERM;
		goto out;
	}

	/*
	 *	(2) it's not being traced by _you_, or
	 */
	if (t->p_pptr != p) {
		proc_unlock(t);
		error = EBUSY;
		goto out;
	}

	/*
	 *	(3) it's not currently stopped.
	 */
	if (t->p_stat != SSTOP) {
		proc_unlock(t);
		error = EBUSY;
		goto out;
	}

	/*
	 *	Mach version of ptrace executes request directly here,
	 *	thus simplifying the interaction of ptrace and signals.
	 */
	/* proc lock is held here */
	switch (uap->req) {

	case PT_DETACH:
		if (t->p_oppid != t->p_ppid) {
			struct proc *pp;

			proc_unlock(t);
			pp = proc_find(t->p_oppid);
			if (pp != PROC_NULL) {
				proc_reparentlocked(t, pp, 1, 0);
				proc_rele(pp);
			} else {
				/* original parent exited while traced */
				proc_list_lock();
				t->p_listflag |= P_LIST_DEADPARENT;
				proc_list_unlock();
				proc_reparentlocked(t, initproc, 1, 0);
			}
			proc_lock(t);
		}

		t->p_oppid = 0;
		CLR(t->p_lflag, P_LTRACED);
		CLR(t->p_lflag, P_LSIGEXC);
		proc_unlock(t);
		goto resume;
		
	case PT_KILL:
		/*
		 *	Tell child process to kill itself after it
		 *	is resumed by adding NSIG to p_cursig. [see issig]
		 */
		proc_unlock(t);
#if CONFIG_MACF
		error = mac_proc_check_signal(p, t, SIGKILL);
		if (0 != error)
			goto resume;
#endif
		psignal(t, SIGKILL);
		goto resume;

	case PT_STEP:			/* single step the child */
	case PT_CONTINUE:		/* continue the child */
		proc_unlock(t);
		th_act = (thread_t)get_firstthread(task);
		if (th_act == THREAD_NULL) {
			error = EINVAL;
			goto out;
		}

		/* force use of Mach SPIs (and task_for_pid security checks) to adjust PC */
		if (uap->addr != (user_addr_t)1) {
			error = ENOTSUP;
			goto out;
		}

		if ((unsigned)uap->data >= NSIG) {
			error = EINVAL;
			goto out;
		}

		if (uap->data != 0) {
#if CONFIG_MACF
			error = mac_proc_check_signal(p, t, uap->data);
			if (0 != error)
				goto out;
#endif
			psignal(t, uap->data);
		}

		if (uap->req == PT_STEP) {
		        /*
			 * set trace bit 
			 * we use sending SIGSTOP as a comparable security check.
			 */
#if CONFIG_MACF
			error = mac_proc_check_signal(p, t, SIGSTOP);
			if (0 != error) {
				goto out;
			}
#endif
			if (thread_setsinglestep(th_act, 1) != KERN_SUCCESS) {
				error = ENOTSUP;
				goto out;
			}
		} else {
		        /*
			 * clear trace bit if on
			 * we use sending SIGCONT as a comparable security check.
			 */
#if CONFIG_MACF
			error = mac_proc_check_signal(p, t, SIGCONT);
			if (0 != error) {
				goto out;
			}
#endif
			if (thread_setsinglestep(th_act, 0) != KERN_SUCCESS) {
				error = ENOTSUP;
				goto out;
			}
		}	
	resume:
		proc_lock(t);
		t->p_xstat = uap->data;
		t->p_stat = SRUN;
		if (t->sigwait) {
			wakeup((caddr_t)&(t->sigwait));
			proc_unlock(t);
			if ((t->p_lflag & P_LSIGEXC) == 0) {
				task_resume(task);
			}
		} else
			proc_unlock(t);
			
		break;
		
	case PT_THUPDATE:  {
		proc_unlock(t);
		if ((unsigned)uap->data >= NSIG) {
			error = EINVAL;
			goto out;
		}
		th_act = port_name_to_thread(CAST_MACH_PORT_TO_NAME(uap->addr));
		if (th_act == THREAD_NULL) {
			error = ESRCH;
			goto out;
		}
		ut = (uthread_t)get_bsdthread_info(th_act);
		if (uap->data)
			ut->uu_siglist |= sigmask(uap->data);
		proc_lock(t);
		t->p_xstat = uap->data;
		t->p_stat = SRUN;
		proc_unlock(t);
		thread_deallocate(th_act);
		error = 0;
		}
		break;
	default:
		proc_unlock(t);
		error = EINVAL;
		goto out;
	}

	error = 0;
out:
	proc_rele(t);
	return(error);
}
Example #24
0
int afspag_PSetTokens(char *ain, afs_int32 ainSize, afs_ucred_t **acred)
{
    afs_int32 i;
    register struct unixuser *tu;
    struct afspag_cell *tcell;
    struct ClearToken clear;
    char *stp;
    int stLen;
    afs_int32 flag, set_parent_pag = 0;
    afs_int32 pag, uid;

    AFS_STATCNT(PSetTokens);
    if (!afs_resourceinit_flag) {
	return EIO;
    }
    memcpy((char *)&i, ain, sizeof(afs_int32));
    ain += sizeof(afs_int32);
    stp = ain;			/* remember where the ticket is */
    if (i < 0 || i > MAXKTCTICKETLEN)
	return EINVAL;		/* malloc may fail */
    stLen = i;
    ain += i;			/* skip over ticket */
    memcpy((char *)&i, ain, sizeof(afs_int32));
    ain += sizeof(afs_int32);
    if (i != sizeof(struct ClearToken)) {
	return EINVAL;
    }
    memcpy((char *)&clear, ain, sizeof(struct ClearToken));
    if (clear.AuthHandle == -1)
	clear.AuthHandle = 999;	/* more rxvab compat stuff */
    ain += sizeof(struct ClearToken);
    if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
	/* still stuff left?  we've got primary flag and cell name.  Set these */
	memcpy((char *)&flag, ain, sizeof(afs_int32));	/* primary id flag */
	ain += sizeof(afs_int32);	/* skip id field */
	/* rest is cell name, look it up */
	/* some versions of gcc appear to need != 0 in order to get this right */
	if ((flag & 0x8000) != 0) {	/* XXX Use Constant XXX */
	    flag &= ~0x8000;
	    set_parent_pag = 1;
	}
	tcell = afspag_GetCell(ain);
    } else {
	/* default to primary cell, primary id */
	flag = 1;		/* primary id */
	tcell = afspag_GetPrimaryCell();
    }
    if (!tcell) return ESRCH;
    if (set_parent_pag) {
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
# if defined(AFS_DARWIN_ENV)
	afs_proc_t *p = current_proc();	/* XXX */
# else
	afs_proc_t *p = curproc;	/* XXX */
# endif
# ifndef AFS_DARWIN80_ENV
	uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
		p->p_pid, p->p_comm);
# endif
	setpag(p, acred, -1, &pag, 1);
#else
	setpag(acred, -1, &pag, 1);
#endif
    }
    pag = PagInCred(*acred);
    uid = (pag == NOPAG) ? afs_cr_uid(*acred) : pag;
    /* now we just set the tokens */
    tu = afs_GetUser(uid, tcell->cellnum, WRITE_LOCK);
    if (!tu->cellinfo)
	tu->cellinfo = (void *)tcell;
    tu->vid = clear.ViceId;
    if (tu->stp != NULL) {
	afs_osi_Free(tu->stp, tu->stLen);
    }
    tu->stp = (char *)afs_osi_Alloc(stLen);
    tu->stLen = stLen;
    memcpy(tu->stp, stp, stLen);
    tu->ct = clear;
#ifndef AFS_NOSTATS
    afs_stats_cmfullperf.authent.TicketUpdates++;
    afs_ComputePAGStats();
#endif /* AFS_NOSTATS */
    tu->states |= UHasTokens;
    tu->states &= ~UTokensBad;
    afs_SetPrimary(tu, flag);
    tu->tokenTime = osi_Time();
    afs_PutUser(tu, WRITE_LOCK);

    return 0;
}
Example #25
0
static int
dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, user_addr_t pc,
    user_addr_t sp)
{
#if 0
	volatile uint16_t *flags =
	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;

	uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack crawl */
	size_t s1, s2;
#endif
	int ret = 0;
	boolean_t is64Bit = proc_is64bit(current_proc());

	ASSERT(pcstack == NULL || pcstack_limit > 0);
	
#if 0 /* XXX signal stack crawl */
	if (p->p_model == DATAMODEL_NATIVE) {
		s1 = sizeof (struct frame) + 2 * sizeof (long);
		s2 = s1 + sizeof (siginfo_t);
	} else {
		s1 = sizeof (struct frame32) + 3 * sizeof (int);
		s2 = s1 + sizeof (siginfo32_t);
	}
#endif

	while (pc != 0) {
		ret++;
		if (pcstack != NULL) {
			*pcstack++ = (uint64_t)pc;
			pcstack_limit--;
			if (pcstack_limit <= 0)
				break;
		}

		if (sp == 0)
			break;

#if 0 /* XXX signal stack crawl */
		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
			if (p->p_model == DATAMODEL_NATIVE) {
				ucontext_t *ucp = (ucontext_t *)oldcontext;
				greg_t *gregs = ucp->uc_mcontext.gregs;

				sp = dtrace_fulword(&gregs[REG_FP]);
				pc = dtrace_fulword(&gregs[REG_PC]);

				oldcontext = dtrace_fulword(&ucp->uc_link);
			} else {
				ucontext32_t *ucp = (ucontext32_t *)oldcontext;
				greg32_t *gregs = ucp->uc_mcontext.gregs;

				sp = dtrace_fuword32(&gregs[EBP]);
				pc = dtrace_fuword32(&gregs[EIP]);

				oldcontext = dtrace_fuword32(&ucp->uc_link);
			}
		} 
		else
#endif
		{
			if (is64Bit) {
				pc = dtrace_fuword64((sp + RETURN_OFFSET64));
				sp = dtrace_fuword64(sp);
			} else {
				pc = dtrace_fuword32((sp + RETURN_OFFSET));
				sp = dtrace_fuword32(sp);
			}
		}

#if 0 /* XXX */
		/*
		 * This is totally bogus:  if we faulted, we're going to clear
		 * the fault and break.  This is to deal with the apparently
		 * broken Java stacks on x86.
		 */
		if (*flags & CPU_DTRACE_FAULT) {
			*flags &= ~CPU_DTRACE_FAULT;
			break;
		}
#endif
	}

	return (ret);
}
Example #26
0
int
physio( void (*f_strategy)(buf_t), 
	buf_t bp,
	dev_t dev,
	int flags,
	u_int (*f_minphys)(buf_t),
	struct uio *uio,
	int blocksize)
{
	struct proc *p = current_proc();
	int error, i, buf_allocated, todo, iosize;
	int orig_bflags = 0;
	int64_t done;

	error = 0;
	flags &= B_READ | B_WRITE;
	buf_allocated = 0;

	/*
	 * [check user read/write access to the data buffer]
	 *
	 * Check each iov one by one.  Note that we know if we're reading or
	 * writing, so we ignore the uio's rw parameter.  Also note that if
	 * we're doing a read, that's a *write* to user-space.
	 */
	for (i = 0; i < uio->uio_iovcnt; i++) {
		if (UIO_SEG_IS_USER_SPACE(uio->uio_segflg)) {
			user_addr_t base;
			user_size_t len;
			
			if (uio_getiov(uio, i, &base, &len) ||
				!useracc(base,
					len,
		    		(flags == B_READ) ? B_WRITE : B_READ))
			return (EFAULT);
		}
	}
	/*
	 * Make sure we have a buffer, creating one if necessary.
	 */
	if (bp == NULL) {
		bp = buf_alloc((vnode_t)0);
		buf_allocated = 1;
	} else
	        orig_bflags = buf_flags(bp);
	/*
	 * at this point we should have a buffer
	 * that is marked BL_BUSY... we either 
	 * acquired it via buf_alloc, or it was
	 * passed into us... if it was passed
	 * in, it needs to already be owned by
	 * the caller (i.e. BL_BUSY is set)
	 */
	assert(bp->b_lflags & BL_BUSY);

	/*
	 * [set up the fixed part of the buffer for a transfer]
	 */
	bp->b_dev = dev;
	bp->b_proc = p;

	/*
	 * [mark the buffer busy for physical I/O]
	 * (i.e. set B_PHYS (because it's an I/O to user
	 * memory, and B_RAW, because B_RAW is to be
	 * "Set by physio for raw transfers.", in addition
	 * to the read/write flag.)
	 */
        buf_setflags(bp, B_PHYS | B_RAW);

	/*
	 * [while there is data to transfer and no I/O error]
	 * Note that I/O errors are handled with a 'goto' at the bottom
	 * of the 'while' loop.
	 */
	while (uio_resid(uio) > 0) {
			
			if ( (iosize = uio_curriovlen(uio)) > MAXPHYSIO_WIRED)
			        iosize = MAXPHYSIO_WIRED;
			/*
			 * make sure we're set to issue a fresh I/O
			 * in the right direction
			 */
			buf_reset(bp, flags);

			/* [set up the buffer for a maximum-sized transfer] */
 			buf_setblkno(bp, uio_offset(uio) / blocksize);
			buf_setcount(bp, iosize);
			buf_setdataptr(bp, (uintptr_t)CAST_DOWN(caddr_t, uio_curriovbase(uio)));
			
			/*
			 * [call f_minphys to bound the tranfer size]
			 * and remember the amount of data to transfer,
			 * for later comparison.
			 */
			(*f_minphys)(bp);
			todo = buf_count(bp);

			/*
			 * [lock the part of the user address space involved
			 *    in the transfer]
			 */

			if(UIO_SEG_IS_USER_SPACE(uio->uio_segflg)) {
				error = vslock(CAST_USER_ADDR_T(buf_dataptr(bp)),
					       (user_size_t)todo);
				if (error)
					goto done;
			}
			
			/* [call f_strategy to start the transfer] */
			(*f_strategy)(bp);


			/* [wait for the transfer to complete] */
			error = (int)buf_biowait(bp);

			/*
			 * [unlock the part of the address space previously
			 *    locked]
			 */
			if(UIO_SEG_IS_USER_SPACE(uio->uio_segflg))
				vsunlock(CAST_USER_ADDR_T(buf_dataptr(bp)),
					 (user_size_t)todo,
					 (flags & B_READ));

			/*
			 * [deduct the transfer size from the total number
			 *    of data to transfer]
			 */
			done = buf_count(bp) - buf_resid(bp);
			uio_update(uio, done);

			/*
			 * Now, check for an error.
			 * Also, handle weird end-of-disk semantics.
			 */
			if (error || done < todo)
				goto done;
	}

done:
	if (buf_allocated)
	        buf_free(bp);
	else
		buf_setflags(bp, orig_bflags);

	return (error);
}
Example #27
0
void
dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
{
	thread_t thread = current_thread();
	savearea_t *regs;
	user_addr_t pc, sp;
	volatile uint16_t *flags =
	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
#if 0
	uintptr_t oldcontext;
	size_t s1, s2;
#endif
	boolean_t is64Bit = proc_is64bit(current_proc());

	if (*flags & CPU_DTRACE_FAULT)
		return;

	if (pcstack_limit <= 0)
		return;

	/*
	 * If there's no user context we still need to zero the stack.
	 */
	if (thread == NULL)
		goto zero;

	regs = (savearea_t *)find_user_regs(thread);
	if (regs == NULL)
		goto zero;
		
	*pcstack++ = (uint64_t)proc_selfpid();
	pcstack_limit--;

	if (pcstack_limit <= 0)
		return;

	pc = regs->ss_32.eip;
	sp = regs->ss_32.ebp;
	
#if 0 /* XXX signal stack crawl */
	oldcontext = lwp->lwp_oldcontext;

	if (p->p_model == DATAMODEL_NATIVE) {
		s1 = sizeof (struct frame) + 2 * sizeof (long);
		s2 = s1 + sizeof (siginfo_t);
	} else {
		s1 = sizeof (struct frame32) + 3 * sizeof (int);
		s2 = s1 + sizeof (siginfo32_t);
	}
#endif

	if(dtrace_adjust_stack(&pcstack, &pcstack_limit, &pc, sp) == 1) {
            /*
	     * we made a change.
	     */
	    *fpstack++ = 0;
	    if (pcstack_limit <= 0)
		return;
	}

	while (pc != 0) {
		*pcstack++ = (uint64_t)pc;
		*fpstack++ = sp;
		pcstack_limit--;
		if (pcstack_limit <= 0)
			break;

		if (sp == 0)
			break;

#if 0 /* XXX signal stack crawl */
		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
			if (p->p_model == DATAMODEL_NATIVE) {
				ucontext_t *ucp = (ucontext_t *)oldcontext;
				greg_t *gregs = ucp->uc_mcontext.gregs;

				sp = dtrace_fulword(&gregs[REG_FP]);
				pc = dtrace_fulword(&gregs[REG_PC]);

				oldcontext = dtrace_fulword(&ucp->uc_link);
			} else {
				ucontext_t *ucp = (ucontext_t *)oldcontext;
				greg_t *gregs = ucp->uc_mcontext.gregs;

				sp = dtrace_fuword32(&gregs[EBP]);
				pc = dtrace_fuword32(&gregs[EIP]);

				oldcontext = dtrace_fuword32(&ucp->uc_link);
			}
		} 
		else
#endif
		{
			if (is64Bit) {
				pc = dtrace_fuword64((sp + RETURN_OFFSET64));
				sp = dtrace_fuword64(sp);
			} else {
				pc = dtrace_fuword32((sp + RETURN_OFFSET));
				sp = dtrace_fuword32(sp);
			}
		}

#if 0 /* XXX */
		/*
		 * This is totally bogus:  if we faulted, we're going to clear
		 * the fault and break.  This is to deal with the apparently
		 * broken Java stacks on x86.
		 */
		if (*flags & CPU_DTRACE_FAULT) {
			*flags &= ~CPU_DTRACE_FAULT;
			break;
		}
#endif
	}

zero:
	while (pcstack_limit-- > 0)
		*pcstack++ = 0;
}
Example #28
0
errno_t
sock_accept(socket_t sock, struct sockaddr *from, int fromlen, int flags,
            sock_upcall callback, void *cookie, socket_t *new_sock)
{
    struct sockaddr *sa;
    struct socket *new_so;
    lck_mtx_t *mutex_held;
    int dosocklock;
    errno_t	error = 0;

    if (sock == NULL || new_sock == NULL)
        return (EINVAL);

    socket_lock(sock, 1);
    if ((sock->so_options & SO_ACCEPTCONN) == 0) {
        socket_unlock(sock, 1);
        return (EINVAL);
    }
    if ((flags & ~(MSG_DONTWAIT)) != 0) {
        socket_unlock(sock, 1);
        return (ENOTSUP);
    }
    if (((flags & MSG_DONTWAIT) != 0 || (sock->so_state & SS_NBIO) != 0) &&
            sock->so_comp.tqh_first == NULL) {
        socket_unlock(sock, 1);
        return (EWOULDBLOCK);
    }

    if (sock->so_proto->pr_getlock != NULL)  {
        mutex_held = (*sock->so_proto->pr_getlock)(sock, 0);
        dosocklock = 1;
    } else {
        mutex_held = sock->so_proto->pr_domain->dom_mtx;
        dosocklock = 0;
    }

    while (TAILQ_EMPTY(&sock->so_comp) && sock->so_error == 0) {
        if (sock->so_state & SS_CANTRCVMORE) {
            sock->so_error = ECONNABORTED;
            break;
        }
        error = msleep((caddr_t)&sock->so_timeo, mutex_held,
                       PSOCK | PCATCH, "sock_accept", NULL);
        if (error != 0) {
            socket_unlock(sock, 1);
            return (error);
        }
    }
    if (sock->so_error != 0) {
        error = sock->so_error;
        sock->so_error = 0;
        socket_unlock(sock, 1);
        return (error);
    }

    new_so = TAILQ_FIRST(&sock->so_comp);
    TAILQ_REMOVE(&sock->so_comp, new_so, so_list);
    sock->so_qlen--;

    /*
     * Pass the pre-accepted socket to any interested socket filter(s).
     * Upon failure, the socket would have been closed by the callee.
     */
    if (new_so->so_filt != NULL) {
        /*
         * Temporarily drop the listening socket's lock before we
         * hand off control over to the socket filter(s), but keep
         * a reference so that it won't go away.  We'll grab it
         * again once we're done with the filter(s).
         */
        socket_unlock(sock, 0);
        if ((error = soacceptfilter(new_so)) != 0) {
            /* Drop reference on listening socket */
            sodereference(sock);
            return (error);
        }
        socket_lock(sock, 0);
    }

    if (dosocklock)	{
        lck_mtx_assert(new_so->so_proto->pr_getlock(new_so, 0),
                       LCK_MTX_ASSERT_NOTOWNED);
        socket_lock(new_so, 1);
    }

    new_so->so_state &= ~SS_COMP;
    new_so->so_head = NULL;
    (void) soacceptlock(new_so, &sa, 0);

    socket_unlock(sock, 1);	/* release the head */

    /* see comments in sock_setupcall() */
    if (callback != NULL) {
        sock_setupcalls_common(new_so, callback, cookie, NULL, NULL);
    }

    if (sa != NULL && from != NULL) {
        if (fromlen > sa->sa_len)
            fromlen = sa->sa_len;
        memcpy(from, sa, fromlen);
    }
    if (sa != NULL)
        FREE(sa, M_SONAME);

    /*
     * If the socket has been marked as inactive by sosetdefunct(),
     * disallow further operations on it.
     */
    if (new_so->so_flags & SOF_DEFUNCT) {
        (void) sodefunct(current_proc(), new_so,
                         SHUTDOWN_SOCKET_LEVEL_DISCONNECT_INTERNAL);
    }
    *new_sock = new_so;
    if (dosocklock)
        socket_unlock(new_so, 1);
    return (error);
}
Example #29
0
/*
 *	Routine:	macx_swapon
 *	Function:
 *		Syscall interface to add a file to backing store
 */
int
macx_swapon(
	struct macx_swapon_args *args)
{
	int			size = args->size;
	vnode_t			vp = (vnode_t)NULL; 
	struct nameidata 	nd, *ndp;
	register int		error;
	kern_return_t		kr;
	mach_port_t		backing_store;
	memory_object_default_t	default_pager;
	int			i;
	boolean_t		funnel_state;
	off_t			file_size;
	vfs_context_t		ctx = vfs_context_current();
	struct proc		*p =  current_proc();

	AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPON);
	AUDIT_ARG(value32, args->priority);

	funnel_state = thread_funnel_set(kernel_flock, TRUE);
	ndp = &nd;

	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,
	       ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
	       (user_addr_t) args->filename, ctx);

	if ((error = namei(ndp)))
		goto swapon_bailout;
	nameidone(ndp);
	vp = ndp->ni_vp;

	if (vp->v_type != VREG) {
		error = EINVAL;
		goto swapon_bailout;
	}

	/* get file size */
	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, ctx)) != 0))
		goto swapon_bailout;

	/* add new backing store to list */
	i = 0;
	while(bs_port_table[i].vp != 0) {
		if(i == MAX_BACKING_STORE)
			break;
		i++;
	}
	if(i == MAX_BACKING_STORE) {
	   	error = ENOMEM;
		goto swapon_bailout;
	}

	/* remember the vnode. This vnode has namei() reference */
	bs_port_table[i].vp = vp;
	
	/*
	 * Look to see if we are already paging to this file.
	 */
	/* make certain the copy send of kernel call will work */
	default_pager = MEMORY_OBJECT_DEFAULT_NULL;
	kr = host_default_memory_manager(host_priv_self(), &default_pager, 0);
	if(kr != KERN_SUCCESS) {
	   error = EAGAIN;
	   bs_port_table[i].vp = 0;
	   goto swapon_bailout;
	}

	kr = default_pager_backing_store_create(default_pager, 
					-1, /* default priority */
					0, /* default cluster size */
					&backing_store);
	memory_object_default_deallocate(default_pager);

	if(kr != KERN_SUCCESS) {
	   error = ENOMEM;
	   bs_port_table[i].vp = 0;
	   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:
	 *	a: we do not support offsets from the beginning of the
	 *		file (allowing for non page size/record modulo offsets.
	 *	b: because allow paging will be done modulo page size
	 */

	kr = default_pager_add_file(backing_store, (vnode_ptr_t) vp,
				PAGE_SIZE, (int)(file_size/PAGE_SIZE));
	if(kr != KERN_SUCCESS) {
	   bs_port_table[i].vp = 0;
	   if(kr == KERN_INVALID_ARGUMENT)
		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;

	ubc_setthreadcred(vp, p, current_thread());

	/*
	 * take a long term reference on the vnode to keep
	 * vnreclaim() away from this vnode.
	 */
	vnode_ref(vp);

swapon_bailout:
	if (vp) {
		vnode_put(vp);
	}
	(void) thread_funnel_set(kernel_flock, FALSE);
	AUDIT_MACH_SYSCALL_EXIT(error);
	return(error);
}
//
// if fase is returned the request has been completed as the access is denied
//
bool
DldIOSCSIProtocolInterface::ExecuteCommand(
    __in IOSCSIProtocolInterface* service,
    __in SCSITaskIdentifier request
    )
{
    //SCSICommandDescriptorBlock   cdb;
    
    //assert( sizeof( cdb ) == kSCSICDBSize_Maximum );
    
    //DldSCSITaskGetCommandDescriptorBlock( request, &cdb );
    
    ///////
    /// start of the test
    /*
      DldSCSITaskCompleteAccessDenied( request );
      return false;
     */
    /// end of the test
    ////////
    /*
    dld_classic_rights_t   access;
    access = DldSCSITaskGetCdbRequestedAccess( request );
    if( 0x0 != ( DEVICE_WRITE & access ) ){
        
        DldSCSITaskCompleteAccessDenied( request );
        return false;
    }*/
    
    
    assert( preemption_enabled() );
    
    DldIOService*             dldSCSIDev;
    DldObjectPropertyEntry*   property;
    dld_classic_rights_t      requestedAccess;
    DldAccessCheckParam       param;
    bool                      disable        = false;
    bool                      isShadowedUser = false;
    
    requestedAccess = DldSCSITaskGetCdbRequestedAccess( request );
    if( 0x0 == requestedAccess )
        return true;
    
    dldSCSIDev = DldIOService::RetrieveDldIOServiceForIOService( service );
    assert( dldSCSIDev );
    if( !dldSCSIDev ){
        
        DBG_PRINT_ERROR(("DldIOService::RetrieveDldIOServiceForIOService( 0x%p ) returned NULL\n", service ));
        return true;
    }
    
    //
    // do not check read operations if there is a CD or DVD object in the stack,
    // as read requests are generated by every client including a mounted FSD( i.e. BSD susbsystem ),
    // but if there is no CD or DVD object then a user mode client dismantled them and
    // attached directly to the SCSI object, in that case the read requests must be 
    // checked and audited
    //
    if( DEVICE_READ == requestedAccess ){
        
        DldObjectPropertyEntry*   media;
        
        //
        // look for actual CD/DVD properties
        //

        media = dldSCSIDev->retrievePropertyByTypeRef( DldObjectPopertyType_IODVDMedia );
        if( NULL == media )
            media = dldSCSIDev->retrievePropertyByTypeRef( DldObjectPopertyType_IOCDMedia );
        
        if( media ){
            
            //
            // a request from the BSD subssytem, the request has been checked by the BSD KAUTH callbacks
            //
            media->release();
            goto __exit;
        }
        
    } // end if( DEVICE_READ == requestedAccess )
    
    property = dldSCSIDev->getObjectProperty();
    if( !property ){
        
        //
        // we are not interested in this device, this means that
        // there is another IOSCSIProtocolInterface device attached
        // to this one and this last is visible for user apps
        //
        goto __exit;
    }
    
    if( DldObjectPopertyType_SCSIPeripheralDeviceType05 != property->dataU.property->typeDsc.type ){
     
        DBG_PRINT_ERROR(("It seems you added a new SCSI type %i but forgot to add its processing\n", property->dataU.property->typeDsc.type ));
        assert( !"It seems you added a new SCSI type but forgot to add its processing" );
        goto __exit;
    }
        
    bzero( &param, sizeof( param ) );
    
    param.userSelectionFlavor = kDefaultUserSelectionFlavor;
    param.aclType             = kDldAclTypeSecurity;
    param.checkParentType     = true;
    param.dldRequestedAccess.winRequestedAccess   = requestedAccess;
    //param.dldRequestedAccess.kauthRequestedAccess = requestedAccess; // TO DO remove when the daemon will be able to proide ACL
    param.credential          = NULL;// current thread's user
    param.dldIOService        = dldSCSIDev;
#if defined(LOG_ACCESS)
    param.sourceFunction      = __PRETTY_FUNCTION__;
    param.sourceFile          = __FILE__;
    param.sourceLine          = __LINE__;
#endif//#if defined(LOG_ACCESS)
    
    /*if( dldIOService->getObjectProperty() &&
     DLD_DEVICE_TYPE_REMOVABLE == dldIOService->getObjectProperty()->dataU.property->deviceType.type.major ){}*/
    
    ::DldAcquireResources( &param );
    {
        ::isAccessAllowed( &param );
        
        disable = ( param.output.access.result[ DldFullTypeFlavor ].disable || 
                    param.output.access.result[ DldMajorTypeFlavor ].disable || 
                    param.output.access.result[ DldParentTypeFlavor ].disable );
        
#if defined( DBG )
        /*if( disable ){
         __asm__ volatile( "int $0x3" );
         }*/
#endif
        
        //
        // should we log?
        //
        if( param.output.access.result[ DldFullTypeFlavor ].log ||
            param.output.access.result[ DldMajorTypeFlavor ].log ){
            
            DldDriverDataLogInt intData;
            DldDriverDataLog    data;
            bool                logDataValid;
            kauth_cred_t        credentials;
            
            intData.logDataSize = sizeof( data );
            intData.logData = &data;
            
            credentials = kauth_cred_proc_ref( current_proc() ); // just like in isAccessAllowed()
            assert( credentials );
            if( credentials ){
                
                logDataValid = dldSCSIDev->initDeviceLogData( &param.dldRequestedAccess,
                                                              (ALL_WRITE & requestedAccess) ? DldFileOperationWrite : DldFileOperationRead,
                                                              proc_pid(current_proc()),
                                                              credentials,
                                                              ( param.output.access.result[ DldFullTypeFlavor ].disable || 
                                                                param.output.access.result[ DldMajorTypeFlavor ].disable ),
                                                              &intData );
                
                assert( logDataValid );
                if( logDataValid ){
                    
                    gLog->logData( &intData );
                    
                } else {
                    
                    DBG_PRINT_ERROR(("device log data is invalid\n"));
                }
                
                kauth_cred_unref( &credentials );
            } else {
                
                DBG_PRINT_ERROR(("kauth_cred_proc_ref failed\n"));
            }
            
        }// end log
    }
    ::DldReleaseResources( &param );
    
    if( !disable ){
        
        //
        // check for ejection
        //
        if( DldSCSITaskIsMediaEjectionRequest( request ) ){
            
            /*
             a media is ejected by calling IOSCSIMultimediaCommandsDevice::EjectTheMedia which in turn
             calls IOSCSIProtocolInterface::ExecuteCommand with two commands - the first unlocks the tray
             and the second is kSCSICmd_START_STOP_UNIT, the stack is as follows
             
             #0  0x015eae43 in IOSCSIMultimediaCommandsDevice::EjectTheMedia (this=0x57c2d00) at /SourceCache/IOSCSIArchitectureModelFamily/IOSCSIArchitectureModelFamily-265.0.3/IOSCSIMultimediaCommands/IOSCSIMultimediaCommandsDevice.cpp:722
             #1  0x015f0cb3 in IODVDServices::doEjectMedia (this=0x57c6380) at /SourceCache/IOSCSIArchitectureModelFamily/IOSCSIArchitectureModelFamily-265.0.3/IOSCSIMultimediaCommands/IODVDServices.cpp:594
             #2  0x011edfd8 in IOBlockStorageDriver::ejectMedia (this=0x57c2200) at /SourceCache/IOStorageFamily/IOStorageFamily-116.1/IOBlockStorageDriver.cpp:1191
             #3  0x011f70ef in dkioctl (dev=234881028, cmd=536896533, data=0x31d93e94 "", flags=1, proc=0x5bf4d20) at /SourceCache/IOStorageFamily/IOStorageFamily-116.1/IOMediaBSDClient.cpp:1382
             #4  0x003662a1 in spec_ioctl (ap=0x31d93d9c) at /work/Mac_OS_X_kernel/10_6_4/xnu-1504.7.4/bsd/miscfs/specfs/spec_vnops.c:529
             #5  0x00357488 in VNOP_IOCTL (vp=0x8f612e4, command=536896533, data=0x31d93e94 "", fflag=1, ctx=0x31d93e8c) at /work/Mac_OS_X_kernel/10_6_4/xnu-1504.7.4/bsd/vfs/kpi_vfs.c:3606
             #6  0x0034ca2f in vn_ioctl (fp=0x63504a0, com=536896533, data=0x31d93e94 "", ctx=0x31d93e8c) at /work/Mac_OS_X_kernel/10_6_4/xnu-1504.7.4/bsd/vfs/vfs_vnops.c:1147
             #7  0x00515c35 in fo_ioctl (fp=0x63504a0, com=536896533, data=0x31d93e94 "", ctx=0x31d93e8c) at /work/Mac_OS_X_kernel/10_6_4/xnu-1504.7.4/bsd/kern/kern_descrip.c:4826
             #8  0x005458ff in ioctl (p=0x5bf4d20, uap=0x54bea28, retval=0x5680324) at /work/Mac_OS_X_kernel/10_6_4/xnu-1504.7.4/bsd/kern/sys_generic.c:914
             #9  0x005b19b5 in unix_syscall64 (state=0x54bea24) at /work/Mac_OS_X_kernel/10_6_4/xnu-1504.7.4/bsd/dev/i386/systemcalls.c:365
             
             a description for the START_STOP_UNIT command can be found here
             http://en.wikipedia.org/wiki/SCSI_Start_Stop_Unit_Command
             we are interested in the following field
             LoEj (load/eject) and Start - these two bits are used together:
             00 - Stop motor
             01 - Start motor
             10 - Eject media
             11 - Load media
             */
            
            //
            // the media is being removed, invalidate the CD/DVD white list state,
            // the FSD has been already unmounted as the tray is locked when FSD
            // is mounted, if the white list results will be removed prematurely
            // when they will be restored on the next request
            //
            
            DldAclObject*  wlACLToRemove;
            
            property->dataU.property->LockExclusive();
            { // start of the lock
                
                wlACLToRemove = property->dataU.property->whiteListState.acl;
                property->dataU.property->whiteListState.acl              = NULL;
                property->dataU.property->whiteListState.inWhiteList      = false;
                property->dataU.property->whiteListState.currentWLApplied = false;// this value is a main driver to start reinitialization
                
                //
                // meaningless for DVD/CD
                //
                assert( false == property->dataU.property->whiteListState.propagateUp );
                
                if( DldObjectPopertyType_SCSIPeripheralDeviceType05 == property->dataU.property->typeDsc.type ){
                    
                    //
                    // the media is being removed
                    //
                    
                    property->dataU.ioSCSIPeripheralType05Property->uidValid = false;
                    
                    bzero( &property->dataU.ioSCSIPeripheralType05Property->mediaUID,
                           sizeof( property->dataU.ioSCSIPeripheralType05Property->mediaUID ) );
                }
                
            }// end of the lock
            property->dataU.property->UnLockExclusive();
            
            if( wlACLToRemove )
                wlACLToRemove->release();
            
            property->setUIDProperty();
            
        }// end if( DldSCSITaskIsMediaEjectionRequest( request )
        
        
        //
        // check for shadowing
        //
        DldAccessCheckParam param;
        
        bzero( &param, sizeof( param ) );
        
        param.userSelectionFlavor = kDefaultUserSelectionFlavor;
        param.aclType             = kDldAclTypeShadow;
        param.checkParentType     = true;
        param.dldRequestedAccess.kauthRequestedAccess = requestedAccess;// actually the value is ignored
        param.credential          = NULL;// current thread's user
        param.service             = NULL;
        param.dldIOService        = dldSCSIDev;
        
        ::DldAcquireResources( &param );
        ::DldIsShadowedUser( &param );
        ::DldReleaseResources( &param );
        
        isShadowedUser = ( param.output.shadow.result[ DldFullTypeFlavor ].shadow || 
                           param.output.shadow.result[ DldMajorTypeFlavor ].shadow || 
                           param.output.shadow.result[ DldParentTypeFlavor ].shadow );
        
    }// end if( !disable )
    
    
    //
    // shadow the write request
    //
    if( isShadowedUser && 0x0 != ( DEVICE_WRITE & requestedAccess ) ){
        
        assert( !disable );
        
        DldCommonShadowParams commonParams;
        UInt32       completionEvent    = DLD_INVALID_EVENT_VALUE;
        IOReturn     shadowCompletionRC = kIOReturnInvalid;
        bool         synchronousShadow  = false;
        bool         shadowed           = false;
        
        if( gSecuritySettings.securitySettings.disableOnShadowErrors ){
            
            //
            // the shadow operation must be synchronous
            //
            synchronousShadow = true;
        }
        
        bzero( &commonParams, sizeof( commonParams ) );
        
        commonParams.operationID = gShadow->generateUniqueID();
        if( synchronousShadow ){
            
            //
            // for synchronous processing we need an event to wait for shadow completion
            //
            DldInitNotificationEvent( &completionEvent );
            commonParams.completionEvent    = &completionEvent;
            commonParams.shadowCompletionRC = &shadowCompletionRC;
        }
        
        //
        // shadow the request
        //
        shadowed = gShadow->shadowSCSIOperation( dldSCSIDev, request, &commonParams );        
        if( shadowed && synchronousShadow ){
            
            //
            // wait for shadow completion
            //
            DldWaitForNotificationEvent( &completionEvent );
            
            //
            // the status code must be valid
            //
            assert( kIOReturnInvalid != completionEvent );
            
        } else if( shadowed ){
            
            //
            // an asynchronous shadowing, the first phase was successful
            //
            assert( !synchronousShadow );
            assert( DLD_INVALID_EVENT_VALUE == completionEvent );
            
            shadowCompletionRC = KERN_SUCCESS;
            
        } else {
            
            //
            // failed on the first phase
            //
            DBG_PRINT_ERROR(("the first phase of the shadowing failed\n"));
            shadowCompletionRC = KERN_FAILURE;
        }
        
        if( KERN_SUCCESS != shadowCompletionRC && gSecuritySettings.securitySettings.disableOnShadowErrors ){
            
            //
            // the shadowing failed so must the request
            //
            DBG_PRINT_ERROR(("shadowing failed\n"));
            disable = true;
        }
        
        //
        // the SCSI operation completion status is reported by a completion callback hook, see shadowSCSIOperation()
        //
        
    }// end if( isShadowedUser )
    
    
__exit:
    assert( dldSCSIDev );
    dldSCSIDev->release();
    
    if( disable )
        DldSCSITaskCompleteAccessDenied( request );
    
    return (!disable);
}