コード例 #1
0
ファイル: dir.c プロジェクト: JBTech/ralink_rt5350
/*
 * Return a path relative to our root.
 */
char * umsdos_d_path(struct dentry *dentry, char * buffer, int len)
{
	struct dentry * old_root;
	char * path;

	read_lock(&current->fs->lock);
	old_root = dget(current->fs->root);
	read_unlock(&current->fs->lock);
	spin_lock(&dcache_lock);
	path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */
	spin_unlock(&dcache_lock);

	if (IS_ERR(path))
		return path;

	if (*path == '/')
		path++; /* skip leading '/' */

	if (current->fs->root->d_inode == pseudo_root)
	{
		*(path-1) = '/';
		path -= (UMSDOS_PSDROOT_LEN+1);
		memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);
	}
	dput(old_root);

	return path;
}
コード例 #2
0
static int _xx_realpath_from_path(struct path *path, char *newname,
				  int newname_len)
{
	struct dentry *dentry = path->dentry;
	int error = -ENOMEM;
	char *sp;

	if (!dentry || !path->mnt || !newname || newname_len <= 2048)
		return -EINVAL;
	if (dentry->d_op && dentry->d_op->d_dname) {
		/* For "socket:[\$]" and "pipe:[\$]". */
		static const int offset = 1536;
		sp = dentry->d_op->d_dname(dentry, newname + offset,
					   newname_len - offset);
	} else {
		/* Taken from d_namespace_path(). */
		struct path ns_root = { };
		struct path root;
		struct path tmp;

		read_lock(&current->fs->lock);
		root = current->fs->root;
		path_get(&root);
		read_unlock(&current->fs->lock);
		spin_lock(&vfsmount_lock);
		if (root.mnt && root.mnt->mnt_ns)
			ns_root.mnt = mntget(root.mnt->mnt_ns->root);
		if (ns_root.mnt)
			ns_root.dentry = dget(ns_root.mnt->mnt_root);
		spin_unlock(&vfsmount_lock);
		spin_lock(&dcache_lock);
		tmp = ns_root;
		sp = __d_path(path, &tmp, newname, newname_len);
		spin_unlock(&dcache_lock);
		path_put(&root);
		path_put(&ns_root);
	}
	if (IS_ERR(sp)) {
		error = PTR_ERR(sp);
	} else {
		error = _xx_encode(newname, sp - newname, sp);
	}
#if 1
	/* Append trailing '/' if dentry is a directory. */
	if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
	    && *newname) {
		sp = newname + strlen(newname);
		if (*(sp - 1) != '/') {
			if (sp < newname + newname_len - 4) {
				*sp++ = '/';
				*sp = '\0';
			} else {
				error = -ENOMEM;
			}
		}
	}
#endif
	return error;
}
コード例 #3
0
int _xx_realpath_from_path(struct path *path, char *newname,
                           int newname_len)
{
	int error = -ENOMEM;
	struct dentry *dentry = path->dentry;
	char *sp;

	if (!dentry || !path->mnt || !newname || newname_len <= 2048)
		return -EINVAL;
	if (dentry->d_op && dentry->d_op->d_dname) {
		/* For "socket:[\$]" and "pipe:[\$]". */
		static const int offset = 1536;
		sp = dentry->d_op->d_dname(dentry, newname + offset,
		                           newname_len - offset);
	} else {
		struct path ns_root = {.mnt = NULL, .dentry = NULL};

		spin_lock(&dcache_lock);
		/* go to whatever namespace root we are under */
		sp = __d_path(path, &ns_root, newname, newname_len);
		spin_unlock(&dcache_lock);
		/* Prepend "/proc" prefix if using internal proc vfs mount. */
		if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
		    (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
			sp -= 5;
			if (sp >= newname)
				memcpy(sp, "/proc", 5);
			else
			
	sp = ERR_PTR(-ENOMEM);
		}
	}
	if (IS_ERR(sp))
		error = PTR_ERR(sp);
	else
		error = _xx_encode(newname, sp - newname, sp);
	/* Append trailing '/' if dentry is a directory. */
	if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
	    && *newname) {
		sp = newname + strlen(newname);
		if (*(sp - 1) != '/') {
			if (sp < newname + newname_len - 4) {
				*sp++ = '/';
				*sp = '\0';
			} else {
				error = -ENOMEM;
			}
		}
	}
	return error;
}
コード例 #4
0
ファイル: realpath.c プロジェクト: CSCLOG/beaglebone
/**
 * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
 *
 * @path:   Pointer to "struct path".
 * @buffer: Pointer to buffer to return value in.
 * @buflen: Sizeof @buffer.
 *
 * Returns the buffer on success, an error code otherwise.
 *
 * If dentry is a directory, trailing '/' is appended.
 */
static char *tomoyo_get_absolute_path(struct path *path, char * const buffer,
				      const int buflen)
{
	char *pos = ERR_PTR(-ENOMEM);
	if (buflen >= 256) {
		struct path ns_root = { };
		/* go to whatever namespace root we are under */
		pos = __d_path(path, &ns_root, buffer, buflen - 1);
		if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
			struct inode *inode = path->dentry->d_inode;
			if (inode && S_ISDIR(inode->i_mode)) {
				buffer[buflen - 2] = '/';
				buffer[buflen - 1] = '\0';
			}
		}
	}
	return pos;
}
コード例 #5
0
char * tux_print_path (tux_req_t *req, struct dentry *dentry, struct vfsmount *mnt, char *buf, unsigned int max_len)
{
	char *res;
	struct dentry *cwd, *root;
	struct vfsmount *cwd_mnt, *rootmnt;

	cwd = dget(dentry);
	cwd_mnt = mntget(mnt);
	root = dget(req->docroot_dentry);
	rootmnt = mntget(req->docroot_mnt);

	spin_lock(&dcache_lock);
	res = __d_path(cwd, cwd_mnt, root, rootmnt, buf, max_len);
	spin_unlock(&dcache_lock);

	dput(cwd);
	mntput(cwd_mnt);
	dput(root);
	mntput(rootmnt);

	return res;
}
コード例 #6
0
ファイル: path.c プロジェクト: CSCLOG/beaglebone
/**
 * d_namespace_path - lookup a name associated with a given path
 * @path: path to lookup  (NOT NULL)
 * @buf:  buffer to store path to  (NOT NULL)
 * @buflen: length of @buf
 * @name: Returns - pointer for start of path name with in @buf (NOT NULL)
 * @flags: flags controlling path lookup
 *
 * Handle path name lookup.
 *
 * Returns: %0 else error code if path lookup fails
 *          When no error the path name is returned in @name which points to
 *          to a position in @buf
 */
static int d_namespace_path(struct path *path, char *buf, int buflen,
			    char **name, int flags)
{
	struct path root, tmp;
	char *res;
	int connected, error = 0;

	/* Get the root we want to resolve too, released below */
	if (flags & PATH_CHROOT_REL) {
		/* resolve paths relative to chroot */
		get_fs_root(current->fs, &root);
	} else {
		/* resolve paths relative to namespace */
		root.mnt = current->nsproxy->mnt_ns->root;
		root.dentry = root.mnt->mnt_root;
		path_get(&root);
	}

	tmp = root;
	res = __d_path(path, &tmp, buf, buflen);

	*name = res;
	/* handle error conditions - and still allow a partial path to
	 * be returned.
	 */
	if (IS_ERR(res)) {
		error = PTR_ERR(res);
		*name = buf;
		goto out;
	}

	/* Handle two cases:
	 * 1. A deleted dentry && profile is not allowing mediation of deleted
	 * 2. On some filesystems, newly allocated dentries appear to the
	 *    security_path hooks as a deleted dentry except without an inode
	 *    allocated.
	 */
	if (d_unlinked(path->dentry) && path->dentry->d_inode &&
	    !(flags & PATH_MEDIATE_DELETED)) {
			error = -ENOENT;
			goto out;
	}

	/* Determine if the path is connected to the expected root */
	connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;

	/* If the path is not connected,
	 * check if it is a sysctl and handle specially else remove any
	 * leading / that __d_path may have returned.
	 * Unless
	 *     specifically directed to connect the path,
	 * OR
	 *     if in a chroot and doing chroot relative paths and the path
	 *     resolves to the namespace root (would be connected outside
	 *     of chroot) and specifically directed to connect paths to
	 *     namespace root.
	 */
	if (!connected) {
		/* is the disconnect path a sysctl? */
		if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
		    strncmp(*name, "/sys/", 5) == 0) {
			/* TODO: convert over to using a per namespace
			 * control instead of hard coded /proc
			 */
			error = prepend(name, *name - buf, "/proc", 5);
		} else if (!(flags & PATH_CONNECT_PATH) &&
			   !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
			     (tmp.mnt == current->nsproxy->mnt_ns->root &&
			      tmp.dentry == tmp.mnt->mnt_root))) {
			/* disconnected path, don't return pathname starting
			 * with '/'
			 */
			error = -ESTALE;
			if (*res == '/')
				*name = res + 1;
		}
	}

out:
	path_put(&root);

	return error;
}
コード例 #7
0
/**
 * d_namespace_path - lookup a name associated with a given path
 * @path: path to lookup  (NOT NULL)
 * @buf:  buffer to store path to  (NOT NULL)
 * @buflen: length of @buf
 * @name: Returns - pointer for start of path name with in @buf (NOT NULL)
 * @flags: flags controlling path lookup
 *
 * Handle path name lookup.
 *
 * Returns: %0 else error code if path lookup fails
 *          When no error the path name is returned in @name which points to
 *          to a position in @buf
 */
static int d_namespace_path(struct path *path, char *buf, int buflen,
			    char **name, int flags)
{
	char *res;
	int error = 0;
	int connected = 1;

	if (path->mnt->mnt_flags & MNT_INTERNAL) {
		/* it's not mounted anywhere */
		res = dentry_path(path->dentry, buf, buflen);
		*name = res;
		if (IS_ERR(res)) {
			*name = buf;
			return PTR_ERR(res);
		}
		if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
		    strncmp(*name, "/sys/", 5) == 0) {
			/* TODO: convert over to using a per namespace
			 * control instead of hard coded /proc
			 */
			return prepend(name, *name - buf, "/proc", 5);
		}
		return 0;
	}

	/* resolve paths relative to chroot?*/
	if (flags & PATH_CHROOT_REL) {
		struct path root;
		get_fs_root(current->fs, &root);
		res = __d_path(path, &root, buf, buflen);
		path_put(&root);
	} else {
		res = d_absolute_path(path, buf, buflen);
		if (!our_mnt(path->mnt))
			connected = 0;
	}

	/* handle error conditions - and still allow a partial path to
	 * be returned.
	 */
	if (!res || IS_ERR(res)) {
		connected = 0;
		res = dentry_path_raw(path->dentry, buf, buflen);
		if (IS_ERR(res)) {
			error = PTR_ERR(res);
			*name = buf;
			goto out;
		};
	} else if (!our_mnt(path->mnt))
		connected = 0;

	*name = res;

	/* Handle two cases:
	 * 1. A deleted dentry && profile is not allowing mediation of deleted
	 * 2. On some filesystems, newly allocated dentries appear to the
	 *    security_path hooks as a deleted dentry except without an inode
	 *    allocated.
	 */
	if (d_unlinked(path->dentry) && path->dentry->d_inode &&
	    !(flags & PATH_MEDIATE_DELETED)) {
			error = -ENOENT;
			goto out;
	}

	/* If the path is not connected to the expected root,
	 * check if it is a sysctl and handle specially else remove any
	 * leading / that __d_path may have returned.
	 * Unless
	 *     specifically directed to connect the path,
	 * OR
	 *     if in a chroot and doing chroot relative paths and the path
	 *     resolves to the namespace root (would be connected outside
	 *     of chroot) and specifically directed to connect paths to
	 *     namespace root.
	 */
	if (!connected) {
		if (!(flags & PATH_CONNECT_PATH) &&
			   !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
			     our_mnt(path->mnt))) {
			/* disconnected path, don't return pathname starting
			 * with '/'
			 */
			error = -ESTALE;
			if (*res == '/')
				*name = res + 1;
		}
	}

out:
	return error;
}
コード例 #8
0
ファイル: realpath.c プロジェクト: friackazoid/linux-2.6
/**
 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
 *
 * @path:        Pointer to "struct path".
 * @newname:     Pointer to buffer to return value in.
 * @newname_len: Size of @newname.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * If dentry is a directory, trailing '/' is appended.
 * Characters out of 0x20 < c < 0x7F range are converted to
 * \ooo style octal string.
 * Character \ is converted to \\ string.
 */
int tomoyo_realpath_from_path2(struct path *path, char *newname,
			       int newname_len)
{
	int error = -ENOMEM;
	struct dentry *dentry = path->dentry;
	char *sp;

	if (!dentry || !path->mnt || !newname || newname_len <= 2048)
		return -EINVAL;
	if (dentry->d_op && dentry->d_op->d_dname) {
		/* For "socket:[\$]" and "pipe:[\$]". */
		static const int offset = 1536;
		sp = dentry->d_op->d_dname(dentry, newname + offset,
					   newname_len - offset);
	} else {
		/* Taken from d_namespace_path(). */
		struct path root;
		struct path ns_root = { };
		struct path tmp;

		read_lock(&current->fs->lock);
		root = current->fs->root;
		path_get(&root);
		read_unlock(&current->fs->lock);
		spin_lock(&vfsmount_lock);
		if (root.mnt && root.mnt->mnt_ns)
			ns_root.mnt = mntget(root.mnt->mnt_ns->root);
		if (ns_root.mnt)
			ns_root.dentry = dget(ns_root.mnt->mnt_root);
		spin_unlock(&vfsmount_lock);
		spin_lock(&dcache_lock);
		tmp = ns_root;
		sp = __d_path(path, &tmp, newname, newname_len);
		spin_unlock(&dcache_lock);
		path_put(&root);
		path_put(&ns_root);
		/* Prepend "/proc" prefix if using internal proc vfs mount. */
		if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
		    (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
			sp -= 5;
			if (sp >= newname)
				memcpy(sp, "/proc", 5);
			else
				sp = ERR_PTR(-ENOMEM);
		}
	}
	if (IS_ERR(sp))
		error = PTR_ERR(sp);
	else
		error = tomoyo_encode(newname, sp - newname, sp);
	/* Append trailing '/' if dentry is a directory. */
	if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
	    && *newname) {
		sp = newname + strlen(newname);
		if (*(sp - 1) != '/') {
			if (sp < newname + newname_len - 4) {
				*sp++ = '/';
				*sp = '\0';
			} else {
				error = -ENOMEM;
			}
		}
	}
	if (error)
		printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
	return error;
}
コード例 #9
0
/**
 * d_namespace_path - lookup a name associated with a given path
 * @path: path to lookup  (NOT NULL)
 * @buf:  buffer to store path to  (NOT NULL)
 * @buflen: length of @buf
 * @name: return pointer for start of path name with in @buf  (NOT NULL)
 * @flags: flags controling path lookup
 *
 * Handle path name lookup.
 *
 * Returns: %0 else error code if path lookup fails
 *          When no error the path name is returned in @name which points to
 *          to a position in @buf
 */
static int d_namespace_path(struct path *path, char *buf, int buflen,
                            char **name, int flags)
{
    struct path root, tmp;
    char *res;
    int deleted, connected;
    int error = 0;

    /* Get the root we want to resolve too */
    if (flags & PATH_CHROOT_REL) {
        /* resolve paths relative to chroot */
        read_lock(&current->fs->lock);
        root = current->fs->root;
        /* released below */
        path_get(&root);
        read_unlock(&current->fs->lock);
    } else {
        /* resolve paths relative to namespace */
        root.mnt = current->nsproxy->mnt_ns->root;
        root.dentry = root.mnt->mnt_root;
        /* released below */
        path_get(&root);
    }

    spin_lock(&dcache_lock);
    /* There is a race window between path lookup here and the
     * need to strip the " (deleted) string that __d_path applies
     * Detect the race and relookup the path
     *
     * The stripping of (deleted) is a hack that could be removed
     * with an updated __d_path
     */
    do {
        tmp = root;
        deleted = d_unlinked(path->dentry);
        res = __d_path(path, &tmp, buf, buflen);

    } while (deleted != d_unlinked(path->dentry));
    spin_unlock(&dcache_lock);

    *name = res;
    /* handle error conditions - and still allow a partial path to
     * be returned.
     */
    if (IS_ERR(res)) {
        error = PTR_ERR(res);
        *name = buf;
        goto out;
    }
    if (deleted) {
        /* On some filesystems, newly allocated dentries appear to the
         * security_path hooks as a deleted dentry except without an
         * inode allocated.
         *
         * Remove the appended deleted text and return as string for
         * normal mediation, or auditing.  The (deleted) string is
         * guarenteed to be added in this case, so just strip it.
         */
        buf[buflen - 11] = 0;	/* - (len(" (deleted)") +\0) */

        if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
            error = -ENOENT;
            goto out;
        }
    }

    /* Determine if the path is connected to the expected root */
    connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;

    /* If the path is not connected, then remove any leading / that
     * __d_path may have returned.
     * Unless
     *     specifically directed to connect the path,
     * OR
     *     if in a chroot and doing chroot relative paths and the path
     *     resolves to the namespace root (would be connected outside
     *     of chroot) and specifically directed to connect paths to
     *     namespace root.
     */
    if (!connected &&
            !(flags & PATH_CONNECT_PATH) &&
            !((flags & PATH_CHROOT_REL) && (flags & PATH_CHROOT_NSCONNECT) &&
              (tmp.mnt == current->nsproxy->mnt_ns->root &&
               tmp.dentry == current->nsproxy->mnt_ns->root->mnt_root))) {
        /* disconnected path, don't return pathname starting with '/' */
        error = -ESTALE;
        if (*res == '/')
            *name = res + 1;
    }

out:
    path_put(&root);

    return error;
}