aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c133
1 files changed, 65 insertions, 68 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 6e283c93b50d..cce46702d33c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1167,19 +1167,19 @@ asmlinkage long sys_oldumount(char __user * name)
1167 1167
1168#endif 1168#endif
1169 1169
1170static int mount_is_safe(struct nameidata *nd) 1170static int mount_is_safe(struct path *path)
1171{ 1171{
1172 if (capable(CAP_SYS_ADMIN)) 1172 if (capable(CAP_SYS_ADMIN))
1173 return 0; 1173 return 0;
1174 return -EPERM; 1174 return -EPERM;
1175#ifdef notyet 1175#ifdef notyet
1176 if (S_ISLNK(nd->path.dentry->d_inode->i_mode)) 1176 if (S_ISLNK(path->dentry->d_inode->i_mode))
1177 return -EPERM; 1177 return -EPERM;
1178 if (nd->path.dentry->d_inode->i_mode & S_ISVTX) { 1178 if (path->dentry->d_inode->i_mode & S_ISVTX) {
1179 if (current->uid != nd->path.dentry->d_inode->i_uid) 1179 if (current->uid != path->dentry->d_inode->i_uid)
1180 return -EPERM; 1180 return -EPERM;
1181 } 1181 }
1182 if (vfs_permission(nd, MAY_WRITE)) 1182 if (inode_permission(path->dentry->d_inode, MAY_WRITE))
1183 return -EPERM; 1183 return -EPERM;
1184 return 0; 1184 return 0;
1185#endif 1185#endif
@@ -1425,11 +1425,10 @@ out_unlock:
1425 1425
1426/* 1426/*
1427 * recursively change the type of the mountpoint. 1427 * recursively change the type of the mountpoint.
1428 * noinline this do_mount helper to save do_mount stack space.
1429 */ 1428 */
1430static noinline int do_change_type(struct nameidata *nd, int flag) 1429static int do_change_type(struct path *path, int flag)
1431{ 1430{
1432 struct vfsmount *m, *mnt = nd->path.mnt; 1431 struct vfsmount *m, *mnt = path->mnt;
1433 int recurse = flag & MS_REC; 1432 int recurse = flag & MS_REC;
1434 int type = flag & ~MS_REC; 1433 int type = flag & ~MS_REC;
1435 int err = 0; 1434 int err = 0;
@@ -1437,7 +1436,7 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
1437 if (!capable(CAP_SYS_ADMIN)) 1436 if (!capable(CAP_SYS_ADMIN))
1438 return -EPERM; 1437 return -EPERM;
1439 1438
1440 if (nd->path.dentry != nd->path.mnt->mnt_root) 1439 if (path->dentry != path->mnt->mnt_root)
1441 return -EINVAL; 1440 return -EINVAL;
1442 1441
1443 down_write(&namespace_sem); 1442 down_write(&namespace_sem);
@@ -1459,40 +1458,39 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
1459 1458
1460/* 1459/*
1461 * do loopback mount. 1460 * do loopback mount.
1462 * noinline this do_mount helper to save do_mount stack space.
1463 */ 1461 */
1464static noinline int do_loopback(struct nameidata *nd, char *old_name, 1462static int do_loopback(struct path *path, char *old_name,
1465 int recurse) 1463 int recurse)
1466{ 1464{
1467 struct nameidata old_nd; 1465 struct path old_path;
1468 struct vfsmount *mnt = NULL; 1466 struct vfsmount *mnt = NULL;
1469 int err = mount_is_safe(nd); 1467 int err = mount_is_safe(path);
1470 if (err) 1468 if (err)
1471 return err; 1469 return err;
1472 if (!old_name || !*old_name) 1470 if (!old_name || !*old_name)
1473 return -EINVAL; 1471 return -EINVAL;
1474 err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd); 1472 err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
1475 if (err) 1473 if (err)
1476 return err; 1474 return err;
1477 1475
1478 down_write(&namespace_sem); 1476 down_write(&namespace_sem);
1479 err = -EINVAL; 1477 err = -EINVAL;
1480 if (IS_MNT_UNBINDABLE(old_nd.path.mnt)) 1478 if (IS_MNT_UNBINDABLE(old_path.mnt))
1481 goto out; 1479 goto out;
1482 1480
1483 if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) 1481 if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt))
1484 goto out; 1482 goto out;
1485 1483
1486 err = -ENOMEM; 1484 err = -ENOMEM;
1487 if (recurse) 1485 if (recurse)
1488 mnt = copy_tree(old_nd.path.mnt, old_nd.path.dentry, 0); 1486 mnt = copy_tree(old_path.mnt, old_path.dentry, 0);
1489 else 1487 else
1490 mnt = clone_mnt(old_nd.path.mnt, old_nd.path.dentry, 0); 1488 mnt = clone_mnt(old_path.mnt, old_path.dentry, 0);
1491 1489
1492 if (!mnt) 1490 if (!mnt)
1493 goto out; 1491 goto out;
1494 1492
1495 err = graft_tree(mnt, &nd->path); 1493 err = graft_tree(mnt, path);
1496 if (err) { 1494 if (err) {
1497 LIST_HEAD(umount_list); 1495 LIST_HEAD(umount_list);
1498 spin_lock(&vfsmount_lock); 1496 spin_lock(&vfsmount_lock);
@@ -1503,7 +1501,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
1503 1501
1504out: 1502out:
1505 up_write(&namespace_sem); 1503 up_write(&namespace_sem);
1506 path_put(&old_nd.path); 1504 path_put(&old_path);
1507 return err; 1505 return err;
1508} 1506}
1509 1507
@@ -1528,33 +1526,37 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
1528 * change filesystem flags. dir should be a physical root of filesystem. 1526 * change filesystem flags. dir should be a physical root of filesystem.
1529 * If you've mounted a non-root directory somewhere and want to do remount 1527 * If you've mounted a non-root directory somewhere and want to do remount
1530 * on it - tough luck. 1528 * on it - tough luck.
1531 * noinline this do_mount helper to save do_mount stack space.
1532 */ 1529 */
1533static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags, 1530static int do_remount(struct path *path, int flags, int mnt_flags,
1534 void *data) 1531 void *data)
1535{ 1532{
1536 int err; 1533 int err;
1537 struct super_block *sb = nd->path.mnt->mnt_sb; 1534 struct super_block *sb = path->mnt->mnt_sb;
1538 1535
1539 if (!capable(CAP_SYS_ADMIN)) 1536 if (!capable(CAP_SYS_ADMIN))
1540 return -EPERM; 1537 return -EPERM;
1541 1538
1542 if (!check_mnt(nd->path.mnt)) 1539 if (!check_mnt(path->mnt))
1543 return -EINVAL; 1540 return -EINVAL;
1544 1541
1545 if (nd->path.dentry != nd->path.mnt->mnt_root) 1542 if (path->dentry != path->mnt->mnt_root)
1546 return -EINVAL; 1543 return -EINVAL;
1547 1544
1548 down_write(&sb->s_umount); 1545 down_write(&sb->s_umount);
1549 if (flags & MS_BIND) 1546 if (flags & MS_BIND)
1550 err = change_mount_flags(nd->path.mnt, flags); 1547 err = change_mount_flags(path->mnt, flags);
1551 else 1548 else
1552 err = do_remount_sb(sb, flags, data, 0); 1549 err = do_remount_sb(sb, flags, data, 0);
1553 if (!err) 1550 if (!err)
1554 nd->path.mnt->mnt_flags = mnt_flags; 1551 path->mnt->mnt_flags = mnt_flags;
1555 up_write(&sb->s_umount); 1552 up_write(&sb->s_umount);
1556 if (!err) 1553 if (!err) {
1557 security_sb_post_remount(nd->path.mnt, flags, data); 1554 security_sb_post_remount(path->mnt, flags, data);
1555
1556 spin_lock(&vfsmount_lock);
1557 touch_mnt_namespace(path->mnt->mnt_ns);
1558 spin_unlock(&vfsmount_lock);
1559 }
1558 return err; 1560 return err;
1559} 1561}
1560 1562
@@ -1568,90 +1570,85 @@ static inline int tree_contains_unbindable(struct vfsmount *mnt)
1568 return 0; 1570 return 0;
1569} 1571}
1570 1572
1571/* 1573static int do_move_mount(struct path *path, char *old_name)
1572 * noinline this do_mount helper to save do_mount stack space.
1573 */
1574static noinline int do_move_mount(struct nameidata *nd, char *old_name)
1575{ 1574{
1576 struct nameidata old_nd; 1575 struct path old_path, parent_path;
1577 struct path parent_path;
1578 struct vfsmount *p; 1576 struct vfsmount *p;
1579 int err = 0; 1577 int err = 0;
1580 if (!capable(CAP_SYS_ADMIN)) 1578 if (!capable(CAP_SYS_ADMIN))
1581 return -EPERM; 1579 return -EPERM;
1582 if (!old_name || !*old_name) 1580 if (!old_name || !*old_name)
1583 return -EINVAL; 1581 return -EINVAL;
1584 err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd); 1582 err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
1585 if (err) 1583 if (err)
1586 return err; 1584 return err;
1587 1585
1588 down_write(&namespace_sem); 1586 down_write(&namespace_sem);
1589 while (d_mountpoint(nd->path.dentry) && 1587 while (d_mountpoint(path->dentry) &&
1590 follow_down(&nd->path.mnt, &nd->path.dentry)) 1588 follow_down(&path->mnt, &path->dentry))
1591 ; 1589 ;
1592 err = -EINVAL; 1590 err = -EINVAL;
1593 if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) 1591 if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt))
1594 goto out; 1592 goto out;
1595 1593
1596 err = -ENOENT; 1594 err = -ENOENT;
1597 mutex_lock(&nd->path.dentry->d_inode->i_mutex); 1595 mutex_lock(&path->dentry->d_inode->i_mutex);
1598 if (IS_DEADDIR(nd->path.dentry->d_inode)) 1596 if (IS_DEADDIR(path->dentry->d_inode))
1599 goto out1; 1597 goto out1;
1600 1598
1601 if (!IS_ROOT(nd->path.dentry) && d_unhashed(nd->path.dentry)) 1599 if (!IS_ROOT(path->dentry) && d_unhashed(path->dentry))
1602 goto out1; 1600 goto out1;
1603 1601
1604 err = -EINVAL; 1602 err = -EINVAL;
1605 if (old_nd.path.dentry != old_nd.path.mnt->mnt_root) 1603 if (old_path.dentry != old_path.mnt->mnt_root)
1606 goto out1; 1604 goto out1;
1607 1605
1608 if (old_nd.path.mnt == old_nd.path.mnt->mnt_parent) 1606 if (old_path.mnt == old_path.mnt->mnt_parent)
1609 goto out1; 1607 goto out1;
1610 1608
1611 if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != 1609 if (S_ISDIR(path->dentry->d_inode->i_mode) !=
1612 S_ISDIR(old_nd.path.dentry->d_inode->i_mode)) 1610 S_ISDIR(old_path.dentry->d_inode->i_mode))
1613 goto out1; 1611 goto out1;
1614 /* 1612 /*
1615 * Don't move a mount residing in a shared parent. 1613 * Don't move a mount residing in a shared parent.
1616 */ 1614 */
1617 if (old_nd.path.mnt->mnt_parent && 1615 if (old_path.mnt->mnt_parent &&
1618 IS_MNT_SHARED(old_nd.path.mnt->mnt_parent)) 1616 IS_MNT_SHARED(old_path.mnt->mnt_parent))
1619 goto out1; 1617 goto out1;
1620 /* 1618 /*
1621 * Don't move a mount tree containing unbindable mounts to a destination 1619 * Don't move a mount tree containing unbindable mounts to a destination
1622 * mount which is shared. 1620 * mount which is shared.
1623 */ 1621 */
1624 if (IS_MNT_SHARED(nd->path.mnt) && 1622 if (IS_MNT_SHARED(path->mnt) &&
1625 tree_contains_unbindable(old_nd.path.mnt)) 1623 tree_contains_unbindable(old_path.mnt))
1626 goto out1; 1624 goto out1;
1627 err = -ELOOP; 1625 err = -ELOOP;
1628 for (p = nd->path.mnt; p->mnt_parent != p; p = p->mnt_parent) 1626 for (p = path->mnt; p->mnt_parent != p; p = p->mnt_parent)
1629 if (p == old_nd.path.mnt) 1627 if (p == old_path.mnt)
1630 goto out1; 1628 goto out1;
1631 1629
1632 err = attach_recursive_mnt(old_nd.path.mnt, &nd->path, &parent_path); 1630 err = attach_recursive_mnt(old_path.mnt, path, &parent_path);
1633 if (err) 1631 if (err)
1634 goto out1; 1632 goto out1;
1635 1633
1636 /* if the mount is moved, it should no longer be expire 1634 /* if the mount is moved, it should no longer be expire
1637 * automatically */ 1635 * automatically */
1638 list_del_init(&old_nd.path.mnt->mnt_expire); 1636 list_del_init(&old_path.mnt->mnt_expire);
1639out1: 1637out1:
1640 mutex_unlock(&nd->path.dentry->d_inode->i_mutex); 1638 mutex_unlock(&path->dentry->d_inode->i_mutex);
1641out: 1639out:
1642 up_write(&namespace_sem); 1640 up_write(&namespace_sem);
1643 if (!err) 1641 if (!err)
1644 path_put(&parent_path); 1642 path_put(&parent_path);
1645 path_put(&old_nd.path); 1643 path_put(&old_path);
1646 return err; 1644 return err;
1647} 1645}
1648 1646
1649/* 1647/*
1650 * create a new mount for userspace and request it to be added into the 1648 * create a new mount for userspace and request it to be added into the
1651 * namespace's tree 1649 * namespace's tree
1652 * noinline this do_mount helper to save do_mount stack space.
1653 */ 1650 */
1654static noinline int do_new_mount(struct nameidata *nd, char *type, int flags, 1651static int do_new_mount(struct path *path, char *type, int flags,
1655 int mnt_flags, char *name, void *data) 1652 int mnt_flags, char *name, void *data)
1656{ 1653{
1657 struct vfsmount *mnt; 1654 struct vfsmount *mnt;
@@ -1667,7 +1664,7 @@ static noinline int do_new_mount(struct nameidata *nd, char *type, int flags,
1667 if (IS_ERR(mnt)) 1664 if (IS_ERR(mnt))
1668 return PTR_ERR(mnt); 1665 return PTR_ERR(mnt);
1669 1666
1670 return do_add_mount(mnt, &nd->path, mnt_flags, NULL); 1667 return do_add_mount(mnt, path, mnt_flags, NULL);
1671} 1668}
1672 1669
1673/* 1670/*
@@ -1902,7 +1899,7 @@ int copy_mount_options(const void __user * data, unsigned long *where)
1902long do_mount(char *dev_name, char *dir_name, char *type_page, 1899long do_mount(char *dev_name, char *dir_name, char *type_page,
1903 unsigned long flags, void *data_page) 1900 unsigned long flags, void *data_page)
1904{ 1901{
1905 struct nameidata nd; 1902 struct path path;
1906 int retval = 0; 1903 int retval = 0;
1907 int mnt_flags = 0; 1904 int mnt_flags = 0;
1908 1905
@@ -1940,29 +1937,29 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
1940 MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); 1937 MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT);
1941 1938
1942 /* ... and get the mountpoint */ 1939 /* ... and get the mountpoint */
1943 retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); 1940 retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
1944 if (retval) 1941 if (retval)
1945 return retval; 1942 return retval;
1946 1943
1947 retval = security_sb_mount(dev_name, &nd.path, 1944 retval = security_sb_mount(dev_name, &path,
1948 type_page, flags, data_page); 1945 type_page, flags, data_page);
1949 if (retval) 1946 if (retval)
1950 goto dput_out; 1947 goto dput_out;
1951 1948
1952 if (flags & MS_REMOUNT) 1949 if (flags & MS_REMOUNT)
1953 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, 1950 retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
1954 data_page); 1951 data_page);
1955 else if (flags & MS_BIND) 1952 else if (flags & MS_BIND)
1956 retval = do_loopback(&nd, dev_name, flags & MS_REC); 1953 retval = do_loopback(&path, dev_name, flags & MS_REC);
1957 else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) 1954 else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
1958 retval = do_change_type(&nd, flags); 1955 retval = do_change_type(&path, flags);
1959 else if (flags & MS_MOVE) 1956 else if (flags & MS_MOVE)
1960 retval = do_move_mount(&nd, dev_name); 1957 retval = do_move_mount(&path, dev_name);
1961 else 1958 else
1962 retval = do_new_mount(&nd, type_page, flags, mnt_flags, 1959 retval = do_new_mount(&path, type_page, flags, mnt_flags,
1963 dev_name, data_page); 1960 dev_name, data_page);
1964dput_out: 1961dput_out:
1965 path_put(&nd.path); 1962 path_put(&path);
1966 return retval; 1963 return retval;
1967} 1964}
1968 1965