aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c124
1 files changed, 106 insertions, 18 deletions
diff --git a/fs/inode.c b/fs/inode.c
index c474c1d7062b..c99163b1b310 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1487,10 +1487,30 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
1487 return 0; 1487 return 0;
1488} 1488}
1489 1489
1490/*
1491 * This does the actual work of updating an inodes time or version. Must have
1492 * had called mnt_want_write() before calling this.
1493 */
1494static int update_time(struct inode *inode, struct timespec *time, int flags)
1495{
1496 if (inode->i_op->update_time)
1497 return inode->i_op->update_time(inode, time, flags);
1498
1499 if (flags & S_ATIME)
1500 inode->i_atime = *time;
1501 if (flags & S_VERSION)
1502 inode_inc_iversion(inode);
1503 if (flags & S_CTIME)
1504 inode->i_ctime = *time;
1505 if (flags & S_MTIME)
1506 inode->i_mtime = *time;
1507 mark_inode_dirty_sync(inode);
1508 return 0;
1509}
1510
1490/** 1511/**
1491 * touch_atime - update the access time 1512 * touch_atime - update the access time
1492 * @mnt: mount the inode is accessed on 1513 * @path: the &struct path to update
1493 * @dentry: dentry accessed
1494 * 1514 *
1495 * Update the accessed time on an inode and mark it for writeback. 1515 * Update the accessed time on an inode and mark it for writeback.
1496 * This function automatically handles read only file systems and media, 1516 * This function automatically handles read only file systems and media,
@@ -1525,12 +1545,83 @@ void touch_atime(struct path *path)
1525 if (mnt_want_write(mnt)) 1545 if (mnt_want_write(mnt))
1526 return; 1546 return;
1527 1547
1528 inode->i_atime = now; 1548 /*
1529 mark_inode_dirty_sync(inode); 1549 * File systems can error out when updating inodes if they need to
1550 * allocate new space to modify an inode (such is the case for
1551 * Btrfs), but since we touch atime while walking down the path we
1552 * really don't care if we failed to update the atime of the file,
1553 * so just ignore the return value.
1554 */
1555 update_time(inode, &now, S_ATIME);
1530 mnt_drop_write(mnt); 1556 mnt_drop_write(mnt);
1531} 1557}
1532EXPORT_SYMBOL(touch_atime); 1558EXPORT_SYMBOL(touch_atime);
1533 1559
1560/*
1561 * The logic we want is
1562 *
1563 * if suid or (sgid and xgrp)
1564 * remove privs
1565 */
1566int should_remove_suid(struct dentry *dentry)
1567{
1568 umode_t mode = dentry->d_inode->i_mode;
1569 int kill = 0;
1570
1571 /* suid always must be killed */
1572 if (unlikely(mode & S_ISUID))
1573 kill = ATTR_KILL_SUID;
1574
1575 /*
1576 * sgid without any exec bits is just a mandatory locking mark; leave
1577 * it alone. If some exec bits are set, it's a real sgid; kill it.
1578 */
1579 if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
1580 kill |= ATTR_KILL_SGID;
1581
1582 if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
1583 return kill;
1584
1585 return 0;
1586}
1587EXPORT_SYMBOL(should_remove_suid);
1588
1589static int __remove_suid(struct dentry *dentry, int kill)
1590{
1591 struct iattr newattrs;
1592
1593 newattrs.ia_valid = ATTR_FORCE | kill;
1594 return notify_change(dentry, &newattrs);
1595}
1596
1597int file_remove_suid(struct file *file)
1598{
1599 struct dentry *dentry = file->f_path.dentry;
1600 struct inode *inode = dentry->d_inode;
1601 int killsuid;
1602 int killpriv;
1603 int error = 0;
1604
1605 /* Fast path for nothing security related */
1606 if (IS_NOSEC(inode))
1607 return 0;
1608
1609 killsuid = should_remove_suid(dentry);
1610 killpriv = security_inode_need_killpriv(dentry);
1611
1612 if (killpriv < 0)
1613 return killpriv;
1614 if (killpriv)
1615 error = security_inode_killpriv(dentry);
1616 if (!error && killsuid)
1617 error = __remove_suid(dentry, killsuid);
1618 if (!error && (inode->i_sb->s_flags & MS_NOSEC))
1619 inode->i_flags |= S_NOSEC;
1620
1621 return error;
1622}
1623EXPORT_SYMBOL(file_remove_suid);
1624
1534/** 1625/**
1535 * file_update_time - update mtime and ctime time 1626 * file_update_time - update mtime and ctime time
1536 * @file: file accessed 1627 * @file: file accessed
@@ -1540,18 +1631,20 @@ EXPORT_SYMBOL(touch_atime);
1540 * usage in the file write path of filesystems, and filesystems may 1631 * usage in the file write path of filesystems, and filesystems may
1541 * choose to explicitly ignore update via this function with the 1632 * choose to explicitly ignore update via this function with the
1542 * S_NOCMTIME inode flag, e.g. for network filesystem where these 1633 * S_NOCMTIME inode flag, e.g. for network filesystem where these
1543 * timestamps are handled by the server. 1634 * timestamps are handled by the server. This can return an error for
1635 * file systems who need to allocate space in order to update an inode.
1544 */ 1636 */
1545 1637
1546void file_update_time(struct file *file) 1638int file_update_time(struct file *file)
1547{ 1639{
1548 struct inode *inode = file->f_path.dentry->d_inode; 1640 struct inode *inode = file->f_path.dentry->d_inode;
1549 struct timespec now; 1641 struct timespec now;
1550 enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; 1642 int sync_it = 0;
1643 int ret;
1551 1644
1552 /* First try to exhaust all avenues to not sync */ 1645 /* First try to exhaust all avenues to not sync */
1553 if (IS_NOCMTIME(inode)) 1646 if (IS_NOCMTIME(inode))
1554 return; 1647 return 0;
1555 1648
1556 now = current_fs_time(inode->i_sb); 1649 now = current_fs_time(inode->i_sb);
1557 if (!timespec_equal(&inode->i_mtime, &now)) 1650 if (!timespec_equal(&inode->i_mtime, &now))
@@ -1564,21 +1657,16 @@ void file_update_time(struct file *file)
1564 sync_it |= S_VERSION; 1657 sync_it |= S_VERSION;
1565 1658
1566 if (!sync_it) 1659 if (!sync_it)
1567 return; 1660 return 0;
1568 1661
1569 /* Finally allowed to write? Takes lock. */ 1662 /* Finally allowed to write? Takes lock. */
1570 if (mnt_want_write_file(file)) 1663 if (mnt_want_write_file(file))
1571 return; 1664 return 0;
1572 1665
1573 /* Only change inode inside the lock region */ 1666 ret = update_time(inode, &now, sync_it);
1574 if (sync_it & S_VERSION)
1575 inode_inc_iversion(inode);
1576 if (sync_it & S_CTIME)
1577 inode->i_ctime = now;
1578 if (sync_it & S_MTIME)
1579 inode->i_mtime = now;
1580 mark_inode_dirty_sync(inode);
1581 mnt_drop_write_file(file); 1667 mnt_drop_write_file(file);
1668
1669 return ret;
1582} 1670}
1583EXPORT_SYMBOL(file_update_time); 1671EXPORT_SYMBOL(file_update_time);
1584 1672