V4L/DVB (9824): m52790: convert to v4l2_subdev.
[safe/jmp/linux-2.6] / fs / namei.c
index 2b8f823..af3783f 100644 (file)
@@ -186,7 +186,7 @@ int generic_permission(struct inode *inode, int mask,
 
        mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
 
-       if (current->fsuid == inode->i_uid)
+       if (current_fsuid() == inode->i_uid)
                mode >>= 6;
        else {
                if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
@@ -212,8 +212,7 @@ int generic_permission(struct inode *inode, int mask,
         * 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;
 
@@ -249,23 +248,11 @@ int inode_permission(struct inode *inode, int mask)
        }
 
        /* 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;
 
@@ -454,7 +441,7 @@ static int exec_permission_lite(struct inode *inode)
        if (inode->i_op && inode->i_op->permission)
                return -EAGAIN;
 
-       if (current->fsuid == inode->i_uid)
+       if (current_fsuid() == inode->i_uid)
                mode >>= 6;
        else if (in_group_p(inode->i_gid))
                mode >>= 3;
@@ -1347,11 +1334,13 @@ static int user_path_parent(int dfd, const char __user *path,
  */
 static inline int check_sticky(struct inode *dir, struct inode *inode)
 {
+       uid_t fsuid = current_fsuid();
+
        if (!(dir->i_mode & S_ISVTX))
                return 0;
-       if (inode->i_uid == current->fsuid)
+       if (inode->i_uid == fsuid)
                return 0;
-       if (dir->i_uid == current->fsuid)
+       if (dir->i_uid == fsuid)
                return 0;
        return !capable(CAP_FOWNER);
 }
@@ -1391,7 +1380,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
        if (IS_APPEND(dir))
                return -EPERM;
        if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
-           IS_IMMUTABLE(victim->d_inode))
+           IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
                return -EPERM;
        if (isdir) {
                if (!S_ISDIR(victim->d_inode->i_mode))
@@ -1454,20 +1443,18 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
 
        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);
@@ -2172,16 +2159,19 @@ static long do_rmdir(int dfd, const char __user *pathname)
                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);
@@ -2259,6 +2249,9 @@ static long do_unlinkat(int dfd, const char __user *pathname)
        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);
@@ -2648,6 +2641,10 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
        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);