From 22865e85c91a841d44747d1a84dc8a4ad4ed8147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Tue, 11 Jan 2011 10:37:09 +0100 Subject: [PATCH] Check whether set limits fit into the range supported by quota format --- ...t-limits-fit-into-the-range-supporte.patch | 159 ++++++++++++++++++ quota.spec | 5 + 2 files changed, 164 insertions(+) create mode 100644 quota-4.00_pre1-Check-whether-set-limits-fit-into-the-range-supporte.patch diff --git a/quota-4.00_pre1-Check-whether-set-limits-fit-into-the-range-supporte.patch b/quota-4.00_pre1-Check-whether-set-limits-fit-into-the-range-supporte.patch new file mode 100644 index 0000000..9ba5c6a --- /dev/null +++ b/quota-4.00_pre1-Check-whether-set-limits-fit-into-the-range-supporte.patch @@ -0,0 +1,159 @@ +From 8a4dc3612c6c170c05e5eef68dd3555baeb341c1 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 6 Jan 2011 21:15:46 +0100 +Subject: [PATCH 5/6] Check whether set limits fit into the range supported by quota format. + +Petr Pisar: Changelog update remove +--- + quotaio.c | 24 ++++++++++++++++++++++++ + quotaio.h | 8 ++++++++ + quotaio_v1.c | 8 ++++++++ + quotaio_v2.c | 23 ++++++++++++++++++++++- + +diff --git a/quotaio.c b/quotaio.c +index dbd7cc8..21881fc 100644 +--- a/quotaio.c ++++ b/quotaio.c +@@ -287,3 +287,27 @@ struct dquot *get_empty_dquot(void) + dquot->dq_id = -1; + return dquot; + } ++ ++/* ++ * Check whether values in current dquot can be stored on disk ++ */ ++int check_dquot_range(struct dquot *dquot) ++{ ++ struct util_dqinfo *info = &dquot->dq_h->qh_info; ++ ++ if (dquot->dq_dqb.dqb_bhardlimit > info->dqi_max_b_limit || ++ dquot->dq_dqb.dqb_bsoftlimit > info->dqi_max_b_limit || ++ dquot->dq_dqb.dqb_ihardlimit > info->dqi_max_i_limit || ++ dquot->dq_dqb.dqb_isoftlimit > info->dqi_max_i_limit) { ++ errstr(_("Trying to set quota limits out of range " ++ "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev); ++ return -1; ++ } ++ if (dquot->dq_dqb.dqb_curinodes > info->dqi_max_i_usage || ++ dquot->dq_dqb.dqb_curspace > info->dqi_max_b_usage) { ++ errstr(_("Trying to set quota usage out of range " ++ "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev); ++ return -1; ++ } ++ return 0; ++} +diff --git a/quotaio.h b/quotaio.h +index d797034..3cd33ba 100644 +--- a/quotaio.h ++++ b/quotaio.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "quota.h" + #include "mntopt.h" +@@ -69,6 +70,10 @@ struct quotafile_ops; + struct util_dqinfo { + time_t dqi_bgrace; /* Block grace time for given quotafile */ + time_t dqi_igrace; /* Inode grace time for given quotafile */ ++ uint64_t dqi_max_b_limit; /* Maximal block limit storable in current format */ ++ uint64_t dqi_max_i_limit; /* Maximal inode limit storable in current format */ ++ uint64_t dqi_max_b_usage; /* Maximal block usage storable in current format */ ++ uint64_t dqi_max_i_usage; /* Maximal inode usage storable in current format */ + union { + struct v2_mem_dqinfo v2_mdqi; + struct xfs_mem_dqinfo xfs_mdqi; +@@ -171,4 +176,7 @@ int end_io(struct quota_handle *h); + /* Get empty quota structure */ + struct dquot *get_empty_dquot(void); + ++/* Check whether values in current dquot can be stored on disk */ ++int check_dquot_range(struct dquot *dquot); ++ + #endif /* GUARD_QUOTAIO_H */ +diff --git a/quotaio_v1.c b/quotaio_v1.c +index 1533ffc..305bff2 100644 +--- a/quotaio_v1.c ++++ b/quotaio_v1.c +@@ -174,6 +174,10 @@ static int v1_init_io(struct quota_handle *h) + h->qh_info.dqi_bgrace = MAX_DQ_TIME; + if (!h->qh_info.dqi_igrace) + h->qh_info.dqi_igrace = MAX_IQ_TIME; ++ h->qh_info.dqi_max_b_limit = ~(uint32_t)0; ++ h->qh_info.dqi_max_i_limit = ~(uint32_t)0; ++ h->qh_info.dqi_max_b_usage = ((uint64_t)(~(uint32_t)0)) << V1_DQBLK_SIZE_BITS; ++ h->qh_info.dqi_max_i_usage = ~(uint32_t)0; + + return 0; + } +@@ -327,6 +331,10 @@ static int v1_commit_dquot(struct dquot *dquot, int flags) + } + } + else { ++ if (check_dquot_range(dquot) < 0) { ++ errno = ERANGE; ++ return -1; ++ } + v1_mem2diskdqblk(&ddqblk, &dquot->dq_dqb); + lseek(h->qh_fd, (long)V1_DQOFF(dquot->dq_id), SEEK_SET); + if (write(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk)) +diff --git a/quotaio_v2.c b/quotaio_v2.c +index 38440e7..2242c88 100644 +--- a/quotaio_v2.c ++++ b/quotaio_v2.c +@@ -307,9 +307,17 @@ static int v2_init_io(struct quota_handle *h) + if (__le32_to_cpu(header.dqh_version) == 0) { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops; ++ h->qh_info.dqi_max_b_limit = ~(uint32_t)0; ++ h->qh_info.dqi_max_i_limit = ~(uint32_t)0; ++ h->qh_info.dqi_max_b_usage = ~(uint64_t)0; ++ h->qh_info.dqi_max_i_usage = ~(uint32_t)0; + } else { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops; ++ h->qh_info.dqi_max_b_limit = ~(uint64_t)0; ++ h->qh_info.dqi_max_i_limit = ~(uint64_t)0; ++ h->qh_info.dqi_max_b_usage = ~(uint64_t)0; ++ h->qh_info.dqi_max_i_usage = ~(uint64_t)0; + } + } else { + /* We don't have the file open -> we don't need quota tree operations */ +@@ -351,9 +359,17 @@ static int v2_new_io(struct quota_handle *h) + if (version == 0) { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops; ++ h->qh_info.dqi_max_b_limit = ~(uint32_t)0; ++ h->qh_info.dqi_max_i_limit = ~(uint32_t)0; ++ h->qh_info.dqi_max_b_usage = ~(uint64_t)0; ++ h->qh_info.dqi_max_i_usage = ~(uint32_t)0; + } else if (version == 1) { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops; ++ h->qh_info.dqi_max_b_limit = ~(uint64_t)0; ++ h->qh_info.dqi_max_i_limit = ~(uint64_t)0; ++ h->qh_info.dqi_max_b_usage = ~(uint64_t)0; ++ h->qh_info.dqi_max_i_usage = ~(uint64_t)0; + } + v2_mem2diskdqinfo(&ddqinfo, &h->qh_info); + lseek(h->qh_fd, V2_DQINFOOFF, SEEK_SET); +@@ -477,8 +493,13 @@ static int v2_commit_dquot(struct dquot *dquot, int flags) + if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit && !b->dqb_isoftlimit + && !b->dqb_bhardlimit && !b->dqb_ihardlimit) + qtree_delete_dquot(dquot); +- else ++ else { ++ if (check_dquot_range(dquot) < 0) { ++ errno = ERANGE; ++ return -1; ++ } + qtree_write_dquot(dquot); ++ } + return 0; + } + +-- +1.7.3.4 + diff --git a/quota.spec b/quota.spec index 6f049ac..4458d0c 100644 --- a/quota.spec +++ b/quota.spec @@ -35,6 +35,8 @@ Patch11: quota-4.00_pre1-Add-always-resolve-to-quota.1-manpage.patch Patch12: quota-4.00_pre1-Document-always-resolve-at-edquota-and-setquota.patch # Bug #667757 Patch13: quota-4.00_pre1-Make-RPC-block-factor-dynamic.patch +# Bug #668688, included in upstream 4.00_pre2 +Patch14: quota-4.00_pre1-Check-whether-set-limits-fit-into-the-range-supporte.patch %description The quota package contains system administration tools for monitoring @@ -118,6 +120,7 @@ Linux/UNIX environment. %patch11 -p1 -b .document_always_resolve_quota %patch12 -p1 -b .document_always_resolve_setquota %patch13 -p1 -b .rpc_block_factor_dynamic +%patch14 -p1 -b .check_set_limits # quotactl(2) moved into `man-pages' package (bug #640590) rm -f quotactl.2 # remove VCS files @@ -241,6 +244,8 @@ rm -rf %{buildroot} %changelog * Tue Jan 11 2011 Petr Pisar - 1:4.00-0.4.pre1 - Make RPC block factor dynamic (bug #667757) +- Check whether set limits fit into the range supported by quota format + (bug #668688) * Mon Jan 10 2011 Petr Pisar - 1:4.00-0.3.pre1 - Document --always-resolve option