diff options
| -rw-r--r-- | fs/namei.c | 171 |
1 files changed, 103 insertions, 68 deletions
diff --git a/fs/namei.c b/fs/namei.c index 60b74b3946a1..3c39fa1608c5 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1645,6 +1645,104 @@ exit: | |||
| 1645 | return ERR_PTR(error); | 1645 | return ERR_PTR(error); |
| 1646 | } | 1646 | } |
| 1647 | 1647 | ||
| 1648 | static struct file *do_last(struct nameidata *nd, struct path *path, | ||
| 1649 | int open_flag, int flag, int acc_mode, | ||
| 1650 | int mode, const char *pathname, | ||
| 1651 | struct dentry *dir, int *is_link) | ||
| 1652 | { | ||
| 1653 | struct file *filp; | ||
| 1654 | int error; | ||
| 1655 | |||
| 1656 | *is_link = 0; | ||
| 1657 | |||
| 1658 | error = PTR_ERR(path->dentry); | ||
| 1659 | if (IS_ERR(path->dentry)) { | ||
| 1660 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 1661 | goto exit; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | if (IS_ERR(nd->intent.open.file)) { | ||
| 1665 | error = PTR_ERR(nd->intent.open.file); | ||
| 1666 | goto exit_mutex_unlock; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | /* Negative dentry, just create the file */ | ||
| 1670 | if (!path->dentry->d_inode) { | ||
| 1671 | /* | ||
| 1672 | * This write is needed to ensure that a | ||
| 1673 | * ro->rw transition does not occur between | ||
| 1674 | * the time when the file is created and when | ||
| 1675 | * a permanent write count is taken through | ||
| 1676 | * the 'struct file' in nameidata_to_filp(). | ||
| 1677 | */ | ||
| 1678 | error = mnt_want_write(nd->path.mnt); | ||
| 1679 | if (error) | ||
| 1680 | goto exit_mutex_unlock; | ||
| 1681 | error = __open_namei_create(nd, path, open_flag, mode); | ||
| 1682 | if (error) { | ||
| 1683 | mnt_drop_write(nd->path.mnt); | ||
| 1684 | goto exit; | ||
| 1685 | } | ||
| 1686 | filp = nameidata_to_filp(nd); | ||
| 1687 | mnt_drop_write(nd->path.mnt); | ||
| 1688 | if (nd->root.mnt) | ||
| 1689 | path_put(&nd->root); | ||
| 1690 | if (!IS_ERR(filp)) { | ||
| 1691 | error = ima_file_check(filp, acc_mode); | ||
| 1692 | if (error) { | ||
| 1693 | fput(filp); | ||
| 1694 | filp = ERR_PTR(error); | ||
| 1695 | } | ||
| 1696 | } | ||
| 1697 | return filp; | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | /* | ||
| 1701 | * It already exists. | ||
| 1702 | */ | ||
| 1703 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 1704 | audit_inode(pathname, path->dentry); | ||
| 1705 | |||
| 1706 | error = -EEXIST; | ||
| 1707 | if (flag & O_EXCL) | ||
| 1708 | goto exit_dput; | ||
| 1709 | |||
| 1710 | if (__follow_mount(path)) { | ||
| 1711 | error = -ELOOP; | ||
| 1712 | if (flag & O_NOFOLLOW) | ||
| 1713 | goto exit_dput; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | error = -ENOENT; | ||
| 1717 | if (!path->dentry->d_inode) | ||
| 1718 | goto exit_dput; | ||
| 1719 | if (path->dentry->d_inode->i_op->follow_link) { | ||
| 1720 | *is_link = 1; | ||
| 1721 | return NULL; | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | path_to_nameidata(path, nd); | ||
| 1725 | error = -EISDIR; | ||
| 1726 | if (S_ISDIR(path->dentry->d_inode->i_mode)) | ||
| 1727 | goto exit; | ||
| 1728 | filp = finish_open(nd, open_flag, flag, acc_mode); | ||
| 1729 | if (nd->root.mnt) | ||
| 1730 | path_put(&nd->root); | ||
| 1731 | return filp; | ||
| 1732 | |||
| 1733 | exit_mutex_unlock: | ||
| 1734 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 1735 | exit_dput: | ||
| 1736 | path_put_conditional(path, nd); | ||
| 1737 | exit: | ||
| 1738 | if (!IS_ERR(nd->intent.open.file)) | ||
| 1739 | release_open_intent(nd); | ||
| 1740 | if (nd->root.mnt) | ||
| 1741 | path_put(&nd->root); | ||
| 1742 | path_put(&nd->path); | ||
| 1743 | return ERR_PTR(error); | ||
| 1744 | } | ||
| 1745 | |||
| 1648 | /* | 1746 | /* |
| 1649 | * Note that the low bits of the passed in "open_flag" | 1747 | * Note that the low bits of the passed in "open_flag" |
| 1650 | * are not the same as in the local variable "flag". See | 1748 | * are not the same as in the local variable "flag". See |
| @@ -1661,6 +1759,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
| 1661 | int count = 0; | 1759 | int count = 0; |
| 1662 | int flag = open_to_namei_flags(open_flag); | 1760 | int flag = open_to_namei_flags(open_flag); |
| 1663 | int force_reval = 0; | 1761 | int force_reval = 0; |
| 1762 | int is_link; | ||
| 1664 | 1763 | ||
| 1665 | /* | 1764 | /* |
| 1666 | * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only | 1765 | * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only |
| @@ -1754,82 +1853,18 @@ reval: | |||
| 1754 | path.mnt = nd.path.mnt; | 1853 | path.mnt = nd.path.mnt; |
| 1755 | 1854 | ||
| 1756 | do_last: | 1855 | do_last: |
| 1757 | error = PTR_ERR(path.dentry); | 1856 | filp = do_last(&nd, &path, open_flag, flag, acc_mode, mode, |
| 1758 | if (IS_ERR(path.dentry)) { | 1857 | pathname, dir, &is_link); |
| 1759 | mutex_unlock(&dir->d_inode->i_mutex); | 1858 | if (is_link) |
| 1760 | goto exit; | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | if (IS_ERR(nd.intent.open.file)) { | ||
| 1764 | error = PTR_ERR(nd.intent.open.file); | ||
| 1765 | goto exit_mutex_unlock; | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | /* Negative dentry, just create the file */ | ||
| 1769 | if (!path.dentry->d_inode) { | ||
| 1770 | /* | ||
| 1771 | * This write is needed to ensure that a | ||
| 1772 | * ro->rw transition does not occur between | ||
| 1773 | * the time when the file is created and when | ||
| 1774 | * a permanent write count is taken through | ||
| 1775 | * the 'struct file' in nameidata_to_filp(). | ||
| 1776 | */ | ||
| 1777 | error = mnt_want_write(nd.path.mnt); | ||
| 1778 | if (error) | ||
| 1779 | goto exit_mutex_unlock; | ||
| 1780 | error = __open_namei_create(&nd, &path, open_flag, mode); | ||
| 1781 | if (error) { | ||
| 1782 | mnt_drop_write(nd.path.mnt); | ||
| 1783 | goto exit; | ||
| 1784 | } | ||
| 1785 | filp = nameidata_to_filp(&nd); | ||
| 1786 | mnt_drop_write(nd.path.mnt); | ||
| 1787 | if (nd.root.mnt) | ||
| 1788 | path_put(&nd.root); | ||
| 1789 | if (!IS_ERR(filp)) { | ||
| 1790 | error = ima_file_check(filp, acc_mode); | ||
| 1791 | if (error) { | ||
| 1792 | fput(filp); | ||
| 1793 | filp = ERR_PTR(error); | ||
| 1794 | } | ||
| 1795 | } | ||
| 1796 | return filp; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | /* | ||
| 1800 | * It already exists. | ||
| 1801 | */ | ||
| 1802 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 1803 | audit_inode(pathname, path.dentry); | ||
| 1804 | |||
| 1805 | error = -EEXIST; | ||
| 1806 | if (flag & O_EXCL) | ||
| 1807 | goto exit_dput; | ||
| 1808 | |||
| 1809 | if (__follow_mount(&path)) { | ||
| 1810 | error = -ELOOP; | ||
| 1811 | if (flag & O_NOFOLLOW) | ||
| 1812 | goto exit_dput; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | error = -ENOENT; | ||
| 1816 | if (!path.dentry->d_inode) | ||
| 1817 | goto exit_dput; | ||
| 1818 | if (path.dentry->d_inode->i_op->follow_link) | ||
| 1819 | goto do_link; | 1859 | goto do_link; |
| 1860 | return filp; | ||
| 1820 | 1861 | ||
| 1821 | path_to_nameidata(&path, &nd); | ||
| 1822 | error = -EISDIR; | ||
| 1823 | if (S_ISDIR(path.dentry->d_inode->i_mode)) | ||
| 1824 | goto exit; | ||
| 1825 | ok: | 1862 | ok: |
| 1826 | filp = finish_open(&nd, open_flag, flag, acc_mode); | 1863 | filp = finish_open(&nd, open_flag, flag, acc_mode); |
| 1827 | if (nd.root.mnt) | 1864 | if (nd.root.mnt) |
| 1828 | path_put(&nd.root); | 1865 | path_put(&nd.root); |
| 1829 | return filp; | 1866 | return filp; |
| 1830 | 1867 | ||
| 1831 | exit_mutex_unlock: | ||
| 1832 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 1833 | exit_dput: | 1868 | exit_dput: |
| 1834 | path_put_conditional(&path, &nd); | 1869 | path_put_conditional(&path, &nd); |
| 1835 | exit: | 1870 | exit: |
