Example #1
0
static int
linux_unlink_dircheck(const char *path)
{
	struct nameidata nd;
	struct pathbuf *pb;
	int error;

	/*
	 * Linux returns EISDIR if unlink(2) is called on a directory.
	 * We return EPERM in such cases. To emulate correct behaviour,
	 * check if the path points to directory and return EISDIR if this
	 * is the case.
	 *
	 * XXX this should really not copy in the path buffer twice...
	 */
	error = pathbuf_copyin(path, &pb);
	if (error) {
		return error;
	}
	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
	if (namei(&nd) == 0) {
		struct stat sb;

		if (vn_stat(nd.ni_vp, &sb) == 0
		    && S_ISDIR(sb.st_mode))
			error = EISDIR;

		vput(nd.ni_vp);
	}
	pathbuf_destroy(pb);
	return error ? error : EPERM;
}
Example #2
0
int
linux_newstat(struct proc *p, struct linux_newstat_args *args)
{
    struct stat buf;
    struct nameidata nd;
    int error;
    caddr_t sg;

    sg = stackgap_init();
    CHECKALTEXIST(p, &sg, args->path);

#ifdef DEBUG
    printf("Linux-emul(%ld): newstat(%s, *)\n", (long)p->p_pid,
           args->path);
#endif

    NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
           args->path, p);
    error = namei(&nd);
    if (error)
        return (error);
    NDFREE(&nd, NDF_ONLY_PNBUF);

    error = vn_stat(nd.ni_vp, &buf, p);
    vput(nd.ni_vp);
    if (error)
        return (error);

    return (newstat_copyout(&buf, args->buf));
}
Example #3
0
/*
 * MPSAFE
 */
static int
vn_statfile(struct file *fp, struct stat *sb, struct ucred *cred)
{
	struct vnode *vp;
	int error;

	vp = (struct vnode *)fp->f_data;
	error = vn_stat(vp, sb, cred);
	return (error);
}
Example #4
0
/*
 * File table vnode stat routine.
 */
static int
vn_statfile(file_t *fp, struct stat *sb)
{
	struct vnode *vp = fp->f_data;
	int error;

	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
	error = vn_stat(vp, sb);
	VOP_UNLOCK(vp);
	return error;
}
Example #5
0
static int
verify_file(struct ucred *cred, struct vnode *vp)
{
	char buffer[256];
	char hash[SHA256_DIGEST_LENGTH > uECC_BYTES ? SHA256_DIGEST_LENGTH : uECC_BYTES];
	char signature[2*uECC_BYTES];

	int error, len;
	ssize_t resid;
	off_t i, size;
	SHA256_CTX ctx;
	struct stat stat;

	i = 0;
	error = vn_stat(vp, &stat, cred, NOCRED, curthread);
	size = stat.st_size;
	if (error)
		return (EPERM);

	len = sizeof(signature);
	error = vn_extattr_get(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM, 
	    "signature", &len, signature, curthread);
	if (error)
		return (EPERM);

#ifdef DEBUG
	printf("Signature: ");
	print_hex(signature, sizeof(signature));
#endif
	SHA256_Init(&ctx);
	while(i < size && !error) {
		len = size - i > sizeof(buffer) ? sizeof(buffer) : size - i;
		error = vn_rdwr(UIO_READ, vp, buffer, len, i,
		    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED,
		    &resid, curthread);
		SHA256_Update(&ctx, buffer, len);
		i += len;
	}
	if (error)
		return (EPERM);

	SHA256_Final(hash, &ctx);
#ifdef DEBUG
	printf("Hash: ");
	print_hex(hash, sizeof(hash));
#endif
	if (!uECC_verify(pubkey, hash, signature))
		return (EPERM);

	return (0);
}
Example #6
0
int
kern_file_size(struct file *fp, off_t *size)
{
        struct vnode *vp = (struct vnode *)fp->f_data;
        struct stat sb;
        int     rc;

        rc = vn_stat(vp, &sb, current_proc());
        if (rc) {
                *size = 0;
                return rc;
        }
        *size = sb.st_size;
        return 0;
}
Example #7
0
/*
 * fhstat_args(struct fhandle *u_fhp, struct dfbsd12_stat *sb)
 *
 * MPALMOSTSAFE
 */
int
sys_dfbsd12_fhstat(struct dfbsd12_fhstat_args *uap)
{
	struct thread *td = curthread;
	struct dfbsd12_stat osb;
	struct stat sb;
	fhandle_t fh;
	struct mount *mp;
	struct vnode *vp;
	int error;

	/*
	 * Must be super user
	 */
	error = priv_check(td, PRIV_ROOT);
	if (error)
		return (error);
	
	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
	if (error)
		return (error);

	get_mplock();
	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
		error = ESTALE;
		goto done;
	}
	if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)))
		goto done;
	error = vn_stat(vp, &sb, td->td_ucred);
	vput(vp);
	if (error)
		goto done;
	cvtstat(&osb, &sb);
	error = copyout(&osb, uap->sb, sizeof(osb));
done:
	rel_mplock();
	return (error);
}
int
compat_30_netbsd32_fhstat(struct lwp *l, const struct compat_30_netbsd32_fhstat_args *uap, register_t *retval)
{
	/* {
		syscallarg(const netbsd32_fhandlep_t) fhp;
		syscallarg(netbsd32_stat13p_t) sb;
	} */
	struct stat sb;
	struct netbsd32_stat13 sb32;
	int error;
	struct compat_30_fhandle fh;
	struct mount *mp;
	struct vnode *vp;

	/*
	 * Must be super user
	 */
	if ((error = kauth_authorize_system(l->l_cred,
	    KAUTH_SYSTEM_FILEHANDLE, 0, NULL, NULL, NULL)))
		return (error);

	if ((error = copyin(SCARG_P32(uap, fhp), &fh, sizeof(fh))) != 0)
		return (error);

	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
		return (ESTALE);
	if (mp->mnt_op->vfs_fhtovp == NULL)
		return EOPNOTSUPP;
	if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, &vp)))
		return (error);
	error = vn_stat(vp, &sb);
	vput(vp);
	if (error)
		return (error);
	netbsd32_from___stat13(&sb, &sb32);
	error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
	return (error);
}
Example #9
0
/*
 * File table wrapper for vn_stat
 */
int
vn_statfile(struct file *fp, struct stat *sb, struct proc *p)
{
	struct vnode *vp = (struct vnode *)fp->f_data;
	return vn_stat(vp, sb, p);
}
Example #10
0
int
maruioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
    ENTERSC(dev);
    DB("maruioctl(%d, %ld, %p, %d, %p)\n", dev, cmd, data, flag, p);
    switch (cmd)
	{
	    case MARUIOCATTACH:
		{
		    struct maru_ioc_attach *ma = (struct maru_ioc_attach *)data;
		    int fd = ma->ma_kue_fd;
		    struct filedesc *fdp = p->p_fd;
		    struct file *fp;
		    int err;
		    struct stat st;
		    struct kue_kapi *kapi;
		    
		    if (ma->ma_size < 512 * 16 * 32)
			EXITSC(EINVAL);
		    if (fd>=fdp->fd_nfiles || (fp=fdp->fd_ofiles[fd]) == NULL)
			EXITSC(EBADF);
		    if (fp->f_type != DTYPE_VNODE)
			EXITSC(ENOENT); /* some fool handed us a socket */
		    /* ok, so, this is cheating a little :) */
		    err = vn_stat((struct vnode *)fp->f_data, &st, p);
		    if (err)
			EXITSC(err);

		    /* pull in a pointer to the kue kernel api. we need
		     * this hack in order to avoid nasty limitations in netbsd's
		     * kernel linker: symbols from one module
		     * are not linked against symbols from another, only
		     * the kernel image. we splinter a little wood */
		    err = fp->f_ops->fo_ioctl(fp, KUEIOCGKAPI, (caddr_t)&kapi, p);
		    DB("post ioctl");
		    if (err)
			EXITSC(err);
		    DB("post ioctl:2");
		    /* now install our hooks of evil */
		    sc->sc_kapi = kapi;
		    DB("post ioctl:3");
		    kapi->ka_read2_hook = maru_kue_read2_callback;
		    DB("post ioctl:4");
		    kapi->ka_free_hook = maru_kue_free_callback;
		    kapi->ka_write_hook = maru_kue_write_callback;

		    disk_attach(&sc->sc_dkdev);
		    
		    memcpy(&sc->sc_size, &ma->ma_size, sizeof sc->sc_size);
		    sc->sc_flags|=MUF_INITED;
		    maru_getdisklabel(sc);
		}
		break;
	case DIOCGDINFO:
	    maru_getdefaultlabel(sc, (struct disklabel*)data);
	    break;
	case DIOCGPART:
	    ((struct partinfo *)data)->disklab = sc->sc_dkdev.dk_label;
	    ((struct partinfo *)data)->part =
		&sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
	    break;
	case DIOCWDINFO:
	case DIOCSDINFO:
	    {
		int err;
		sc->sc_flags |= MUF_LABELING; /* marustrategy maybe called by writedisklabel() */
		err = setdisklabel(sc->sc_dkdev.dk_label,
				   (struct disklabel *)data, 0, sc->sc_dkdev.dk_cpulabel);
		if (!err)
		    {
			if (cmd == DIOCWDINFO)
			    err = writedisklabel(MARULABELDEV(dev),
						 marustrategy, sc->sc_dkdev.dk_label,
						 sc->sc_dkdev.dk_cpulabel);
		    }
		
		sc->sc_flags &= ~MUF_LABELING;

		if (err)
			EXITSC(err);
	    }
	    break;
	case DIOCWLABEL:
	    if (*(int *)data != 0)
		sc->sc_flags |= MUF_WLABEL;
	    else
		sc->sc_flags &= ~MUF_WLABEL;
	    break;
	case DIOCGDEFLABEL:
	    maru_getdefaultlabel(sc, (struct disklabel*)data);
	    break;
	default:
	    return (ENOTTY);
	}
    EXITSC(0);
}
/* ARGSUSED */
int
compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval)
{
	/* {
		syscallarg(char *) path;
		syscallarg(struct ostat *) ub;
	} */
	struct vnode *vp, *dvp;
	struct stat sb, sb1;
	struct stat43 osb;
	int error;
	struct pathbuf *pb;
	struct nameidata nd;
	int ndflags;

	error = pathbuf_copyin(SCARG(uap, path), &pb);
	if (error) {
		return error;
	}

	ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT | TRYEMULROOT;
again:
	NDINIT(&nd, LOOKUP, ndflags, pb);
	if ((error = namei(&nd))) {
		if (error == EISDIR && (ndflags & LOCKPARENT) != 0) {
			/*
			 * Should only happen on '/'. Retry without LOCKPARENT;
			 * this is safe since the vnode won't be a VLNK.
			 */
			ndflags &= ~LOCKPARENT;
			goto again;
		}
		pathbuf_destroy(pb);
		return (error);
	}
	/*
	 * For symbolic links, always return the attributes of its
	 * containing directory, except for mode, size, and links.
	 */
	vp = nd.ni_vp;
	dvp = nd.ni_dvp;
	pathbuf_destroy(pb);
	if (vp->v_type != VLNK) {
		if ((ndflags & LOCKPARENT) != 0) {
			if (dvp == vp)
				vrele(dvp);
			else
				vput(dvp);
		}
		error = vn_stat(vp, &sb);
		vput(vp);
		if (error)
			return (error);
	} else {
		error = vn_stat(dvp, &sb);
		vput(dvp);
		if (error) {
			vput(vp);
			return (error);
		}
		error = vn_stat(vp, &sb1);
		vput(vp);
		if (error)
			return (error);
		sb.st_mode &= ~S_IFDIR;
		sb.st_mode |= S_IFLNK;
		sb.st_nlink = sb1.st_nlink;
		sb.st_size = sb1.st_size;
		sb.st_blocks = sb1.st_blocks;
	}
	cvtstat(&sb, &osb);
	error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
	return (error);
}
Example #12
0
/*
 * module_load_plist_vfs:
 *
 *	Load a plist located in the file system into memory.
 */
static int
module_load_plist_vfs(const char *modpath, const bool nochroot,
    prop_dictionary_t *filedictp)
{
	struct pathbuf *pb;
	struct nameidata nd;
	struct stat sb;
	void *base;
	char *proppath;
	const size_t plistsize = 8192;
	size_t resid;
	int error, pathlen;

	KASSERT(filedictp != NULL);
	base = NULL;

	proppath = PNBUF_GET();
	strcpy(proppath, modpath);
	pathlen = strlen(proppath);
	if ((pathlen >= 6) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) {
		strcpy(&proppath[pathlen - 5], ".plist");
	} else if (pathlen < MAXPATHLEN - 6) {
			strcat(proppath, ".plist");
	} else {
		error = ENOENT;
		goto out1;
	}

	/* XXX this makes an unnecessary extra copy of the path */
	pb = pathbuf_create(proppath);
	if (pb == NULL) {
		error = ENOMEM;
		goto out1;
	}
	
	NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), pb);

	error = vn_open(&nd, FREAD, 0);
 	if (error != 0) {
	 	goto out2;
	}

	error = vn_stat(nd.ni_vp, &sb);
	if (error != 0) {
		goto out3;
	}
	if (sb.st_size >= (plistsize - 1)) {	/* leave space for term \0 */
		error = EFBIG;
		goto out3;
	}

	base = kmem_alloc(plistsize, KM_SLEEP);
	if (base == NULL) {
		error = ENOMEM;
		goto out3;
	}

	error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0,
	    UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp);
	*((uint8_t *)base + sb.st_size) = '\0';
	if (error == 0 && resid != 0) {
		error = EFBIG;
	}
	if (error != 0) {
		kmem_free(base, plistsize);
		base = NULL;
		goto out3;
	}

	*filedictp = prop_dictionary_internalize(base);
	if (*filedictp == NULL) {
		error = EINVAL;
	}
	kmem_free(base, plistsize);
	base = NULL;
	KASSERT(error == 0);

out3:
	VOP_UNLOCK(nd.ni_vp);
	vn_close(nd.ni_vp, FREAD, kauth_cred_get());

out2:
	pathbuf_destroy(pb);

out1:
	PNBUF_PUT(proppath);
	return error;
}
Example #13
0
static int
devfs_fo_stat(struct file *fp, struct stat *sb, struct ucred *cred)
{
	struct vnode *vp;
	struct vattr vattr;
	struct vattr *vap;
	u_short mode;
	cdev_t dev;
	int error;

	vp = (struct vnode *)fp->f_data;
	if (vp == NULL || vp->v_type == VBAD)
		return EBADF;

	error = vn_stat(vp, sb, cred);
	if (error)
		return (error);

	vap = &vattr;
	error = VOP_GETATTR(vp, vap);
	if (error)
		return (error);

	/*
	 * Zero the spare stat fields
	 */
	sb->st_lspare = 0;
	sb->st_qspare1 = 0;
	sb->st_qspare2 = 0;

	/*
	 * Copy from vattr table ... or not in case it's a cloned device
	 */
	if (vap->va_fsid != VNOVAL)
		sb->st_dev = vap->va_fsid;
	else
		sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0];

	sb->st_ino = vap->va_fileid;

	mode = vap->va_mode;
	mode |= S_IFCHR;
	sb->st_mode = mode;

	if (vap->va_nlink > (nlink_t)-1)
		sb->st_nlink = (nlink_t)-1;
	else
		sb->st_nlink = vap->va_nlink;

	sb->st_uid = vap->va_uid;
	sb->st_gid = vap->va_gid;
	sb->st_rdev = dev2udev(DEVFS_NODE(vp)->d_dev);
	sb->st_size = vap->va_bytes;
	sb->st_atimespec = vap->va_atime;
	sb->st_mtimespec = vap->va_mtime;
	sb->st_ctimespec = vap->va_ctime;

	/*
	 * A VCHR and VBLK device may track the last access and last modified
	 * time independantly of the filesystem.  This is particularly true
	 * because device read and write calls may bypass the filesystem.
	 */
	if (vp->v_type == VCHR || vp->v_type == VBLK) {
		dev = vp->v_rdev;
		if (dev != NULL) {
			if (dev->si_lastread) {
				sb->st_atimespec.tv_sec = time_second +
							  (time_uptime -
							   dev->si_lastread);
				sb->st_atimespec.tv_nsec = 0;
			}
			if (dev->si_lastwrite) {
				sb->st_atimespec.tv_sec = time_second +
							  (time_uptime -
							   dev->si_lastwrite);
				sb->st_atimespec.tv_nsec = 0;
			}
		}
	}

        /*
	 * According to www.opengroup.org, the meaning of st_blksize is
	 *   "a filesystem-specific preferred I/O block size for this
	 *    object.  In some filesystem types, this may vary from file
	 *    to file"
	 * Default to PAGE_SIZE after much discussion.
	 */

	sb->st_blksize = PAGE_SIZE;

	sb->st_flags = vap->va_flags;

	error = priv_check_cred(cred, PRIV_VFS_GENERATION, 0);
	if (error)
		sb->st_gen = 0;
	else
		sb->st_gen = (u_int32_t)vap->va_gen;

	sb->st_blocks = vap->va_bytes / S_BLKSIZE;

	return (0);
}