return -EACCES;
}
+/**
+ * inode_permission - check for access rights to a given inode
+ * @inode: inode to check permission on
+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
+ *
+ * Used to check for read/write/execute permissions on an inode.
+ * We use "fsuid" for this, letting us set arbitrary permissions
+ * for filesystem access without changing the "normal" uids which
+ * are used for other things.
+ */
int inode_permission(struct inode *inode, int mask)
{
int retval;
return -EACCES;
}
- /* Ordinary permission routines do not understand MAY_APPEND. */
if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, mask);
else
mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
}
-/**
- * vfs_permission - check for access rights to a given path
- * @nd: lookup result that describes the path
- * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
- *
- * Used to check for read/write/execute permissions on a path.
- * We use "fsuid" for this, letting us set arbitrary permissions
- * for filesystem access without changing the "normal" uids which
- * are used for other things.
- */
-int vfs_permission(struct nameidata *nd, int mask)
-{
- return inode_permission(nd->path.dentry->d_inode, mask);
-}
-
/**
* file_permission - check for additional access rights to a given file
* @file: file to check access rights for
*
* Note:
* Do not use this function in new code. All access checks should
- * be done using vfs_permission().
+ * be done using inode_permission().
*/
int file_permission(struct file *file, int mask)
{
return result;
}
-/* SMP-safe */
-static __always_inline void
-walk_init_root(const char *name, struct nameidata *nd)
-{
- struct fs_struct *fs = current->fs;
-
- read_lock(&fs->lock);
- nd->path = fs->root;
- path_get(&fs->root);
- read_unlock(&fs->lock);
-}
-
/*
* Wrapper to retry pathname resolution whenever the underlying
* file system returns an ESTALE.
goto fail;
if (*link == '/') {
+ struct fs_struct *fs = current->fs;
+
path_put(&nd->path);
- walk_init_root(link, nd);
+
+ read_lock(&fs->lock);
+ nd->path = fs->root;
+ path_get(&fs->root);
+ read_unlock(&fs->lock);
}
+
res = link_path_walk(link, nd);
if (nd->depth || res || nd->last_type!=LAST_NORM)
return res;
nd->flags |= LOOKUP_CONTINUE;
err = exec_permission_lite(inode);
if (err == -EAGAIN)
- err = vfs_permission(nd, MAY_EXEC);
+ err = inode_permission(nd->path.dentry->d_inode,
+ MAY_EXEC);
if (err)
break;
return error;
}
-int may_open(struct nameidata *nd, int acc_mode, int flag)
+int may_open(struct path *path, int acc_mode, int flag)
{
- struct dentry *dentry = nd->path.dentry;
+ struct dentry *dentry = path->dentry;
struct inode *inode = dentry->d_inode;
int error;
if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
flag &= ~O_TRUNC;
} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
- if (nd->path.mnt->mnt_flags & MNT_NODEV)
+ if (path->mnt->mnt_flags & MNT_NODEV)
return -EACCES;
flag &= ~O_TRUNC;
}
- error = vfs_permission(nd, acc_mode);
+ error = inode_permission(inode, acc_mode);
if (error)
return error;
/*
*/
error = locks_verify_locked(inode);
if (!error)
- error = security_path_truncate(&nd->path, 0,
+ error = security_path_truncate(path, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
if (!error) {
DQUOT_INIT(inode);
if (error)
return error;
/* Don't check for write permission, don't truncate */
- return may_open(nd, 0, flag & ~O_TRUNC);
+ return may_open(&nd->path, 0, flag & ~O_TRUNC);
}
/*
if (error)
goto exit;
}
- error = may_open(&nd, acc_mode, flag);
+ error = may_open(&nd.path, acc_mode, flag);
if (error) {
if (will_write)
mnt_drop_write(nd.path.mnt);
/* get the link contents into pagecache */
static char *page_getlink(struct dentry * dentry, struct page **ppage)
{
- struct page * page;
+ char *kaddr;
+ struct page *page;
struct address_space *mapping = dentry->d_inode->i_mapping;
page = read_mapping_page(mapping, 0, NULL);
if (IS_ERR(page))
return (char*)page;
*ppage = page;
- return kmap(page);
+ kaddr = kmap(page);
+ nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1);
+ return kaddr;
}
int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
EXPORT_SYMBOL(kern_path);
EXPORT_SYMBOL(vfs_path_lookup);
EXPORT_SYMBOL(inode_permission);
-EXPORT_SYMBOL(vfs_permission);
EXPORT_SYMBOL(file_permission);
EXPORT_SYMBOL(unlock_rename);
EXPORT_SYMBOL(vfs_create);
EXPORT_SYMBOL(vfs_unlink);
EXPORT_SYMBOL(dentry_unhash);
EXPORT_SYMBOL(generic_readlink);
+
+/* to be mentioned only in INIT_TASK */
+struct fs_struct init_fs = {
+ .count = ATOMIC_INIT(1),
+ .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
+ .umask = 0022,
+};