This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / namei.c
index 656430d..89281b7 100644 (file)
@@ -165,8 +165,7 @@ int vfs_permission(struct inode * inode, int mask)
 {
        umode_t                 mode = inode->i_mode;
 
-       /* Prevent vservers from escaping chroot() barriers */
-       if (IS_BARRIER(inode) && !vx_check(0, VX_ADMIN))
+       if (IS_BARRIER(inode) && !vx_check(0, VX_ADMIN|VX_WATCH))
                return -EACCES;
 
        if (mask & MAY_WRITE) {
@@ -214,19 +213,25 @@ int vfs_permission(struct inode * inode, int mask)
        return -EACCES;
 }
 
+static inline int xid_permission(struct inode *inode)
+{
+       if (inode->i_xid == 0)
+               return 0;
+       if (vx_check(inode->i_xid, VX_ADMIN|VX_WATCH|VX_IDENT))
+               return 0;
+       return -EACCES;
+}
+
 int permission(struct inode * inode,int mask, struct nameidata *nd)
 {
        int retval;
        int submask;
-       umode_t mode = inode->i_mode;
 
        /* Ordinary permission routines do not understand MAY_APPEND. */
        submask = mask & ~MAY_APPEND;
 
-       if (nd && (mask & MAY_WRITE) && MNT_IS_RDONLY(nd->mnt) &&
-               (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-               return -EROFS;
-
+       if ((retval = xid_permission(inode)))
+               return retval;
        if (inode->i_op && inode->i_op->permission)
                retval = inode->i_op->permission(inode, submask, nd);
        else
@@ -669,11 +674,9 @@ int fastcall link_path_walk(const char * name, struct nameidata *nd)
 {
        struct path next;
        struct inode *inode;
-       int err, atomic;
+       int err;
        unsigned int lookup_flags = nd->flags;
-
-       atomic = (lookup_flags & LOOKUP_ATOMIC);
-
+       
        while (*name=='/')
                name++;
        if (!*name)
@@ -741,9 +744,6 @@ int fastcall link_path_walk(const char * name, struct nameidata *nd)
                        if (err < 0)
                                break;
                }
-               err = -EWOULDBLOCKIO;
-               if (atomic)
-                       break;
                nd->flags |= LOOKUP_CONTINUE;
                /* This does the actual lookups.. */
                err = do_lookup(nd, &this, &next);
@@ -808,9 +808,6 @@ last_component:
                        if (err < 0)
                                break;
                }
-               err = -EWOULDBLOCKIO;
-               if (atomic)
-                       break;
                err = do_lookup(nd, &this, &next);
                if (err)
                        break;
@@ -1159,24 +1156,6 @@ static inline int may_create(struct inode *dir, struct dentry *child,
        return permission(dir,MAY_WRITE | MAY_EXEC, nd);
 }
 
-static inline int mnt_may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
-       if (child->d_inode)
-               return -EEXIST;
-       if (IS_DEADDIR(dir))
-               return -ENOENT;
-       if (mnt->mnt_flags & MNT_RDONLY)
-               return -EROFS;
-       return 0;
-}
-
-static inline int mnt_may_unlink(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
-       if (!child->d_inode)
-               return -ENOENT;
-       if (mnt->mnt_flags & MNT_RDONLY)
-               return -EROFS;
-       return 0;
-}
-
 /* 
  * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
  * reasons.
@@ -1195,8 +1174,6 @@ static inline int lookup_flags(unsigned int f)
        
        if (f & O_DIRECTORY)
                retval |= LOOKUP_DIRECTORY;
-       if (f & O_ATOMICLOOKUP)
-               retval |= LOOKUP_ATOMIC;
 
        return retval;
 }
@@ -1300,8 +1277,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
                        return -EACCES;
 
                flag &= ~O_TRUNC;
-       } else if ((IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt)))
-               && (flag & FMODE_WRITE))
+       } else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
                return -EROFS;
        /*
         * An append-only file must be opened in append mode for writing.
@@ -1539,28 +1515,23 @@ do_link:
 struct dentry *lookup_create(struct nameidata *nd, int is_dir)
 {
        struct dentry *dentry;
-       int error;
 
        down(&nd->dentry->d_inode->i_sem);
-       error = -EEXIST;
+       dentry = ERR_PTR(-EEXIST);
        if (nd->last_type != LAST_NORM)
-               goto out;
+               goto fail;
        nd->flags &= ~LOOKUP_PARENT;
        dentry = lookup_hash(&nd->last, nd->dentry);
        if (IS_ERR(dentry))
-               goto ret;
-       error = mnt_may_create(nd->mnt, nd->dentry->d_inode, dentry);
-       if (error)
                goto fail;
-       error = -ENOENT;
        if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-               goto fail;
-ret:
+               goto enoent;
        return dentry;
-fail:
+enoent:
        dput(dentry);
-out:
-       return ERR_PTR(error);
+       dentry = ERR_PTR(-ENOENT);
+fail:
+       return dentry;
 }
 
 int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
@@ -1789,11 +1760,7 @@ asmlinkage long sys_rmdir(const char __user * pathname)
        dentry = lookup_hash(&nd.last, nd.dentry);
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
-               error = mnt_may_unlink(nd.mnt, nd.dentry->d_inode, dentry);
-               if (error)
-                       goto exit2;
                error = vfs_rmdir(nd.dentry->d_inode, dentry);
-       exit2:
                dput(dentry);
        }
        up(&nd.dentry->d_inode->i_sem);
@@ -1865,9 +1832,6 @@ asmlinkage long sys_unlink(const char __user * pathname)
                /* Why not before? Because we want correct error value */
                if (nd.last.name[nd.last.len])
                        goto slashes;
-               error = mnt_may_unlink(nd.mnt, nd.dentry->d_inode, dentry);
-               if (error)
-                       goto exit2;
                inode = dentry->d_inode;
                if (inode)
                        atomic_inc(&inode->i_count);
@@ -2013,13 +1977,8 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam
        error = path_lookup(to, LOOKUP_PARENT, &nd);
        if (error)
                goto out;
-       /*
-        * We allow hard-links to be created to a bind-mount as long
-        * as the bind-mount is not read-only.  Checking for cross-dev
-        * links is subsumed by the superblock check in vfs_link().
-        */
-       error = -EROFS;
-       if (MNT_IS_RDONLY(old_nd.mnt))
+       error = -EXDEV;
+       if (old_nd.mnt != nd.mnt)
                goto out_release;
        new_dentry = lookup_create(&nd, 0);
        error = PTR_ERR(new_dentry);
@@ -2237,9 +2196,6 @@ static inline int do_rename(const char * oldname, const char * newname)
        error = -EINVAL;
        if (old_dentry == trap)
                goto exit4;
-       error = -EROFS;
-       if (MNT_IS_RDONLY(newnd.mnt))
-               goto exit4;
        new_dentry = lookup_hash(&newnd.last, new_dir);
        error = PTR_ERR(new_dentry);
        if (IS_ERR(new_dentry))