Example #1
0
asmlinkage long sys_chroot(const char * filename)
{
	int error;
	struct nameidata nd;
	char *name;

	name = getname(filename);
	error = PTR_ERR(name);
	if (IS_ERR(name))
		goto out;

	path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
		      LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
	error = path_walk(name, &nd);	
	putname(name);
	if (error)
		goto out;

	error = permission(nd.dentry->d_inode,MAY_EXEC);
	if (error)
		goto dput_and_out;

	error = -EPERM;
	if (!capable(CAP_SYS_CHROOT))
		goto dput_and_out;

	set_fs_root(current->fs, nd.mnt, nd.dentry);
	set_fs_altroot();
	error = 0;
dput_and_out:
	path_release(&nd);
out:
	return error;
}
Example #2
0
int
dm_path_to_fshdl(
	char		*path,		/* any path name */
	void		*hanp,		/* user's data buffer */
	size_t		*hlenp)		/* set to size of data copied */
{
	/* REFERENCED */
	dm_fsreg_t	*fsrp;
	xfs_handle_t	handle;
	vnode_t		*vp;
	size_t		hlen;
	int		error;
	int		lc;		/* lock cookie */
	struct nameidata nd;
	struct inode *inode;
	size_t		len;
	char		*name;

	/* XXX get things straightened out so getname() works here? */
	len = strnlen_user(path, 2000);
	name = kmem_alloc(len, KM_SLEEP);
	if (copy_from_user(name, path, len))
		return(EFAULT);

	error = 0;
	if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd))
		error = path_walk(name, &nd);
	if (error)
		return error;
	kmem_free(name, len);

	ASSERT(nd.dentry);
	ASSERT(nd.dentry->d_inode);

	inode = igrab(nd.dentry->d_inode);
	path_release(&nd);

	/* we need the vnode */
	vp = LINVFS_GET_VP(inode);
	if (!vp || !vp->v_vfsp->vfs_altfsid) {
		/* we're not in XFS anymore, Toto */
		iput(inode);
		return EINVAL;
	}

	error = dm_vp_to_handle(vp, &handle);
	iput(inode);/*was VN_RELE(vp);*/

	if (error)
		return(error);

	if ((fsrp = dm_find_fsreg_and_lock((fsid_t*)&handle.ha_fsid, &lc)) == NULL)
		return(EBADF);
	mutex_spinunlock(&fsrp->fr_lock, lc);

	hlen = FSHSIZE;
	if(copy_to_user(hanp, &handle, (int)hlen))
		return(EFAULT);
	return(put_user(hlen,hlenp));
}
Example #3
0
asmlinkage long sys_chdir(const char * filename)
{
	int error;
	struct nameidata nd;
	char *name;

	name = getname(filename);
	error = PTR_ERR(name);
	if (IS_ERR(name))
		goto out;

	error = 0;
	if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))
		error = path_walk(name, &nd);
	putname(name);
	if (error)
		goto out;

	error = permission(nd.dentry->d_inode,MAY_EXEC);
	if (error)
		goto dput_and_out;

	set_fs_pwd(current->fs, nd.mnt, nd.dentry);

dput_and_out:
	path_release(&nd);
out:
	return error;
}
Example #4
0
/* Lookup name and return vnode for same. */
int
osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
                        struct dentry **dpp)
{
    int code;
    struct nameidata nd;
    int flags = LOOKUP_POSITIVE;
    code = ENOENT;

    if (followlink)
        flags |= LOOKUP_FOLLOW;
    if (path_init(aname, flags, &nd))
        code = path_walk(aname, &nd);

    if (!code) {
#if defined(STRUCT_NAMEIDATA_HAS_PATH)
        *dpp = dget(nd.path.dentry);
        if (mnt)
            *mnt = mntget(nd.path.mnt);
        path_put(&nd.path);
#else
        *dpp = dget(nd.dentry);
        if (mnt)
            *mnt = mntget(nd.mnt);
        path_release(&nd);
#endif
    }
    return code;
}
Example #5
0
/* XXX: this function is utterly bogus.  Every use of it is racy and the
        prototype is stupid.  You have been warned.  --hch.  */
hwgfs_handle_t
hwgfs_find_handle(
	hwgfs_handle_t		base,
	const char		*name,
	unsigned int		major,		/* IGNORED */
	unsigned int		minor,		/* IGNORED */
	char			type,		/* IGNORED */
	int			traverse_symlinks)
{
	struct dentry		*dentry = NULL;
	struct nameidata	nd;
	int			error;

	BUG_ON(*name=='/');

	memset(&nd, 0, sizeof(nd));

	nd.mnt = mntget(hwgfs_vfsmount);
	nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root);
	nd.flags = (traverse_symlinks ? LOOKUP_FOLLOW : 0);

	error = path_walk(name, &nd);
	if (likely(!error)) {
		dentry = nd.dentry;
		path_release(&nd);		/* stale data from here! */
	}

	return dentry;
}
Example #6
0
/* On success, returns with parent_inode->i_sem taken. */
static int
hwgfs_decode(
	hwgfs_handle_t		dir,
	const char		*name,
	int			is_dir,
	struct inode		**parent_inode,
	struct dentry		**dentry)
{
	struct nameidata	nd;
	int			error;

	if (!dir)
		dir = hwgfs_vfsmount->mnt_sb->s_root;

	memset(&nd, 0, sizeof(nd));
	nd.flags = LOOKUP_PARENT;
	nd.mnt = mntget(hwgfs_vfsmount);
	nd.dentry = dget(dir);

	error = walk_parents_mkdir(&name, &nd, is_dir);
	if (unlikely(error))
		return error;

	error = path_walk(name, &nd);
	if (unlikely(error))
		return error;

	*dentry = lookup_create(&nd, is_dir);

	if (IS_ERR(*dentry))
		return PTR_ERR(*dentry);
	*parent_inode = (*dentry)->d_parent->d_inode;
	return 0;
}
Example #7
0
static struct file *do_open(char *name, int flags)
{
	struct nameidata nd;
	int error;

	nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);

	if (IS_ERR(nd.mnt))
		return (struct file *)nd.mnt;

	nd.dentry = dget(nd.mnt->mnt_root);
	nd.last_type = LAST_ROOT;
	nd.flags = 0;
	nd.depth = 0;

	error = path_walk(name, &nd);
	if (error)
		return ERR_PTR(error);

	if (flags == O_RDWR)
		error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE);
	else
		error = may_open(&nd, MAY_WRITE, FMODE_WRITE);

	if (!error)
		return dentry_open(nd.dentry, nd.mnt, flags);

	path_release(&nd);
	return ERR_PTR(error);
}
Example #8
0
// Deletes a file.
//
int
unlink(const char *path)
{
	int r;
	struct Inode *dirino, *ino;
	struct Direntry *de;

	if ((r = path_walk(path, &dirino, &de, 0)) < 0)
		goto done;
	if ((r = inode_open(de->de_inum, &ino)) < 0)
		goto closedirino;
	if (ino->i_ftype == FTYPE_DIR) {
		r = -E_IS_DIR;
		goto closeino;
	}
	// clear directory entry
	de->de_inum = 0;
	--ino->i_refcount;
	bcache_ipc(de, BCREQ_FLUSH);
	bcache_ipc(ino, BCREQ_FLUSH);
	r = 0;
 closeino:
	inode_close(ino);
 closedirino:
	inode_close(dirino);
 done:
	return r;
}
Example #9
0
static inline int translucent_is_whiteout2(char *path) {
        int i_Ret;
        struct nameidata n;
        path_init(path, 0, &n);
        i_Ret=path_walk(path, &n);
        if(i_Ret) return 0;
        i_Ret=translucent_is_whiteout(&n);
        path_release(&n);
        return i_Ret;
}
Example #10
0
File: redir.c Project: lb1a/avfs
static int a_path_walk(const char *pathname, int flags, struct nameidata *nd)
{
	int error;

	error = 0;
	if (path_init(pathname, flags, nd))
		error = path_walk(pathname, nd);

	return error;
}
Example #11
0
int presto_walk(const char *name, struct nameidata *nd)
{
        int err;
        /* we do not follow symlinks to support symlink operations 
           correctly. The vfs should always hand us resolved dentries
           so we should not be required to use LOOKUP_FOLLOW. At the
           reintegrating end, lento again should be working with the 
           resolved pathname and not the symlink. SHP
           XXX: This code implies that direct symlinks do not work. SHP
        */
        unsigned int flags = LOOKUP_POSITIVE;

        ENTRY;
        err = 0;
        if (path_init(name, flags, nd)) 
                err = path_walk(name, nd);
        return err;
}
Example #12
0
static int
walk_parents_mkdir(
	const char		**path,
	struct nameidata	*nd,
	int			is_dir)
{
	char			*slash;
	char			buf[strlen(*path)+1];
	int			error;

	while ((slash = strchr(*path, '/')) != NULL) {
		int len = slash - *path;
		memcpy(buf, *path, len);
		buf[len] = '\0';

		error = path_walk(buf, nd);
		if (unlikely(error))
			return error;

		nd->dentry = lookup_create(nd, is_dir);
		nd->flags |= LOOKUP_PARENT;
		if (IS_ERR(nd->dentry))
			return PTR_ERR(nd->dentry);

		if (!nd->dentry->d_inode)
			error = vfs_mkdir(nd->dentry->d_parent->d_inode,
					nd->dentry, 0755);
		
		up(&nd->dentry->d_parent->d_inode->i_sem);
		if (unlikely(error))
			return error;

		*path += len + 1;
	}

	return 0;
}
Example #13
0
// Open a file (or directory).
//
// Returns:
// 	The file descriptor index on success
// 	-E_BAD_PATH if the path is too long (>= MAXPATHLEN)
//	-E_BAD_PATH if an intermediate path component is not a directory
//	-E_MAX_FD if no more file descriptors
//	-E_NOT_FOUND if the file (or a path component) was not found
//	(and others)
int
open(const char *path, int mode)
{
	// Find an unused file descriptor page using fd_find_unused
	// and allocate a page there (PTE_P|PTE_U|PTE_W|PTE_SHARE).
	//
	// LAB 5: Your code here
    int r;
    struct Fd *fd;
    if((r = fd_find_unused(&fd)) < 0 || 
    (r = sys_page_alloc(0, fd, PTE_P|PTE_U|PTE_W|PTE_SHARE)) < 0)
        goto err1;
	// Check the pathname.  Error if too long.
	// Use path_walk to find the corresponding directory entry.
	// If '(mode & O_CREAT) == 0' (Exercise 4),
	//   Return -E_NOT_FOUND if the file is not found.
	//   Otherwise, use inode_open to open the inode.
	// If '(mode & O_CREAT) != 0' (Exercise 7),
	//   Create the file if it doesn't exist yet.
	//   Allocate a new inode, initialize its fields, and
	//   reference that inode from the new directory entry.
	//   Flush any blocks you change.
	// Directories can be opened, but only as read-only:
	// return -E_IS_DIR if '(mode & O_ACCMODE) != O_RDONLY'.
	//
	// Check for errors.  On error, make sure you clean up any
	// allocated objects.
	//
	// The root directory is a special case -- if you aren't careful,
	// you will deadlock when the root directory is opened.  (Why?)
	//
	// LAB 5: Your code here.
    int i;
    for(i = 0; i < MAXNAMELEN && path[i]; i++); 
    if(i == MAXNAMELEN)
    {
        r = -E_BAD_PATH;
        goto err2;
    }
    struct Inode *dirino;
    struct Direntry *de;
    if((r = path_walk(path, &dirino, &de, mode & O_CREAT)))
        goto err2;
    struct Inode *fileino;
    
    if(!(mode & O_CREAT))
    {
        if(de == &super->s_root)
            fileino = dirino;
        else if((r = inode_open(de->de_inum, &fileino)) < 0)
            goto err3;
        
        if(fileino->i_ftype == FTYPE_DIR && (
           mode & O_ACCMODE) != O_RDONLY)
        {
            r = -E_IS_DIR;
            goto err4;
        }
    }
    else 
    {
        if((r = inode_alloc(&fileino)) < 0)
            goto err3;
        fileino->i_ftype = FTYPE_REG;
        fileino->i_refcount = 1;
        fileino->i_size = 0;
        memset(&fileino->i_direct, 0, NDIRECT * sizeof (blocknum_t));
        de->de_inum = fileino->i_inum;
        bcache_ipc(fileino, BCREQ_FLUSH); 
        bcache_ipc(dirino, BCREQ_FLUSH); 
    }
	// If '(mode & O_TRUNC) != 0' and the open mode is not read-only,
	// set the file's length to 0.  Flush any blocks you change.
	//
	// LAB 5: Your code here (Exercise 8).
    if((mode & O_TRUNC))
    {
        inode_set_size(fileino, 0);
    }        

	// The open has succeeded.
	// Fill in all parts of the 'fd' appropriately.  Use 'devfile.dev_id'.
	// Copy the file's pathname into 'fd->fd_file.open_path' to improve
	// error messages later.
	// You must account for the open file reference in the inode as well.
	// Clean up any open inodes.
	//
	// LAB 5: Your code here (Exercise 4).
    fd->fd_dev_id = devfile.dev_id;
    fd->fd_offset = 0;
    fd->fd_omode = mode;
    fd->fd_file.inum = fileino->i_inum; 
    strcpy(fd->fd_file.open_path, path);
    fileino->i_opencount++;
    inode_close(dirino);
    inode_close(fileino);
    return fd2num(fd);

err4:
    inode_close(fileino);
err3:
    inode_close(dirino);
err2:
    sys_page_unmap(thisenv->env_id, fd);
err1:
    return r;
}
Example #14
0
static void do_dir_line (tux_req_t *req, int cachemiss)
{
	struct linux_dirent64 *dirp, *dirp0;
	char string0[MAX_OBJECTNAME_LEN+200], *tmp;
	int len, curroff, total, str_len = 0;
	int err, flag = cachemiss ? 0 : LOOKUP_ATOMIC;
	struct nameidata base = { };
	struct dentry *dentry = NULL;
	struct inode *inode = NULL;
	struct vfsmount *mnt = NULL;

	if (req->proto->check_req_err(req, cachemiss))
		return;

	tmp = NULL;
	dirp0 = req->dirp0;
	curroff = req->curroff;
	total = req->total;

	dirp = (struct linux_dirent64 *)((char *)dirp0 + curroff);
	if (!dirp->d_name || !dirp->d_name[0])
		goto next_dir;
	/*
	 * Hide .xxxxx files:
	 */
	if (dirp->d_name[0] == '.')
		goto next_dir;
	Dprintk("<%s T:%d (off:%Ld) (len:%d)>\n", dirp->d_name, dirp->d_type, dirp->d_off, dirp->d_reclen);
	if (tux_hide_unreadable) {
		switch (dirp->d_type) {
			default:
				goto next_dir;
			case DT_UNKNOWN:
			case DT_REG:
			case DT_DIR:
			case DT_LNK:
			/* valid entries - fall through. */
				;
		}
	}
	len = strlen(dirp->d_name);
	if (len >= MAX_OBJECTNAME_LEN) {
		dirp->d_name[MAX_OBJECTNAME_LEN] = 0;
		len = MAX_OBJECTNAME_LEN-1;
	}

	if (!req->dentry)
		TUX_BUG();

	base.flags = flag;
	base.last_type = LAST_ROOT;
	base.dentry = dget(req->dentry);
	base.mnt = mntget(req->cwd_mnt);

	switch_docroot(req);
	err = path_walk(dirp->d_name, &base);

	Dprintk("path_walk() returned %d.\n", err);

	if (err) {
		if (err == -EWOULDBLOCKIO) {
			add_tux_atom(req, do_dir_line);
			queue_cachemiss(req);
			return;
		}
		goto next_dir;
	}

	dentry = base.dentry;
	mnt = base.mnt;
	if (!dentry)
		TUX_BUG();
	if (IS_ERR(dentry))
		TUX_BUG();
	inode = dentry->d_inode;
	if (!inode)
		TUX_BUG();
	if (!dirp->d_type)
		dirp->d_type = get_d_type(dentry);
	if (tux_hide_unreadable) {
		umode_t mode;

		mode = inode->i_mode;
		if (mode & tux_mode_forbidden)
			goto out_dput;
		if (!(mode & tux_mode_allowed))
			goto out_dput;

		err = permission(inode, MAY_READ, NULL);
		if (err)
			goto out_dput;
		if (dirp->d_type == DT_DIR) {
			err = permission(inode, MAY_EXEC, NULL);
			if (err)
				goto out_dput;
		}
	}

	tmp = req->proto->print_dir_line(req, string0, dirp->d_name, len, dirp->d_type, dentry, inode);
	if (tmp)
		str_len = tmp-string0;
out_dput:
	dput(dentry);
	mntput(mnt);
next_dir:
	curroff += dirp->d_reclen;

	if (tmp && (tmp != string0))
		Dprintk("writing line (len: %d): <%s>\n", strlen(string0), string0);

	if (curroff < total) {
		req->dirp0 = dirp0;
		req->curroff = curroff;
		add_tux_atom(req, do_dir_line);
	} else {
		kfree(dirp0);
		req->dirp0 = NULL;
		req->curroff = 0;
		// falls back to the list_directory atom
	}
	if (tmp && (tmp != string0))
		__send_async_message(req, string0, 200, str_len, 0);
	else
		add_req_to_workqueue(req);
}