コード例 #1
0
ファイル: darwin-fs.c プロジェクト: dmlb2000/lustre-release
struct cfs_kern_file *
kern_file_open(const char * filename, int uflags, int mode, int *err)
{
        struct cfs_kern_file    *fp;
        vnode_t         vp;
        int             error;

        fp = (struct cfs_kern_file *)_MALLOC(sizeof(struct cfs_kern_file), M_TEMP, M_WAITOK);
        if (fp == NULL) {
                if (err != NULL)
                        *err = -ENOMEM;
                return NULL;
        }
        fp->f_flags = FFLAGS(uflags);
        fp->f_ctxt = vfs_context_create(NULL);

        if ((error = vnode_open(filename, fp->f_flags, 
                                mode, 0, &vp, fp->f_ctxt))){
                if (err != NULL)
                        *err = -error;
                _FREE(fp, M_TEMP);
        } else {
                if (err != NULL)
                        *err = 0;
                fp->f_vp = vp;
        }

        return fp;
}
コード例 #2
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int zfs_vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, ssize_t len,
                offset_t offset, enum uio_seg seg, int ioflag, rlim64_t ulimit,
                cred_t *cr, ssize_t *residp)
{
    uio_t *auio;
    int spacetype;
    int error=0;
    vfs_context_t vctx;

    spacetype = UIO_SEG_IS_USER_SPACE(seg) ? UIO_USERSPACE32 : UIO_SYSSPACE;

    vctx = vfs_context_create((vfs_context_t)0);
    auio = uio_create(1, 0, spacetype, rw);
    uio_reset(auio, offset, spacetype, rw);
    uio_addiov(auio, (uint64_t)(uintptr_t)base, len);

    if (rw == UIO_READ) {
        error = VNOP_READ(vp, auio, ioflag, vctx);
    } else {
        error = VNOP_WRITE(vp, auio, ioflag, vctx);
    }

    if (residp) {
        *residp = uio_resid(auio);
    } else {
        if (uio_resid(auio) && error == 0)
            error = EIO;
    }

    uio_free(auio);
    vfs_context_rele(vctx);

    return (error);
}
コード例 #3
0
int readFile(char *file, uint8_t *buffer, off_t offset, user_size_t size) {
    int res = EIO;

    vfs_context_t vfsContext = vfs_context_create(NULL);
    if (vfsContext == NULL) {
        return EIO;
    }

    vnode_t fileVnode = NULLVP;
    if (vnode_lookup(file, 0, &fileVnode, vfsContext) == 0) {
        uio_t uio = uio_create(1, offset, UIO_SYSSPACE, UIO_READ);
        if (uio == NULL)
            goto exit;

        if (uio_addiov(uio, CAST_USER_ADDR_T(buffer), size))
            goto exit;

        if (VNOP_READ(fileVnode, uio, 0, vfsContext))
            goto exit;

        if (uio_resid(uio))
            goto exit;

        res = 0;
    } else {
        vfs_context_rele(vfsContext);
        return ENOENT;
    }

exit:
    vnode_put(fileVnode);
    vfs_context_rele(vfsContext);
    return res;
}
コード例 #4
0
void VNodeDiskDeviceClass::closeVNode() 
{
  if (m_vnode != NULL) {
    IOLog("Closing the file node\n");
    vfs_context_t vfsContext = vfs_context_create((vfs_context_t) 0);
    vnode_close(m_vnode, 0, vfsContext);
    vfs_context_rele(vfsContext);
    m_vnode = NULL;
  }
}
コード例 #5
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int
VOP_FSYNC(struct vnode *vp, int flags, void* unused, void *uused2)
{
    vfs_context_t vctx;
    int error;

    vctx = vfs_context_create((vfs_context_t)0);
    error = VNOP_FSYNC(vp, (flags == FSYNC), vctx);
    (void) vfs_context_rele(vctx);
    return (error);
}
コード例 #6
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int
VOP_CLOSE(struct vnode *vp, int flag, int count, offset_t off, void *cr, void *k)
{
    vfs_context_t vctx;
    int error;

    vctx = vfs_context_create((vfs_context_t)0);
    error = vnode_close(vp, flag & FWRITE, vctx);
    (void) vfs_context_rele(vctx);
    return (error);
}
コード例 #7
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int
vn_rename(char *from, char *to, enum uio_seg seg)
{
    vfs_context_t vctx;
    int error;

    vctx = vfs_context_create((vfs_context_t)0);

    error = vnode_rename(from, to, 0, vctx);

    (void) vfs_context_rele(vctx);

    return (error);
}
コード例 #8
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int VOP_GETATTR(struct vnode *vp, vattr_t *vap, int flags, void *x3, void *x4)
{
    vfs_context_t vctx;
    int error;

    //vap->va_size = 134217728;
    //return 0;

    //    panic("take this");
    //printf("VOP_GETATTR(%p, %p, %d)\n", vp, vap, flags);
    vctx = vfs_context_create((vfs_context_t)0);
    error= vnode_getattr(vp, vap, vctx);
    (void) vfs_context_rele(vctx);
    return error;
}
コード例 #9
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int
vn_remove(char *fnamep, enum uio_seg seg, enum rm dirflag)
{
    vfs_context_t vctx;
    enum vtype type;
    int error;

    type = dirflag == RMDIRECTORY ? VDIR : VREG;

    vctx = vfs_context_create((vfs_context_t)0);

    error = vnode_remove(fnamep, 0, type, vctx);

    (void) vfs_context_rele(vctx);

    return (error);
}
コード例 #10
0
bool VNodeDiskDeviceClass::setupVNode() {
  int vapError = -1;
  struct vnode_attr vap;

  if (m_vnode != NULL)
    return true;

  vfs_context_t vfsContext = vfs_context_create((vfs_context_t) 0);

  int vnodeError = vnode_open(m_filePath->getCStringNoCopy(), (FREAD | FWRITE), 0, 0,
    &m_vnode, vfsContext);

  if (vnodeError || m_vnode == NULL) {
    IOLog("Error when opening file %s: error %d\n", 
      m_filePath->getCStringNoCopy(), vnodeError);
    goto failure;
  }

  if (!vnode_isreg(m_vnode)) {
    IOLog("Error when opening file %s: not a regular file\n", 
      m_filePath->getCStringNoCopy());
    vnode_close(m_vnode, (FREAD | FWRITE), vfsContext);
    goto failure;
  }

  VATTR_INIT(&vap);
  VATTR_WANTED(&vap, va_data_size);
  vapError = vnode_getattr(m_vnode, &vap, vfsContext);
  if (vapError) {
    IOLog("Error when retrieving vnode's attributes with error code %d\n", vapError);
    goto failure;
  }

  if (vap.va_data_size < m_blockSize * m_blockNum) {
    IOLog("Error file %s is too small, actual size is %llu\n", 
      m_filePath->getCStringNoCopy(), vap.va_data_size);
    goto failure;
  }

  vfs_context_rele(vfsContext);
  return true;

failure:
  vfs_context_rele(vfsContext);
  return false;
}
コード例 #11
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
int
vn_open(char *pnamep, enum uio_seg seg, int filemode, int createmode,
        struct vnode **vpp, enum create crwhy, mode_t umask)
{
    vfs_context_t vctx;
    int fmode;
    int error;

    fmode = filemode;
    if (crwhy)
        fmode |= O_CREAT;
    // TODO I think this should be 'fmode' instead of 'filemode'
    vctx = vfs_context_create((vfs_context_t)0);
    error = vnode_open(pnamep, filemode, createmode, 0, vpp, vctx);
    (void) vfs_context_rele(vctx);
    //printf("vn_open '%s' -> %d (vp %p)\n", pnamep, error, *vpp);
    return (error);
}
コード例 #12
0
ファイル: osi_misc.c プロジェクト: jisqyv/openafs
int
osi_lookupname(char *aname, enum uio_seg seg, int followlink,
	       struct vnode **vpp) {
    vfs_context_t ctx;
    int code, flags;

    flags = 0;
    if (!followlink)
	flags |= VNODE_LOOKUP_NOFOLLOW;
    ctx=vfs_context_create(NULL);
    code = vnode_lookup(aname, flags, vpp, ctx);
    if (!code) { /* get a usecount */
	vnode_ref(*vpp);
	vnode_put(*vpp);
    }
    vfs_context_rele(ctx);
    return code;
}
コード例 #13
0
ファイル: spl-vnode.c プロジェクト: rottegift/spl
/*
 * Our version of vn_rdwr, here "vp" is not actually a vnode, but a ptr
 * to the node allocated in getf(). We use the "fp" part of the node to
 * be able to issue IO.
 * You must call getf() before calling spl_vn_rdwr().
 */
int spl_vn_rdwr(enum uio_rw rw,
                struct vnode *vp,
                caddr_t base,
                ssize_t len,
                offset_t offset,
                enum uio_seg seg,
                int ioflag,
                rlim64_t ulimit,    /* meaningful only if rw is UIO_WRITE */
                cred_t *cr,
                ssize_t *residp)
{
    struct spl_fileproc *sfp = (struct spl_fileproc*)vp;
    uio_t *auio;
    int spacetype;
    int error=0;
    vfs_context_t vctx;

    spacetype = UIO_SEG_IS_USER_SPACE(seg) ? UIO_USERSPACE32 : UIO_SYSSPACE;

    vctx = vfs_context_create((vfs_context_t)0);
    auio = uio_create(1, 0, spacetype, rw);
    uio_reset(auio, offset, spacetype, rw);
    uio_addiov(auio, (uint64_t)(uintptr_t)base, len);

    if (rw == UIO_READ) {
        error = fo_read(sfp->f_fp, auio, ioflag, vctx);
    } else {
        error = fo_write(sfp->f_fp, auio, ioflag, vctx);
        sfp->f_writes = 1;
    }

    if (residp) {
        *residp = uio_resid(auio);
    } else {
        if (uio_resid(auio) && error == 0)
            error = EIO;
    }

    uio_free(auio);
    vfs_context_rele(vctx);

    return (error);
}
コード例 #14
0
ファイル: vdev_disk.c プロジェクト: awesome/zfs
static void
vdev_disk_close(vdev_t *vd)
{
	vdev_disk_t *dvd = vd->vdev_tsd;

	if (dvd == NULL)
		return;

	if (dvd->vd_devvp != NULL) {
		vfs_context_t context;

		context = vfs_context_create((vfs_context_t)0);

		(void) vnode_close(dvd->vd_devvp, spa_mode(vd->vdev_spa), context);
		(void) vfs_context_rele(context);
	}

	kmem_free(dvd, sizeof (vdev_disk_t));
	vd->vdev_tsd = NULL;
}
コード例 #15
0
void DldIOShadowFile::free()
{
    assert( preemption_enabled() );
    
    if( NULLVP != this->vnode ){
        
        //
        // write a terminator
        //
        UInt64  terminator = DLD_SHADOW_FILE_TERMINATOR;
        this->write( &terminator, sizeof( terminator ), DLD_IGNR_FSIZE );
     
        //
        // TO DO - ponder the vfs context retrieval as it seems vfs_context_current might be 
        // an arbitrary one which differs from the open context
        //
        vfs_context_t   vfs_context;
        vfs_context = vfs_context_create( NULL );
        assert( vfs_context );
        if( vfs_context ){
        
            VNOP_FSYNC( this->vnode, MNT_WAIT, vfs_context );
            vnode_close( this->vnode, ( this->bytesWritten )? FWASWRITTEN: 0x0, vfs_context );
            vfs_context_rele( vfs_context );
            
        }// end if( vfs_context )
    }
    
    if( this->path ){
        
        assert( this->pathLength );
        IOFree( this->path, this->pathLength );
    }
    
    if( this->rwLock )
        IORWLockFree( this->rwLock );
    
}
コード例 #16
0
ファイル: osi_misc.c プロジェクト: jisqyv/openafs
void
get_vfs_context(void)
{
    int isglock = ISAFS_GLOCK();

    if (!isglock)
	AFS_GLOCK();
    if (afs_osi_ctxtp_initialized) {
	if (!isglock)
	    AFS_GUNLOCK();
	return;
    }
    osi_Assert(vfs_context_owner != current_thread());
    if (afs_osi_ctxtp && current_proc() == vfs_context_curproc) {
	vfs_context_ref++;
	vfs_context_owner = current_thread();
	if (!isglock)
	    AFS_GUNLOCK();
	return;
    }
    while (afs_osi_ctxtp && vfs_context_ref) {
	afs_osi_Sleep(&afs_osi_ctxtp);
	if (afs_osi_ctxtp_initialized) {
	    if (!isglock)
		AFS_GUNLOCK();
	    return;
	}
    }
    vfs_context_rele(afs_osi_ctxtp);
    vfs_context_ref=1;
    afs_osi_ctxtp = vfs_context_create(NULL);
    vfs_context_owner = current_thread();
    vfs_context_curproc = current_proc();
    if (!isglock)
	AFS_GUNLOCK();
}
コード例 #17
0
bool DldIOShadowFile::initWithFileName( __in char* name, __in size_t nameLength )
{
    assert( preemption_enabled() );
    
    
    if( nameLength > (MAXPATHLEN + sizeof( L'\0' )) ){
        
        DBG_PRINT_ERROR(("length > (MAXPATHLEN + sizeof( L'\\0' ))\n"));
        return false;
    }
    
    
    if( !super::init() ){
        
        DBG_PRINT_ERROR(("super::init() failed\n"));
        return false;
    }
    
    this->rwLock = IORWLockAlloc();
    assert( this->rwLock );
    if( !this->rwLock ){
        
        DBG_PRINT_ERROR(("this->rwLock = IORWLockAlloc() failed\n" ));
        return false;
    }
    
    //
    // set a maximum file size to infinity
    //
    this->maxSize = DLD_IGNR_FSIZE;
    
    //
    // set switch size to 512 MB
    //
    this->switchSize = 0x20000000ll;
    
    this->path = (char*)IOMalloc( nameLength );
    assert( this->path );
    if( !this->path ){
        
        DBG_PRINT_ERROR(("this->path = IOMalloc( %u ) failed\n", (int)nameLength ));
        return false;
    }
    
    this->pathLength = nameLength;
    
    memcpy( this->path, name, nameLength );
    assert( L'\0' == this->path[ this->pathLength - 0x1 ] );
    
    //
    // open or create the file
    //
    errno_t  error;
    vfs_context_t   vfs_context;
    
    vfs_context = vfs_context_create( NULL );
    assert( vfs_context );
    if( !vfs_context )
        return false;
    
    //
    // open or create a file, truncate if the file exists
    //
    error = vnode_open( this->path,
                        O_EXLOCK | O_RDWR | O_CREAT | O_TRUNC | O_SYNC, // fmode
                        0644,// cmode
                        0x0,// flags
                        &this->vnode,
                        vfs_context );
    vfs_context_rele( vfs_context );
    if( error ){
        
        DBG_PRINT_ERROR(("vnode_open() failed with the %u error\n", error));
        return false;
    }
    
    //
    // vn_open returns with both a use_count
    // and an io_count on the found vnode
    //
    
    //
    // mark as an internal non shadowed vnode, use the CreateAndAddIOVnodByBSDVnode
    // as the kauth callback might have not been registered so the vnode open
    // was not seen by the DL driver
    //
    DldIOVnode*  dldVnode;
    dldVnode = DldVnodeHashTable::sVnodesHashTable->CreateAndAddIOVnodByBSDVnode( this->vnode );
    assert( dldVnode );
    if( !dldVnode ){
        
        //
        // we can't use this vnode as will be unable to distinguish
        // the DL internal writes from the user writes this will result
        // in an endless loop
        //
        DBG_PRINT_ERROR(("RetrieveReferencedIOVnodByBSDVnode() failed\n"));
        
        this->release();
        return NULL;
    }
    
    //
    // mark as skipped for log, shadowing and any other operations
    //
    dldVnode->flags.internal = 0x1;
    
    dldVnode->release();
    DLD_DBG_MAKE_POINTER_INVALID( dldVnode );
    
    this->expandFile();
    
    //
    // mark as noncached vnode, writes must be sector aligned!
    //
    //vnode_setnocache( this->vnode );
    
    return true;
}
コード例 #18
0
ファイル: process_events.c プロジェクト: theopolis/osquery
static int process_cred_label_update_execvew(kauth_cred_t old_cred,
                                             kauth_cred_t new_cred,
                                             struct proc *p,
                                             struct vnode *vp,
                                             off_t offset,
                                             struct vnode *scriptvp,
                                             struct label *vnodelabel,
                                             struct label *scriptvnodelabel,
                                             struct label *execlabel,
                                             u_int *csflags,
                                             void *macpolicyattr,
                                             size_t macpolicyattrlen,
                                             int *disjointp) {
  int path_len = MAXPATHLEN;

  if (!vnode_isreg(vp)) {
    goto error_exit;
  }

  // Determine address of image_params based off of csflags pointer. (HACKY)
  struct image_params *img =
      (struct image_params *)((char *)csflags -
                              offsetof(struct image_params, ip_csflags));

  // Find the length of arg and env we will copy.
  size_t arg_length =
      MIN(MAX_VECTOR_LENGTH, img->ip_endargv - img->ip_startargv);
  size_t env_length = MIN(MAX_VECTOR_LENGTH, img->ip_endenvv - img->ip_endargv);

  osquery_process_event_t *e =
      (osquery_process_event_t *)osquery_cqueue_reserve(
          cqueue,
          OSQUERY_PROCESS_EVENT,
          sizeof(osquery_process_event_t) + arg_length + env_length);

  if (!e) {
    goto error_exit;
  }
  // Copy the arg and env vectors.
  e->argv_offset = 0;
  e->envv_offset = arg_length;

  e->arg_length = arg_length;
  e->env_length = env_length;

  memcpy(&(e->flexible_data[e->argv_offset]), img->ip_startargv, arg_length);
  memcpy(&(e->flexible_data[e->envv_offset]), img->ip_endargv, env_length);

  e->actual_argc = img->ip_argc;
  e->actual_envc = img->ip_envc;

  // Calculate our argc and envc based on the number of null bytes we find in
  // the buffer.
  e->argc = MIN(e->actual_argc,
                str_num(&(e->flexible_data[e->argv_offset]), arg_length));
  e->envc = MIN(e->actual_envc,
                str_num(&(e->flexible_data[e->envv_offset]), env_length));

  e->pid = proc_pid(p);
  e->ppid = proc_ppid(p);
  e->owner_uid = 0;
  e->owner_gid = 0;
  e->mode = -1;
  vfs_context_t context = vfs_context_create(NULL);
  if (context) {
    struct vnode_attr vattr = {0};
    VATTR_INIT(&vattr);
    VATTR_WANTED(&vattr, va_uid);
    VATTR_WANTED(&vattr, va_gid);
    VATTR_WANTED(&vattr, va_mode);
    VATTR_WANTED(&vattr, va_create_time);
    VATTR_WANTED(&vattr, va_access_time);
    VATTR_WANTED(&vattr, va_modify_time);
    VATTR_WANTED(&vattr, va_change_time);

    if (vnode_getattr(vp, &vattr, context) == 0) {
      e->owner_uid = vattr.va_uid;
      e->owner_gid = vattr.va_gid;
      e->mode = vattr.va_mode;
      e->create_time = vattr.va_create_time.tv_sec;
      e->access_time = vattr.va_access_time.tv_sec;
      e->modify_time = vattr.va_modify_time.tv_sec;
      e->change_time = vattr.va_change_time.tv_sec;
    }

    vfs_context_rele(context);
  }

  e->uid = kauth_cred_getruid(new_cred);
  e->euid = kauth_cred_getuid(new_cred);

  e->gid = kauth_cred_getrgid(new_cred);
  e->egid = kauth_cred_getgid(new_cred);

  vn_getpath(vp, e->path, &path_len);

  osquery_cqueue_commit(cqueue, e);
error_exit:

  return 0;
}
コード例 #19
0
ファイル: vdev_disk.c プロジェクト: gcracker/zfs
static int
vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
    uint64_t *ashift)
{
	spa_t *spa = vd->vdev_spa;
	vdev_disk_t *dvd = vd->vdev_tsd;
	vnode_t *devvp = NULLVP;
	vfs_context_t context = NULL;
	uint64_t blkcnt;
	uint32_t blksize;
	int fmode = 0;
	int error = 0;
	int isssd;

	/*
	 * We must have a pathname, and it must be absolute.
	 */
	if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') {
		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
		return (SET_ERROR(EINVAL));
	}

	/*
	 * Reopen the device if it's not currently open. Otherwise,
	 * just update the physical size of the device.
	 */
	if (dvd != NULL) {
	  if (dvd->vd_offline) {
	    /*
	     * If we are opening a device in its offline notify
	     * context, the LDI handle was just closed. Clean
	     * up the LDI event callbacks and free vd->vdev_tsd.
	     */
	    vdev_disk_free(vd);
	  } else {
	    ASSERT(vd->vdev_reopening);
		devvp = dvd->vd_devvp;
	    goto skip_open;
	  }
	}

	/*
	 * Create vd->vdev_tsd.
	 */
	vdev_disk_alloc(vd);
	dvd = vd->vdev_tsd;

	/*
	 * When opening a disk device, we want to preserve the user's original
	 * intent.  We always want to open the device by the path the user gave
	 * us, even if it is one of multiple paths to the same device.  But we
	 * also want to be able to survive disks being removed/recabled.
	 * Therefore the sequence of opening devices is:
	 *
	 * 1. Try opening the device by path.  For legacy pools without the
	 *    'whole_disk' property, attempt to fix the path by appending 's0'.
	 *
	 * 2. If the devid of the device matches the stored value, return
	 *    success.
	 *
	 * 3. Otherwise, the device may have moved.  Try opening the device
	 *    by the devid instead.
	 */
	/* ### APPLE TODO ### */
#ifdef illumos
	if (vd->vdev_devid != NULL) {
		if (ddi_devid_str_decode(vd->vdev_devid, &dvd->vd_devid,
		    &dvd->vd_minor) != 0) {
			vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
			return (SET_ERROR(EINVAL));
		}
	}
#endif

	error = EINVAL;		/* presume failure */

	if (vd->vdev_path != NULL) {

		context = vfs_context_create( spl_vfs_context_kernel() );

		/* Obtain an opened/referenced vnode for the device. */
		if ((error = vnode_open(vd->vdev_path, spa_mode(spa), 0, 0,
								&devvp, context))) {
			goto out;
		}
		if (!vnode_isblk(devvp)) {
			error = ENOTBLK;
			goto out;
		}
		/*
		 * ### APPLE TODO ###
		 * vnode_authorize devvp for KAUTH_VNODE_READ_DATA and
		 * KAUTH_VNODE_WRITE_DATA
		 */

		/*
		 * Disallow opening of a device that is currently in use.
		 * Flush out any old buffers remaining from a previous use.
		 */
		if ((error = vfs_mountedon(devvp))) {
			goto out;
		}
		if (VNOP_FSYNC(devvp, MNT_WAIT, context) != 0) {
			error = ENOTBLK;
			goto out;
		}
		if ((error = buf_invalidateblks(devvp, BUF_WRITE_DATA, 0, 0))) {
			goto out;
		}

	} else {
		goto out;
	}


	int len = MAXPATHLEN;
	if (vn_getpath(devvp, dvd->vd_readlinkname, &len) == 0) {
		dprintf("ZFS: '%s' resolved name is '%s'\n",
			   vd->vdev_path, dvd->vd_readlinkname);
	} else {
		dvd->vd_readlinkname[0] = 0;
	}



skip_open:
	/*
	 * Determine the actual size of the device.
	 */
	if (VNOP_IOCTL(devvp, DKIOCGETBLOCKSIZE, (caddr_t)&blksize, 0,
	    context) != 0 ||
	    VNOP_IOCTL(devvp, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt, 0,
	    context) != 0) {
		error = EINVAL;
		goto out;
	}

	*psize = blkcnt * (uint64_t)blksize;
	*max_psize = *psize;

	dvd->vd_ashift = highbit(blksize) - 1;
	dprintf("vdev_disk: Device %p ashift set to %d\n", devvp,
	    dvd->vd_ashift);


	*ashift = highbit(MAX(blksize, SPA_MINBLOCKSIZE)) - 1;

	/*
	 *  ### APPLE TODO ###
	 */
#ifdef illumos
	if (vd->vdev_wholedisk == 1) {
		int wce = 1;
		if (error == 0) {
			/*
			 * If we have the capability to expand, we'd have
			 * found out via success from DKIOCGMEDIAINFO{,EXT}.
			 * Adjust max_psize upward accordingly since we know
			 * we own the whole disk now.
			 */
			*max_psize = capacity * blksz;
		}

		/*
		 * Since we own the whole disk, try to enable disk write
		 * caching.  We ignore errors because it's OK if we can't do it.
		 */
		(void) ldi_ioctl(dvd->vd_lh, DKIOCSETWCE, (intptr_t)&wce,
		    FKIOCTL, kcred, NULL);
	}
#endif

	/*
	 * Clear the nowritecache bit, so that on a vdev_reopen() we will
	 * try again.
	 */
	vd->vdev_nowritecache = B_FALSE;

	/* Inform the ZIO pipeline that we are non-rotational */
	vd->vdev_nonrot = B_FALSE;
	if (VNOP_IOCTL(devvp, DKIOCISSOLIDSTATE, (caddr_t)&isssd, 0,
				   context) == 0) {
		if (isssd)
			vd->vdev_nonrot = B_TRUE;
	}
	dprintf("ZFS: vdev_disk(%s) isSSD %d\n", vd->vdev_path ? vd->vdev_path : "",
			isssd);

	dvd->vd_devvp = devvp;
out:
	if (error) {
	  if (devvp) {
			vnode_close(devvp, fmode, context);
			dvd->vd_devvp = NULL;
	  }
		vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
	}
	if (context)
		(void) vfs_context_rele(context);

	if (error) printf("ZFS: vdev_disk_open('%s') failed error %d\n",
					  vd->vdev_path ? vd->vdev_path : "", error);
	return (error);
}
コード例 #20
0
ファイル: vdev_disk.c プロジェクト: gcracker/zfs
static void
vdev_disk_io_start(zio_t *zio)
{
	vdev_t *vd = zio->io_vd;
	vdev_disk_t *dvd = vd->vdev_tsd;
	struct buf *bp;
	vfs_context_t context;
	int flags, error = 0;

	/*
	 * If the vdev is closed, it's likely in the REMOVED or FAULTED state.
	 * Nothing to be done here but return failure.
	 */
	if (dvd == NULL || (dvd->vd_offline) || dvd->vd_devvp == NULL) {
		zio->io_error = ENXIO;
		zio_interrupt(zio);
		return;
	}

	switch (zio->io_type) {
		case ZIO_TYPE_IOCTL:

			if (!vdev_readable(vd)) {
				zio->io_error = SET_ERROR(ENXIO);
				zio_interrupt(zio);
				return;
			}

			switch (zio->io_cmd) {

				case DKIOCFLUSHWRITECACHE:

					if (zfs_nocacheflush)
						break;

					if (vd->vdev_nowritecache) {
						zio->io_error = SET_ERROR(ENOTSUP);
						break;
					}

					context = vfs_context_create(spl_vfs_context_kernel());
					error = VNOP_IOCTL(dvd->vd_devvp, DKIOCSYNCHRONIZECACHE,
									   NULL, FWRITE, context);
					(void) vfs_context_rele(context);

					if (error == 0)
						vdev_disk_ioctl_done(zio, error);
					else
						error = ENOTSUP;

					if (error == 0) {
						/*
						 * The ioctl will be done asychronously,
						 * and will call vdev_disk_ioctl_done()
						 * upon completion.
						 */
						return;
					} else if (error == ENOTSUP || error == ENOTTY) {
						/*
						 * If we get ENOTSUP or ENOTTY, we know that
						 * no future attempts will ever succeed.
						 * In this case we set a persistent bit so
						 * that we don't bother with the ioctl in the
						 * future.
						 */
						vd->vdev_nowritecache = B_TRUE;
					}
					zio->io_error = error;

					break;

				default:
					zio->io_error = SET_ERROR(ENOTSUP);
			} /* io_cmd */

			zio_execute(zio);
			return;

	case ZIO_TYPE_WRITE:
		if (zio->io_priority == ZIO_PRIORITY_SYNC_WRITE)
			flags = B_WRITE;
		else
			flags = B_WRITE | B_ASYNC;
		break;

	case ZIO_TYPE_READ:
		if (zio->io_priority == ZIO_PRIORITY_SYNC_READ)
			flags = B_READ;
		else
			flags = B_READ | B_ASYNC;
		break;

		default:
			zio->io_error = SET_ERROR(ENOTSUP);
			zio_interrupt(zio);
			return;
	} /* io_type */

	ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE);

	/* Stop OSX from also caching our data */
	flags |= B_NOCACHE;

	if (zio->io_flags & ZIO_FLAG_FAILFAST)
		flags |= B_FAILFAST;

	zio->io_target_timestamp = zio_handle_io_delay(zio);

	bp = buf_alloc(dvd->vd_devvp);

	ASSERT(bp != NULL);
	ASSERT(zio->io_data != NULL);
	ASSERT(zio->io_size != 0);

	buf_setflags(bp, flags);
	buf_setcount(bp, zio->io_size);
	buf_setdataptr(bp, (uintptr_t)zio->io_data);

	/*
	 * Map offset to blcknumber, based on physical block number.
	 * (512, 4096, ..). If we fail to map, default back to
	 * standard 512. lbtodb() is fixed at 512.
	 */
	buf_setblkno(bp, zio->io_offset >> dvd->vd_ashift);
	buf_setlblkno(bp, zio->io_offset >> dvd->vd_ashift);

	buf_setsize(bp, zio->io_size);
	if (buf_setcallback(bp, vdev_disk_io_intr, zio) != 0)
		panic("vdev_disk_io_start: buf_setcallback failed\n");

	if (zio->io_type == ZIO_TYPE_WRITE) {
		vnode_startwrite(dvd->vd_devvp);
	}
	error = VNOP_STRATEGY(bp);
	ASSERT(error == 0);

	if (error) {
		zio->io_error = error;
		zio_interrupt(zio);
		return;
	}
}
コード例 #21
0
/*
 * entrypoint function to read necessary information from running kernel and kernel at disk
 * such as kaslr slide, linkedit location
 * the reads from disk are implemented using the available KPI VFS functions
 */
kern_return_t init_kernel_info(kernel_info *kinfo) {
	kern_return_t error = 0;
	// lookup vnode for /mach_kernel
	
	void *kernel_header = _MALLOC(HEADER_SIZE, M_TEMP, M_ZERO);
	if (kernel_header == NULL) {
		return KERN_FAILURE;
	}
	
	vnode_t kernel_vnode = NULLVP;
	vfs_context_t ctxt = NULL;
	
	int found_kernel = 0;
	for(int i = 0; i < sizeof(kernel_paths) / sizeof(*kernel_paths); i++) {
		kernel_vnode = NULLVP;
		ctxt = vfs_context_create(NULL);
		
		error = vnode_lookup(kernel_paths[i], 0, &kernel_vnode, ctxt);
		if(!error) {
			error = get_mach_header(kernel_header, kernel_vnode, ctxt);
			if(!error) {
				if(!is_current_kernel(kernel_header)) {
					vnode_put(kernel_vnode);
				} else {
					found_kernel = 1;
					break;
				}
			}
		}
		
		vfs_context_rele(ctxt);
	}
	
	if(!found_kernel) {
		_FREE(kernel_header, M_TEMP);
		return KERN_FAILURE;
	}
	
	error = process_kernel_mach_header(kernel_header, kinfo);
	if (error) goto failure;
	
	// compute kaslr slide
	get_running_text_address(kinfo, 0);
	// we know the location of linkedit and offsets into symbols and their strings
	// now we need to read linkedit into a buffer so we can process it later
	// __LINKEDIT total size is around 1MB
	// we should free this buffer later when we don't need anymore to solve symbols
	kinfo->linkedit_buf = _MALLOC(kinfo->linkedit_size, M_TEMP, M_ZERO);
	if (kinfo->linkedit_buf == NULL) {
		_FREE(kernel_header, M_TEMP);
		return KERN_FAILURE;
	}
	// read linkedit from filesystem
	error = get_kernel_linkedit(kernel_vnode, ctxt, kinfo);
	if (error) goto failure;
	
success:
	_FREE(kernel_header, M_TEMP);
	vfs_context_rele(ctxt);
	// drop the iocount due to vnode_lookup()
	// we must do this else machine will block on shutdown/reboot
	vnode_put(kernel_vnode);
	return KERN_SUCCESS;
failure:
	if (kinfo->linkedit_buf != NULL) _FREE(kinfo->linkedit_buf, M_TEMP);
	_FREE(kernel_header, M_TEMP);
	vfs_context_rele(ctxt);
	vnode_put(kernel_vnode);
	return KERN_FAILURE;
}
コード例 #22
0
ファイル: vdev_disk.c プロジェクト: awesome/zfs
static int
vdev_disk_open(vdev_t *vd, uint64_t *size, uint64_t *max_size, uint64_t *ashift)
{
	vdev_disk_t *dvd = NULL;
	vnode_t *devvp = NULLVP;
	vfs_context_t context = NULL;
	uint64_t blkcnt;
	uint32_t blksize;
	int fmode = 0;
	int error = 0;

	/*
	 * We must have a pathname, and it must be absolute.
	 */
	if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') {
		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
		return (EINVAL);
	}

	dvd = kmem_zalloc(sizeof (vdev_disk_t), KM_SLEEP);
    if (dvd == NULL)
        return ENOMEM;

	/*
	 * When opening a disk device, we want to preserve the user's original
	 * intent.  We always want to open the device by the path the user gave
	 * us, even if it is one of multiple paths to the save device.  But we
	 * also want to be able to survive disks being removed/recabled.
	 * Therefore the sequence of opening devices is:
	 *
	 * 1. Try opening the device by path.  For legacy pools without the
	 *    'whole_disk' property, attempt to fix the path by appending 's0'.
	 *
	 * 2. If the devid of the device matches the stored value, return
	 *    success.
	 *
	 * 3. Otherwise, the device may have moved.  Try opening the device
	 *    by the devid instead.
	 *
	 */

	/* ### APPLE TODO ### */
	/* ddi_devid_str_decode */

	context = vfs_context_create((vfs_context_t)0);

	/* Obtain an opened/referenced vnode for the device. */
	error = vnode_open(vd->vdev_path, spa_mode(vd->vdev_spa), 0, 0, &devvp, context);
	if (error) {
		goto out;
	}

	if (!vnode_isblk(devvp)) {
		error = ENOTBLK;
		goto out;
	}

	/* ### APPLE TODO ### */
	/* vnode_authorize devvp for KAUTH_VNODE_READ_DATA and
	 * KAUTH_VNODE_WRITE_DATA
	 */

	/*
	 * Disallow opening of a device that is currently in use.
	 * Flush out any old buffers remaining from a previous use.
	 */
	if ((error = vfs_mountedon(devvp))) {
		goto out;
	}
	if (VNOP_FSYNC(devvp, MNT_WAIT, context) != 0) {
		error = ENOTBLK;
		goto out;
	}
	if ((error = buf_invalidateblks(devvp, BUF_WRITE_DATA, 0, 0))) {
		goto out;
	}

	/*
	 * Determine the actual size of the device.
	 */
	if (VNOP_IOCTL(devvp, DKIOCGETBLOCKSIZE, (caddr_t)&blksize, 0, context)
	       	!= 0 || VNOP_IOCTL(devvp, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt,
		0, context) != 0) {

		error = EINVAL;
		goto out;
	}
	*size = blkcnt * (uint64_t)blksize;

	/*
	 *  ### APPLE TODO ###
	 * If we own the whole disk, try to enable disk write caching.
	 */

	/*
	 * Take the device's minimum transfer size into account.
	 */
	*ashift = highbit(MAX(blksize, SPA_MINBLOCKSIZE)) - 1;

    /*
     * Setting the vdev_ashift did in fact break the pool for import
     * on ZEVO. This puts the logic into question. It appears that vdev_top
     * will also then change. It then panics in space_map from metaslab_alloc
     */
    //vd->vdev_ashift = *ashift;
    dvd->vd_ashift = *ashift;


	/*
	 * Clear the nowritecache bit, so that on a vdev_reopen() we will
	 * try again.
	 */
	vd->vdev_nowritecache = B_FALSE;
	vd->vdev_tsd = dvd;
	dvd->vd_devvp = devvp;
out:
	if (error) {
		if (devvp)
			vnode_close(devvp, fmode, context);
		if (dvd)
			kmem_free(dvd, sizeof (vdev_disk_t));

		/*
		 * Since the open has failed, vd->vdev_tsd should
		 * be NULL when we get here, signaling to the
		 * rest of the spa not to try and reopen or close this device
		 */
		vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
	}
	if (context) {
		(void) vfs_context_rele(context);
	}
	return (error);
}
コード例 #23
0
ファイル: vdev_disk.c プロジェクト: awesome/zfs
static int
vdev_disk_io_start(zio_t *zio)
{
	vdev_t *vd = zio->io_vd;
	vdev_disk_t *dvd = vd->vdev_tsd;
	struct buf *bp;
	vfs_context_t context;
	int flags, error = 0;

	if (zio->io_type == ZIO_TYPE_IOCTL) {
		zio_vdev_io_bypass(zio);

		/* XXPOLICY */
		if (vdev_is_dead(vd)) {
			zio->io_error = ENXIO;
			//zio_next_stage_async(zio);
			return (ZIO_PIPELINE_CONTINUE);
            //return;
		}

		switch (zio->io_cmd) {

		case DKIOCFLUSHWRITECACHE:

			if (zfs_nocacheflush)
				break;

			if (vd->vdev_nowritecache) {
				zio->io_error = SET_ERROR(ENOTSUP);
				break;
			}

			context = vfs_context_create((vfs_context_t)0);
			error = VNOP_IOCTL(dvd->vd_devvp, DKIOCSYNCHRONIZECACHE, NULL, FWRITE, context);
			(void) vfs_context_rele(context);

			if (error == 0)
				vdev_disk_ioctl_done(zio, error);
			else
				error = ENOTSUP;

			if (error == 0) {
				/*
				 * The ioctl will be done asychronously,
				 * and will call vdev_disk_ioctl_done()
				 * upon completion.
				 */
				return ZIO_PIPELINE_STOP;
			} else if (error == ENOTSUP || error == ENOTTY) {
				/*
				 * If we get ENOTSUP or ENOTTY, we know that
				 * no future attempts will ever succeed.
				 * In this case we set a persistent bit so
				 * that we don't bother with the ioctl in the
				 * future.
				 */
				vd->vdev_nowritecache = B_TRUE;
			}
			zio->io_error = error;

			break;

		default:
			zio->io_error = SET_ERROR(ENOTSUP);
		}

		//zio_next_stage_async(zio);
        return (ZIO_PIPELINE_CONTINUE);
	}

	if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio) == 0)
        return (ZIO_PIPELINE_STOP);
    //		return;

	if ((zio = vdev_queue_io(zio)) == NULL)
        return (ZIO_PIPELINE_CONTINUE);
    //		return;

	flags = (zio->io_type == ZIO_TYPE_READ ? B_READ : B_WRITE);
	//flags |= B_NOCACHE;

	if (zio->io_flags & ZIO_FLAG_FAILFAST)
		flags |= B_FAILFAST;

	/*
	 * Check the state of this device to see if it has been offlined or
	 * is in an error state.  If the device was offlined or closed,
	 * dvd will be NULL and buf_alloc below will fail
	 */
	//error = vdev_is_dead(vd) ? ENXIO : vdev_error_inject(vd, zio);
	if (vdev_is_dead(vd)) {
        error = ENXIO;
    }

	if (error) {
		zio->io_error = error;
		//zio_next_stage_async(zio);
		return (ZIO_PIPELINE_CONTINUE);
	}

	bp = buf_alloc(dvd->vd_devvp);

	ASSERT(bp != NULL);
	ASSERT(zio->io_data != NULL);
	ASSERT(zio->io_size != 0);

	buf_setflags(bp, flags);
	buf_setcount(bp, zio->io_size);
	buf_setdataptr(bp, (uintptr_t)zio->io_data);
    if (dvd->vd_ashift) {
        buf_setlblkno(bp, zio->io_offset>>dvd->vd_ashift);
        buf_setblkno(bp,  zio->io_offset>>dvd->vd_ashift);
    } else {
コード例 #24
0
ファイル: kern_symfile.c プロジェクト: Algozjb/xnu
struct kern_direct_file_io_ref_t *
kern_open_file_for_direct_io(const char * name, 
			     kern_get_file_extents_callback_t callback, 
			     void * callback_ref,
			     dev_t * partition_device_result,
			     dev_t * image_device_result,
                             uint64_t * partitionbase_result,
                             uint64_t * maxiocount_result,
                             uint32_t * oflags,
                             off_t offset,
                             caddr_t addr,
                             vm_size_t len)
{
    struct kern_direct_file_io_ref_t * ref;

    proc_t			p;
    struct vnode_attr		va;
    int				error;
    off_t			f_offset;
    uint64_t                    fileblk;
    size_t                      filechunk;
    uint64_t                    physoffset;
    dev_t			device;
    dev_t			target = 0;
    int			        isssd = 0;
    uint32_t                    flags = 0;
    uint32_t			blksize;
    off_t 			maxiocount, count;
    boolean_t                   locked = FALSE;

    int (*do_ioctl)(void * p1, void * p2, u_long theIoctl, caddr_t result);
    void * p1 = NULL;
    void * p2 = NULL;

    error = EFAULT;

    ref = (struct kern_direct_file_io_ref_t *) kalloc(sizeof(struct kern_direct_file_io_ref_t));
    if (!ref)
    {
	error = EFAULT;
    	goto out;
    }

    bzero(ref, sizeof(*ref));
    p = kernproc;
    ref->ctx = vfs_context_create(vfs_context_current());

    if ((error = vnode_open(name, (O_CREAT | FWRITE), (0), 0, &ref->vp, ref->ctx)))
        goto out;

    if (addr && len)
    {
	if ((error = kern_write_file(ref, offset, addr, len)))
	    goto out;
    }

    VATTR_INIT(&va);
    VATTR_WANTED(&va, va_rdev);
    VATTR_WANTED(&va, va_fsid);
    VATTR_WANTED(&va, va_data_size);
    VATTR_WANTED(&va, va_nlink);
    error = EFAULT;
    if (vnode_getattr(ref->vp, &va, ref->ctx))
    	goto out;

    kprintf("vp va_rdev major %d minor %d\n", major(va.va_rdev), minor(va.va_rdev));
    kprintf("vp va_fsid major %d minor %d\n", major(va.va_fsid), minor(va.va_fsid));
    kprintf("vp size %qd\n", va.va_data_size);

    if (ref->vp->v_type == VREG)
    {
	/* Don't dump files with links. */
	if (va.va_nlink != 1)
	    goto out;

        device = va.va_fsid;
        p1 = &device;
        p2 = p;
        do_ioctl = &file_ioctl;
    }
    else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR))
    {
	/* Partition. */
        device = va.va_rdev;

        p1 = ref->vp;
        p2 = ref->ctx;
        do_ioctl = &device_ioctl;
    }
    else
    {
	/* Don't dump to non-regular files. */
	error = EFAULT;
        goto out;
    }
    ref->device = device;

    // get block size

    error = do_ioctl(p1, p2, DKIOCGETBLOCKSIZE, (caddr_t) &ref->blksize);
    if (error)
        goto out;

    if (ref->vp->v_type == VREG)
        ref->filelength = va.va_data_size;
    else
    {
        error = do_ioctl(p1, p2, DKIOCGETBLOCKCOUNT, (caddr_t) &fileblk);
        if (error)
            goto out;
	ref->filelength = fileblk * ref->blksize;    
    }

    // pin logical extents

    error = kern_ioctl_file_extents(ref, _DKIOCCSPINEXTENT, 0, ref->filelength);
    if (error && (ENOTTY != error)) goto out;
    ref->pinned = (error == 0);

    // generate the block list

    error = do_ioctl(p1, p2, DKIOCLOCKPHYSICALEXTENTS, NULL);
    if (error)
        goto out;
    locked = TRUE;

    f_offset = 0;
    while (f_offset < ref->filelength) 
    {
        if (ref->vp->v_type == VREG)
        {
            filechunk = 1*1024*1024*1024;
            daddr64_t blkno;

            error = VNOP_BLOCKMAP(ref->vp, f_offset, filechunk, &blkno, &filechunk, NULL, 0, NULL);
            if (error)
                goto out;

            fileblk = blkno * ref->blksize;
        }
        else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR))
        {
            fileblk = f_offset;
            filechunk = f_offset ? 0 : ref->filelength;
        }

        physoffset = 0;
        while (physoffset < filechunk)
        {
            dk_physical_extent_t getphysreq;
            bzero(&getphysreq, sizeof(getphysreq));

            getphysreq.offset = fileblk + physoffset;
            getphysreq.length = (filechunk - physoffset);
            error = do_ioctl(p1, p2, DKIOCGETPHYSICALEXTENT, (caddr_t) &getphysreq);
            if (error)
                goto out;
            if (!target)
            {
                target = getphysreq.dev;
            }
            else if (target != getphysreq.dev)
            {
                error = ENOTSUP;
                goto out;
            }
            callback(callback_ref, getphysreq.offset, getphysreq.length);
            physoffset += getphysreq.length;
        }
        f_offset += filechunk;
    }
    callback(callback_ref, 0ULL, 0ULL);

    if (ref->vp->v_type == VREG)
        p1 = &target;

    // get partition base

    error = do_ioctl(p1, p2, DKIOCGETBASE, (caddr_t) partitionbase_result);
    if (error)
        goto out;

    // get block size & constraints

    error = do_ioctl(p1, p2, DKIOCGETBLOCKSIZE, (caddr_t) &blksize);
    if (error)
        goto out;

    maxiocount = 1*1024*1024*1024;

    error = do_ioctl(p1, p2, DKIOCGETMAXBLOCKCOUNTREAD, (caddr_t) &count);
    if (error)
        count = 0;
    count *= blksize;
    if (count && (count < maxiocount))
        maxiocount = count;

    error = do_ioctl(p1, p2, DKIOCGETMAXBLOCKCOUNTWRITE, (caddr_t) &count);
    if (error)
        count = 0;
    count *= blksize;
    if (count && (count < maxiocount))
        maxiocount = count;

    error = do_ioctl(p1, p2, DKIOCGETMAXBYTECOUNTREAD, (caddr_t) &count);
    if (error)
        count = 0;
    if (count && (count < maxiocount))
        maxiocount = count;

    error = do_ioctl(p1, p2, DKIOCGETMAXBYTECOUNTWRITE, (caddr_t) &count);
    if (error)
        count = 0;
    if (count && (count < maxiocount))
        maxiocount = count;

    error = do_ioctl(p1, p2, DKIOCGETMAXSEGMENTBYTECOUNTREAD, (caddr_t) &count);
    if (error)
        count = 0;
    if (count && (count < maxiocount))
        maxiocount = count;

    error = do_ioctl(p1, p2, DKIOCGETMAXSEGMENTBYTECOUNTWRITE, (caddr_t) &count);
    if (error)
        count = 0;
    if (count && (count < maxiocount))
        maxiocount = count;

    kprintf("max io 0x%qx bytes\n", maxiocount);
    if (maxiocount_result)
        *maxiocount_result = maxiocount;

    error = do_ioctl(p1, p2, DKIOCISSOLIDSTATE, (caddr_t)&isssd);
    if (!error && isssd)
        flags |= kIOHibernateOptionSSD;

    if (partition_device_result)
        *partition_device_result = device;
    if (image_device_result)
        *image_device_result = target;
    if (flags)
        *oflags = flags;

out:
    kprintf("kern_open_file_for_direct_io(%d)\n", error);

    if (error && locked)
    {
        p1 = &device;
        (void) do_ioctl(p1, p2, DKIOCUNLOCKPHYSICALEXTENTS, NULL);
    }

    if (error && ref)
    {
	if (ref->vp)
	{
	    vnode_close(ref->vp, FWRITE, ref->ctx);
	    ref->vp = NULLVP;
	}
	vfs_context_rele(ref->ctx);
	kfree(ref, sizeof(struct kern_direct_file_io_ref_t));
	ref = NULL;
    }
    return(ref);
}
コード例 #25
0
IOReturn VNodeDiskDeviceClass::doAsyncReadWrite(
  IOMemoryDescriptor *buffer, UInt64 block, UInt64 nblks, 
  IOStorageAttributes *attributes, IOStorageCompletion *completion)
{    
  IOLog("doAsyncReadWrite with parameters %llu block num, %llu num of blocks\n", block, nblks);

  if (m_vnode == NULL)
    return kIOReturnIOError;

  IOReturn returnMessage = kIOReturnSuccess;
  if ((block + nblks - 1) >= m_blockNum || nblks == 0) {
    IOLog("Attempting to write outside vnode disk\n");
    return kIOReturnIOError;
  }

  IODirection direction = buffer->getDirection();
  if ((direction != kIODirectionIn) && (direction != kIODirectionOut)) {
    IOLog("No valid direction of transfer: required either in or out\n");
    return kIOReturnIOError;
  }

  IOByteCount actualByteCount = nblks * m_blockSize;
  off_t byteOffset = block * m_blockSize;
  int aresid = -1;

  char * rawBuffer = (char *) buffer;
  rawBuffer = (char *) IOMalloc(sizeof(char) * actualByteCount);
  if (rawBuffer == NULL) {
    IOLog("Unable to allocate buffer\n");
    return kIOReturnIOError;
  }

  vfs_context_t vfsContext = vfs_context_create((vfs_context_t) 0);
  proc_t proc = vfs_context_proc(vfsContext);
  kauth_cred_t cr = vfs_context_ucred(vfsContext);

  if (direction == kIODirectionIn) {
    IOLog("Reading from disk\n");

    // TODO: Remove warning (unsigned long long) -> int
    int readError = vn_rdwr(UIO_READ, m_vnode, (caddr_t) rawBuffer,
      (int) actualByteCount, byteOffset, UIO_SYSSPACE, 0, cr, &aresid, proc);

    if (readError || aresid > 0) {
      returnMessage = kIOReturnIOError;
      goto cleanup;
    }

    buffer->writeBytes(0, rawBuffer, actualByteCount); // Why the offset?
  } else { // (direction == kIODirectionOut)
    IOLog("Writing to disk\n");

    buffer->readBytes(0, rawBuffer, actualByteCount); // first arg is offset

    // TODO: Remove warning (unsigned long long) -> int
    int writeError = vn_rdwr(UIO_WRITE, m_vnode, (caddr_t) rawBuffer,
      (int) actualByteCount, byteOffset, UIO_SYSSPACE, 0, cr, &aresid, proc);

    if (writeError || aresid > 0) {
      returnMessage = kIOReturnIOError;
      goto cleanup;
    }
  }

cleanup:
  vfs_context_rele(vfsContext);
  if (rawBuffer)
    IOFree(rawBuffer, sizeof(char) * actualByteCount);

  actualByteCount = actualByteCount > aresid ? actualByteCount - aresid : 0;

  completion->action(completion->target, completion->parameter, kIOReturnSuccess, 
    actualByteCount);
  return returnMessage;
}
コード例 #26
0
bool
com_VFSFilter0::start(
    __in IOService *provider
    )
{
    
    //__asm__ volatile( "int $0x3" );
    
    VNodeMap::Init();
    
    if( kIOReturnSuccess != VFSHookInit() ){
        
        DBG_PRINT_ERROR( ( "VFSHookInit() failed\n" ) );
        goto __exit_on_error;
    }
    
    if( ! QvrVnodeHooksHashTable::CreateStaticTableWithSize( 8, true ) ){
        
        DBG_PRINT_ERROR( ( "QvrVnodeHooksHashTable::CreateStaticTableWithSize() failed\n" ) );
        goto __exit_on_error;
    }

    
    //
    // gSuperUserContext must have a valid thread and process pointer
    // TO DO redesign this! Indefinit holding a thread or task object is a bad behaviour.
    //
    thread_reference( current_thread() );
    task_reference( current_task() );
    
    gSuperUserContext = vfs_context_create(NULL); // vfs_context_kernel()
    
    //
    // create an object for the vnodes KAuth callback and register the callback,
    // the callback might be called immediatelly just after registration!
    //
    gVnodeGate = QvrIOKitKAuthVnodeGate::withCallbackRegistration( this );
    assert( NULL != gVnodeGate );
    if( NULL == gVnodeGate ){
        
        DBG_PRINT_ERROR( ( "QvrIOKitKAuthVnodeGate::withDefaultSettings() failed\n" ) );
        goto __exit_on_error;
    }
    
    Instance = this;
    
    //
    // register with IOKit to allow the class matching
    //
    registerService();

    return true;
    
__exit_on_error:
    
    //
    // all cleanup will be done in stop() and free()
    //
    this->release();
    return false;
}
コード例 #27
0
off_t DldIOShadowFile::expandFile( __in off_t lowTargetSize )
{
    assert( preemption_enabled() );
    
    off_t             target;
    off_t             currentLastExpansion;
#if defined( DBG )
    currentLastExpansion = DLD_IGNR_FSIZE;
#endif//DBG
    
    //
    // Make sure that we are root.  Growing a file
    // without zero filling the data is a security hole 
    // root would have access anyway so we'll allow it
    //
    
    //
    // TO DO - is_suser is not supported for 64 bit kext
    //

/*
#if defined(__i386__)
    assert( is_suser() );
    if( !is_suser() )
        return this->lastExpansion;// an unsafe unprotected access to 64b value
#elif defined(__x86_64__)
#endif//defined(__x86_64__)
*/

    
    //
    // check that the limit has not been reached
    //
    if( DLD_IGNR_FSIZE != this->maxSize  && this->lastExpansion == this->maxSize )
        return this->maxSize;// a safe access to 64b value as the value can't change
    
    
    this->LockExclusive();
    {// start of the lock
        
        off_t   valueToAdd;
        
        currentLastExpansion = this->lastExpansion;
        
        //
        // try to extend the file on 128 MB
        // ( the same value is used as a maximum value for a mapping
        //   range in DldIOShadow::processFileWriteWQ )
        //
        valueToAdd = 0x8*0x1000*0x1000;
        
        
        if( this->offset > this->lastExpansion )
            target = this->offset + valueToAdd;
        else
            target = this->lastExpansion + valueToAdd;
        
        if( target < lowTargetSize )
            target  = lowTargetSize;
        
        if( DLD_IGNR_FSIZE != this->maxSize && target > this->maxSize )
            target = this->maxSize;
        
    }// end of the lock
    this->UnLockExclusive();
    
    
    if( target < lowTargetSize ){
        
        //
        // there is no point for extension as the goal won't be reached, fail the request
        //
        return currentLastExpansion;
    }
    
    assert( DLD_IGNR_FSIZE != currentLastExpansion && currentLastExpansion <= target );
    
    //
    // extend the file
    //
    vfs_context_t       vfs_context;
    int                 error;
    
    error = vnode_getwithref( this->vnode );
    assert( !error );
    if( !error ){
        
        struct vnode_attr	va;
        
        VATTR_INIT(&va);
        VATTR_SET(&va, va_data_size, target);
        va.va_vaflags =(IO_NOZEROFILL) & 0xffff;
        
        vfs_context = vfs_context_create( NULL );
        assert( vfs_context );
        if( vfs_context ){
            
            this->LockExclusive();
            {// start of the lock
                
                assert( currentLastExpansion <= this->lastExpansion );
                //
                // do not truncate the file incidentally!
                //
                if( target > this->offset ){
                    
                    error = vnode_setattr( this->vnode, &va, vfs_context );
                    if( !error ){
                        
                        this->lastExpansion = target;
                        currentLastExpansion = target;
                    }
                    
                } else {
                  
                    //
                    // the file has been extended by the write operation
                    //
                    this->lastExpansion = this->offset;
                    currentLastExpansion = this->offset;

                }// end if( target < this->offset )
                
            }// end of the lock
            this->UnLockExclusive();
            
            vfs_context_rele( vfs_context );
            DLD_DBG_MAKE_POINTER_INVALID( vfs_context );
            
        }// end if( vfs_context )
        
        vnode_put( this->vnode );
        
    }// end if( !error )
    
    assert( DLD_IGNR_FSIZE != currentLastExpansion );
    
    return currentLastExpansion;
}
コード例 #28
0
ファイル: library_injector.c プロジェクト: gdbinit/mario
/*
 * inject a dynamic library into the header
 */
kern_return_t
inject_library(vm_map_t task_port, mach_vm_address_t base_address, char *path, int path_len)
{
    char library_to_inject[MAXPATHLEN] = {0};
    /* verify is library to be injected exists in the filesystem */
    vnode_t lib_vnode = NULLVP;
    vfs_context_t libvfs_context = vfs_context_create(NULL);
    if (vnode_lookup(PATCH_LIBRARY, 0, &lib_vnode, libvfs_context))
    {
        LOG_ERROR("Library to be injected not found in filesystem! Please copy it to the configured path %s.", PATCH_LIBRARY);
        vfs_context_rele(libvfs_context);
        return KERN_FAILURE;
    }
    vnode_put(lib_vnode);
    vfs_context_rele(libvfs_context);
    /* set library to be injected to patch version */
    strlcpy(library_to_inject, PATCH_LIBRARY, sizeof(library_to_inject));
    
    kern_return_t kr = 0;
    struct header_info header_info = {0};
    /*
     * we need to read the header of the target process so we can find the injection space and modify it
     */
    struct mach_header_64 header = {0};
    kr = _vm_map_read_user(task_port, base_address, (void*)&header, sizeof(header));
    if (kr != KERN_SUCCESS)
    {
        LOG_ERROR("Couldn't read target mach-o header. error %x at address 0x%llx", kr, base_address);
        return KERN_FAILURE;
    }
    uint32_t header_size = sizeof(struct mach_header);
    switch (header.magic)
    {
        case MH_MAGIC_64:
            header_size = sizeof(struct mach_header_64);
            header_info.is64bits = 1;
            break;
        case MH_MAGIC:
            header_info.is64bits = 0;
            break;
        default:
            LOG_ERROR("Unknown header magic value %x!", header.magic);
            return KERN_FAILURE;
    }
    if (header.ncmds == 0 || header.sizeofcmds == 0)
    {
        LOG_ERROR("Bad ncmds or sizeofcmds!");
        return KERN_FAILURE;
    }
    
    /* calculate the buffer size we will need to hold the whole mach-o header */
    uint32_t total_header_size = header.sizeofcmds + header_size;
    uint8_t *full_header = _MALLOC(total_header_size, M_TEMP, M_WAITOK | M_ZERO);
    if (full_header == NULL)
    {
        LOG_ERROR("Can't allocate space for target full mach-o header!");
        return KERN_FAILURE;
    }
    /* copy the full header into our buffer */
    if (_vm_map_read_user(task_port, base_address, (void*)full_header, total_header_size))
    {
        LOG_ERROR("Can't read full target header!");
        goto failure;
    }

    header_info.lowest_fileoff = 0xFFFFFFFF;
    struct mach_header_64 *mh = (struct mach_header_64*)full_header;
    
    /* process the header and retrieve some information we will use */
    if (process_target_header(task_port, full_header, header_size, base_address, &header_info))
    {
        LOG_ERROR("Can't process mach-o header!");
        goto failure;
    }

    /* the injection position is after the last command */
    uint32_t injection_offset = mh->sizeofcmds + header_size; // overflow checked inside find_library_injection_space
    uint32_t libpath_len = (uint32_t)strlen(library_to_inject) + 1;;
    /* prepare the LC_LOAD_DYLIB command to be injected */
    struct dylib_command newlib_cmd = {0};
    newlib_cmd.cmd = LC_LOAD_DYLIB;
    newlib_cmd.dylib.name.offset = 24;         // usually the name string is located just after the command
    newlib_cmd.dylib.timestamp = 0;
    newlib_cmd.dylib.current_version = 0;
    newlib_cmd.dylib.compatibility_version = 0;
    newlib_cmd.cmdsize = sizeof(struct dylib_command) + libpath_len;
    /* cmdsize must be a multiple of uint32_t */
    uint32_t remainder = ( sizeof(struct dylib_command) + libpath_len ) % sizeof(uint32_t);
    if (remainder != 0)
    {
        newlib_cmd.cmdsize += sizeof(uint32_t) - remainder;
    }
    if (header_info.free_space < newlib_cmd.cmdsize)
    {
        LOG_ERROR("Not enough space to inject library at %s!", path);
    }
    else
    {
        if (inject_normal_method(full_header, &header_info, base_address, injection_offset, &newlib_cmd, library_to_inject))
        {
            goto failure;
        }
    }
    
success:
    _FREE(full_header, M_TEMP);
    full_header = NULL;
    _FREE(header_info.linkedit_buf, M_TEMP);
    header_info.linkedit_buf = NULL;
    return KERN_SUCCESS;
failure:
    if (full_header)
    {
        _FREE(full_header, M_TEMP);
        full_header = NULL;
    }
    if (header_info.linkedit_buf)
    {
        _FREE(header_info.linkedit_buf, M_TEMP);
        header_info.linkedit_buf = NULL;
    }
    return KERN_FAILURE;
}
コード例 #29
0
ファイル: afs_daemons.c プロジェクト: meffie/openafs
/* This function always holds the GLOCK whilst it is running. The caller
 * gets the GLOCK before invoking it, and afs_osi_Sleep drops the GLOCK
 * whilst we are sleeping, and regains it when we're woken up.
 */
void
afs_Daemon(void)
{
    afs_int32 code;
    struct afs_exporter *exporter;
    afs_int32 now;
    afs_int32 last3MinCheck, last10MinCheck, last60MinCheck, lastNMinCheck;
    afs_int32 last1MinCheck, last5MinCheck;
    afs_uint32 lastCBSlotBump;
    char cs_warned = 0;

    AFS_STATCNT(afs_Daemon);

    afs_rootFid.Fid.Volume = 0;
    while (afs_initState < 101)
	afs_osi_Sleep(&afs_initState);

#ifdef AFS_DARWIN80_ENV
    if (afs_osi_ctxtp_initialized)
        osi_Panic("vfs context already initialized");
    while (afs_osi_ctxtp && vfs_context_ref)
        afs_osi_Sleep(&afs_osi_ctxtp);
    if (afs_osi_ctxtp && !vfs_context_ref)
       vfs_context_rele(afs_osi_ctxtp);
    afs_osi_ctxtp = vfs_context_create(NULL);
    afs_osi_ctxtp_initialized = 1;
#endif
    now = osi_Time();
    lastCBSlotBump = now;

    /* when a lot of clients are booted simultaneously, they develop
     * annoying synchronous VL server bashing behaviors.  So we stagger them.
     */
    last1MinCheck = now + ((afs_random() & 0x7fffffff) % 60);	/* an extra 30 */
    last3MinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180);
    last60MinCheck = now - 1800 + ((afs_random() & 0x7fffffff) % 3600);
    last10MinCheck = now - 300 + ((afs_random() & 0x7fffffff) % 600);
    last5MinCheck = now - 150 + ((afs_random() & 0x7fffffff) % 300);
    lastNMinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180);

    /* start off with afs_initState >= 101 (basic init done) */
    while (1) {
	afs_CheckCallbacks(20);	/* unstat anything which will expire soon */

	/* things to do every 20 seconds or less - required by protocol spec */
	if (afs_nfsexporter)
	    afs_FlushActiveVcaches(0);	/* flush NFS writes */
	afs_FlushVCBs(1);	/* flush queued callbacks */

	afs_MaybeWakeupTruncateDaemon();	/* free cache space if have too */
	rx_CheckPackets();	/* Does RX need more packets? */

	now = osi_Time();
	if (lastCBSlotBump + CBHTSLOTLEN < now) {	/* pretty time-dependant */
	    lastCBSlotBump = now;
	    if (afs_BumpBase()) {
		afs_CheckCallbacks(20);	/* unstat anything which will expire soon */
	    }
	}

	if (last1MinCheck + 60 < now) {
	    /* things to do every minute */
	    DFlush();		/* write out dir buffers */
	    afs_WriteThroughDSlots();	/* write through cacheinfo entries */
	    ObtainWriteLock(&afs_xvcache, 736);
	    afs_FlushReclaimedVcaches();
	    ReleaseWriteLock(&afs_xvcache);
	    afs_FlushActiveVcaches(1);	/* keep flocks held & flush nfs writes */
#if 0
	    afs_StoreDirtyVcaches();
#endif
	    afs_CheckRXEpoch();
	    last1MinCheck = now;
	}

	if (last3MinCheck + 180 < now) {
	    afs_CheckTokenCache();	/* check for access cache resets due to expired
					 * tickets */
	    last3MinCheck = now;
	}

        if (afsd_dynamic_vcaches && (last5MinCheck + 300 < now)) {
            /* start with trying to drop us back to our base usage */
            int anumber = VCACHE_FREE + (afs_vcount - afs_cacheStats);

	    if (anumber > 0) {
		ObtainWriteLock(&afs_xvcache, 734);
		afs_ShakeLooseVCaches(anumber);
		ReleaseWriteLock(&afs_xvcache);
	    }
            last5MinCheck = now;
        }

	if (!afs_CheckServerDaemonStarted) {
	    /* Do the check here if the correct afsd is not installed. */
	    if (!cs_warned) {
		cs_warned = 1;
		afs_warn("Please install afsd with check server daemon.\n");
	    }
	    if (lastNMinCheck + afs_probe_interval < now) {
		/* only check down servers */
		afs_CheckServers(1, NULL);
		lastNMinCheck = now;
	    }
	}
	if (last10MinCheck + 600 < now) {
#ifdef AFS_USERSPACE_IP_ADDR
	    extern int rxi_GetcbiInfo(void);
#endif
	    afs_Trace1(afs_iclSetp, CM_TRACE_PROBEUP, ICL_TYPE_INT32, 600);
#ifdef AFS_USERSPACE_IP_ADDR
	    if (rxi_GetcbiInfo()) {	/* addresses changed from last time */
		afs_FlushCBs();
	    }
#else /* AFS_USERSPACE_IP_ADDR */
	    if (rxi_GetIFInfo()) {	/* addresses changed from last time */
		afs_FlushCBs();
	    }
#endif /* else AFS_USERSPACE_IP_ADDR */
	    if (!afs_CheckServerDaemonStarted)
		afs_CheckServers(0, NULL);
	    afs_GCUserData(0);	/* gc old conns */
	    /* This is probably the wrong way of doing GC for the various exporters but it will suffice for a while */
	    for (exporter = root_exported; exporter;
		 exporter = exporter->exp_next) {
		(void)EXP_GC(exporter, 0);	/* Generalize params */
	    }
	    {
		static int cnt = 0;
		if (++cnt < 12) {
		    afs_CheckVolumeNames(AFS_VOLCHECK_EXPIRED |
					 AFS_VOLCHECK_BUSY);
		} else {
		    cnt = 0;
		    afs_CheckVolumeNames(AFS_VOLCHECK_EXPIRED |
					 AFS_VOLCHECK_BUSY |
					 AFS_VOLCHECK_MTPTS);
		}
	    }
	    last10MinCheck = now;
	}
	if (last60MinCheck + 3600 < now) {
	    afs_Trace1(afs_iclSetp, CM_TRACE_PROBEVOLUME, ICL_TYPE_INT32,
		       3600);
	    afs_CheckRootVolume();
#if AFS_GCPAGS
	    if (afs_gcpags == AFS_GCPAGS_OK) {
		afs_int32 didany;
		afs_GCPAGs(&didany);
	    }
#endif
	    last60MinCheck = now;
	}
	if (afs_initState < 300) {	/* while things ain't rosy */
	    code = afs_CheckRootVolume();
	    if (code == 0)
		afs_initState = 300;	/* succeeded */
	    if (afs_initState < 200)
		afs_initState = 200;	/* tried once */
	    afs_osi_Wakeup(&afs_initState);
	}

	/* 18285 is because we're trying to divide evenly into 128, that is,
	 * CBSlotLen, while staying just under 20 seconds.  If CBSlotLen
	 * changes, should probably change this interval, too.
	 * Some of the preceding actions may take quite some time, so we
	 * might not want to wait the entire interval */
	now = 18285 - (osi_Time() - now);
	if (now > 0) {
	    afs_osi_Wait(now, &AFS_WaitHandler, 0);
	}

	if (afs_termState == AFSOP_STOP_AFS) {
	    if (afs_CheckServerDaemonStarted)
		afs_termState = AFSOP_STOP_CS;
	    else
		afs_termState = AFSOP_STOP_TRUNCDAEMON;
	    afs_osi_Wakeup(&afs_termState);
	    return;
	}
    }
}
コード例 #30
0
ファイル: kauth.c プロジェクト: gdbinit/rex_versus_the_romans
/* 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;
}