[quota] Check whether set limits fit into the range supported by quota format

Petr Pisar ppisar at fedoraproject.org
Tue Jan 11 10:05:13 UTC 2011


commit 22865e85c91a841d44747d1a84dc8a4ad4ed8147
Author: Petr Písař <ppisar at redhat.com>
Date:   Tue Jan 11 10:37:09 2011 +0100

    Check whether set limits fit into the range supported by quota format

 ...er-set-limits-fit-into-the-range-supporte.patch |  159 ++++++++++++++++++++
 quota.spec                                         |    5 +
 2 files changed, 164 insertions(+), 0 deletions(-)
---
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 <jack at suse.cz>
+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 <limits.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <stdint.h>
+ 
+ #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 <ppisar at redhat.com> - 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 <ppisar at redhat.com> - 1:4.00-0.3.pre1
 - Document --always-resolve option


More information about the scm-commits mailing list