diff options
author | Christoph Hellwig <hch@lst.de> | 2009-06-08 09:33:21 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@brick.lst.de> | 2009-06-08 09:33:21 -0400 |
commit | 0c5e1ce89f1eacc366ec421c0f5f681159479c28 (patch) | |
tree | c73fb303fa25d58773ecb989c428041994933b92 /fs/xfs | |
parent | e1696834e8a15d7ef9ae8ffdffe00bac1399a2e3 (diff) |
xfs: validate quota log items during log recovery
Arkadiusz has seen really strange crashes in xfs_qm_dqcheck that
I can only explain by a log item being too smal to actually fit the
xfs_dqblk_t we're dereferencing all over xfs_qm_dqcheck. So add
graceful checks for NULL or too small quota items to the log recovery
code.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Eric Sandeen <sandeen@sandeen.net>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 7ba450116d4f..47da2fb45377 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1975,16 +1975,30 @@ xlog_recover_do_reg_buffer( | |||
1975 | error = 0; | 1975 | error = 0; |
1976 | if (buf_f->blf_flags & | 1976 | if (buf_f->blf_flags & |
1977 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { | 1977 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { |
1978 | if (item->ri_buf[i].i_addr == NULL) { | ||
1979 | cmn_err(CE_ALERT, | ||
1980 | "XFS: NULL dquot in %s.", __func__); | ||
1981 | goto next; | ||
1982 | } | ||
1983 | if (item->ri_buf[i].i_len < sizeof(xfs_dqblk_t)) { | ||
1984 | cmn_err(CE_ALERT, | ||
1985 | "XFS: dquot too small (%d) in %s.", | ||
1986 | item->ri_buf[i].i_len, __func__); | ||
1987 | goto next; | ||
1988 | } | ||
1978 | error = xfs_qm_dqcheck((xfs_disk_dquot_t *) | 1989 | error = xfs_qm_dqcheck((xfs_disk_dquot_t *) |
1979 | item->ri_buf[i].i_addr, | 1990 | item->ri_buf[i].i_addr, |
1980 | -1, 0, XFS_QMOPT_DOWARN, | 1991 | -1, 0, XFS_QMOPT_DOWARN, |
1981 | "dquot_buf_recover"); | 1992 | "dquot_buf_recover"); |
1993 | if (error) | ||
1994 | goto next; | ||
1982 | } | 1995 | } |
1983 | if (!error) | 1996 | |
1984 | memcpy(xfs_buf_offset(bp, | 1997 | memcpy(xfs_buf_offset(bp, |
1985 | (uint)bit << XFS_BLI_SHIFT), /* dest */ | 1998 | (uint)bit << XFS_BLI_SHIFT), /* dest */ |
1986 | item->ri_buf[i].i_addr, /* source */ | 1999 | item->ri_buf[i].i_addr, /* source */ |
1987 | nbits<<XFS_BLI_SHIFT); /* length */ | 2000 | nbits<<XFS_BLI_SHIFT); /* length */ |
2001 | next: | ||
1988 | i++; | 2002 | i++; |
1989 | bit += nbits; | 2003 | bit += nbits; |
1990 | } | 2004 | } |
@@ -2615,7 +2629,19 @@ xlog_recover_do_dquot_trans( | |||
2615 | return (0); | 2629 | return (0); |
2616 | 2630 | ||
2617 | recddq = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr; | 2631 | recddq = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr; |
2618 | ASSERT(recddq); | 2632 | |
2633 | if (item->ri_buf[1].i_addr == NULL) { | ||
2634 | cmn_err(CE_ALERT, | ||
2635 | "XFS: NULL dquot in %s.", __func__); | ||
2636 | return XFS_ERROR(EIO); | ||
2637 | } | ||
2638 | if (item->ri_buf[1].i_len < sizeof(xfs_dqblk_t)) { | ||
2639 | cmn_err(CE_ALERT, | ||
2640 | "XFS: dquot too small (%d) in %s.", | ||
2641 | item->ri_buf[1].i_len, __func__); | ||
2642 | return XFS_ERROR(EIO); | ||
2643 | } | ||
2644 | |||
2619 | /* | 2645 | /* |
2620 | * This type of quotas was turned off, so ignore this record. | 2646 | * This type of quotas was turned off, so ignore this record. |
2621 | */ | 2647 | */ |