diff options
author | Jan Kara <jack@suse.cz> | 2020-09-21 13:30:32 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2020-09-21 13:30:32 +0200 |
commit | e777f46f3044ade15908dbb4c925dbb66556a595 (patch) | |
tree | 614cf24cc7300ac97982db5cf3db59db0dc691c6 | |
parent | 16b60cb9e315ed0e859dba6bea0f206d674d519f (diff) | |
download | linuxquota-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.c | 26 | ||||
-rw-r--r-- | quotaio_xfs.h | 3 |
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. */ |