diff options
| -rw-r--r-- | fs/namei.c | 109 |
1 files changed, 56 insertions, 53 deletions
diff --git a/fs/namei.c b/fs/namei.c index 1fc038b117be..0f0fcccab19f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1444,69 +1444,52 @@ int may_open(struct path *path, int acc_mode, int flag) | |||
| 1444 | if (error) | 1444 | if (error) |
| 1445 | return error; | 1445 | return error; |
| 1446 | 1446 | ||
| 1447 | error = ima_path_check(path, acc_mode ? | ||
| 1448 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) : | ||
| 1449 | ACC_MODE(flag) & (MAY_READ | MAY_WRITE), | ||
| 1450 | IMA_COUNT_UPDATE); | ||
| 1451 | |||
| 1452 | if (error) | ||
| 1453 | return error; | ||
| 1454 | /* | 1447 | /* |
| 1455 | * An append-only file must be opened in append mode for writing. | 1448 | * An append-only file must be opened in append mode for writing. |
| 1456 | */ | 1449 | */ |
| 1457 | if (IS_APPEND(inode)) { | 1450 | if (IS_APPEND(inode)) { |
| 1458 | error = -EPERM; | ||
| 1459 | if ((flag & FMODE_WRITE) && !(flag & O_APPEND)) | 1451 | if ((flag & FMODE_WRITE) && !(flag & O_APPEND)) |
| 1460 | goto err_out; | 1452 | return -EPERM; |
| 1461 | if (flag & O_TRUNC) | 1453 | if (flag & O_TRUNC) |
| 1462 | goto err_out; | 1454 | return -EPERM; |
| 1463 | } | 1455 | } |
| 1464 | 1456 | ||
| 1465 | /* O_NOATIME can only be set by the owner or superuser */ | 1457 | /* O_NOATIME can only be set by the owner or superuser */ |
| 1466 | if (flag & O_NOATIME) | 1458 | if (flag & O_NOATIME && !is_owner_or_cap(inode)) |
| 1467 | if (!is_owner_or_cap(inode)) { | 1459 | return -EPERM; |
| 1468 | error = -EPERM; | ||
| 1469 | goto err_out; | ||
| 1470 | } | ||
| 1471 | 1460 | ||
| 1472 | /* | 1461 | /* |
| 1473 | * Ensure there are no outstanding leases on the file. | 1462 | * Ensure there are no outstanding leases on the file. |
| 1474 | */ | 1463 | */ |
| 1475 | error = break_lease(inode, flag); | 1464 | error = break_lease(inode, flag); |
| 1476 | if (error) | 1465 | if (error) |
| 1477 | goto err_out; | 1466 | return error; |
| 1478 | |||
| 1479 | if (flag & O_TRUNC) { | ||
| 1480 | error = get_write_access(inode); | ||
| 1481 | if (error) | ||
| 1482 | goto err_out; | ||
| 1483 | |||
| 1484 | /* | ||
| 1485 | * Refuse to truncate files with mandatory locks held on them. | ||
| 1486 | */ | ||
| 1487 | error = locks_verify_locked(inode); | ||
| 1488 | if (!error) | ||
| 1489 | error = security_path_truncate(path, 0, | ||
| 1490 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
| 1491 | if (!error) { | ||
| 1492 | vfs_dq_init(inode); | ||
| 1493 | 1467 | ||
| 1494 | error = do_truncate(dentry, 0, | 1468 | return ima_path_check(path, acc_mode ? |
| 1495 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, | 1469 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) : |
| 1496 | NULL); | 1470 | ACC_MODE(flag) & (MAY_READ | MAY_WRITE), |
| 1497 | } | 1471 | IMA_COUNT_UPDATE); |
| 1498 | put_write_access(inode); | 1472 | } |
| 1499 | if (error) | ||
| 1500 | goto err_out; | ||
| 1501 | } else | ||
| 1502 | if (flag & FMODE_WRITE) | ||
| 1503 | vfs_dq_init(inode); | ||
| 1504 | 1473 | ||
| 1505 | return 0; | 1474 | static int handle_truncate(struct path *path) |
| 1506 | err_out: | 1475 | { |
| 1507 | ima_counts_put(path, acc_mode ? | 1476 | struct inode *inode = path->dentry->d_inode; |
| 1508 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) : | 1477 | int error = get_write_access(inode); |
| 1509 | ACC_MODE(flag) & (MAY_READ | MAY_WRITE)); | 1478 | if (error) |
| 1479 | return error; | ||
| 1480 | /* | ||
| 1481 | * Refuse to truncate files with mandatory locks held on them. | ||
| 1482 | */ | ||
| 1483 | error = locks_verify_locked(inode); | ||
| 1484 | if (!error) | ||
| 1485 | error = security_path_truncate(path, 0, | ||
| 1486 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
| 1487 | if (!error) { | ||
| 1488 | error = do_truncate(path->dentry, 0, | ||
| 1489 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, | ||
| 1490 | NULL); | ||
| 1491 | } | ||
| 1492 | put_write_access(inode); | ||
| 1510 | return error; | 1493 | return error; |
| 1511 | } | 1494 | } |
| 1512 | 1495 | ||
| @@ -1561,7 +1544,7 @@ static inline int open_to_namei_flags(int flag) | |||
| 1561 | return flag; | 1544 | return flag; |
| 1562 | } | 1545 | } |
| 1563 | 1546 | ||
| 1564 | static int open_will_write_to_fs(int flag, struct inode *inode) | 1547 | static int open_will_truncate(int flag, struct inode *inode) |
| 1565 | { | 1548 | { |
| 1566 | /* | 1549 | /* |
| 1567 | * We'll never write to the fs underlying | 1550 | * We'll never write to the fs underlying |
| @@ -1586,7 +1569,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
| 1586 | struct path path, save; | 1569 | struct path path, save; |
| 1587 | struct dentry *dir; | 1570 | struct dentry *dir; |
| 1588 | int count = 0; | 1571 | int count = 0; |
| 1589 | int will_write; | 1572 | int will_truncate; |
| 1590 | int flag = open_to_namei_flags(open_flag); | 1573 | int flag = open_to_namei_flags(open_flag); |
| 1591 | 1574 | ||
| 1592 | /* | 1575 | /* |
| @@ -1752,28 +1735,48 @@ ok: | |||
| 1752 | * be avoided. Taking this mnt write here | 1735 | * be avoided. Taking this mnt write here |
| 1753 | * ensures that (2) can not occur. | 1736 | * ensures that (2) can not occur. |
| 1754 | */ | 1737 | */ |
| 1755 | will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode); | 1738 | will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode); |
| 1756 | if (will_write) { | 1739 | if (will_truncate) { |
| 1757 | error = mnt_want_write(nd.path.mnt); | 1740 | error = mnt_want_write(nd.path.mnt); |
| 1758 | if (error) | 1741 | if (error) |
| 1759 | goto exit; | 1742 | goto exit; |
| 1760 | } | 1743 | } |
| 1761 | error = may_open(&nd.path, acc_mode, flag); | 1744 | error = may_open(&nd.path, acc_mode, flag); |
| 1762 | if (error) { | 1745 | if (error) { |
| 1763 | if (will_write) | 1746 | if (will_truncate) |
| 1764 | mnt_drop_write(nd.path.mnt); | 1747 | mnt_drop_write(nd.path.mnt); |
| 1765 | goto exit; | 1748 | goto exit; |
| 1766 | } | 1749 | } |
| 1767 | filp = nameidata_to_filp(&nd, open_flag); | 1750 | filp = nameidata_to_filp(&nd, open_flag); |
| 1768 | if (IS_ERR(filp)) | 1751 | if (IS_ERR(filp)) { |
| 1769 | ima_counts_put(&nd.path, | 1752 | ima_counts_put(&nd.path, |
| 1770 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); | 1753 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); |
| 1754 | if (will_truncate) | ||
| 1755 | mnt_drop_write(nd.path.mnt); | ||
| 1756 | if (nd.root.mnt) | ||
| 1757 | path_put(&nd.root); | ||
| 1758 | return filp; | ||
| 1759 | } | ||
| 1760 | |||
| 1761 | if (acc_mode & MAY_WRITE) | ||
| 1762 | vfs_dq_init(nd.path.dentry->d_inode); | ||
| 1763 | |||
| 1764 | if (will_truncate) { | ||
| 1765 | error = handle_truncate(&nd.path); | ||
| 1766 | if (error) { | ||
| 1767 | mnt_drop_write(nd.path.mnt); | ||
| 1768 | fput(filp); | ||
| 1769 | if (nd.root.mnt) | ||
| 1770 | path_put(&nd.root); | ||
| 1771 | return ERR_PTR(error); | ||
| 1772 | } | ||
| 1773 | } | ||
| 1771 | /* | 1774 | /* |
| 1772 | * It is now safe to drop the mnt write | 1775 | * It is now safe to drop the mnt write |
| 1773 | * because the filp has had a write taken | 1776 | * because the filp has had a write taken |
| 1774 | * on its behalf. | 1777 | * on its behalf. |
| 1775 | */ | 1778 | */ |
| 1776 | if (will_write) | 1779 | if (will_truncate) |
| 1777 | mnt_drop_write(nd.path.mnt); | 1780 | mnt_drop_write(nd.path.mnt); |
| 1778 | if (nd.root.mnt) | 1781 | if (nd.root.mnt) |
| 1779 | path_put(&nd.root); | 1782 | path_put(&nd.root); |
