aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorDave Hansen <haveblue@us.ibm.com>2008-02-15 17:37:57 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2008-04-19 00:25:34 -0400
commit463c3197263bd26ac59a00d2484990e17e35c50e (patch)
treeb27c04f978ccd447ae33f7387b6a4aba0033acc5 /fs/namei.c
parent0622753b800e4cc6cb9319b36b27658c72dd7cdc (diff)
[PATCH] r/o bind mounts: get callers of vfs_mknod/create/mkdir()
This takes care of all of the direct callers of vfs_mknod(). Since a few of these cases also handle normal file creation as well, this also covers some calls to vfs_create(). So that we don't have to make three mnt_want/drop_write() calls inside of the switch statement, we move some of its logic outside of the switch and into a helper function suggested by Christoph. This also encapsulates a fix for mknod(S_IFREG) that Miklos found. [AV: merged mkdir handling, added missing nfsd pieces] Acked-by: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Dave Hansen <haveblue@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 89ef3178eaaa..3fbcf2021a2e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1984,6 +1984,23 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
1984 return error; 1984 return error;
1985} 1985}
1986 1986
1987static int may_mknod(mode_t mode)
1988{
1989 switch (mode & S_IFMT) {
1990 case S_IFREG:
1991 case S_IFCHR:
1992 case S_IFBLK:
1993 case S_IFIFO:
1994 case S_IFSOCK:
1995 case 0: /* zero mode translates to S_IFREG */
1996 return 0;
1997 case S_IFDIR:
1998 return -EPERM;
1999 default:
2000 return -EINVAL;
2001 }
2002}
2003
1987asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, 2004asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
1988 unsigned dev) 2005 unsigned dev)
1989{ 2006{
@@ -2002,12 +2019,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
2002 if (error) 2019 if (error)
2003 goto out; 2020 goto out;
2004 dentry = lookup_create(&nd, 0); 2021 dentry = lookup_create(&nd, 0);
2005 error = PTR_ERR(dentry); 2022 if (IS_ERR(dentry)) {
2006 2023 error = PTR_ERR(dentry);
2024 goto out_unlock;
2025 }
2007 if (!IS_POSIXACL(nd.path.dentry->d_inode)) 2026 if (!IS_POSIXACL(nd.path.dentry->d_inode))
2008 mode &= ~current->fs->umask; 2027 mode &= ~current->fs->umask;
2009 if (!IS_ERR(dentry)) { 2028 error = may_mknod(mode);
2010 switch (mode & S_IFMT) { 2029 if (error)
2030 goto out_dput;
2031 error = mnt_want_write(nd.path.mnt);
2032 if (error)
2033 goto out_dput;
2034 switch (mode & S_IFMT) {
2011 case 0: case S_IFREG: 2035 case 0: case S_IFREG:
2012 error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); 2036 error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
2013 break; 2037 break;
@@ -2018,14 +2042,11 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
2018 case S_IFIFO: case S_IFSOCK: 2042 case S_IFIFO: case S_IFSOCK:
2019 error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); 2043 error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
2020 break; 2044 break;
2021 case S_IFDIR:
2022 error = -EPERM;
2023 break;
2024 default:
2025 error = -EINVAL;
2026 }
2027 dput(dentry);
2028 } 2045 }
2046 mnt_drop_write(nd.path.mnt);
2047out_dput:
2048 dput(dentry);
2049out_unlock:
2029 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2050 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2030 path_put(&nd.path); 2051 path_put(&nd.path);
2031out: 2052out:
@@ -2083,7 +2104,12 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
2083 2104
2084 if (!IS_POSIXACL(nd.path.dentry->d_inode)) 2105 if (!IS_POSIXACL(nd.path.dentry->d_inode))
2085 mode &= ~current->fs->umask; 2106 mode &= ~current->fs->umask;
2107 error = mnt_want_write(nd.path.mnt);
2108 if (error)
2109 goto out_dput;
2086 error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); 2110 error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
2111 mnt_drop_write(nd.path.mnt);
2112out_dput:
2087 dput(dentry); 2113 dput(dentry);
2088out_unlock: 2114out_unlock:
2089 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2115 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);