22865e8
From 8a4dc3612c6c170c05e5eef68dd3555baeb341c1 Mon Sep 17 00:00:00 2001
22865e8
From: Jan Kara <jack@suse.cz>
22865e8
Date: Thu, 6 Jan 2011 21:15:46 +0100
22865e8
Subject: [PATCH 5/6] Check whether set limits fit into the range supported by quota format.
22865e8
22865e8
Petr Pisar: Changelog update remove
22865e8
---
22865e8
 quotaio.c    |   24 ++++++++++++++++++++++++
22865e8
 quotaio.h    |    8 ++++++++
22865e8
 quotaio_v1.c |    8 ++++++++
22865e8
 quotaio_v2.c |   23 ++++++++++++++++++++++-
22865e8
22865e8
diff --git a/quotaio.c b/quotaio.c
22865e8
index dbd7cc8..21881fc 100644
22865e8
--- a/quotaio.c
22865e8
+++ b/quotaio.c
22865e8
@@ -287,3 +287,27 @@ struct dquot *get_empty_dquot(void)
22865e8
 	dquot->dq_id = -1;
22865e8
 	return dquot;
22865e8
 }
22865e8
+
22865e8
+/*
22865e8
+ *	Check whether values in current dquot can be stored on disk
22865e8
+ */
22865e8
+int check_dquot_range(struct dquot *dquot)
22865e8
+{
22865e8
+	struct util_dqinfo *info = &dquot->dq_h->qh_info;
22865e8
+
22865e8
+	if (dquot->dq_dqb.dqb_bhardlimit > info->dqi_max_b_limit ||
22865e8
+	    dquot->dq_dqb.dqb_bsoftlimit > info->dqi_max_b_limit ||
22865e8
+	    dquot->dq_dqb.dqb_ihardlimit > info->dqi_max_i_limit ||
22865e8
+	    dquot->dq_dqb.dqb_isoftlimit > info->dqi_max_i_limit) {
22865e8
+		errstr(_("Trying to set quota limits out of range "
22865e8
+				 "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev);
22865e8
+		return -1;
22865e8
+	}
22865e8
+	if (dquot->dq_dqb.dqb_curinodes > info->dqi_max_i_usage ||
22865e8
+	    dquot->dq_dqb.dqb_curspace > info->dqi_max_b_usage) {
22865e8
+		errstr(_("Trying to set quota usage out of range "
22865e8
+			 "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev);
22865e8
+		return -1;
22865e8
+	}
22865e8
+	return 0;
22865e8
+}
22865e8
diff --git a/quotaio.h b/quotaio.h
22865e8
index d797034..3cd33ba 100644
22865e8
--- a/quotaio.h
22865e8
+++ b/quotaio.h
22865e8
@@ -10,6 +10,7 @@
22865e8
 #include <limits.h>
22865e8
 #include <sys/types.h>
22865e8
 #include <sys/stat.h>
22865e8
+#include <stdint.h>
22865e8
 
22865e8
 #include "quota.h"
22865e8
 #include "mntopt.h"
22865e8
@@ -69,6 +70,10 @@ struct quotafile_ops;
22865e8
 struct util_dqinfo {
22865e8
 	time_t dqi_bgrace;	/* Block grace time for given quotafile */
22865e8
 	time_t dqi_igrace;	/* Inode grace time for given quotafile */
22865e8
+	uint64_t dqi_max_b_limit;	/* Maximal block limit storable in current format */
22865e8
+	uint64_t dqi_max_i_limit;	/* Maximal inode limit storable in current format */
22865e8
+	uint64_t dqi_max_b_usage;	/* Maximal block usage storable in current format */
22865e8
+	uint64_t dqi_max_i_usage;	/* Maximal inode usage storable in current format */
22865e8
 	union {
22865e8
 		struct v2_mem_dqinfo v2_mdqi;
22865e8
 		struct xfs_mem_dqinfo xfs_mdqi;
22865e8
@@ -171,4 +176,7 @@ int end_io(struct quota_handle *h);
22865e8
 /* Get empty quota structure */
22865e8
 struct dquot *get_empty_dquot(void);
22865e8
 
22865e8
+/* Check whether values in current dquot can be stored on disk */
22865e8
+int check_dquot_range(struct dquot *dquot);
22865e8
+
22865e8
 #endif /* GUARD_QUOTAIO_H */
22865e8
diff --git a/quotaio_v1.c b/quotaio_v1.c
22865e8
index 1533ffc..305bff2 100644
22865e8
--- a/quotaio_v1.c
22865e8
+++ b/quotaio_v1.c
22865e8
@@ -174,6 +174,10 @@ static int v1_init_io(struct quota_handle *h)
22865e8
 		h->qh_info.dqi_bgrace = MAX_DQ_TIME;
22865e8
 	if (!h->qh_info.dqi_igrace)
22865e8
 		h->qh_info.dqi_igrace = MAX_IQ_TIME;
22865e8
+	h->qh_info.dqi_max_b_limit = ~(uint32_t)0;
22865e8
+	h->qh_info.dqi_max_i_limit = ~(uint32_t)0;
22865e8
+	h->qh_info.dqi_max_b_usage = ((uint64_t)(~(uint32_t)0)) << V1_DQBLK_SIZE_BITS;
22865e8
+	h->qh_info.dqi_max_i_usage = ~(uint32_t)0;
22865e8
 
22865e8
 	return 0;
22865e8
 }
22865e8
@@ -327,6 +331,10 @@ static int v1_commit_dquot(struct dquot *dquot, int flags)
22865e8
 		}
22865e8
 	}
22865e8
 	else {
22865e8
+		if (check_dquot_range(dquot) < 0) {
22865e8
+			errno = ERANGE;
22865e8
+			return -1;
22865e8
+		}
22865e8
 		v1_mem2diskdqblk(&ddqblk, &dquot->dq_dqb);
22865e8
 		lseek(h->qh_fd, (long)V1_DQOFF(dquot->dq_id), SEEK_SET);
22865e8
 		if (write(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
22865e8
diff --git a/quotaio_v2.c b/quotaio_v2.c
22865e8
index 38440e7..2242c88 100644
22865e8
--- a/quotaio_v2.c
22865e8
+++ b/quotaio_v2.c
22865e8
@@ -307,9 +307,17 @@ static int v2_init_io(struct quota_handle *h)
22865e8
 		if (__le32_to_cpu(header.dqh_version) == 0) {
22865e8
 			h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
22865e8
 			h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops;
22865e8
+			h->qh_info.dqi_max_b_limit = ~(uint32_t)0;
22865e8
+			h->qh_info.dqi_max_i_limit = ~(uint32_t)0;
22865e8
+			h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
22865e8
+			h->qh_info.dqi_max_i_usage = ~(uint32_t)0;
22865e8
 		} else {
22865e8
 			h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
22865e8
 			h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
22865e8
+			h->qh_info.dqi_max_b_limit = ~(uint64_t)0;
22865e8
+			h->qh_info.dqi_max_i_limit = ~(uint64_t)0;
22865e8
+			h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
22865e8
+			h->qh_info.dqi_max_i_usage = ~(uint64_t)0;
22865e8
 		}
22865e8
 	} else {
22865e8
 		/* We don't have the file open -> we don't need quota tree operations */
22865e8
@@ -351,9 +359,17 @@ static int v2_new_io(struct quota_handle *h)
22865e8
 	if (version == 0) {
22865e8
 		h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
22865e8
 		h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops;
22865e8
+		h->qh_info.dqi_max_b_limit = ~(uint32_t)0;
22865e8
+		h->qh_info.dqi_max_i_limit = ~(uint32_t)0;
22865e8
+		h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
22865e8
+		h->qh_info.dqi_max_i_usage = ~(uint32_t)0;
22865e8
 	} else if (version == 1) {
22865e8
 		h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
22865e8
 		h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
22865e8
+		h->qh_info.dqi_max_b_limit = ~(uint64_t)0;
22865e8
+		h->qh_info.dqi_max_i_limit = ~(uint64_t)0;
22865e8
+		h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
22865e8
+		h->qh_info.dqi_max_i_usage = ~(uint64_t)0;
22865e8
 	}
22865e8
 	v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
22865e8
 	lseek(h->qh_fd, V2_DQINFOOFF, SEEK_SET);
22865e8
@@ -477,8 +493,13 @@ static int v2_commit_dquot(struct dquot *dquot, int flags)
22865e8
 	if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit && !b->dqb_isoftlimit
22865e8
 	    && !b->dqb_bhardlimit && !b->dqb_ihardlimit)
22865e8
 		qtree_delete_dquot(dquot);
22865e8
-	else
22865e8
+	else {
22865e8
+		if (check_dquot_range(dquot) < 0) {
22865e8
+			errno = ERANGE;
22865e8
+			return -1;
22865e8
+		}
22865e8
 		qtree_write_dquot(dquot);
22865e8
+	}
22865e8
 	return 0;
22865e8
 }
22865e8
 
22865e8
-- 
22865e8
1.7.3.4
22865e8