Exemplo n.º 1
0
/*
 * kobj_load_file:
 *
 *	Load an object located in the file system.
 */
int
kobj_load_file(kobj_t *kop, const char *filename, const char *base,
	       bool autoload)
{
	struct nameidata nd;
	kauth_cred_t cred;
	char *path;
	int error;
	kobj_t ko;

	cred = kauth_cred_get();

	ko = kmem_zalloc(sizeof(*ko), KM_SLEEP);
	if (ko == NULL) {
		return ENOMEM;
	}

	if (autoload) {
		error = ENOENT;
	} else {
		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename);
		error = vn_open(&nd, FREAD, 0);
	}
	if (error != 0) {
		if (error != ENOENT) {
			goto out;
		}
		path = PNBUF_GET();
		snprintf(path, MAXPATHLEN - 1, "%s/%s/%s.kmod", base,
		    filename, filename);
		NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, UIO_SYSSPACE, path);
		error = vn_open(&nd, FREAD, 0);
		if (error != 0) {
			strlcat(path, ".o", MAXPATHLEN);
			NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, UIO_SYSSPACE,
			    path);
			error = vn_open(&nd, FREAD, 0);
		}
		PNBUF_PUT(path);
		if (error != 0) {
			goto out;
		}
	}

 out:
 	if (error != 0) {
	 	kmem_free(ko, sizeof(*ko));
	 	return error;
	}

	ko->ko_type = KT_VNODE;
	ko->ko_source = nd.ni_vp;
	*kop = ko;
	return kobj_load(ko);
}
Exemplo n.º 2
0
static int
vfs_mountroot_readconf(struct thread *td, struct sbuf *sb)
{
	static char buf[128];
	struct nameidata nd;
	off_t ofs;
	ssize_t resid;
	int error, flags, len;

	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/.mount.conf", td);
	flags = FREAD;
	error = vn_open(&nd, &flags, 0, NULL);
	if (error)
		return (error);

	NDFREE(&nd, NDF_ONLY_PNBUF);
	ofs = 0;
	len = sizeof(buf) - 1;
	while (1) {
		error = vn_rdwr(UIO_READ, nd.ni_vp, buf, len, ofs,
		    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
		    NOCRED, &resid, td);
		if (error)
			break;
		if (resid == len)
			break;
		buf[len - resid] = 0;
		sbuf_printf(sb, "%s", buf);
		ofs += len - resid;
	}

	VOP_UNLOCK(nd.ni_vp, 0);
	vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
	return (error);
}
Exemplo n.º 3
0
int
randomdev_write_file(const char *filename, void *buf, size_t length)
{
	struct nameidata nd;
	struct thread* td = curthread;
	int error;
	ssize_t resid;
	int flags;

	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
	flags = FWRITE | O_CREAT | O_TRUNC;
	error = vn_open(&nd, &flags, 0, NULL);
	if (error == 0) {
		NDFREE(&nd, NDF_ONLY_PNBUF);
		if (nd.ni_vp->v_type != VREG)
			error = ENOEXEC;
		else
			error = vn_rdwr(UIO_WRITE, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);

		VOP_UNLOCK(nd.ni_vp, 0);
		vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
	}

	return (error);
}
Exemplo n.º 4
0
/*
 * fp_open:
 *
 *	Open a file as specified.  Use O_* flags for flags.
 *
 *	vn_open() asserts that the cred must match the process's cred.
 *
 *	NOTE! when fp_open() is called from a pure thread, root creds are
 *	used.
 */
int
fp_open(const char *path, int flags, int mode, file_t *fpp)
{
    struct nlookupdata nd;
    struct thread *td;
    struct file *fp;
    int error;

    if ((error = falloc(NULL, fpp, NULL)) != 0)
	return (error);
    fp = *fpp;
    td = curthread;
    if (td->td_proc)
	fsetcred(fp, td->td_proc->p_ucred);
    error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_LOCKVP);
    flags = FFLAGS(flags);
    if (error == 0)
	error = vn_open(&nd, fp, flags, mode);
    nlookup_done(&nd);
    if (error) {
	fdrop(fp);
	*fpp = NULL;
    }
    return(error);
}
Exemplo n.º 5
0
static int
swap_file_open(struct chip_swap *swap, const char *swap_file)
{
	struct nameidata nd;
	int flags, error;

	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, swap_file,
	    curthread);

	flags = FWRITE | FREAD | O_NOFOLLOW | O_CREAT | O_TRUNC;

	error = vn_open(&nd, &flags, CHIP_SWAP_CMODE, NULL);
	if (error) {
		nand_debug(NDBG_SIM,"Cannot create swap file %s", swap_file);
		NDFREE(&nd, NDF_ONLY_PNBUF);
		return (error);
	}

	swap->swap_cred = crhold(curthread->td_ucred);
	NDFREE(&nd, NDF_ONLY_PNBUF);

	/* We just unlock so we hold a reference */
	VOP_UNLOCK(nd.ni_vp, 0);

	swap->swap_vp = nd.ni_vp;

	return (0);
}
Exemplo n.º 6
0
static int
kfcreate(char *filename, kfile_t **kfilep)
{
	kfile_t	*fp;
	int	rval;

	ASSERT(modrootloaded);

	fp = kmem_alloc(sizeof (kfile_t), KM_SLEEP);

	fp->kf_vnflags = FCREAT | FWRITE | FTRUNC;
	fp->kf_fname = filename;
	fp->kf_fpos = 0;
	fp->kf_state = 0;

	KFDEBUG((CE_CONT, "create: %s flags 0x%x\n",
		filename, fp->kf_vnflags));
	rval = vn_open(filename, UIO_SYSSPACE, fp->kf_vnflags,
	    0444, &fp->kf_vp, CRCREAT, 0);
	if (rval != 0) {
		kmem_free(fp, sizeof (kfile_t));
		KFDEBUG((CE_CONT, "%s: create error %d\n",
			filename, rval));
		return (rval);
	}

	*kfilep = fp;
	return (0);
}
Exemplo n.º 7
0
static int
splat_vnode_test1(struct file *file, void *arg)
{
	vnode_t *vp;
	int rc;

	if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
			  FREAD, 0644, &vp, 0, 0))) {
		splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
			     "Failed to vn_open test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE, rc);
		return -rc;
	}

        rc = VOP_CLOSE(vp, 0, 0, 0, 0, 0);

	if (rc) {
		splat_vprint(file, SPLAT_VNODE_TEST1_NAME,
			     "Failed to vn_close test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE, rc);
		return -rc;
	}

	splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully vn_open'ed "
		     "and vn_closed test file: %s\n", SPLAT_VNODE_TEST_FILE);

        return -rc;
} /* splat_vnode_test1() */
Exemplo n.º 8
0
static int
splat_vnode_test3(struct file *file, void *arg)
{
	vnode_t *vp;
	char buf1[32] = "SPL VNode Interface Test File\n";
	char buf2[32] = "";
	int rc;

	if ((rc = splat_vnode_unlink_all(file, arg, SPLAT_VNODE_TEST3_NAME)))
		return rc;

	if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
			  FWRITE | FREAD | FCREAT | FEXCL,
			  0644, &vp, 0, 0))) {
		splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
			     "Failed to vn_open test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE_RW, rc);
		return -rc;
	}

        rc = vn_rdwr(UIO_WRITE, vp, buf1, strlen(buf1), 0,
                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
	if (rc) {
		splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
			     "Failed vn_rdwr write of test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE_RW, rc);
		goto out;
	}

        rc = vn_rdwr(UIO_READ, vp, buf2, strlen(buf1), 0,
                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
	if (rc) {
		splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
			     "Failed vn_rdwr read of test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE_RW, rc);
		goto out;
	}

	if (strncmp(buf1, buf2, strlen(buf1))) {
		rc = EINVAL;
		splat_vprint(file, SPLAT_VNODE_TEST3_NAME,
			     "Failed strncmp data written does not match "
			     "data read\nWrote: %sRead:  %s\n", buf1, buf2);
		goto out;
	}

	rc = 0;
	splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Wrote: %s", buf1);
	splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Read:  %s", buf2);
	splat_vprint(file, SPLAT_VNODE_TEST3_NAME, "Successfully wrote and "
		     "read expected data pattern to test file: %s\n",
		     SPLAT_VNODE_TEST_FILE_RW);

out:
        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
	vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);

        return -rc;
} /* splat_vnode_test3() */
Exemplo n.º 9
0
void
vdsp_open(void *arg1, void *arg2)
{
	struct vdsp_softc *sc = arg1;
	struct proc *p = curproc;
	struct vd_attr_info ai;

	if (sc->sc_vp == NULL) {
		struct nameidata nd;
		struct vattr va;
		const char *name;
		int error;

		name = mdesc_get_prop_str(sc->sc_idx, "vds-block-device");
		if (name == NULL)
			return;

		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
		error = vn_open(&nd, FREAD | FWRITE, 0);
		if (error) {
			printf("VOP_OPEN: %s, %d\n", name, error);
			return;
		}

		error = VOP_GETATTR(nd.ni_vp, &va, p->p_ucred, p);
		if (error)
			printf("VOP_GETATTR: %s, %d\n", name, error);
		sc->sc_vdisk_block_size = DEV_BSIZE;
		sc->sc_vdisk_size = va.va_size / DEV_BSIZE;

		VOP_UNLOCK(nd.ni_vp, 0, p);
		sc->sc_vp = nd.ni_vp;

		vdsp_readlabel(sc);
	}

	bzero(&ai, sizeof(ai));
	ai.tag.type = VIO_TYPE_CTRL;
	ai.tag.stype = VIO_SUBTYPE_ACK;
	ai.tag.stype_env = VIO_ATTR_INFO;
	ai.tag.sid = sc->sc_local_sid;
	ai.xfer_mode = sc->sc_xfer_mode;
	ai.vd_type = VD_DISK_TYPE_DISK;
	if (sc->sc_major > 1 || sc->sc_minor >= 1) {
		if (vdsp_is_iso(sc))
			ai.vd_mtype = VD_MEDIA_TYPE_CD;
		else
			ai.vd_mtype = VD_MEDIA_TYPE_FIXED;
	}
	ai.vdisk_block_size = sc->sc_vdisk_block_size;
	ai.operations = VD_OP_MASK;
	ai.vdisk_size = sc->sc_vdisk_size;
	ai.max_xfer_sz = MAXPHYS / sc->sc_vdisk_block_size;
	vdsp_sendmsg(sc, &ai, sizeof(ai), 1);
}
Exemplo n.º 10
0
/*
 * Accounting system call.  Written based on the specification and
 * previous implementation done by Mark Tinguely.
 */
int
sys_acct(struct proc *p, void *v, register_t *retval)
{
	struct sys_acct_args /* {
		syscallarg(const char *) path;
	} */ *uap = v;
	struct nameidata nd;
	int error;

	/* Make sure that the caller is root. */
	if ((error = suser(p, 0)) != 0)
		return (error);

	/*
	 * If accounting is to be started to a file, open that file for
	 * writing and make sure it's 'normal'.
	 */
	if (SCARG(uap, path) != NULL) {
		NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path),
		    p);
		if ((error = vn_open(&nd, FWRITE|O_APPEND, 0)) != 0)
			return (error);
		VOP_UNLOCK(nd.ni_vp, 0);
		if (nd.ni_vp->v_type != VREG) {
			vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
			return (EACCES);
		}
	}

	/*
	 * If accounting was previously enabled, kill the old space-watcher,
	 * close the file, and (if no new file was specified, leave).
	 */
	if (acctp != NULL || savacctp != NULL) {
		wakeup(&acct_proc);
		error = vn_close((acctp != NULL ? acctp : savacctp), FWRITE,
		    p->p_ucred, p);
		acctp = savacctp = NULL;
	}
	if (SCARG(uap, path) == NULL)
		return (0);

	/*
	 * Save the new accounting file vnode, and schedule the new
	 * free space watcher.
	 */
	acctp = nd.ni_vp;
	if ((error = acct_start()) != 0) {
		acctp = NULL;
		(void)vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
		return (error);
	}
	return (0);
}
Exemplo n.º 11
0
static int
spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
{
	size_t buflen;
	char *buf;
	vnode_t *vp;
	int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
	char *temp;
	int err;

	/*
	 * If the nvlist is empty (NULL), then remove the old cachefile.
	 */
	if (nvl == NULL) {
		err = vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
		return (err);
	}

	/*
	 * Pack the configuration into a buffer.
	 */
	VERIFY(nvlist_size(nvl, &buflen, NV_ENCODE_XDR) == 0);

	buf = kmem_alloc(buflen, KM_SLEEP);
	temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP);

	VERIFY(nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_XDR,
	    KM_SLEEP) == 0);

	/*
	 * Write the configuration to disk.  We need to do the traditional
	 * 'write to temporary file, sync, move over original' to make sure we
	 * always have a consistent view of the data.
	 */
	(void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);

	err = vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0);
	if (err == 0) {
		err = vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
		    0, RLIM64_INFINITY, kcred, NULL);
		if (err == 0)
			err = VOP_FSYNC(vp, FSYNC, kcred, NULL);
		if (err == 0)
			err = vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
		(void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
	}

	(void) vn_remove(temp, UIO_SYSSPACE, RMFILE);

	kmem_free(buf, buflen);
	kmem_free(temp, MAXPATHLEN);
	return (err);
}
Exemplo n.º 12
0
static int
vniocattach_shadow(struct vn_softc *vn, struct vn_ioctl_64 *vniop, 
				   __unused dev_t dev, int in_kernel, proc_t p)
{
	vfs_context_t ctx = vfs_context_current();
	struct nameidata nd;
	int error, flags;
	shadow_map_t *	map;
	off_t file_size;

	flags = FREAD|FWRITE;
	if (in_kernel) {
		NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, UIO_SYSSPACE, vniop->vn_file, ctx);
	}
	else {
		NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, 
			   (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), 
			   vniop->vn_file, ctx);
	}
	/* vn_open gives both long- and short-term references */
	error = vn_open(&nd, flags, 0);
	if (error) {
		/* shadow MUST be writable! */
		return (error);
	}
	if (nd.ni_vp->v_type != VREG 
	    || (error = vnode_size(nd.ni_vp, &file_size, ctx))) {
		(void)vn_close(nd.ni_vp, flags, ctx);
		vnode_put(nd.ni_vp);
		return (error ? error : EINVAL);
	}
	map = shadow_map_create(vn->sc_fsize, file_size,
				0, vn->sc_secsize);
	if (map == NULL) {
		(void)vn_close(nd.ni_vp, flags, ctx);
		vnode_put(nd.ni_vp);
		vn->sc_shadow_vp = NULL;
		return (ENOMEM);
	}
	vn->sc_shadow_vp = nd.ni_vp;
	vn->sc_shadow_vid = vnode_vid(nd.ni_vp);
	vn->sc_shadow_vp->v_flag |= VNOCACHE_DATA;
	vn->sc_shadow_map = map;
	vn->sc_flags &= ~VNF_READONLY; /* we're now read/write */

	/* lose the short-term reference */
	vnode_put(nd.ni_vp);
	return(0);
}
Exemplo n.º 13
0
char *
linker_search_path(const char *name)
{
    struct nameidata	nd;
    struct proc		*p = curproc;	/* XXX */
    char		*cp, *ep, *result;
    int			error;
    enum vtype		type;

    /* qualified at all? */
    if (index(name, '/'))
	return(linker_strdup(name));

    /* traverse the linker path */
    cp = linker_path;
    for (;;) {

	/* find the end of this component */
	for (ep = cp; (*ep != 0) && (*ep != ';'); ep++)
	    ;
	result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK);
	if (result == NULL)	/* actually ENOMEM */
	    return(NULL);

	strncpy(result, cp, ep - cp);
	strcpy(result + (ep - cp), name);

	/*
	 * Attempt to open the file, and return the path if we succeed and it's
	 * a regular file.
	 */
	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p);
	error = vn_open(&nd, FREAD, 0);
	if (error == 0) {
	    type = nd.ni_vp->v_type;
	    VOP_UNLOCK(nd.ni_vp, 0, p);
	    vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
	    if (type == VREG)
		return(result);
	}
	free(result, M_LINKER);

	if (*ep == 0)
	    break;
	cp = ep + 1;
    }
    return(NULL);
}
Exemplo n.º 14
0
/*
 * Lookup the provided name in the filesystem.  If the file exists,
 * is a valid block device, and isn't being used by anyone else,
 * set *vpp to the file's vnode.
 */
int
dk_lookup(struct pathbuf *pb, struct lwp *l, struct vnode **vpp)
{
	struct nameidata nd;
	struct vnode *vp;
	int     error;

	if (l == NULL)
		return ESRCH;	/* Is ESRCH the best choice? */

	NDINIT(&nd, LOOKUP, FOLLOW, pb);
	if ((error = vn_open(&nd, FREAD | FWRITE, 0)) != 0) {
		DPRINTF((DKDB_FOLLOW|DKDB_INIT),
		    ("%s: vn_open error = %d\n", __func__, error));
		return error;
	}

	vp = nd.ni_vp;
	if (vp->v_type != VBLK) {
		error = ENOTBLK;
		goto out;
	}

	/* Reopen as anonymous vnode to protect against forced unmount. */
	if ((error = bdevvp(vp->v_rdev, vpp)) != 0)
		goto out;
	VOP_UNLOCK(vp);
	if ((error = vn_close(vp, FREAD | FWRITE, l->l_cred)) != 0) {
		vrele(*vpp);
		return error;
	}
	if ((error = VOP_OPEN(*vpp, FREAD | FWRITE, l->l_cred)) != 0) {
		vrele(*vpp);
		return error;
	}
	mutex_enter((*vpp)->v_interlock);
	(*vpp)->v_writecount++;
	mutex_exit((*vpp)->v_interlock);

	IFDEBUG(DKDB_VNODE, vprint("dk_lookup: vnode info", *vpp));

	return 0;
out:
	VOP_UNLOCK(vp);
	(void) vn_close(vp, FREAD | FWRITE, l->l_cred);
	return error;
}
Exemplo n.º 15
0
int
vn_openat(char *path, enum uio_seg x1, int flags, int mode, vnode_t **vpp, enum create x2,
          mode_t x3, vnode_t *startvp, int fd)
{
    char *realpath = kmem_alloc(strlen(path) + 2, KM_SLEEP);
    int ret;

    ASSERT(startvp == rootdir);
    (void) sprintf(realpath, "/%s", path);

    /* fd ignored for now, need if want to simulate nbmand support */
    ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);

    kmem_free(realpath, strlen(path) + 2);

    return (ret);
}
Exemplo n.º 16
0
/*
 * Lookup the provided name in the filesystem.  If the file exists,
 * is a valid block device, and isn't being used by anyone else,
 * set *vpp to the file's vnode.
 */
int
ccdlookup(char *path, struct proc *p, struct vnode **vpp)
{
	struct nameidata nd;
	struct vnode *vp;
	struct vattr va;
	int error;

	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
	if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
		CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT,
		    ("ccdlookup: vn_open error = %d\n", error));
		return (error);
	}
	vp = nd.ni_vp;

	if (vp->v_usecount > 1) {
		VOP_UNLOCK(vp, 0, p);
		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
		return (EBUSY);
	}

	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
		CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT,
		    ("ccdlookup: getattr error = %d\n", error));
		VOP_UNLOCK(vp, 0, p);
		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
		return (error);
	}

	/* XXX: eventually we should handle VREG, too. */
	if (va.va_type != VBLK) {
		VOP_UNLOCK(vp, 0, p);
		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
		return (ENOTBLK);
	}

#ifdef DIAGNOSTIC
	CCD_DCALL(CCDB_VNODE, vprint("ccdlookup: vnode info", vp));
#endif

	VOP_UNLOCK(vp, 0, p);
	*vpp = vp;
	return (0);
}
Exemplo n.º 17
0
cfs_file_t *
kern_file_open(const char * filename, int flags, int mode, int *err)
{
	struct nameidata nd;
	cfs_file_t	*fp;
	register struct vnode	*vp;
	int			rc;
	extern struct fileops	vnops;
	extern int nfiles;
        CFS_DECL_CONE_DATA;

        CFS_CONE_IN;
	nfiles++;
	MALLOC_ZONE(fp, cfs_file_t *, sizeof(cfs_file_t), M_FILE, M_WAITOK|M_ZERO);
	bzero(fp, sizeof(cfs_file_t));
	fp->f_count = 1;
        LIST_CIRCLE(fp, f_list);
	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (char *)filename, current_proc());
	if ((rc = vn_open(&nd, flags, mode)) != 0){
                printf("filp_open failed at (%d)\n", rc);
                if (err != NULL)
                        *err = rc;
                FREE_ZONE(fp, sizeof *fp, M_FILE);
                CFS_CONE_EX;
		return NULL;
	}
	vp = nd.ni_vp;
	fp->f_flag = flags & FMASK;
	fp->f_type = DTYPE_VNODE;
	fp->f_ops = &vnops;
	fp->f_data = (caddr_t)vp;
	fp->f_cred = current_proc()->p_ucred;
	/*
	 * Hold cred to increase reference
	 */
	crhold(fp->f_cred);
	/*
	 * vnode is locked inside vn_open for lookup,
	 * we should release the lock before return
	 */
	VOP_UNLOCK(vp, 0, current_proc());
        CFS_CONE_EX;

	return fp;
}
/*
 * kobj_load_vfs:
 *
 *	Load an object located in the file system.
 */
int
kobj_load_vfs(kobj_t *kop, const char *path, const bool nochroot)
{
	struct nameidata nd;
	struct pathbuf *pb;
	kauth_cred_t cred;
	int error;
	kobj_t ko;

	KASSERT(path != NULL);
	if (strchr(path, '/') == NULL)
		return ENOENT;

	cred = kauth_cred_get();

	ko = kmem_zalloc(sizeof(*ko), KM_SLEEP);
	if (ko == NULL) {
		return ENOMEM;
	}

	pb = pathbuf_create(path);
	if (pb == NULL) {
	 	kmem_free(ko, sizeof(*ko));
		return ENOMEM;
	}

	NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), pb);
	error = vn_open(&nd, FREAD, 0);

 	if (error != 0) {
		pathbuf_destroy(pb);
	 	kmem_free(ko, sizeof(*ko));
	 	return error;
	}

	ko->ko_type = KT_VNODE;
	kobj_setname(ko, path);
	ko->ko_source = nd.ni_vp;
	ko->ko_read = kobj_read_vfs;
	ko->ko_close = kobj_close_vfs;
	pathbuf_destroy(pb);

	*kop = ko;
	return kobj_load(ko);
}
Exemplo n.º 19
0
static int
splat_vnode_test6(struct file *file, void *arg)
{
	vnode_t *vp;
	char buf[32] = "SPL VNode Interface Test File\n";
	int rc;

	if ((rc = splat_vnode_unlink_all(file, arg, SPLAT_VNODE_TEST6_NAME)))
		return rc;

	if ((rc = vn_open(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE,
			  FWRITE | FCREAT | FEXCL, 0644, &vp, 0, 0))) {
		splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
			     "Failed to vn_open test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE_RW, rc);
		return -rc;
	}

        rc = vn_rdwr(UIO_WRITE, vp, buf, strlen(buf), 0,
                     UIO_SYSSPACE, 0, RLIM64_INFINITY, 0, NULL);
	if (rc) {
		splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
			     "Failed vn_rdwr write of test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE_RW, rc);
		goto out;
	}

	rc = vn_fsync(vp, 0, 0, 0);
	if (rc) {
		splat_vprint(file, SPLAT_VNODE_TEST6_NAME,
			     "Failed vn_fsync of test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE_RW, rc);
		goto out;
	}

	rc = 0;
	splat_vprint(file, SPLAT_VNODE_TEST6_NAME, "Successfully "
		     "fsync'ed test file %s\n", SPLAT_VNODE_TEST_FILE_RW);
out:
        VOP_CLOSE(vp, 0, 0, 0, 0, 0);
	vn_remove(SPLAT_VNODE_TEST_FILE_RW, UIO_SYSSPACE, RMFILE);

        return -rc;
} /* splat_vnode_test6() */
Exemplo n.º 20
0
/*
 * Lookup the provided name in the filesystem.  If the file exists,
 * is a valid block device, and isn't being used by anyone else,
 * set *vpp to the file's vnode.
 */
int
dk_lookup(const char *path, struct lwp *l, struct vnode **vpp,
    enum uio_seg segflg)
{
	struct nameidata nd;
	struct vnode *vp;
	struct vattr va;
	int     error;

	if (l == NULL)
		return ESRCH;	/* Is ESRCH the best choice? */

	NDINIT(&nd, LOOKUP, FOLLOW, segflg, path);
	if ((error = vn_open(&nd, FREAD | FWRITE, 0)) != 0) {
		DPRINTF((DKDB_FOLLOW|DKDB_INIT),
		    ("dk_lookup: vn_open error = %d\n", error));
		return error;
	}

	vp = nd.ni_vp;
	if ((error = VOP_GETATTR(vp, &va, l->l_cred)) != 0) {
		DPRINTF((DKDB_FOLLOW|DKDB_INIT),
		    ("dk_lookup: getattr error = %d\n", error));
		goto out;
	}

	/* XXX: eventually we should handle VREG, too. */
	if (va.va_type != VBLK) {
		error = ENOTBLK;
		goto out;
	}

	IFDEBUG(DKDB_VNODE, vprint("dk_lookup: vnode info", vp));

	VOP_UNLOCK(vp, 0);
	*vpp = vp;
	return 0;
out:
	VOP_UNLOCK(vp, 0);
	(void) vn_close(vp, FREAD | FWRITE, l->l_cred);
	return error;
}
Exemplo n.º 21
0
struct _buf *
kobj_open_file(const char *name)
{
	struct _buf *file;
	vnode_t *vp;
	int rc;

	file = kmalloc(sizeof(_buf_t), kmem_flags_convert(KM_SLEEP));
	if (file == NULL)
		return ((_buf_t *)-1UL);

	if ((rc = vn_open(name, UIO_SYSSPACE, FREAD, 0644, &vp, 0, 0))) {
		kfree(file);
		return ((_buf_t *)-1UL);
	}

	file->vp = vp;

	return (file);
} /* kobj_open_file() */
Exemplo n.º 22
0
int
vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode,
          struct vnode **vpp, enum create crwhy,
          mode_t umask, struct vnode *startvp)
{
    char *path;
    int pathlen = MAXPATHLEN;
    int error;

    path = (char *)kmem_zalloc(MAXPATHLEN, KM_SLEEP);

    error = vn_getpath(startvp, path, &pathlen);
    if (error == 0) {
        strlcat(path, pnamep, MAXPATHLEN);
        error = vn_open(path, seg, filemode, createmode, vpp, crwhy,
                        umask);
    }

    kmem_free(path, MAXPATHLEN);
    return (error);
}
Exemplo n.º 23
0
static int
splat_vnode_test5(struct file *file, void *arg)
{
	vnode_t *vp;
	vattr_t vap;
	int rc;

	if ((rc = vn_open(SPLAT_VNODE_TEST_FILE, UIO_SYSSPACE,
			  FREAD, 0644, &vp, 0, 0))) {
		splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
			     "Failed to vn_open test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE, rc);
		return -rc;
	}

	rc = VOP_GETATTR(vp, &vap, 0, 0, NULL);
	if (rc) {
		splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
			     "Failed to vn_getattr test file: %s (%d)\n",
			     SPLAT_VNODE_TEST_FILE, rc);
		goto out;
	}

	if (vap.va_type != VREG) {
		rc = EINVAL;
		splat_vprint(file, SPLAT_VNODE_TEST5_NAME,
			     "Failed expected regular file type "
			     "(%d != VREG): %s (%d)\n", vap.va_type,
			     SPLAT_VNODE_TEST_FILE, rc);
		goto out;
	}

	splat_vprint(file, SPLAT_VNODE_TEST1_NAME, "Successfully "
		     "vn_getattr'ed test file: %s\n", SPLAT_VNODE_TEST_FILE);

out:
        VOP_CLOSE(vp, 0, 0, 0, 0, 0);

        return -rc;
} /* splat_vnode_test5() */
Exemplo n.º 24
0
/*
 * reads config data into cprconfig
 */
static int
cpr_get_config(void)
{
	static char config_path[] = CPR_CONFIG;
	struct cprconfig *cf = &cprconfig;
	struct vnode *vp;
	char *fmt;
	int err;

	if (cprconfig_loaded)
		return (0);

	fmt = "cannot %s config file \"%s\", error %d\n";
	if (err = vn_open(config_path, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0)) {
		cpr_err(CE_CONT, fmt, "open", config_path, err);
		return (err);
	}

	err = cpr_rdwr(UIO_READ, vp, cf, sizeof (*cf));
	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
	VN_RELE(vp);
	if (err) {
		cpr_err(CE_CONT, fmt, "read", config_path, err);
		return (err);
	}

	if (cf->cf_magic == CPR_CONFIG_MAGIC)
		cprconfig_loaded = 1;
	else {
		cpr_err(CE_CONT, "invalid config file \"%s\", "
		    "rerun pmconfig(1M)\n", config_path);
		err = EINVAL;
	}

	return (err);
}
Exemplo n.º 25
0
/* ARGSUSED */
int
auditctl(struct thread *td, struct auditctl_args *uap)
{
	struct nameidata nd;
	struct ucred *cred;
	struct vnode *vp;
	int error = 0;
	int flags, vfslocked;

	if (jailed(td->td_ucred))
		return (ENOSYS);
	error = priv_check(td, PRIV_AUDIT_CONTROL);
	if (error)
		return (error);

	vp = NULL;
	cred = NULL;

	/*
	 * If a path is specified, open the replacement vnode, perform
	 * validity checks, and grab another reference to the current
	 * credential.
	 *
	 * On Darwin, a NULL path argument is also used to disable audit.
	 */
	if (uap->path == NULL)
		return (EINVAL);

	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
	    UIO_USERSPACE, uap->path, td);
	flags = AUDIT_OPEN_FLAGS;
	error = vn_open(&nd, &flags, 0, NULL);
	if (error)
		return (error);
	vfslocked = NDHASGIANT(&nd);
	vp = nd.ni_vp;
#ifdef MAC
	error = mac_system_check_auditctl(td->td_ucred, vp);
	VOP_UNLOCK(vp, 0);
	if (error) {
		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
		VFS_UNLOCK_GIANT(vfslocked);
		return (error);
	}
#else
	VOP_UNLOCK(vp, 0);
#endif
	NDFREE(&nd, NDF_ONLY_PNBUF);
	if (vp->v_type != VREG) {
		vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
		VFS_UNLOCK_GIANT(vfslocked);
		return (EINVAL);
	}
	VFS_UNLOCK_GIANT(vfslocked);
	cred = td->td_ucred;
	crhold(cred);

	/*
	 * XXXAUDIT: Should audit_suspended actually be cleared by
	 * audit_worker?
	 */
	audit_suspended = 0;

	audit_rotate_vnode(cred, vp);

	return (error);
}
Exemplo n.º 26
0
/*
 * Synchronize all pools to disk.  This must be called with the namespace lock
 * held.
 */
void
spa_config_sync(void)
{
	spa_t *spa = NULL;
	nvlist_t *config;
	size_t buflen;
	char *buf;
	vnode_t *vp;
	int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
	char pathname[128];
	char pathname2[128];

	ASSERT(MUTEX_HELD(&spa_namespace_lock));

	VERIFY(nvlist_alloc(&config, NV_UNIQUE_NAME, KM_SLEEP) == 0);

	/*
	 * Add all known pools to the configuration list, ignoring those with
	 * alternate root paths.
	 */
	spa = NULL;
	while ((spa = spa_next(spa)) != NULL) {
		mutex_enter(&spa->spa_config_cache_lock);
		if (spa->spa_config && spa->spa_name && spa->spa_root == NULL)
			VERIFY(nvlist_add_nvlist(config, spa->spa_name,
			    spa->spa_config) == 0);
		mutex_exit(&spa->spa_config_cache_lock);
	}

	/*
	 * Pack the configuration into a buffer.
	 */
	VERIFY(nvlist_size(config, &buflen, NV_ENCODE_XDR) == 0);

	buf = kmem_alloc(buflen, KM_SLEEP);

	VERIFY(nvlist_pack(config, &buf, &buflen, NV_ENCODE_XDR,
	    KM_SLEEP) == 0);

	/*
	 * Write the configuration to disk.  We need to do the traditional
	 * 'write to temporary file, sync, move over original' to make sure we
	 * always have a consistent view of the data.
	 */
	(void) snprintf(pathname, sizeof (pathname), "%s/%s", spa_config_dir,
	    ZPOOL_CACHE_TMP);

	if (vn_open(pathname, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0) != 0)
		goto out;

	if (vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
	    0, RLIM64_INFINITY, kcred, NULL) == 0 &&
	    VOP_FSYNC(vp, FSYNC, kcred) == 0) {
		(void) snprintf(pathname2, sizeof (pathname2), "%s/%s",
		    spa_config_dir, ZPOOL_CACHE_FILE);
		(void) vn_rename(pathname, pathname2, UIO_SYSSPACE);
	}

	(void) VOP_CLOSE(vp, oflags, 1, 0, kcred);
	VN_RELE(vp);

out:
	(void) vn_remove(pathname, UIO_SYSSPACE, RMFILE);
	spa_config_generation++;

	kmem_free(buf, buflen);
	nvlist_free(config);
}
Exemplo n.º 27
0
static int
link_elf_load_file(linker_class_t cls, const char *filename,
    linker_file_t *result)
{
	struct nameidata nd;
	struct thread *td = curthread;	/* XXX */
	Elf_Ehdr *hdr;
	Elf_Shdr *shdr;
	Elf_Sym *es;
	int nbytes, i, j;
	vm_offset_t mapbase;
	size_t mapsize;
	int error = 0;
	ssize_t resid;
	int flags;
	elf_file_t ef;
	linker_file_t lf;
	int symtabindex;
	int symstrindex;
	int shstrindex;
	int nsym;
	int pb, rl, ra;
	int alignmask;

	shdr = NULL;
	lf = NULL;
	mapsize = 0;
	hdr = NULL;

	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
	flags = FREAD;
	error = vn_open(&nd, &flags, 0, NULL);
	if (error)
		return error;
	NDFREE(&nd, NDF_ONLY_PNBUF);
	if (nd.ni_vp->v_type != VREG) {
		error = ENOEXEC;
		goto out;
	}
#ifdef MAC
	error = mac_kld_check_load(td->td_ucred, nd.ni_vp);
	if (error) {
		goto out;
	}
#endif

	/* Read the elf header from the file. */
	hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK);
	error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)hdr, sizeof(*hdr), 0,
	    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
	    &resid, td);
	if (error)
		goto out;
	if (resid != 0){
		error = ENOEXEC;
		goto out;
	}

	if (!IS_ELF(*hdr)) {
		error = ENOEXEC;
		goto out;
	}

	if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
	    || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
		link_elf_error(filename, "Unsupported file layout");
		error = ENOEXEC;
		goto out;
	}
	if (hdr->e_ident[EI_VERSION] != EV_CURRENT
	    || hdr->e_version != EV_CURRENT) {
		link_elf_error(filename, "Unsupported file version");
		error = ENOEXEC;
		goto out;
	}
	if (hdr->e_type != ET_REL) {
		error = ENOSYS;
		goto out;
	}
	if (hdr->e_machine != ELF_TARG_MACH) {
		link_elf_error(filename, "Unsupported machine");
		error = ENOEXEC;
		goto out;
	}

	lf = linker_make_file(filename, &link_elf_class);
	if (!lf) {
		error = ENOMEM;
		goto out;
	}
	ef = (elf_file_t) lf;
	ef->nprogtab = 0;
	ef->e_shdr = 0;
	ef->nreltab = 0;
	ef->nrelatab = 0;

	/* Allocate and read in the section header */
	nbytes = hdr->e_shnum * hdr->e_shentsize;
	if (nbytes == 0 || hdr->e_shoff == 0 ||
	    hdr->e_shentsize != sizeof(Elf_Shdr)) {
		error = ENOEXEC;
		goto out;
	}
	shdr = malloc(nbytes, M_LINKER, M_WAITOK);
	ef->e_shdr = shdr;
	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff,
	    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
	if (error)
		goto out;
	if (resid) {
		error = ENOEXEC;
		goto out;
	}

	/* Scan the section header for information and table sizing. */
	nsym = 0;
	symtabindex = -1;
	symstrindex = -1;
	for (i = 0; i < hdr->e_shnum; i++) {
		if (shdr[i].sh_size == 0)
			continue;
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			ef->nprogtab++;
			break;
		case SHT_SYMTAB:
			nsym++;
			symtabindex = i;
			symstrindex = shdr[i].sh_link;
			break;
		case SHT_REL:
			ef->nreltab++;
			break;
		case SHT_RELA:
			ef->nrelatab++;
			break;
		case SHT_STRTAB:
			break;
		}
	}
	if (ef->nprogtab == 0) {
		link_elf_error(filename, "file has no contents");
		error = ENOEXEC;
		goto out;
	}
	if (nsym != 1) {
		/* Only allow one symbol table for now */
		link_elf_error(filename, "file has no valid symbol table");
		error = ENOEXEC;
		goto out;
	}
	if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
	    shdr[symstrindex].sh_type != SHT_STRTAB) {
		link_elf_error(filename, "file has invalid symbol strings");
		error = ENOEXEC;
		goto out;
	}

	/* Allocate space for tracking the load chunks */
	if (ef->nprogtab != 0)
		ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
		    M_LINKER, M_WAITOK | M_ZERO);
	if (ef->nreltab != 0)
		ef->reltab = malloc(ef->nreltab * sizeof(*ef->reltab),
		    M_LINKER, M_WAITOK | M_ZERO);
	if (ef->nrelatab != 0)
		ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab),
		    M_LINKER, M_WAITOK | M_ZERO);

	if (symtabindex == -1)
		panic("lost symbol table index");
	/* Allocate space for and load the symbol table */
	ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
	ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
	error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ef->ddbsymtab,
	    shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
	    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
	    &resid, td);
	if (error)
		goto out;
	if (resid != 0){
		error = EINVAL;
		goto out;
	}

	if (symstrindex == -1)
		panic("lost symbol string index");
	/* Allocate space for and load the symbol strings */
	ef->ddbstrcnt = shdr[symstrindex].sh_size;
	ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
	error = vn_rdwr(UIO_READ, nd.ni_vp, ef->ddbstrtab,
	    shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
	    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
	    &resid, td);
	if (error)
		goto out;
	if (resid != 0){
		error = EINVAL;
		goto out;
	}

	/* Do we have a string table for the section names?  */
	shstrindex = -1;
	if (hdr->e_shstrndx != 0 &&
	    shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
		shstrindex = hdr->e_shstrndx;
		ef->shstrcnt = shdr[shstrindex].sh_size;
		ef->shstrtab = malloc(shdr[shstrindex].sh_size, M_LINKER,
		    M_WAITOK);
		error = vn_rdwr(UIO_READ, nd.ni_vp, ef->shstrtab,
		    shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
		    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
		    &resid, td);
		if (error)
			goto out;
		if (resid != 0){
			error = EINVAL;
			goto out;
		}
	}

	/* Size up code/data(progbits) and bss(nobits). */
	alignmask = 0;
	for (i = 0; i < hdr->e_shnum; i++) {
		if (shdr[i].sh_size == 0)
			continue;
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			alignmask = shdr[i].sh_addralign - 1;
			mapsize += alignmask;
			mapsize &= ~alignmask;
			mapsize += shdr[i].sh_size;
			break;
		}
	}

	/*
	 * We know how much space we need for the text/data/bss/etc.
	 * This stuff needs to be in a single chunk so that profiling etc
	 * can get the bounds and gdb can associate offsets with modules
	 */
	ef->object = vm_object_allocate(OBJT_DEFAULT,
	    round_page(mapsize) >> PAGE_SHIFT);
	if (ef->object == NULL) {
		error = ENOMEM;
		goto out;
	}
	ef->address = (caddr_t) vm_map_min(kernel_map);

	/*
	 * In order to satisfy amd64's architectural requirements on the
	 * location of code and data in the kernel's address space, request a
	 * mapping that is above the kernel.  
	 */
#ifdef __amd64__
	mapbase = KERNBASE;
#else
	mapbase = VM_MIN_KERNEL_ADDRESS;
#endif
	error = vm_map_find(kernel_map, ef->object, 0, &mapbase,
	    round_page(mapsize), 0, VMFS_OPTIMAL_SPACE, VM_PROT_ALL,
	    VM_PROT_ALL, 0);
	if (error) {
		vm_object_deallocate(ef->object);
		ef->object = 0;
		goto out;
	}

	/* Wire the pages */
	error = vm_map_wire(kernel_map, mapbase,
	    mapbase + round_page(mapsize),
	    VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
	if (error != KERN_SUCCESS) {
		error = ENOMEM;
		goto out;
	}

	/* Inform the kld system about the situation */
	lf->address = ef->address = (caddr_t)mapbase;
	lf->size = mapsize;

	/*
	 * Now load code/data(progbits), zero bss(nobits), allocate space for
	 * and load relocs
	 */
	pb = 0;
	rl = 0;
	ra = 0;
	alignmask = 0;
	for (i = 0; i < hdr->e_shnum; i++) {
		if (shdr[i].sh_size == 0)
			continue;
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			alignmask = shdr[i].sh_addralign - 1;
			mapbase += alignmask;
			mapbase &= ~alignmask;
			if (ef->shstrtab && shdr[i].sh_name != 0)
				ef->progtab[pb].name =
				    ef->shstrtab + shdr[i].sh_name;
			else if (shdr[i].sh_type == SHT_PROGBITS)
				ef->progtab[pb].name = "<<PROGBITS>>";
			else
				ef->progtab[pb].name = "<<NOBITS>>";
			if (ef->progtab[pb].name != NULL && 
			    !strcmp(ef->progtab[pb].name, DPCPU_SETNAME))
				ef->progtab[pb].addr =
				    dpcpu_alloc(shdr[i].sh_size);
#ifdef VIMAGE
			else if (ef->progtab[pb].name != NULL &&
			    !strcmp(ef->progtab[pb].name, VNET_SETNAME))
				ef->progtab[pb].addr =
				    vnet_data_alloc(shdr[i].sh_size);
#endif
			else
				ef->progtab[pb].addr =
				    (void *)(uintptr_t)mapbase;
			if (ef->progtab[pb].addr == NULL) {
				error = ENOSPC;
				goto out;
			}
			ef->progtab[pb].size = shdr[i].sh_size;
			ef->progtab[pb].sec = i;
			if (shdr[i].sh_type == SHT_PROGBITS) {
				error = vn_rdwr(UIO_READ, nd.ni_vp,
				    ef->progtab[pb].addr,
				    shdr[i].sh_size, shdr[i].sh_offset,
				    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
				    NOCRED, &resid, td);
				if (error)
					goto out;
				if (resid != 0){
					error = EINVAL;
					goto out;
				}
				/* Initialize the per-cpu or vnet area. */
				if (ef->progtab[pb].addr != (void *)mapbase &&
				    !strcmp(ef->progtab[pb].name, DPCPU_SETNAME))
					dpcpu_copy(ef->progtab[pb].addr,
					    shdr[i].sh_size);
#ifdef VIMAGE
				else if (ef->progtab[pb].addr !=
				    (void *)mapbase &&
				    !strcmp(ef->progtab[pb].name, VNET_SETNAME))
					vnet_data_copy(ef->progtab[pb].addr,
					    shdr[i].sh_size);
#endif
			} else
				bzero(ef->progtab[pb].addr, shdr[i].sh_size);

			/* Update all symbol values with the offset. */
			for (j = 0; j < ef->ddbsymcnt; j++) {
				es = &ef->ddbsymtab[j];
				if (es->st_shndx != i)
					continue;
				es->st_value += (Elf_Addr)ef->progtab[pb].addr;
			}
			mapbase += shdr[i].sh_size;
			pb++;
			break;
		case SHT_REL:
			ef->reltab[rl].rel = malloc(shdr[i].sh_size, M_LINKER,
			    M_WAITOK);
			ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
			ef->reltab[rl].sec = shdr[i].sh_info;
			error = vn_rdwr(UIO_READ, nd.ni_vp,
			    (void *)ef->reltab[rl].rel,
			    shdr[i].sh_size, shdr[i].sh_offset,
			    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
			    &resid, td);
			if (error)
				goto out;
			if (resid != 0){
				error = EINVAL;
				goto out;
			}
			rl++;
			break;
		case SHT_RELA:
			ef->relatab[ra].rela = malloc(shdr[i].sh_size, M_LINKER,
			    M_WAITOK);
			ef->relatab[ra].nrela =
			    shdr[i].sh_size / sizeof(Elf_Rela);
			ef->relatab[ra].sec = shdr[i].sh_info;
			error = vn_rdwr(UIO_READ, nd.ni_vp,
			    (void *)ef->relatab[ra].rela,
			    shdr[i].sh_size, shdr[i].sh_offset,
			    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
			    &resid, td);
			if (error)
				goto out;
			if (resid != 0){
				error = EINVAL;
				goto out;
			}
			ra++;
			break;
		}
	}
	if (pb != ef->nprogtab)
		panic("lost progbits");
	if (rl != ef->nreltab)
		panic("lost reltab");
	if (ra != ef->nrelatab)
		panic("lost relatab");
	if (mapbase != (vm_offset_t)ef->address + mapsize)
		panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
		    (u_long)mapbase, ef->address, (u_long)mapsize,
		    (u_long)(vm_offset_t)ef->address + mapsize);

	/* Local intra-module relocations */
	link_elf_reloc_local(lf);

	/* Pull in dependencies */
	VOP_UNLOCK(nd.ni_vp, 0);
	error = linker_load_dependencies(lf);
	vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
	if (error)
		goto out;

	/* External relocations */
	error = relocate_file(ef);
	if (error)
		goto out;

	/* Notify MD code that a module is being loaded. */
	error = elf_cpu_load_file(lf);
	if (error)
		goto out;

	*result = lf;

out:
	VOP_UNLOCK(nd.ni_vp, 0);
	vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
	if (error && lf)
		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
	if (hdr)
		free(hdr, M_LINKER);

	return error;
}
Exemplo n.º 28
0
static int
vniocattach_file(struct vn_softc *vn,
		 struct vn_ioctl_64 *vniop,
		 dev_t dev,
		 int in_kernel,
		 proc_t p)
{
	dev_t	cdev;
	vfs_context_t ctx = vfs_context_current();
	kauth_cred_t cred;
	struct nameidata nd;
	off_t file_size;
	int error, flags;

	flags = FREAD|FWRITE;
	if (in_kernel) {
		NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, UIO_SYSSPACE, vniop->vn_file, ctx);
	}
	else {
		NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, 
			   (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), 
			   vniop->vn_file, ctx);
	}
	/* vn_open gives both long- and short-term references */
	error = vn_open(&nd, flags, 0);
	if (error) {
		if (error != EACCES && error != EPERM && error != EROFS) {
			return (error);
		}
		flags &= ~FWRITE;
		if (in_kernel) {
			NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, UIO_SYSSPACE, 
			       vniop->vn_file, ctx);
		}
		else {
			NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, 
				   (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), 
			       vniop->vn_file, ctx);
		}
		error = vn_open(&nd, flags, 0);
		if (error) {
			return (error);
		}
	}
	if (nd.ni_vp->v_type != VREG) {
		error = EINVAL;
	}
	else {
		error = vnode_size(nd.ni_vp, &file_size, ctx);
	}
	if (error != 0) {
		(void) vn_close(nd.ni_vp, flags, ctx);
		vnode_put(nd.ni_vp);
		return (error);
	}
	cred = kauth_cred_proc_ref(p);
	nd.ni_vp->v_flag |= VNOCACHE_DATA;
	error = setcred(nd.ni_vp, cred);
	if (error) {
		(void)vn_close(nd.ni_vp, flags, ctx);
		vnode_put(nd.ni_vp);
		kauth_cred_unref(&cred);
		return(error);
	}
	vn->sc_secsize = DEV_BSIZE;
	vn->sc_fsize = file_size;
	vn->sc_size = file_size / vn->sc_secsize;
	vn->sc_vp = nd.ni_vp;
	vn->sc_vid = vnode_vid(nd.ni_vp);
	vn->sc_open_flags = flags;
	vn->sc_cred = cred;
	cdev = makedev(vndevice_cdev_major, minor(dev));
	vn->sc_cdev = devfs_make_node(cdev, DEVFS_CHAR,
				      UID_ROOT, GID_OPERATOR, 
				      0600, "rvn%d", 
				      minor(dev));
	vn->sc_flags |= VNF_INITED;
	if (flags == FREAD)
		vn->sc_flags |= VNF_READONLY;
	/* lose the short-term reference */
	vnode_put(nd.ni_vp);
	return(0);
}
Exemplo n.º 29
0
/*
 * set up a quota file for a particular file system.
 */
int
lfsquota1_handle_cmd_quotaon(struct lwp *l, struct ulfsmount *ump, int type,
    const char *fname)
{
	struct mount *mp = ump->um_mountp;
	struct lfs *fs = ump->um_lfs;
	struct vnode *vp, **vpp;
	struct vnode_iterator *marker;
	struct dquot *dq;
	int error;
	struct pathbuf *pb;
	struct nameidata nd;

	if (fs->um_flags & ULFS_QUOTA2) {
		uprintf("%s: quotas v2 already enabled\n",
		    mp->mnt_stat.f_mntonname);
		return (EBUSY);
	}
		
	vpp = &ump->um_quotas[type];

	pb = pathbuf_create(fname);
	if (pb == NULL) {
		return ENOMEM;
	}
	NDINIT(&nd, LOOKUP, FOLLOW, pb);
	if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
		pathbuf_destroy(pb);
		return error;
	}
	vp = nd.ni_vp;
	pathbuf_destroy(pb);

	VOP_UNLOCK(vp);
	if (vp->v_type != VREG) {
		(void) vn_close(vp, FREAD|FWRITE, l->l_cred);
		return (EACCES);
	}
	if (*vpp != vp)
		lfsquota1_handle_cmd_quotaoff(l, ump, type);
	mutex_enter(&lfs_dqlock);
	while ((ump->umq1_qflags[type] & (QTF_CLOSING | QTF_OPENING)) != 0)
		cv_wait(&lfs_dqcv, &lfs_dqlock);
	ump->umq1_qflags[type] |= QTF_OPENING;
	mutex_exit(&lfs_dqlock);
	mp->mnt_flag |= MNT_QUOTA;
	vp->v_vflag |= VV_SYSTEM;	/* XXXSMP */
	*vpp = vp;
	/*
	 * Save the credential of the process that turned on quotas.
	 * Set up the time limits for this quota.
	 */
	kauth_cred_hold(l->l_cred);
	ump->um_cred[type] = l->l_cred;
	ump->umq1_btime[type] = MAX_DQ_TIME;
	ump->umq1_itime[type] = MAX_IQ_TIME;
	if (lfs_dqget(NULLVP, 0, ump, type, &dq) == 0) {
		if (dq->dq_btime > 0)
			ump->umq1_btime[type] = dq->dq_btime;
		if (dq->dq_itime > 0)
			ump->umq1_itime[type] = dq->dq_itime;
		lfs_dqrele(NULLVP, dq);
	}
	/*
	 * Search vnodes associated with this mount point,
	 * adding references to quota file being opened.
	 * NB: only need to add dquot's for inodes being modified.
	 */
	vfs_vnode_iterator_init(mp, &marker);
	while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) {
		error = vn_lock(vp, LK_EXCLUSIVE);
		if (error) {
			vrele(vp);
			continue;
		}
		mutex_enter(vp->v_interlock);
		if (VTOI(vp) == NULL || vp->v_type == VNON ||
		    vp->v_writecount == 0) {
			mutex_exit(vp->v_interlock);
			vput(vp);
			continue;
		}
		mutex_exit(vp->v_interlock);
		if ((error = lfs_getinoquota(VTOI(vp))) != 0) {
			vput(vp);
			break;
		}
		vput(vp);
	}
	vfs_vnode_iterator_destroy(marker);

	mutex_enter(&lfs_dqlock);
	ump->umq1_qflags[type] &= ~QTF_OPENING;
	cv_broadcast(&lfs_dqcv);
	if (error == 0)
		fs->um_flags |= ULFS_QUOTA;
	mutex_exit(&lfs_dqlock);
	if (error)
		lfsquota1_handle_cmd_quotaoff(l, ump, type);
	return (error);
}
Exemplo n.º 30
0
static void
spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
{
	size_t buflen;
	char *buf;
	vnode_t *vp;
	int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
	int error;
	char *temp;

	/*
	 * If the nvlist is empty (NULL), then remove the old cachefile.
	 */
	if (nvl == NULL) {
		(void) vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
		return;
	}

	/*
	 * Pack the configuration into a buffer.
	 */
	VERIFY(nvlist_size(nvl, &buflen, NV_ENCODE_XDR) == 0);

	buf = vmem_alloc(buflen, KM_SLEEP);
	temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP);

	VERIFY(nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_XDR,
	    KM_SLEEP) == 0);

#if defined(__linux__) && defined(_KERNEL)
	/*
	 * Write the configuration to disk.  Due to the complexity involved
	 * in performing a rename from within the kernel the file is truncated
	 * and overwritten in place.  In the event of an error the file is
	 * unlinked to make sure we always have a consistent view of the data.
	 */
	error = vn_open(dp->scd_path, UIO_SYSSPACE, oflags, 0644, &vp, 0, 0);
	if (error == 0) {
		error = vn_rdwr(UIO_WRITE, vp, buf, buflen, 0,
		    UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, NULL);
		if (error == 0)
			error = VOP_FSYNC(vp, FSYNC, kcred, NULL);

		(void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);

		if (error)
			(void) vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
	}
#else
	/*
	 * Write the configuration to disk.  We need to do the traditional
	 * 'write to temporary file, sync, move over original' to make sure we
	 * always have a consistent view of the data.
	 */
	(void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);

	error = vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0);
	if (error == 0) {
		if (vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
		    0, RLIM64_INFINITY, kcred, NULL) == 0 &&
		    VOP_FSYNC(vp, FSYNC, kcred, NULL) == 0) {
			(void) vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
		}
		(void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
	}

	(void) vn_remove(temp, UIO_SYSSPACE, RMFILE);
#endif

	vmem_free(buf, buflen);
	kmem_free(temp, MAXPATHLEN);
}