diff options
author | Andrew Perepechko <andrew.perepechko@sun.com> | 2008-04-28 05:14:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:32 -0400 |
commit | 338bf9afda91ec005a1e9a0de4af0271cc167d56 (patch) | |
tree | e60edf0441efbe8215cdeb08bf05c1b6afff58a1 | |
parent | 3b0cb4caefeca6fe6b05c6c5a76e9c633b44c58f (diff) |
quota: do not allow setting of quota limits to too high values
We should check whether quota limits set via Q_SETQUOTA are not exceeding
limits which quota format is able to handle.
Signed-off-by: Andrew Perepechko <andrew.perepechko@sun.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/dquot.c | 22 | ||||
-rw-r--r-- | fs/quota_v1.c | 3 | ||||
-rw-r--r-- | fs/quota_v2.c | 3 | ||||
-rw-r--r-- | include/linux/quota.h | 2 |
4 files changed, 25 insertions, 5 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index 41b9dbd68b0e..24eef582d2a0 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -1709,10 +1709,19 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d | |||
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | /* Generic routine for setting common part of quota structure */ | 1711 | /* Generic routine for setting common part of quota structure */ |
1712 | static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) | 1712 | static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) |
1713 | { | 1713 | { |
1714 | struct mem_dqblk *dm = &dquot->dq_dqb; | 1714 | struct mem_dqblk *dm = &dquot->dq_dqb; |
1715 | int check_blim = 0, check_ilim = 0; | 1715 | int check_blim = 0, check_ilim = 0; |
1716 | struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; | ||
1717 | |||
1718 | if ((di->dqb_valid & QIF_BLIMITS && | ||
1719 | (di->dqb_bhardlimit > dqi->dqi_maxblimit || | ||
1720 | di->dqb_bsoftlimit > dqi->dqi_maxblimit)) || | ||
1721 | (di->dqb_valid & QIF_ILIMITS && | ||
1722 | (di->dqb_ihardlimit > dqi->dqi_maxilimit || | ||
1723 | di->dqb_isoftlimit > dqi->dqi_maxilimit))) | ||
1724 | return -ERANGE; | ||
1716 | 1725 | ||
1717 | spin_lock(&dq_data_lock); | 1726 | spin_lock(&dq_data_lock); |
1718 | if (di->dqb_valid & QIF_SPACE) { | 1727 | if (di->dqb_valid & QIF_SPACE) { |
@@ -1744,7 +1753,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) | |||
1744 | clear_bit(DQ_BLKS_B, &dquot->dq_flags); | 1753 | clear_bit(DQ_BLKS_B, &dquot->dq_flags); |
1745 | } | 1754 | } |
1746 | else if (!(di->dqb_valid & QIF_BTIME)) /* Set grace only if user hasn't provided his own... */ | 1755 | else if (!(di->dqb_valid & QIF_BTIME)) /* Set grace only if user hasn't provided his own... */ |
1747 | dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace; | 1756 | dm->dqb_btime = get_seconds() + dqi->dqi_bgrace; |
1748 | } | 1757 | } |
1749 | if (check_ilim) { | 1758 | if (check_ilim) { |
1750 | if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) { | 1759 | if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) { |
@@ -1752,7 +1761,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) | |||
1752 | clear_bit(DQ_INODES_B, &dquot->dq_flags); | 1761 | clear_bit(DQ_INODES_B, &dquot->dq_flags); |
1753 | } | 1762 | } |
1754 | else if (!(di->dqb_valid & QIF_ITIME)) /* Set grace only if user hasn't provided his own... */ | 1763 | else if (!(di->dqb_valid & QIF_ITIME)) /* Set grace only if user hasn't provided his own... */ |
1755 | dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; | 1764 | dm->dqb_itime = get_seconds() + dqi->dqi_igrace; |
1756 | } | 1765 | } |
1757 | if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit) | 1766 | if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit) |
1758 | clear_bit(DQ_FAKE_B, &dquot->dq_flags); | 1767 | clear_bit(DQ_FAKE_B, &dquot->dq_flags); |
@@ -1760,21 +1769,24 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) | |||
1760 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 1769 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
1761 | spin_unlock(&dq_data_lock); | 1770 | spin_unlock(&dq_data_lock); |
1762 | mark_dquot_dirty(dquot); | 1771 | mark_dquot_dirty(dquot); |
1772 | |||
1773 | return 0; | ||
1763 | } | 1774 | } |
1764 | 1775 | ||
1765 | int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di) | 1776 | int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di) |
1766 | { | 1777 | { |
1767 | struct dquot *dquot; | 1778 | struct dquot *dquot; |
1779 | int rc; | ||
1768 | 1780 | ||
1769 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 1781 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); |
1770 | if (!(dquot = dqget(sb, id, type))) { | 1782 | if (!(dquot = dqget(sb, id, type))) { |
1771 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 1783 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); |
1772 | return -ESRCH; | 1784 | return -ESRCH; |
1773 | } | 1785 | } |
1774 | do_set_dqblk(dquot, di); | 1786 | rc = do_set_dqblk(dquot, di); |
1775 | dqput(dquot); | 1787 | dqput(dquot); |
1776 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 1788 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); |
1777 | return 0; | 1789 | return rc; |
1778 | } | 1790 | } |
1779 | 1791 | ||
1780 | /* Generic routine for getting common part of quota file information */ | 1792 | /* Generic routine for getting common part of quota file information */ |
diff --git a/fs/quota_v1.c b/fs/quota_v1.c index f3841f233069..a6cf9269105c 100644 --- a/fs/quota_v1.c +++ b/fs/quota_v1.c | |||
@@ -139,6 +139,9 @@ static int v1_read_file_info(struct super_block *sb, int type) | |||
139 | goto out; | 139 | goto out; |
140 | } | 140 | } |
141 | ret = 0; | 141 | ret = 0; |
142 | /* limits are stored as unsigned 32-bit data */ | ||
143 | dqopt->info[type].dqi_maxblimit = 0xffffffff; | ||
144 | dqopt->info[type].dqi_maxilimit = 0xffffffff; | ||
142 | dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME; | 145 | dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME; |
143 | dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; | 146 | dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; |
144 | out: | 147 | out: |
diff --git a/fs/quota_v2.c b/fs/quota_v2.c index c519a583e681..23b647f25d08 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c | |||
@@ -59,6 +59,9 @@ static int v2_read_file_info(struct super_block *sb, int type) | |||
59 | sb->s_id); | 59 | sb->s_id); |
60 | return -1; | 60 | return -1; |
61 | } | 61 | } |
62 | /* limits are stored as unsigned 32-bit data */ | ||
63 | info->dqi_maxblimit = 0xffffffff; | ||
64 | info->dqi_maxilimit = 0xffffffff; | ||
62 | info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); | 65 | info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); |
63 | info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); | 66 | info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); |
64 | info->dqi_flags = le32_to_cpu(dinfo.dqi_flags); | 67 | info->dqi_flags = le32_to_cpu(dinfo.dqi_flags); |
diff --git a/include/linux/quota.h b/include/linux/quota.h index eb560d031acd..326cb80e3867 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -206,6 +206,8 @@ struct mem_dqinfo { | |||
206 | unsigned long dqi_flags; | 206 | unsigned long dqi_flags; |
207 | unsigned int dqi_bgrace; | 207 | unsigned int dqi_bgrace; |
208 | unsigned int dqi_igrace; | 208 | unsigned int dqi_igrace; |
209 | qsize_t dqi_maxblimit; | ||
210 | qsize_t dqi_maxilimit; | ||
209 | union { | 211 | union { |
210 | struct v1_mem_dqinfo v1_i; | 212 | struct v1_mem_dqinfo v1_i; |
211 | struct v2_mem_dqinfo v2_i; | 213 | struct v2_mem_dqinfo v2_i; |