Skip to content

Generalise read and write. #230

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

Merged
merged 1 commit into from
Apr 28, 2021
Merged

Generalise read and write. #230

merged 1 commit into from
Apr 28, 2021

Conversation

wedsonaf
Copy link

This is also in preparation for adding support for read_iter and
write_iter.

An extra argument is being added to write for consistency with the
other functions.

Otherwise, this is a pure refactor.

Based on #229.

Signed-off-by: Wedson Almeida Filho [email protected]

@alex
Copy link
Member

alex commented Apr 27, 2021

One more for rebasing :-)

This is also in preparation for adding support for `read_iter` and
`write_iter`.

An extra argument is being added to `write` for consistency with the
other functions.

Otherwise, this is a pure refactor.

Signed-off-by: Wedson Almeida Filho <[email protected]>
@wedsonaf
Copy link
Author

One more for rebasing :-)

Done. Thanks for the reviews :)

@alex
Copy link
Member

alex commented Apr 27, 2021

Can you explain more about the motivation for this? I read the read_iter PR but it doesn't look like it depends on this.

@wedsonaf
Copy link
Author

wedsonaf commented Apr 27, 2021

Can you explain more about the motivation for this? I read the read_iter PR but it doesn't look like it depends on this.

read_iter and write_iter depend on this.

The idea is that someone writing a driver provides a single implementation of read and write: given that they are generalised on any IoBufferWriter and IoBufferReader, read_iter_callback and writer_iter_callback call the very same read and write called by read_callback and write_callback (only using a different instantiation, IovIterX vs UserSlicePtrX).

IOW, a driver gets read_iter and write_iter for free once it has read and write. See for example read_iter_zero and read_zero here https://elixir.bootlin.com/linux/latest/source/drivers/char/mem.c#L699 -- in C, they need to implement two functions that do the same thing but that deal with char __user * and struct iov_iter; in Rust they only need one.

@alex
Copy link
Member

alex commented Apr 27, 2021 via email

@wedsonaf
Copy link
Author

Is it always desired to use the same implementation for read and read_iter? I'm imagining maybe doing smart things like processing one iov at a time?

Let's suppose a developer wants to do something smart with iovs. We can expose more information to them via IoBufferX that allows them to do so; the non-iter case would be a degenerate case with only one iov, and would optimise away any loops. We still benefit from a single implementation. (Though instead of both being 'dumb', they're both 'smart'.)

My initial inclination was to remove read and write altogether. A quick experiment with dd shows that read is faster than read_iter though, so I thought I'd keep both for now at least. In the future, if read_iter improves we always have the option to drop read; the existence of both seems like an artefact of the kernel evolution -- see for example this comment from who I believe is Al Viro saying "I very much hope to get rid of the piles of read/write methods."

@alex alex merged commit 4e2d67e into Rust-for-Linux:rust Apr 28, 2021
@wedsonaf wedsonaf deleted the read-write branch April 28, 2021 03:00
ojeda pushed a commit that referenced this pull request Jul 31, 2023
BUG: KASAN: slab-use-after-free in bcm_proc_show+0x969/0xa80
Read of size 8 at addr ffff888155846230 by task cat/7862

CPU: 1 PID: 7862 Comm: cat Not tainted 6.5.0-rc1-00153-gc8746099c197 #230
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0xd5/0x150
 print_report+0xc1/0x5e0
 kasan_report+0xba/0xf0
 bcm_proc_show+0x969/0xa80
 seq_read_iter+0x4f6/0x1260
 seq_read+0x165/0x210
 proc_reg_read+0x227/0x300
 vfs_read+0x1d5/0x8d0
 ksys_read+0x11e/0x240
 do_syscall_64+0x35/0xb0
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Allocated by task 7846:
 kasan_save_stack+0x1e/0x40
 kasan_set_track+0x21/0x30
 __kasan_kmalloc+0x9e/0xa0
 bcm_sendmsg+0x264b/0x44e0
 sock_sendmsg+0xda/0x180
 ____sys_sendmsg+0x735/0x920
 ___sys_sendmsg+0x11d/0x1b0
 __sys_sendmsg+0xfa/0x1d0
 do_syscall_64+0x35/0xb0
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Freed by task 7846:
 kasan_save_stack+0x1e/0x40
 kasan_set_track+0x21/0x30
 kasan_save_free_info+0x27/0x40
 ____kasan_slab_free+0x161/0x1c0
 slab_free_freelist_hook+0x119/0x220
 __kmem_cache_free+0xb4/0x2e0
 rcu_core+0x809/0x1bd0

bcm_op is freed before procfs entry be removed in bcm_release(),
this lead to bcm_proc_show() may read the freed bcm_op.

Fixes: ffd980f ("[CAN]: Add broadcast manager (bcm) protocol")
Signed-off-by: YueHaibing <[email protected]>
Reviewed-by: Oliver Hartkopp <[email protected]>
Acked-by: Oliver Hartkopp <[email protected]>
Link: https://lore.kernel.org/all/[email protected]
Cc: [email protected]
Signed-off-by: Marc Kleine-Budde <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants