aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Perepechko <andrew.perepechko@sun.com>2008-04-28 05:14:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:32 -0400
commit338bf9afda91ec005a1e9a0de4af0271cc167d56 (patch)
treee60edf0441efbe8215cdeb08bf05c1b6afff58a1
parent3b0cb4caefeca6fe6b05c6c5a76e9c633b44c58f (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.c22
-rw-r--r--fs/quota_v1.c3
-rw-r--r--fs/quota_v2.c3
-rw-r--r--include/linux/quota.h2
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 */
1712static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) 1712static 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
1765int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di) 1776int 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;
144out: 147out:
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;