diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:38:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:38:14 -0400 |
commit | fd9be4ce2e1eb407a8152f823698cc0d652bbec8 (patch) | |
tree | b1cc279fa5b1f90995253f007564f001aa20c743 /fs/namei.c | |
parent | b1af9ccce9cff5b48c37424dbdbb3aa9021915db (diff) | |
parent | ad775f5a8faa5845377f093ca11caf577404add9 (diff) |
Merge branch 'ro-bind.b6' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'ro-bind.b6' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (24 commits)
[PATCH] r/o bind mounts: debugging for missed calls
[PATCH] r/o bind mounts: honor mount writer counts at remount
[PATCH] r/o bind mounts: track numbers of writers to mounts
[PATCH] r/o bind mounts: check mnt instead of superblock directly
[PATCH] r/o bind mounts: elevate count for xfs timestamp updates
[PATCH] r/o bind mounts: make access() use new r/o helper
[PATCH] r/o bind mounts: write counts for truncate()
[PATCH] r/o bind mounts: elevate write count for chmod/chown callers
[PATCH] r/o bind mounts: elevate write count for open()s
[PATCH] r/o bind mounts: elevate write count for ioctls()
[PATCH] r/o bind mounts: write count for file_update_time()
[PATCH] r/o bind mounts: elevate write count for do_utimes()
[PATCH] r/o bind mounts: write counts for touch_atime()
[PATCH] r/o bind mounts: elevate write count for ncp_ioctl()
[PATCH] r/o bind mounts: elevate write count for xattr_permission() callers
[PATCH] r/o bind mounts: get write access for vfs_rename() callers
[PATCH] r/o bind mounts: write counts for link/symlink
[PATCH] r/o bind mounts: get callers of vfs_mknod/create/mkdir()
[PATCH] r/o bind mounts: elevate write count for rmdir and unlink.
[PATCH] r/o bind mounts: drop write during emergency remount
...
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 275 |
1 files changed, 209 insertions, 66 deletions
diff --git a/fs/namei.c b/fs/namei.c index 8cf9bb9c2fc0..e179f71bfcb0 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1623,8 +1623,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1623 | return -EACCES; | 1623 | return -EACCES; |
1624 | 1624 | ||
1625 | flag &= ~O_TRUNC; | 1625 | flag &= ~O_TRUNC; |
1626 | } else if (IS_RDONLY(inode) && (acc_mode & MAY_WRITE)) | 1626 | } |
1627 | return -EROFS; | ||
1628 | 1627 | ||
1629 | error = vfs_permission(nd, acc_mode); | 1628 | error = vfs_permission(nd, acc_mode); |
1630 | if (error) | 1629 | if (error) |
@@ -1677,7 +1676,12 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1677 | return 0; | 1676 | return 0; |
1678 | } | 1677 | } |
1679 | 1678 | ||
1680 | static int open_namei_create(struct nameidata *nd, struct path *path, | 1679 | /* |
1680 | * Be careful about ever adding any more callers of this | ||
1681 | * function. Its flags must be in the namei format, not | ||
1682 | * what get passed to sys_open(). | ||
1683 | */ | ||
1684 | static int __open_namei_create(struct nameidata *nd, struct path *path, | ||
1681 | int flag, int mode) | 1685 | int flag, int mode) |
1682 | { | 1686 | { |
1683 | int error; | 1687 | int error; |
@@ -1696,26 +1700,56 @@ static int open_namei_create(struct nameidata *nd, struct path *path, | |||
1696 | } | 1700 | } |
1697 | 1701 | ||
1698 | /* | 1702 | /* |
1699 | * open_namei() | 1703 | * Note that while the flag value (low two bits) for sys_open means: |
1704 | * 00 - read-only | ||
1705 | * 01 - write-only | ||
1706 | * 10 - read-write | ||
1707 | * 11 - special | ||
1708 | * it is changed into | ||
1709 | * 00 - no permissions needed | ||
1710 | * 01 - read-permission | ||
1711 | * 10 - write-permission | ||
1712 | * 11 - read-write | ||
1713 | * for the internal routines (ie open_namei()/follow_link() etc) | ||
1714 | * This is more logical, and also allows the 00 "no perm needed" | ||
1715 | * to be used for symlinks (where the permissions are checked | ||
1716 | * later). | ||
1700 | * | 1717 | * |
1701 | * namei for open - this is in fact almost the whole open-routine. | 1718 | */ |
1702 | * | 1719 | static inline int open_to_namei_flags(int flag) |
1703 | * Note that the low bits of "flag" aren't the same as in the open | 1720 | { |
1704 | * system call - they are 00 - no permissions needed | 1721 | if ((flag+1) & O_ACCMODE) |
1705 | * 01 - read permission needed | 1722 | flag++; |
1706 | * 10 - write permission needed | 1723 | return flag; |
1707 | * 11 - read/write permissions needed | 1724 | } |
1708 | * which is a lot more logical, and also allows the "no perm" needed | 1725 | |
1709 | * for symlinks (where the permissions are checked later). | 1726 | static int open_will_write_to_fs(int flag, struct inode *inode) |
1710 | * SMP-safe | 1727 | { |
1728 | /* | ||
1729 | * We'll never write to the fs underlying | ||
1730 | * a device file. | ||
1731 | */ | ||
1732 | if (special_file(inode->i_mode)) | ||
1733 | return 0; | ||
1734 | return (flag & O_TRUNC); | ||
1735 | } | ||
1736 | |||
1737 | /* | ||
1738 | * Note that the low bits of the passed in "open_flag" | ||
1739 | * are not the same as in the local variable "flag". See | ||
1740 | * open_to_namei_flags() for more details. | ||
1711 | */ | 1741 | */ |
1712 | int open_namei(int dfd, const char *pathname, int flag, | 1742 | struct file *do_filp_open(int dfd, const char *pathname, |
1713 | int mode, struct nameidata *nd) | 1743 | int open_flag, int mode) |
1714 | { | 1744 | { |
1745 | struct file *filp; | ||
1746 | struct nameidata nd; | ||
1715 | int acc_mode, error; | 1747 | int acc_mode, error; |
1716 | struct path path; | 1748 | struct path path; |
1717 | struct dentry *dir; | 1749 | struct dentry *dir; |
1718 | int count = 0; | 1750 | int count = 0; |
1751 | int will_write; | ||
1752 | int flag = open_to_namei_flags(open_flag); | ||
1719 | 1753 | ||
1720 | acc_mode = ACC_MODE(flag); | 1754 | acc_mode = ACC_MODE(flag); |
1721 | 1755 | ||
@@ -1733,18 +1767,19 @@ int open_namei(int dfd, const char *pathname, int flag, | |||
1733 | */ | 1767 | */ |
1734 | if (!(flag & O_CREAT)) { | 1768 | if (!(flag & O_CREAT)) { |
1735 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), | 1769 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), |
1736 | nd, flag); | 1770 | &nd, flag); |
1737 | if (error) | 1771 | if (error) |
1738 | return error; | 1772 | return ERR_PTR(error); |
1739 | goto ok; | 1773 | goto ok; |
1740 | } | 1774 | } |
1741 | 1775 | ||
1742 | /* | 1776 | /* |
1743 | * Create - we need to know the parent. | 1777 | * Create - we need to know the parent. |
1744 | */ | 1778 | */ |
1745 | error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); | 1779 | error = path_lookup_create(dfd, pathname, LOOKUP_PARENT, |
1780 | &nd, flag, mode); | ||
1746 | if (error) | 1781 | if (error) |
1747 | return error; | 1782 | return ERR_PTR(error); |
1748 | 1783 | ||
1749 | /* | 1784 | /* |
1750 | * We have the parent and last component. First of all, check | 1785 | * We have the parent and last component. First of all, check |
@@ -1752,14 +1787,14 @@ int open_namei(int dfd, const char *pathname, int flag, | |||
1752 | * will not do. | 1787 | * will not do. |
1753 | */ | 1788 | */ |
1754 | error = -EISDIR; | 1789 | error = -EISDIR; |
1755 | if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) | 1790 | if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len]) |
1756 | goto exit; | 1791 | goto exit; |
1757 | 1792 | ||
1758 | dir = nd->path.dentry; | 1793 | dir = nd.path.dentry; |
1759 | nd->flags &= ~LOOKUP_PARENT; | 1794 | nd.flags &= ~LOOKUP_PARENT; |
1760 | mutex_lock(&dir->d_inode->i_mutex); | 1795 | mutex_lock(&dir->d_inode->i_mutex); |
1761 | path.dentry = lookup_hash(nd); | 1796 | path.dentry = lookup_hash(&nd); |
1762 | path.mnt = nd->path.mnt; | 1797 | path.mnt = nd.path.mnt; |
1763 | 1798 | ||
1764 | do_last: | 1799 | do_last: |
1765 | error = PTR_ERR(path.dentry); | 1800 | error = PTR_ERR(path.dentry); |
@@ -1768,18 +1803,31 @@ do_last: | |||
1768 | goto exit; | 1803 | goto exit; |
1769 | } | 1804 | } |
1770 | 1805 | ||
1771 | if (IS_ERR(nd->intent.open.file)) { | 1806 | if (IS_ERR(nd.intent.open.file)) { |
1772 | mutex_unlock(&dir->d_inode->i_mutex); | 1807 | error = PTR_ERR(nd.intent.open.file); |
1773 | error = PTR_ERR(nd->intent.open.file); | 1808 | goto exit_mutex_unlock; |
1774 | goto exit_dput; | ||
1775 | } | 1809 | } |
1776 | 1810 | ||
1777 | /* Negative dentry, just create the file */ | 1811 | /* Negative dentry, just create the file */ |
1778 | if (!path.dentry->d_inode) { | 1812 | if (!path.dentry->d_inode) { |
1779 | error = open_namei_create(nd, &path, flag, mode); | 1813 | /* |
1814 | * This write is needed to ensure that a | ||
1815 | * ro->rw transition does not occur between | ||
1816 | * the time when the file is created and when | ||
1817 | * a permanent write count is taken through | ||
1818 | * the 'struct file' in nameidata_to_filp(). | ||
1819 | */ | ||
1820 | error = mnt_want_write(nd.path.mnt); | ||
1780 | if (error) | 1821 | if (error) |
1822 | goto exit_mutex_unlock; | ||
1823 | error = __open_namei_create(&nd, &path, flag, mode); | ||
1824 | if (error) { | ||
1825 | mnt_drop_write(nd.path.mnt); | ||
1781 | goto exit; | 1826 | goto exit; |
1782 | return 0; | 1827 | } |
1828 | filp = nameidata_to_filp(&nd, open_flag); | ||
1829 | mnt_drop_write(nd.path.mnt); | ||
1830 | return filp; | ||
1783 | } | 1831 | } |
1784 | 1832 | ||
1785 | /* | 1833 | /* |
@@ -1804,23 +1852,52 @@ do_last: | |||
1804 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) | 1852 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) |
1805 | goto do_link; | 1853 | goto do_link; |
1806 | 1854 | ||
1807 | path_to_nameidata(&path, nd); | 1855 | path_to_nameidata(&path, &nd); |
1808 | error = -EISDIR; | 1856 | error = -EISDIR; |
1809 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) | 1857 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) |
1810 | goto exit; | 1858 | goto exit; |
1811 | ok: | 1859 | ok: |
1812 | error = may_open(nd, acc_mode, flag); | 1860 | /* |
1813 | if (error) | 1861 | * Consider: |
1862 | * 1. may_open() truncates a file | ||
1863 | * 2. a rw->ro mount transition occurs | ||
1864 | * 3. nameidata_to_filp() fails due to | ||
1865 | * the ro mount. | ||
1866 | * That would be inconsistent, and should | ||
1867 | * be avoided. Taking this mnt write here | ||
1868 | * ensures that (2) can not occur. | ||
1869 | */ | ||
1870 | will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode); | ||
1871 | if (will_write) { | ||
1872 | error = mnt_want_write(nd.path.mnt); | ||
1873 | if (error) | ||
1874 | goto exit; | ||
1875 | } | ||
1876 | error = may_open(&nd, acc_mode, flag); | ||
1877 | if (error) { | ||
1878 | if (will_write) | ||
1879 | mnt_drop_write(nd.path.mnt); | ||
1814 | goto exit; | 1880 | goto exit; |
1815 | return 0; | 1881 | } |
1882 | filp = nameidata_to_filp(&nd, open_flag); | ||
1883 | /* | ||
1884 | * It is now safe to drop the mnt write | ||
1885 | * because the filp has had a write taken | ||
1886 | * on its behalf. | ||
1887 | */ | ||
1888 | if (will_write) | ||
1889 | mnt_drop_write(nd.path.mnt); | ||
1890 | return filp; | ||
1816 | 1891 | ||
1892 | exit_mutex_unlock: | ||
1893 | mutex_unlock(&dir->d_inode->i_mutex); | ||
1817 | exit_dput: | 1894 | exit_dput: |
1818 | path_put_conditional(&path, nd); | 1895 | path_put_conditional(&path, &nd); |
1819 | exit: | 1896 | exit: |
1820 | if (!IS_ERR(nd->intent.open.file)) | 1897 | if (!IS_ERR(nd.intent.open.file)) |
1821 | release_open_intent(nd); | 1898 | release_open_intent(&nd); |
1822 | path_put(&nd->path); | 1899 | path_put(&nd.path); |
1823 | return error; | 1900 | return ERR_PTR(error); |
1824 | 1901 | ||
1825 | do_link: | 1902 | do_link: |
1826 | error = -ELOOP; | 1903 | error = -ELOOP; |
@@ -1836,43 +1913,60 @@ do_link: | |||
1836 | * stored in nd->last.name and we will have to putname() it when we | 1913 | * stored in nd->last.name and we will have to putname() it when we |
1837 | * are done. Procfs-like symlinks just set LAST_BIND. | 1914 | * are done. Procfs-like symlinks just set LAST_BIND. |
1838 | */ | 1915 | */ |
1839 | nd->flags |= LOOKUP_PARENT; | 1916 | nd.flags |= LOOKUP_PARENT; |
1840 | error = security_inode_follow_link(path.dentry, nd); | 1917 | error = security_inode_follow_link(path.dentry, &nd); |
1841 | if (error) | 1918 | if (error) |
1842 | goto exit_dput; | 1919 | goto exit_dput; |
1843 | error = __do_follow_link(&path, nd); | 1920 | error = __do_follow_link(&path, &nd); |
1844 | if (error) { | 1921 | if (error) { |
1845 | /* Does someone understand code flow here? Or it is only | 1922 | /* Does someone understand code flow here? Or it is only |
1846 | * me so stupid? Anathema to whoever designed this non-sense | 1923 | * me so stupid? Anathema to whoever designed this non-sense |
1847 | * with "intent.open". | 1924 | * with "intent.open". |
1848 | */ | 1925 | */ |
1849 | release_open_intent(nd); | 1926 | release_open_intent(&nd); |
1850 | return error; | 1927 | return ERR_PTR(error); |
1851 | } | 1928 | } |
1852 | nd->flags &= ~LOOKUP_PARENT; | 1929 | nd.flags &= ~LOOKUP_PARENT; |
1853 | if (nd->last_type == LAST_BIND) | 1930 | if (nd.last_type == LAST_BIND) |
1854 | goto ok; | 1931 | goto ok; |
1855 | error = -EISDIR; | 1932 | error = -EISDIR; |
1856 | if (nd->last_type != LAST_NORM) | 1933 | if (nd.last_type != LAST_NORM) |
1857 | goto exit; | 1934 | goto exit; |
1858 | if (nd->last.name[nd->last.len]) { | 1935 | if (nd.last.name[nd.last.len]) { |
1859 | __putname(nd->last.name); | 1936 | __putname(nd.last.name); |
1860 | goto exit; | 1937 | goto exit; |
1861 | } | 1938 | } |
1862 | error = -ELOOP; | 1939 | error = -ELOOP; |
1863 | if (count++==32) { | 1940 | if (count++==32) { |
1864 | __putname(nd->last.name); | 1941 | __putname(nd.last.name); |
1865 | goto exit; | 1942 | goto exit; |
1866 | } | 1943 | } |
1867 | dir = nd->path.dentry; | 1944 | dir = nd.path.dentry; |
1868 | mutex_lock(&dir->d_inode->i_mutex); | 1945 | mutex_lock(&dir->d_inode->i_mutex); |
1869 | path.dentry = lookup_hash(nd); | 1946 | path.dentry = lookup_hash(&nd); |
1870 | path.mnt = nd->path.mnt; | 1947 | path.mnt = nd.path.mnt; |
1871 | __putname(nd->last.name); | 1948 | __putname(nd.last.name); |
1872 | goto do_last; | 1949 | goto do_last; |
1873 | } | 1950 | } |
1874 | 1951 | ||
1875 | /** | 1952 | /** |
1953 | * filp_open - open file and return file pointer | ||
1954 | * | ||
1955 | * @filename: path to open | ||
1956 | * @flags: open flags as per the open(2) second argument | ||
1957 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
1958 | * | ||
1959 | * This is the helper to open a file from kernelspace if you really | ||
1960 | * have to. But in generally you should not do this, so please move | ||
1961 | * along, nothing to see here.. | ||
1962 | */ | ||
1963 | struct file *filp_open(const char *filename, int flags, int mode) | ||
1964 | { | ||
1965 | return do_filp_open(AT_FDCWD, filename, flags, mode); | ||
1966 | } | ||
1967 | EXPORT_SYMBOL(filp_open); | ||
1968 | |||
1969 | /** | ||
1876 | * lookup_create - lookup a dentry, creating it if it doesn't exist | 1970 | * lookup_create - lookup a dentry, creating it if it doesn't exist |
1877 | * @nd: nameidata info | 1971 | * @nd: nameidata info |
1878 | * @is_dir: directory flag | 1972 | * @is_dir: directory flag |
@@ -1945,6 +2039,23 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
1945 | return error; | 2039 | return error; |
1946 | } | 2040 | } |
1947 | 2041 | ||
2042 | static int may_mknod(mode_t mode) | ||
2043 | { | ||
2044 | switch (mode & S_IFMT) { | ||
2045 | case S_IFREG: | ||
2046 | case S_IFCHR: | ||
2047 | case S_IFBLK: | ||
2048 | case S_IFIFO: | ||
2049 | case S_IFSOCK: | ||
2050 | case 0: /* zero mode translates to S_IFREG */ | ||
2051 | return 0; | ||
2052 | case S_IFDIR: | ||
2053 | return -EPERM; | ||
2054 | default: | ||
2055 | return -EINVAL; | ||
2056 | } | ||
2057 | } | ||
2058 | |||
1948 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | 2059 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, |
1949 | unsigned dev) | 2060 | unsigned dev) |
1950 | { | 2061 | { |
@@ -1963,12 +2074,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1963 | if (error) | 2074 | if (error) |
1964 | goto out; | 2075 | goto out; |
1965 | dentry = lookup_create(&nd, 0); | 2076 | dentry = lookup_create(&nd, 0); |
1966 | error = PTR_ERR(dentry); | 2077 | if (IS_ERR(dentry)) { |
1967 | 2078 | error = PTR_ERR(dentry); | |
2079 | goto out_unlock; | ||
2080 | } | ||
1968 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) | 2081 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
1969 | mode &= ~current->fs->umask; | 2082 | mode &= ~current->fs->umask; |
1970 | if (!IS_ERR(dentry)) { | 2083 | error = may_mknod(mode); |
1971 | switch (mode & S_IFMT) { | 2084 | if (error) |
2085 | goto out_dput; | ||
2086 | error = mnt_want_write(nd.path.mnt); | ||
2087 | if (error) | ||
2088 | goto out_dput; | ||
2089 | switch (mode & S_IFMT) { | ||
1972 | case 0: case S_IFREG: | 2090 | case 0: case S_IFREG: |
1973 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2091 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
1974 | break; | 2092 | break; |
@@ -1979,14 +2097,11 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1979 | case S_IFIFO: case S_IFSOCK: | 2097 | case S_IFIFO: case S_IFSOCK: |
1980 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2098 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
1981 | break; | 2099 | break; |
1982 | case S_IFDIR: | ||
1983 | error = -EPERM; | ||
1984 | break; | ||
1985 | default: | ||
1986 | error = -EINVAL; | ||
1987 | } | ||
1988 | dput(dentry); | ||
1989 | } | 2100 | } |
2101 | mnt_drop_write(nd.path.mnt); | ||
2102 | out_dput: | ||
2103 | dput(dentry); | ||
2104 | out_unlock: | ||
1990 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2105 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
1991 | path_put(&nd.path); | 2106 | path_put(&nd.path); |
1992 | out: | 2107 | out: |
@@ -2044,7 +2159,12 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2044 | 2159 | ||
2045 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) | 2160 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
2046 | mode &= ~current->fs->umask; | 2161 | mode &= ~current->fs->umask; |
2162 | error = mnt_want_write(nd.path.mnt); | ||
2163 | if (error) | ||
2164 | goto out_dput; | ||
2047 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2165 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
2166 | mnt_drop_write(nd.path.mnt); | ||
2167 | out_dput: | ||
2048 | dput(dentry); | 2168 | dput(dentry); |
2049 | out_unlock: | 2169 | out_unlock: |
2050 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2170 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2151,7 +2271,12 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2151 | error = PTR_ERR(dentry); | 2271 | error = PTR_ERR(dentry); |
2152 | if (IS_ERR(dentry)) | 2272 | if (IS_ERR(dentry)) |
2153 | goto exit2; | 2273 | goto exit2; |
2274 | error = mnt_want_write(nd.path.mnt); | ||
2275 | if (error) | ||
2276 | goto exit3; | ||
2154 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2277 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
2278 | mnt_drop_write(nd.path.mnt); | ||
2279 | exit3: | ||
2155 | dput(dentry); | 2280 | dput(dentry); |
2156 | exit2: | 2281 | exit2: |
2157 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2282 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2232,7 +2357,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2232 | inode = dentry->d_inode; | 2357 | inode = dentry->d_inode; |
2233 | if (inode) | 2358 | if (inode) |
2234 | atomic_inc(&inode->i_count); | 2359 | atomic_inc(&inode->i_count); |
2360 | error = mnt_want_write(nd.path.mnt); | ||
2361 | if (error) | ||
2362 | goto exit2; | ||
2235 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2363 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
2364 | mnt_drop_write(nd.path.mnt); | ||
2236 | exit2: | 2365 | exit2: |
2237 | dput(dentry); | 2366 | dput(dentry); |
2238 | } | 2367 | } |
@@ -2313,7 +2442,12 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2313 | if (IS_ERR(dentry)) | 2442 | if (IS_ERR(dentry)) |
2314 | goto out_unlock; | 2443 | goto out_unlock; |
2315 | 2444 | ||
2445 | error = mnt_want_write(nd.path.mnt); | ||
2446 | if (error) | ||
2447 | goto out_dput; | ||
2316 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); | 2448 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); |
2449 | mnt_drop_write(nd.path.mnt); | ||
2450 | out_dput: | ||
2317 | dput(dentry); | 2451 | dput(dentry); |
2318 | out_unlock: | 2452 | out_unlock: |
2319 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2453 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2408,7 +2542,12 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2408 | error = PTR_ERR(new_dentry); | 2542 | error = PTR_ERR(new_dentry); |
2409 | if (IS_ERR(new_dentry)) | 2543 | if (IS_ERR(new_dentry)) |
2410 | goto out_unlock; | 2544 | goto out_unlock; |
2545 | error = mnt_want_write(nd.path.mnt); | ||
2546 | if (error) | ||
2547 | goto out_dput; | ||
2411 | error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); | 2548 | error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); |
2549 | mnt_drop_write(nd.path.mnt); | ||
2550 | out_dput: | ||
2412 | dput(new_dentry); | 2551 | dput(new_dentry); |
2413 | out_unlock: | 2552 | out_unlock: |
2414 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2553 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2634,8 +2773,12 @@ static int do_rename(int olddfd, const char *oldname, | |||
2634 | if (new_dentry == trap) | 2773 | if (new_dentry == trap) |
2635 | goto exit5; | 2774 | goto exit5; |
2636 | 2775 | ||
2776 | error = mnt_want_write(oldnd.path.mnt); | ||
2777 | if (error) | ||
2778 | goto exit5; | ||
2637 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2779 | error = vfs_rename(old_dir->d_inode, old_dentry, |
2638 | new_dir->d_inode, new_dentry); | 2780 | new_dir->d_inode, new_dentry); |
2781 | mnt_drop_write(oldnd.path.mnt); | ||
2639 | exit5: | 2782 | exit5: |
2640 | dput(new_dentry); | 2783 | dput(new_dentry); |
2641 | exit4: | 2784 | exit4: |