forked from Minki/linux
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>
This commit is contained in:
parent
3b0cb4caef
commit
338bf9afda
22
fs/dquot.c
22
fs/dquot.c
@ -1709,10 +1709,19 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
|
||||
}
|
||||
|
||||
/* Generic routine for setting common part of quota structure */
|
||||
static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
|
||||
static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
|
||||
{
|
||||
struct mem_dqblk *dm = &dquot->dq_dqb;
|
||||
int check_blim = 0, check_ilim = 0;
|
||||
struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
|
||||
|
||||
if ((di->dqb_valid & QIF_BLIMITS &&
|
||||
(di->dqb_bhardlimit > dqi->dqi_maxblimit ||
|
||||
di->dqb_bsoftlimit > dqi->dqi_maxblimit)) ||
|
||||
(di->dqb_valid & QIF_ILIMITS &&
|
||||
(di->dqb_ihardlimit > dqi->dqi_maxilimit ||
|
||||
di->dqb_isoftlimit > dqi->dqi_maxilimit)))
|
||||
return -ERANGE;
|
||||
|
||||
spin_lock(&dq_data_lock);
|
||||
if (di->dqb_valid & QIF_SPACE) {
|
||||
@ -1744,7 +1753,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
|
||||
clear_bit(DQ_BLKS_B, &dquot->dq_flags);
|
||||
}
|
||||
else if (!(di->dqb_valid & QIF_BTIME)) /* Set grace only if user hasn't provided his own... */
|
||||
dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
|
||||
dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
|
||||
}
|
||||
if (check_ilim) {
|
||||
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)
|
||||
clear_bit(DQ_INODES_B, &dquot->dq_flags);
|
||||
}
|
||||
else if (!(di->dqb_valid & QIF_ITIME)) /* Set grace only if user hasn't provided his own... */
|
||||
dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
|
||||
dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
|
||||
}
|
||||
if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit)
|
||||
clear_bit(DQ_FAKE_B, &dquot->dq_flags);
|
||||
@ -1760,21 +1769,24 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
|
||||
set_bit(DQ_FAKE_B, &dquot->dq_flags);
|
||||
spin_unlock(&dq_data_lock);
|
||||
mark_dquot_dirty(dquot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
|
||||
{
|
||||
struct dquot *dquot;
|
||||
int rc;
|
||||
|
||||
mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
if (!(dquot = dqget(sb, id, type))) {
|
||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
return -ESRCH;
|
||||
}
|
||||
do_set_dqblk(dquot, di);
|
||||
rc = do_set_dqblk(dquot, di);
|
||||
dqput(dquot);
|
||||
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generic routine for getting common part of quota file information */
|
||||
|
@ -139,6 +139,9 @@ static int v1_read_file_info(struct super_block *sb, int type)
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
/* limits are stored as unsigned 32-bit data */
|
||||
dqopt->info[type].dqi_maxblimit = 0xffffffff;
|
||||
dqopt->info[type].dqi_maxilimit = 0xffffffff;
|
||||
dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
|
||||
dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
|
||||
out:
|
||||
|
@ -59,6 +59,9 @@ static int v2_read_file_info(struct super_block *sb, int type)
|
||||
sb->s_id);
|
||||
return -1;
|
||||
}
|
||||
/* limits are stored as unsigned 32-bit data */
|
||||
info->dqi_maxblimit = 0xffffffff;
|
||||
info->dqi_maxilimit = 0xffffffff;
|
||||
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
||||
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
||||
info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
|
||||
|
@ -206,6 +206,8 @@ struct mem_dqinfo {
|
||||
unsigned long dqi_flags;
|
||||
unsigned int dqi_bgrace;
|
||||
unsigned int dqi_igrace;
|
||||
qsize_t dqi_maxblimit;
|
||||
qsize_t dqi_maxilimit;
|
||||
union {
|
||||
struct v1_mem_dqinfo v1_i;
|
||||
struct v2_mem_dqinfo v2_i;
|
||||
|
Loading…
Reference in New Issue
Block a user