diff mbox series

[2/2] quota: Sanity-check quota file headers on load

Message ID 20201102172733.23444-3-jack@suse.cz
State Accepted
Commit 11c514a99bb960941535134f0587102855e8ddee
Headers show
Series None | expand

Commit Message

Jan Kara Nov. 2, 2020, 5:27 p.m. UTC
Perform basic sanity checks of quota headers to avoid kernel crashes on
corrupted quota files.

CC: stable@vger.kernel.org
Reported-by: syzbot+f816042a7ae2225f25ba@syzkaller.appspotmail.com
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/quota/quota_v2.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

Comments

Andreas Dilger Nov. 2, 2020, 9:32 p.m. UTC | #1
On Nov 2, 2020, at 10:27 AM, Jan Kara <jack@suse.cz> wrote:
> 

> Perform basic sanity checks of quota headers to avoid kernel crashes on

> corrupted quota files.

> 

> CC: stable@vger.kernel.org

> Reported-by: syzbot+f816042a7ae2225f25ba@syzkaller.appspotmail.com

> Signed-off-by: Jan Kara <jack@suse.cz>


Looks reasonable.

Reviewed-by: Andreas Dilger <adilger@dilger.ca>


> ---

> fs/quota/quota_v2.c | 19 +++++++++++++++++++

> 1 file changed, 19 insertions(+)

> 

> diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c

> index e69a2bfdd81c..c21106557a37 100644

> --- a/fs/quota/quota_v2.c

> +++ b/fs/quota/quota_v2.c

> @@ -157,6 +157,25 @@ static int v2_read_file_info(struct super_block *sb, int type)

> 		qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);

> 		qinfo->dqi_ops = &v2r1_qtree_ops;

> 	}

> +	ret = -EUCLEAN;

> +	/* Some sanity checks of the read headers... */

> +	if ((loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits >

> +	    i_size_read(sb_dqopt(sb)->files[type])) {

> +		quota_error(sb, "Number of blocks too big for quota file size (%llu > %llu).",

> +		    (loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits,

> +		    i_size_read(sb_dqopt(sb)->files[type]));

> +		goto out;

> +	}

> +	if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) {

> +		quota_error(sb, "Free block number too big (%u >= %u).",

> +			    qinfo->dqi_free_blk, qinfo->dqi_blocks);

> +		goto out;

> +	}

> +	if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) {

> +		quota_error(sb, "Block with free entry too big (%u >= %u).",

> +			    qinfo->dqi_free_entry, qinfo->dqi_blocks);

> +		goto out;

> +	}

> 	ret = 0;

> out:

> 	up_read(&dqopt->dqio_sem);

> --

> 2.16.4

> 



Cheers, Andreas
diff mbox series

Patch

diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c
index e69a2bfdd81c..c21106557a37 100644
--- a/fs/quota/quota_v2.c
+++ b/fs/quota/quota_v2.c
@@ -157,6 +157,25 @@  static int v2_read_file_info(struct super_block *sb, int type)
 		qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
 		qinfo->dqi_ops = &v2r1_qtree_ops;
 	}
+	ret = -EUCLEAN;
+	/* Some sanity checks of the read headers... */
+	if ((loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits >
+	    i_size_read(sb_dqopt(sb)->files[type])) {
+		quota_error(sb, "Number of blocks too big for quota file size (%llu > %llu).",
+		    (loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits,
+		    i_size_read(sb_dqopt(sb)->files[type]));
+		goto out;
+	}
+	if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) {
+		quota_error(sb, "Free block number too big (%u >= %u).",
+			    qinfo->dqi_free_blk, qinfo->dqi_blocks);
+		goto out;
+	}
+	if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) {
+		quota_error(sb, "Block with free entry too big (%u >= %u).",
+			    qinfo->dqi_free_entry, qinfo->dqi_blocks);
+		goto out;
+	}
 	ret = 0;
 out:
 	up_read(&dqopt->dqio_sem);