diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 119 |
1 files changed, 59 insertions, 60 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 6e283c93b50d..9f6005e55862 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 | ||
1170 | static int mount_is_safe(struct nameidata *nd) | 1170 | static 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 |
@@ -1427,9 +1427,9 @@ out_unlock: | |||
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. | 1428 | * noinline this do_mount helper to save do_mount stack space. |
1429 | */ | 1429 | */ |
1430 | static noinline int do_change_type(struct nameidata *nd, int flag) | 1430 | static noinline int do_change_type(struct path *path, int flag) |
1431 | { | 1431 | { |
1432 | struct vfsmount *m, *mnt = nd->path.mnt; | 1432 | struct vfsmount *m, *mnt = path->mnt; |
1433 | int recurse = flag & MS_REC; | 1433 | int recurse = flag & MS_REC; |
1434 | int type = flag & ~MS_REC; | 1434 | int type = flag & ~MS_REC; |
1435 | int err = 0; | 1435 | int err = 0; |
@@ -1437,7 +1437,7 @@ static noinline int do_change_type(struct nameidata *nd, int flag) | |||
1437 | if (!capable(CAP_SYS_ADMIN)) | 1437 | if (!capable(CAP_SYS_ADMIN)) |
1438 | return -EPERM; | 1438 | return -EPERM; |
1439 | 1439 | ||
1440 | if (nd->path.dentry != nd->path.mnt->mnt_root) | 1440 | if (path->dentry != path->mnt->mnt_root) |
1441 | return -EINVAL; | 1441 | return -EINVAL; |
1442 | 1442 | ||
1443 | down_write(&namespace_sem); | 1443 | down_write(&namespace_sem); |
@@ -1461,38 +1461,38 @@ static noinline int do_change_type(struct nameidata *nd, int flag) | |||
1461 | * do loopback mount. | 1461 | * do loopback mount. |
1462 | * noinline this do_mount helper to save do_mount stack space. | 1462 | * noinline this do_mount helper to save do_mount stack space. |
1463 | */ | 1463 | */ |
1464 | static noinline int do_loopback(struct nameidata *nd, char *old_name, | 1464 | static noinline int do_loopback(struct path *path, char *old_name, |
1465 | int recurse) | 1465 | int recurse) |
1466 | { | 1466 | { |
1467 | struct nameidata old_nd; | 1467 | struct path old_path; |
1468 | struct vfsmount *mnt = NULL; | 1468 | struct vfsmount *mnt = NULL; |
1469 | int err = mount_is_safe(nd); | 1469 | int err = mount_is_safe(path); |
1470 | if (err) | 1470 | if (err) |
1471 | return err; | 1471 | return err; |
1472 | if (!old_name || !*old_name) | 1472 | if (!old_name || !*old_name) |
1473 | return -EINVAL; | 1473 | return -EINVAL; |
1474 | err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd); | 1474 | err = kern_path(old_name, LOOKUP_FOLLOW, &old_path); |
1475 | if (err) | 1475 | if (err) |
1476 | return err; | 1476 | return err; |
1477 | 1477 | ||
1478 | down_write(&namespace_sem); | 1478 | down_write(&namespace_sem); |
1479 | err = -EINVAL; | 1479 | err = -EINVAL; |
1480 | if (IS_MNT_UNBINDABLE(old_nd.path.mnt)) | 1480 | if (IS_MNT_UNBINDABLE(old_path.mnt)) |
1481 | goto out; | 1481 | goto out; |
1482 | 1482 | ||
1483 | if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) | 1483 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1484 | goto out; | 1484 | goto out; |
1485 | 1485 | ||
1486 | err = -ENOMEM; | 1486 | err = -ENOMEM; |
1487 | if (recurse) | 1487 | if (recurse) |
1488 | mnt = copy_tree(old_nd.path.mnt, old_nd.path.dentry, 0); | 1488 | mnt = copy_tree(old_path.mnt, old_path.dentry, 0); |
1489 | else | 1489 | else |
1490 | mnt = clone_mnt(old_nd.path.mnt, old_nd.path.dentry, 0); | 1490 | mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); |
1491 | 1491 | ||
1492 | if (!mnt) | 1492 | if (!mnt) |
1493 | goto out; | 1493 | goto out; |
1494 | 1494 | ||
1495 | err = graft_tree(mnt, &nd->path); | 1495 | err = graft_tree(mnt, path); |
1496 | if (err) { | 1496 | if (err) { |
1497 | LIST_HEAD(umount_list); | 1497 | LIST_HEAD(umount_list); |
1498 | spin_lock(&vfsmount_lock); | 1498 | spin_lock(&vfsmount_lock); |
@@ -1503,7 +1503,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name, | |||
1503 | 1503 | ||
1504 | out: | 1504 | out: |
1505 | up_write(&namespace_sem); | 1505 | up_write(&namespace_sem); |
1506 | path_put(&old_nd.path); | 1506 | path_put(&old_path); |
1507 | return err; | 1507 | return err; |
1508 | } | 1508 | } |
1509 | 1509 | ||
@@ -1530,31 +1530,31 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) | |||
1530 | * on it - tough luck. | 1530 | * on it - tough luck. |
1531 | * noinline this do_mount helper to save do_mount stack space. | 1531 | * noinline this do_mount helper to save do_mount stack space. |
1532 | */ | 1532 | */ |
1533 | static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags, | 1533 | static noinline int do_remount(struct path *path, int flags, int mnt_flags, |
1534 | void *data) | 1534 | void *data) |
1535 | { | 1535 | { |
1536 | int err; | 1536 | int err; |
1537 | struct super_block *sb = nd->path.mnt->mnt_sb; | 1537 | struct super_block *sb = path->mnt->mnt_sb; |
1538 | 1538 | ||
1539 | if (!capable(CAP_SYS_ADMIN)) | 1539 | if (!capable(CAP_SYS_ADMIN)) |
1540 | return -EPERM; | 1540 | return -EPERM; |
1541 | 1541 | ||
1542 | if (!check_mnt(nd->path.mnt)) | 1542 | if (!check_mnt(path->mnt)) |
1543 | return -EINVAL; | 1543 | return -EINVAL; |
1544 | 1544 | ||
1545 | if (nd->path.dentry != nd->path.mnt->mnt_root) | 1545 | if (path->dentry != path->mnt->mnt_root) |
1546 | return -EINVAL; | 1546 | return -EINVAL; |
1547 | 1547 | ||
1548 | down_write(&sb->s_umount); | 1548 | down_write(&sb->s_umount); |
1549 | if (flags & MS_BIND) | 1549 | if (flags & MS_BIND) |
1550 | err = change_mount_flags(nd->path.mnt, flags); | 1550 | err = change_mount_flags(path->mnt, flags); |
1551 | else | 1551 | else |
1552 | err = do_remount_sb(sb, flags, data, 0); | 1552 | err = do_remount_sb(sb, flags, data, 0); |
1553 | if (!err) | 1553 | if (!err) |
1554 | nd->path.mnt->mnt_flags = mnt_flags; | 1554 | path->mnt->mnt_flags = mnt_flags; |
1555 | up_write(&sb->s_umount); | 1555 | up_write(&sb->s_umount); |
1556 | if (!err) | 1556 | if (!err) |
1557 | security_sb_post_remount(nd->path.mnt, flags, data); | 1557 | security_sb_post_remount(path->mnt, flags, data); |
1558 | return err; | 1558 | return err; |
1559 | } | 1559 | } |
1560 | 1560 | ||
@@ -1571,78 +1571,77 @@ static inline int tree_contains_unbindable(struct vfsmount *mnt) | |||
1571 | /* | 1571 | /* |
1572 | * noinline this do_mount helper to save do_mount stack space. | 1572 | * noinline this do_mount helper to save do_mount stack space. |
1573 | */ | 1573 | */ |
1574 | static noinline int do_move_mount(struct nameidata *nd, char *old_name) | 1574 | static noinline int do_move_mount(struct path *path, char *old_name) |
1575 | { | 1575 | { |
1576 | struct nameidata old_nd; | 1576 | struct path old_path, parent_path; |
1577 | struct path parent_path; | ||
1578 | struct vfsmount *p; | 1577 | struct vfsmount *p; |
1579 | int err = 0; | 1578 | int err = 0; |
1580 | if (!capable(CAP_SYS_ADMIN)) | 1579 | if (!capable(CAP_SYS_ADMIN)) |
1581 | return -EPERM; | 1580 | return -EPERM; |
1582 | if (!old_name || !*old_name) | 1581 | if (!old_name || !*old_name) |
1583 | return -EINVAL; | 1582 | return -EINVAL; |
1584 | err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd); | 1583 | err = kern_path(old_name, LOOKUP_FOLLOW, &old_path); |
1585 | if (err) | 1584 | if (err) |
1586 | return err; | 1585 | return err; |
1587 | 1586 | ||
1588 | down_write(&namespace_sem); | 1587 | down_write(&namespace_sem); |
1589 | while (d_mountpoint(nd->path.dentry) && | 1588 | while (d_mountpoint(path->dentry) && |
1590 | follow_down(&nd->path.mnt, &nd->path.dentry)) | 1589 | follow_down(&path->mnt, &path->dentry)) |
1591 | ; | 1590 | ; |
1592 | err = -EINVAL; | 1591 | err = -EINVAL; |
1593 | if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) | 1592 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1594 | goto out; | 1593 | goto out; |
1595 | 1594 | ||
1596 | err = -ENOENT; | 1595 | err = -ENOENT; |
1597 | mutex_lock(&nd->path.dentry->d_inode->i_mutex); | 1596 | mutex_lock(&path->dentry->d_inode->i_mutex); |
1598 | if (IS_DEADDIR(nd->path.dentry->d_inode)) | 1597 | if (IS_DEADDIR(path->dentry->d_inode)) |
1599 | goto out1; | 1598 | goto out1; |
1600 | 1599 | ||
1601 | if (!IS_ROOT(nd->path.dentry) && d_unhashed(nd->path.dentry)) | 1600 | if (!IS_ROOT(path->dentry) && d_unhashed(path->dentry)) |
1602 | goto out1; | 1601 | goto out1; |
1603 | 1602 | ||
1604 | err = -EINVAL; | 1603 | err = -EINVAL; |
1605 | if (old_nd.path.dentry != old_nd.path.mnt->mnt_root) | 1604 | if (old_path.dentry != old_path.mnt->mnt_root) |
1606 | goto out1; | 1605 | goto out1; |
1607 | 1606 | ||
1608 | if (old_nd.path.mnt == old_nd.path.mnt->mnt_parent) | 1607 | if (old_path.mnt == old_path.mnt->mnt_parent) |
1609 | goto out1; | 1608 | goto out1; |
1610 | 1609 | ||
1611 | if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != | 1610 | if (S_ISDIR(path->dentry->d_inode->i_mode) != |
1612 | S_ISDIR(old_nd.path.dentry->d_inode->i_mode)) | 1611 | S_ISDIR(old_path.dentry->d_inode->i_mode)) |
1613 | goto out1; | 1612 | goto out1; |
1614 | /* | 1613 | /* |
1615 | * Don't move a mount residing in a shared parent. | 1614 | * Don't move a mount residing in a shared parent. |
1616 | */ | 1615 | */ |
1617 | if (old_nd.path.mnt->mnt_parent && | 1616 | if (old_path.mnt->mnt_parent && |
1618 | IS_MNT_SHARED(old_nd.path.mnt->mnt_parent)) | 1617 | IS_MNT_SHARED(old_path.mnt->mnt_parent)) |
1619 | goto out1; | 1618 | goto out1; |
1620 | /* | 1619 | /* |
1621 | * Don't move a mount tree containing unbindable mounts to a destination | 1620 | * Don't move a mount tree containing unbindable mounts to a destination |
1622 | * mount which is shared. | 1621 | * mount which is shared. |
1623 | */ | 1622 | */ |
1624 | if (IS_MNT_SHARED(nd->path.mnt) && | 1623 | if (IS_MNT_SHARED(path->mnt) && |
1625 | tree_contains_unbindable(old_nd.path.mnt)) | 1624 | tree_contains_unbindable(old_path.mnt)) |
1626 | goto out1; | 1625 | goto out1; |
1627 | err = -ELOOP; | 1626 | err = -ELOOP; |
1628 | for (p = nd->path.mnt; p->mnt_parent != p; p = p->mnt_parent) | 1627 | for (p = path->mnt; p->mnt_parent != p; p = p->mnt_parent) |
1629 | if (p == old_nd.path.mnt) | 1628 | if (p == old_path.mnt) |
1630 | goto out1; | 1629 | goto out1; |
1631 | 1630 | ||
1632 | err = attach_recursive_mnt(old_nd.path.mnt, &nd->path, &parent_path); | 1631 | err = attach_recursive_mnt(old_path.mnt, path, &parent_path); |
1633 | if (err) | 1632 | if (err) |
1634 | goto out1; | 1633 | goto out1; |
1635 | 1634 | ||
1636 | /* if the mount is moved, it should no longer be expire | 1635 | /* if the mount is moved, it should no longer be expire |
1637 | * automatically */ | 1636 | * automatically */ |
1638 | list_del_init(&old_nd.path.mnt->mnt_expire); | 1637 | list_del_init(&old_path.mnt->mnt_expire); |
1639 | out1: | 1638 | out1: |
1640 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); | 1639 | mutex_unlock(&path->dentry->d_inode->i_mutex); |
1641 | out: | 1640 | out: |
1642 | up_write(&namespace_sem); | 1641 | up_write(&namespace_sem); |
1643 | if (!err) | 1642 | if (!err) |
1644 | path_put(&parent_path); | 1643 | path_put(&parent_path); |
1645 | path_put(&old_nd.path); | 1644 | path_put(&old_path); |
1646 | return err; | 1645 | return err; |
1647 | } | 1646 | } |
1648 | 1647 | ||
@@ -1651,7 +1650,7 @@ out: | |||
1651 | * namespace's tree | 1650 | * namespace's tree |
1652 | * noinline this do_mount helper to save do_mount stack space. | 1651 | * noinline this do_mount helper to save do_mount stack space. |
1653 | */ | 1652 | */ |
1654 | static noinline int do_new_mount(struct nameidata *nd, char *type, int flags, | 1653 | static noinline int do_new_mount(struct path *path, char *type, int flags, |
1655 | int mnt_flags, char *name, void *data) | 1654 | int mnt_flags, char *name, void *data) |
1656 | { | 1655 | { |
1657 | struct vfsmount *mnt; | 1656 | struct vfsmount *mnt; |
@@ -1667,7 +1666,7 @@ static noinline int do_new_mount(struct nameidata *nd, char *type, int flags, | |||
1667 | if (IS_ERR(mnt)) | 1666 | if (IS_ERR(mnt)) |
1668 | return PTR_ERR(mnt); | 1667 | return PTR_ERR(mnt); |
1669 | 1668 | ||
1670 | return do_add_mount(mnt, &nd->path, mnt_flags, NULL); | 1669 | return do_add_mount(mnt, path, mnt_flags, NULL); |
1671 | } | 1670 | } |
1672 | 1671 | ||
1673 | /* | 1672 | /* |
@@ -1902,7 +1901,7 @@ int copy_mount_options(const void __user * data, unsigned long *where) | |||
1902 | long do_mount(char *dev_name, char *dir_name, char *type_page, | 1901 | long do_mount(char *dev_name, char *dir_name, char *type_page, |
1903 | unsigned long flags, void *data_page) | 1902 | unsigned long flags, void *data_page) |
1904 | { | 1903 | { |
1905 | struct nameidata nd; | 1904 | struct path path; |
1906 | int retval = 0; | 1905 | int retval = 0; |
1907 | int mnt_flags = 0; | 1906 | int mnt_flags = 0; |
1908 | 1907 | ||
@@ -1940,29 +1939,29 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1940 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); | 1939 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); |
1941 | 1940 | ||
1942 | /* ... and get the mountpoint */ | 1941 | /* ... and get the mountpoint */ |
1943 | retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); | 1942 | retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); |
1944 | if (retval) | 1943 | if (retval) |
1945 | return retval; | 1944 | return retval; |
1946 | 1945 | ||
1947 | retval = security_sb_mount(dev_name, &nd.path, | 1946 | retval = security_sb_mount(dev_name, &path, |
1948 | type_page, flags, data_page); | 1947 | type_page, flags, data_page); |
1949 | if (retval) | 1948 | if (retval) |
1950 | goto dput_out; | 1949 | goto dput_out; |
1951 | 1950 | ||
1952 | if (flags & MS_REMOUNT) | 1951 | if (flags & MS_REMOUNT) |
1953 | retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, | 1952 | retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, |
1954 | data_page); | 1953 | data_page); |
1955 | else if (flags & MS_BIND) | 1954 | else if (flags & MS_BIND) |
1956 | retval = do_loopback(&nd, dev_name, flags & MS_REC); | 1955 | retval = do_loopback(&path, dev_name, flags & MS_REC); |
1957 | else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) | 1956 | else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) |
1958 | retval = do_change_type(&nd, flags); | 1957 | retval = do_change_type(&path, flags); |
1959 | else if (flags & MS_MOVE) | 1958 | else if (flags & MS_MOVE) |
1960 | retval = do_move_mount(&nd, dev_name); | 1959 | retval = do_move_mount(&path, dev_name); |
1961 | else | 1960 | else |
1962 | retval = do_new_mount(&nd, type_page, flags, mnt_flags, | 1961 | retval = do_new_mount(&path, type_page, flags, mnt_flags, |
1963 | dev_name, data_page); | 1962 | dev_name, data_page); |
1964 | dput_out: | 1963 | dput_out: |
1965 | path_put(&nd.path); | 1964 | path_put(&path); |
1966 | return retval; | 1965 | return retval; |
1967 | } | 1966 | } |
1968 | 1967 | ||