projects
/
powerpc.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
[PATCH] fs/ocfs2/ioctl.c should #include "ioctl.h"
[powerpc.git]
/
fs
/
namei.c
diff --git
a/fs/namei.c
b/fs/namei.c
index
184fe4a
..
432d6bc
100644
(file)
--- a/
fs/namei.c
+++ b/
fs/namei.c
@@
-159,7
+159,7
@@
char * getname(const char __user * filename)
#ifdef CONFIG_AUDITSYSCALL
void putname(const char *name)
{
#ifdef CONFIG_AUDITSYSCALL
void putname(const char *name)
{
- if (unlikely(
current->audit_context
))
+ if (unlikely(
!audit_dummy_context()
))
audit_putname(name);
else
__putname(name);
audit_putname(name);
else
__putname(name);
@@
-227,10
+227,10
@@
int generic_permission(struct inode *inode, int mask,
int permission(struct inode *inode, int mask, struct nameidata *nd)
{
int permission(struct inode *inode, int mask, struct nameidata *nd)
{
+ umode_t mode = inode->i_mode;
int retval, submask;
if (mask & MAY_WRITE) {
int retval, submask;
if (mask & MAY_WRITE) {
- umode_t mode = inode->i_mode;
/*
* Nobody gets write access to a read-only fs.
/*
* Nobody gets write access to a read-only fs.
@@
-247,6
+247,13
@@
int permission(struct inode *inode, int mask, struct nameidata *nd)
}
}
+ /*
+ * MAY_EXEC on regular files requires special handling: We override
+ * filesystem execute permissions if the mode bits aren't set.
+ */
+ if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+ return -EACCES;
+
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission)
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission)
@@
-1125,7
+1132,7
@@
static int fastcall do_path_lookup(int dfd, const char *name,
retval = link_path_walk(name, nd);
out:
if (likely(retval == 0)) {
retval = link_path_walk(name, nd);
out:
if (likely(retval == 0)) {
- if (unlikely(
current->audit_context
&& nd && nd->dentry &&
+ if (unlikely(
!audit_dummy_context()
&& nd && nd->dentry &&
nd->dentry->d_inode))
audit_inode(name, nd->dentry->d_inode);
}
nd->dentry->d_inode))
audit_inode(name, nd->dentry->d_inode);
}
@@
-1357,7
+1364,7
@@
static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
return -ENOENT;
BUG_ON(victim->d_parent->d_inode != dir);
return -ENOENT;
BUG_ON(victim->d_parent->d_inode != dir);
- audit_inode_child(victim->d_name.name, victim->d_inode, dir
->i_ino
);
+ audit_inode_child(victim->d_name.name, victim->d_inode, dir);
error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
@@
-1423,7
+1430,7
@@
struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
struct dentry *p;
if (p1 == p2) {
struct dentry *p;
if (p1 == p2) {
- mutex_lock
(&p1->d_inode->i_mutex
);
+ mutex_lock
_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT
);
return NULL;
}
return NULL;
}
@@
-1431,22
+1438,22
@@
struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
for (p = p1; p->d_parent != p; p = p->d_parent) {
if (p->d_parent == p2) {
for (p = p1; p->d_parent != p; p = p->d_parent) {
if (p->d_parent == p2) {
- mutex_lock
(&p2->d_inode->i_mutex
);
- mutex_lock
(&p1->d_inode->i_mutex
);
+ mutex_lock
_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT
);
+ mutex_lock
_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD
);
return p;
}
}
for (p = p2; p->d_parent != p; p = p->d_parent) {
if (p->d_parent == p1) {
return p;
}
}
for (p = p2; p->d_parent != p; p = p->d_parent) {
if (p->d_parent == p1) {
- mutex_lock
(&p1->d_inode->i_mutex
);
- mutex_lock
(&p2->d_inode->i_mutex
);
+ mutex_lock
_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT
);
+ mutex_lock
_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD
);
return p;
}
}
return p;
}
}
- mutex_lock
(&p1->d_inode->i_mutex
);
- mutex_lock
(&p2->d_inode->i_mutex
);
+ mutex_lock
_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT
);
+ mutex_lock
_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD
);
return NULL;
}
return NULL;
}
@@
-1659,6
+1666,7
@@
do_last:
* It already exists.
*/
mutex_unlock(&dir->d_inode->i_mutex);
* It already exists.
*/
mutex_unlock(&dir->d_inode->i_mutex);
+ audit_inode_update(path.dentry->d_inode);
error = -EEXIST;
if (flag & O_EXCL)
error = -EEXIST;
if (flag & O_EXCL)
@@
-1669,6
+1677,7
@@
do_last:
if (flag & O_NOFOLLOW)
goto exit_dput;
}
if (flag & O_NOFOLLOW)
goto exit_dput;
}
+
error = -ENOENT;
if (!path.dentry->d_inode)
goto exit_dput;
error = -ENOENT;
if (!path.dentry->d_inode)
goto exit_dput;
@@
-1712,8
+1721,14
@@
do_link:
if (error)
goto exit_dput;
error = __do_follow_link(&path, nd);
if (error)
goto exit_dput;
error = __do_follow_link(&path, nd);
- if (error)
+ if (error) {
+ /* Does someone understand code flow here? Or it is only
+ * me so stupid? Anathema to whoever designed this non-sense
+ * with "intent.open".
+ */
+ release_open_intent(nd);
return error;
return error;
+ }
nd->flags &= ~LOOKUP_PARENT;
if (nd->last_type == LAST_BIND)
goto ok;
nd->flags &= ~LOOKUP_PARENT;
if (nd->last_type == LAST_BIND)
goto ok;
@@
-1751,7
+1766,7
@@
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
{
struct dentry *dentry = ERR_PTR(-EEXIST);
{
struct dentry *dentry = ERR_PTR(-EEXIST);
- mutex_lock
(&nd->dentry->d_inode->i_mutex
);
+ mutex_lock
_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT
);
/*
* Yucky last component or no last component at all?
* (foo/., foo/.., /////)
/*
* Yucky last component or no last component at all?
* (foo/., foo/.., /////)
@@
-1759,6
+1774,8
@@
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
if (nd->last_type != LAST_NORM)
goto fail;
nd->flags &= ~LOOKUP_PARENT;
if (nd->last_type != LAST_NORM)
goto fail;
nd->flags &= ~LOOKUP_PARENT;
+ nd->flags |= LOOKUP_CREATE;
+ nd->intent.open.flags = O_EXCL;
/*
* Do the final lookup.
/*
* Do the final lookup.
@@
-2008,7
+2025,7
@@
static long do_rmdir(int dfd, const char __user *pathname)
error = -EBUSY;
goto exit1;
}
error = -EBUSY;
goto exit1;
}
- mutex_lock
(&nd.dentry->d_inode->i_mutex
);
+ mutex_lock
_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT
);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
@@
-2082,7
+2099,7
@@
static long do_unlinkat(int dfd, const char __user *pathname)
error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
- mutex_lock
(&nd.dentry->d_inode->i_mutex
);
+ mutex_lock
_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT
);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
@@
-2243,14
+2260,16
@@
asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
int error;
char * to;
int error;
char * to;
- if (
flags
!= 0)
+ if (
(flags & ~AT_SYMLINK_FOLLOW)
!= 0)
return -EINVAL;
to = getname(newname);
if (IS_ERR(to))
return PTR_ERR(to);
return -EINVAL;
to = getname(newname);
if (IS_ERR(to))
return PTR_ERR(to);
- error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
+ error = __user_walk_fd(olddfd, oldname,
+ flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
+ &old_nd);
if (error)
goto exit;
error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
if (error)
goto exit;
error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
@@
-2577,8
+2596,7
@@
static char *page_getlink(struct dentry * dentry, struct page **ppage)
{
struct page * page;
struct address_space *mapping = dentry->d_inode->i_mapping;
{
struct page * page;
struct address_space *mapping = dentry->d_inode->i_mapping;
- page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage,
- NULL);
+ page = read_mapping_page(mapping, 0, NULL);
if (IS_ERR(page))
goto sync_fail;
wait_on_page_locked(page);
if (IS_ERR(page))
goto sync_fail;
wait_on_page_locked(page);