summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2020-09-21 13:30:32 +0200
committerJan Kara <jack@suse.cz>2020-09-21 13:30:32 +0200
commite777f46f3044ade15908dbb4c925dbb66556a595 (patch)
tree614cf24cc7300ac97982db5cf3db59db0dc691c6
parent16b60cb9e315ed0e859dba6bea0f206d674d519f (diff)
downloadlinuxquota-e777f46f3044ade15908dbb4c925dbb66556a595.tar.gz
Handle grace time overflows for XFS quotas
Add checks and error handling to report when grace times set for XFS quotas would overflow. Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--quotaio_xfs.c26
-rw-r--r--quotaio_xfs.h3
2 files changed, 20 insertions, 9 deletions
diff --git a/quotaio_xfs.c b/quotaio_xfs.c
index 9854ec2..2db1c0c 100644
--- a/quotaio_xfs.c
+++ b/quotaio_xfs.c
@@ -65,6 +65,11 @@ static inline int want_bigtime(time_t timer)
return timer > INT32_MAX || timer < INT32_MIN;
}
+static inline int timer_fits_xfs_dqblk(time_t timer)
+{
+ return timer >= FS_DQUOT_TIMER_MIN && timer <= FS_DQUOT_TIMER_MAX;
+}
+
/*
* Convert XFS kernel quota format to utility format
*/
@@ -83,7 +88,7 @@ static inline void xfs_kern2utildqblk(struct util_dqblk *u, struct xfs_kern_dqbl
/*
* Convert utility quota format to XFS kernel format
*/
-static inline void xfs_util2kerndqblk(struct xfs_kern_dqblk *k, struct util_dqblk *u)
+static inline int xfs_util2kerndqblk(struct xfs_kern_dqblk *k, struct util_dqblk *u)
{
memset(k, 0, sizeof(struct xfs_kern_dqblk));
k->d_ino_hardlimit = u->dqb_ihardlimit;
@@ -92,10 +97,16 @@ static inline void xfs_util2kerndqblk(struct xfs_kern_dqblk *k, struct util_dqbl
k->d_blk_softlimit = u->dqb_bsoftlimit << 1;
k->d_icount = u->dqb_curinodes;
k->d_bcount = u->dqb_curspace >> 9;
+ if (!timer_fits_xfs_dqblk(u->dqb_itime) ||
+ !timer_fits_xfs_dqblk(u->dqb_btime)) {
+ errno = ERANGE;
+ return -1;
+ }
if (want_bigtime(u->dqb_itime) || want_bigtime(u->dqb_btime))
k->d_fieldmask |= FS_DQ_BIGTIME;
xfs_util2kerndqblk_ts(k, &k->d_itimer, &k->d_itimer_hi, u->dqb_itime);
xfs_util2kerndqblk_ts(k, &k->d_btimer, &k->d_btimer_hi, u->dqb_btime);
+ return 0;
}
/*
@@ -176,7 +187,8 @@ static int xfs_commit_dquot(struct dquot *dquot, int flags)
if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h) && !XFS_PRJQUOTA(h))
return 0;
- xfs_util2kerndqblk(&xdqblk, &dquot->dq_dqb);
+ if (xfs_util2kerndqblk(&xdqblk, &dquot->dq_dqb) < 0)
+ return -1;
if (XFS_USRQUOTA(h))
xdqblk.d_flags |= XFS_USER_QUOTA;
else if (XFS_GRPQUOTA(h))
@@ -198,13 +210,9 @@ static int xfs_commit_dquot(struct dquot *dquot, int flags)
}
qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type);
- if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) {
- ;
- }
- else {
- return 0;
- }
- return -1;
+ if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0)
+ return -1;
+ return 0;
}
/*
diff --git a/quotaio_xfs.h b/quotaio_xfs.h
index e0c2a62..28dc27e 100644
--- a/quotaio_xfs.h
+++ b/quotaio_xfs.h
@@ -85,6 +85,9 @@ typedef struct fs_disk_quota {
char d_padding4[8]; /* yet more padding */
} fs_disk_quota_t;
+#define FS_DQUOT_TIMER_MAX (((__s64)1 << 39) - 1)
+#define FS_DQUOT_TIMER_MIN (-((__s64)1 << 39))
+
/*
* These fields are sent to Q_XSETQLIM to specify fields that need to change.
*/