diff options
author | Jan Kara <jack@suse.cz> | 2011-01-06 21:15:46 +0100 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2011-01-06 21:15:46 +0100 |
commit | 8a4dc3612c6c170c05e5eef68dd3555baeb341c1 (patch) | |
tree | 3df70c155be8776c1f549cdbe7e8a677453e8efc | |
parent | 346d2f876c988747f9dc1c57aa8c6fc92052e5de (diff) |
Check whether set limits fit into the range supported by quota format.
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r-- | Changelog | 2 | ||||
-rw-r--r-- | quotaio.c | 24 | ||||
-rw-r--r-- | quotaio.h | 8 | ||||
-rw-r--r-- | quotaio_v1.c | 8 | ||||
-rw-r--r-- | quotaio_v2.c | 23 |
5 files changed, 64 insertions, 1 deletions
@@ -1,4 +1,6 @@ Changes in quota-tools from 3.17 to 4.00-pre2 +* check whether set limits fit into range supported by quota format (Jan Kara) +* remove checking of filesystem type from hasquota() (Jan Kara) * create quota-nfs.sh script for nicer quota(1) output formatting on some NFS clients (Jan Kara) * add options for quota(1) modifying formatting of filesystem identificaion (Jan Kara) * minor updates of manpages (Jan Kara) @@ -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; +} @@ -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; } |