Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull mount leak fix from Al Viro:
"Regression fix for the syscalls-for-init series - fix a leak of a 'struct path'"

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
fs: fix a struct path leak in path_umount

+18 -14
+18 -14
fs/namespace.c
··· 1706 1706 } 1707 1707 #endif 1708 1708 1709 - int path_umount(struct path *path, int flags) 1709 + static int can_umount(const struct path *path, int flags) 1710 1710 { 1711 - struct mount *mnt; 1712 - int retval; 1711 + struct mount *mnt = real_mount(path->mnt); 1713 1712 1714 1713 if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) 1715 1714 return -EINVAL; 1716 1715 if (!may_mount()) 1717 1716 return -EPERM; 1718 - 1719 - mnt = real_mount(path->mnt); 1720 - retval = -EINVAL; 1721 1717 if (path->dentry != path->mnt->mnt_root) 1722 - goto dput_and_out; 1718 + return -EINVAL; 1723 1719 if (!check_mnt(mnt)) 1724 - goto dput_and_out; 1720 + return -EINVAL; 1725 1721 if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */ 1726 - goto dput_and_out; 1727 - retval = -EPERM; 1722 + return -EINVAL; 1728 1723 if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) 1729 - goto dput_and_out; 1724 + return -EPERM; 1725 + return 0; 1726 + } 1730 1727 1731 - retval = do_umount(mnt, flags); 1732 - dput_and_out: 1728 + int path_umount(struct path *path, int flags) 1729 + { 1730 + struct mount *mnt = real_mount(path->mnt); 1731 + int ret; 1732 + 1733 + ret = can_umount(path, flags); 1734 + if (!ret) 1735 + ret = do_umount(mnt, flags); 1736 + 1733 1737 /* we mustn't call path_put() as that would clear mnt_expiry_mark */ 1734 1738 dput(path->dentry); 1735 1739 mntput_no_expire(mnt); 1736 - return retval; 1740 + return ret; 1737 1741 } 1738 1742 1739 1743 static int ksys_umount(char __user *name, int flags)