* Read/write DACs are always overridable.
* Executable DACs are overridable if at least one exec bit is set.
*/
- if (!(mask & MAY_EXEC) ||
- (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
+ if (!(mask & MAY_EXEC) || execute_ok(inode))
if (capable(CAP_DAC_OVERRIDE))
return 0;
}
/* Ordinary permission routines do not understand MAY_APPEND. */
- if (inode->i_op && inode->i_op->permission) {
+ if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, mask);
- if (!retval) {
- /*
- * Exec permission on a regular file is denied if none
- * of the execute bits are set.
- *
- * This check should be done by the ->permission()
- * method.
- */
- if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
- !(inode->i_mode & S_IXUGO))
- return -EACCES;
- }
- } else {
+ else
retval = generic_permission(inode, mask, NULL);
- }
+
if (retval)
return retval;
mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex);
- for (p = p1; p->d_parent != p; p = p->d_parent) {
- if (p->d_parent == p2) {
- mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT);
- mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD);
- return p;
- }
+ p = d_ancestor(p2, p1);
+ if (p) {
+ 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) {
- mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
- mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
- return p;
- }
+ p = d_ancestor(p1, p2);
+ if (p) {
+ mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
+ mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
+ return p;
}
mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
dir = nd.path.dentry;
nd.flags &= ~LOOKUP_PARENT;
nd.flags |= LOOKUP_CREATE | LOOKUP_OPEN;
+ if (flag & O_EXCL)
+ nd.flags |= LOOKUP_EXCL;
mutex_lock(&dir->d_inode->i_mutex);
path.dentry = lookup_hash(&nd);
path.mnt = nd.path.mnt;
if (nd->last_type != LAST_NORM)
goto fail;
nd->flags &= ~LOOKUP_PARENT;
- nd->flags |= LOOKUP_CREATE;
+ nd->flags |= LOOKUP_CREATE | LOOKUP_EXCL;
nd->intent.open.flags = O_EXCL;
/*
return error;
switch(nd.last_type) {
- case LAST_DOTDOT:
- error = -ENOTEMPTY;
- goto exit1;
- case LAST_DOT:
- error = -EINVAL;
- goto exit1;
- case LAST_ROOT:
- error = -EBUSY;
- goto exit1;
+ case LAST_DOTDOT:
+ error = -ENOTEMPTY;
+ goto exit1;
+ case LAST_DOT:
+ error = -EINVAL;
+ goto exit1;
+ case LAST_ROOT:
+ error = -EBUSY;
+ goto exit1;
}
+
+ nd.flags &= ~LOOKUP_PARENT;
+
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
+
+ nd.flags &= ~LOOKUP_PARENT;
+
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (newnd.last_type != LAST_NORM)
goto exit2;
+ oldnd.flags &= ~LOOKUP_PARENT;
+ newnd.flags &= ~LOOKUP_PARENT;
+ newnd.flags |= LOOKUP_RENAME_TARGET;
+
trap = lock_rename(new_dir, old_dir);
old_dentry = lookup_hash(&oldnd);