Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dmu: fix integer overflow in dmu_read #3333

Closed
wants to merge 1 commit into from
Closed

Conversation

perfinion
Copy link
Contributor

The params are uint64_t, but the offsets are calculated as 32bit ints.
PaX's Size Overflow catches this when formatting a zvol. This patch
changes them to also be uint64_t so there isnt an overflow.

Gentoo bug: #546490

PAX: offset: 1ffffb000 db->db_offset: 1ffffa000 db->db_size: 2000 size: 5000
PAX: size overflow detected in function dmu_read /var/tmp/portage/sys-fs/zfs-kmod-0.6.3-r1/work/zfs-zfs-0.6.3/module/zfs/../../module/zfs/dmu.c:781 cicus.366_146 max, count: 15
CPU: 1 PID: 2236 Comm: zvol/10 Tainted: P O 3.17.7-hardened-r1 #1
Call Trace:
[] ? dsl_dataset_get_holds+0x9d58/0x343ce [zfs]
[] dump_stack+0x4e/0x7a
[] ? dsl_dataset_get_holds+0x1aa9a/0x343ce [zfs]
[] report_size_overflow+0x36/0x40
[] dmu_read+0x52b/0x920 [zfs]
[] zrl_is_locked+0x7d1/0x1ce0 [zfs]
[] zil_clean+0x9d2/0xc00 [zfs]
[] zil_commit+0x21/0x30 [zfs]
[] zrl_is_locked+0xce1/0x1ce0 [zfs]
[] ? __schedule+0x547/0xbc0
[] taskq_cancel_id+0x2a6/0x5b0 [spl]
[] ? wake_up_state+0x20/0x20
[] ? taskq_cancel_id+0x110/0x5b0 [spl]
[] kthread+0xc4/0xe0
[] ? kthread_create_on_node+0x170/0x170
[] ret_from_fork+0x74/0xa0
[] ? kthread_create_on_node+0x170/0x170

Signed-off-by: Jason Zaman [email protected]
Reviewed-by: Emese Revfy [email protected]

@ryao
Copy link
Contributor

ryao commented Apr 22, 2015

This looks good to me.

@thegreatgazoo
Copy link

There seemed to be similar overflows also in dmu_read_req(), dmu_write_req(), dmu_read_uio(), and dmu_write_uio_dnode().

@avg-I
Copy link
Contributor

avg-I commented Apr 23, 2015

Given that those values are offsets and sizes within a block it seems that using int is safe in practice.
Not sure if multi-gigabyte sized blocks are going to make sense any time soon.

@perfinion
Copy link
Contributor Author

Given that those values are offsets and sizes within a block it seems that using int is safe in practice.
Not sure if multi-gigabyte sized blocks are going to make sense any time soon.

This cant be true. PaX's size overflow plugin uses double size and recalculates to compare if there is an overflow and only then triggers. and the numbers passed in when i hit it are bigger than a 32bit int. I hit it with a ZVOL tho so maybe for zvols its not limited to within a block?
regardless, changing them to (u)int64_t is better since the parameters to the method are also 64bit.

more about pax's size overflow is here: https://forums.grsecurity.net/viewtopic.php?f=7&t=3043

@behlendorf
Copy link
Contributor

Treating these values all as 64-bit is definitely for the best since it makes everything explicit. @perfinion could you update this patch to made the same fix in dmu_write(), dmu_read_req(), dmu_write_req(), dmu_read_uio(), dmu_write_uio(), and dmu_write_uio_dnode() as @thegreatgazoo suggested.

@perfinion
Copy link
Contributor Author

@behlendorf dmu_read() uses bcopy, all the other ones (dmu_write, dmu_read_req, dmu_req_copy etc) use memcopy. should I also swap dmu_read() to use memcopy to be consistent?

@behlendorf
Copy link
Contributor

Yes, consistently is good. And under the covers bcopy will map to memcpy anyway.

The params to the functions are uint64_t, but the offsets to memcpy
/ bcopy are calculated using 32bit ints. This patch changes them to
also be uint64_t so there isnt an overflow. PaX's Size Overflow
caught this when formatting a zvol.

Gentoo bug: #546490

PAX: offset: 1ffffb000 db->db_offset: 1ffffa000 db->db_size: 2000 size: 5000
PAX: size overflow detected in function dmu_read /var/tmp/portage/sys-fs/zfs-kmod-0.6.3-r1/work/zfs-zfs-0.6.3/module/zfs/../../module/zfs/dmu.c:781 cicus.366_146 max, count: 15
CPU: 1 PID: 2236 Comm: zvol/10 Tainted: P           O   3.17.7-hardened-r1 openzfs#1
Call Trace:
 [<ffffffffa0382ee8>] ? dsl_dataset_get_holds+0x9d58/0x343ce [zfs]
 [<ffffffff81a59c88>] dump_stack+0x4e/0x7a
 [<ffffffffa0393c2a>] ? dsl_dataset_get_holds+0x1aa9a/0x343ce [zfs]
 [<ffffffff81206696>] report_size_overflow+0x36/0x40
 [<ffffffffa02dba2b>] dmu_read+0x52b/0x920 [zfs]
 [<ffffffffa0373ad1>] zrl_is_locked+0x7d1/0x1ce0 [zfs]
 [<ffffffffa0364cd2>] zil_clean+0x9d2/0xc00 [zfs]
 [<ffffffffa0364f21>] zil_commit+0x21/0x30 [zfs]
 [<ffffffffa0373fe1>] zrl_is_locked+0xce1/0x1ce0 [zfs]
 [<ffffffff81a5e2c7>] ? __schedule+0x547/0xbc0
 [<ffffffffa01582e6>] taskq_cancel_id+0x2a6/0x5b0 [spl]
 [<ffffffff81103eb0>] ? wake_up_state+0x20/0x20
 [<ffffffffa0158150>] ? taskq_cancel_id+0x110/0x5b0 [spl]
 [<ffffffff810f7ff4>] kthread+0xc4/0xe0
 [<ffffffff810f7f30>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff81a62fa4>] ret_from_fork+0x74/0xa0
 [<ffffffff810f7f30>] ? kthread_create_on_node+0x170/0x170

Signed-off-by: Jason Zaman <[email protected]>
@perfinion perfinion force-pushed the pax branch 2 times, most recently from f328e60 to 7d0741b Compare April 30, 2015 12:22
@perfinion
Copy link
Contributor Author

I pushed a new version, can you take a look?

  • functions with fixed types: dmu_read, dmu_write, dmu_read_req, dmu_write_req, dmu_read_uio, dmu_write_uid_dnode.
  • dmu_write_uio() does not have the same issue.
  • dmu_read changed bcopy() to memcpy().

I booted this patch on my laptop and it builds and works. But I did not to any extensive testing other than the original dmu_read that i triggered.

@behlendorf
Copy link
Contributor

@perfinion thanks for fixing up the additional cases. This LGTM and the two test failures were for unrelated issues. I'll get this merged tomorrow to give @thegreatgazoo and @ryao a chance to comment.

@behlendorf behlendorf closed this in c9520ec May 4, 2015
dasjoe pushed a commit to dasjoe/zfs that referenced this pull request May 24, 2015
The params to the functions are uint64_t, but the offsets to memcpy
/ bcopy are calculated using 32bit ints. This patch changes them to
also be uint64_t so there isnt an overflow. PaX's Size Overflow
caught this when formatting a zvol.

Gentoo bug: #546490

PAX: offset: 1ffffb000 db->db_offset: 1ffffa000 db->db_size: 2000 size: 5000
PAX: size overflow detected in function dmu_read /var/tmp/portage/sys-fs/zfs-kmod-0.6.3-r1/work/zfs-zfs-0.6.3/module/zfs/../../module/zfs/dmu.c:781 cicus.366_146 max, count: 15
CPU: 1 PID: 2236 Comm: zvol/10 Tainted: P           O   3.17.7-hardened-r1 #1
Call Trace:
 [<ffffffffa0382ee8>] ? dsl_dataset_get_holds+0x9d58/0x343ce [zfs]
 [<ffffffff81a59c88>] dump_stack+0x4e/0x7a
 [<ffffffffa0393c2a>] ? dsl_dataset_get_holds+0x1aa9a/0x343ce [zfs]
 [<ffffffff81206696>] report_size_overflow+0x36/0x40
 [<ffffffffa02dba2b>] dmu_read+0x52b/0x920 [zfs]
 [<ffffffffa0373ad1>] zrl_is_locked+0x7d1/0x1ce0 [zfs]
 [<ffffffffa0364cd2>] zil_clean+0x9d2/0xc00 [zfs]
 [<ffffffffa0364f21>] zil_commit+0x21/0x30 [zfs]
 [<ffffffffa0373fe1>] zrl_is_locked+0xce1/0x1ce0 [zfs]
 [<ffffffff81a5e2c7>] ? __schedule+0x547/0xbc0
 [<ffffffffa01582e6>] taskq_cancel_id+0x2a6/0x5b0 [spl]
 [<ffffffff81103eb0>] ? wake_up_state+0x20/0x20
 [<ffffffffa0158150>] ? taskq_cancel_id+0x110/0x5b0 [spl]
 [<ffffffff810f7ff4>] kthread+0xc4/0xe0
 [<ffffffff810f7f30>] ? kthread_create_on_node+0x170/0x170
 [<ffffffff81a62fa4>] ret_from_fork+0x74/0xa0
 [<ffffffff810f7f30>] ? kthread_create_on_node+0x170/0x170

Signed-off-by: Jason Zaman <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#3333
@perfinion perfinion deleted the pax branch October 5, 2015 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants