On Mon, Dec 9, 2024 at 9:48 AM Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> wrote: > > On Mon, Dec 09, 2024 at 07:27:47AM +0000, Alice Ryhl wrote: > > Providing access to the underlying `struct miscdevice` is useful for > > various reasons. For example, this allows you access the miscdevice's > > internal `struct device` for use with the `dev_*` printing macros. > > > > Note that since the underlying `struct miscdevice` could get freed at > > any point after the fops->open() call, only the open call is given > > access to it. To print from other calls, they should take a refcount on > > the device to keep it alive. > > The lifespan of the miscdevice is at least from open until close, so > it's safe for at least then (i.e. read/write/ioctl/etc.) How is that enforced? What happens if I call misc_deregister while there are open fds? > > Signed-off-by: Alice Ryhl <aliceryhl@xxxxxxxxxx> > > --- > > rust/kernel/miscdevice.rs | 19 ++++++++++++++++--- > > 1 file changed, 16 insertions(+), 3 deletions(-) > > > > diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs > > index 0cb79676c139..c5af1d5ec4be 100644 > > --- a/rust/kernel/miscdevice.rs > > +++ b/rust/kernel/miscdevice.rs > > @@ -104,7 +104,7 @@ pub trait MiscDevice { > > /// Called when the misc device is opened. > > /// > > /// The returned pointer will be stored as the private data for the file. > > - fn open(_file: &File) -> Result<Self::Ptr>; > > + fn open(_file: &File, _misc: &MiscDeviceRegistration<Self>) -> Result<Self::Ptr>; > > > > /// Called when the misc device is released. > > fn release(device: Self::Ptr, _file: &File) { > > @@ -190,14 +190,27 @@ impl<T: MiscDevice> VtableHelper<T> { > > return ret; > > } > > > > + // SAFETY: The opwn call of a file can access the private data. > > s/opwn/open/ :) > > > + let misc_ptr = unsafe { (*file).private_data }; > > Blank line here? > > > + // SAFETY: This is a miscdevice, so `misc_open()` set the private data to a pointer to the > > + // associated `struct miscdevice` before calling into this method. Furthermore, `misc_open()` > > + // ensures that the miscdevice can't be unregistered and freed during this call to `fops_open`. > > Aren't we wrapping comment lines at 80 columns still? I can't remember > anymore... Not sure what the rules are, but I don't think Rust comments are being wrapped at 80. > > + let misc = unsafe { &*misc_ptr.cast::<MiscDeviceRegistration<T>>() }; > > + > > // SAFETY: > > - // * The file is valid for the duration of this call. > > + // * The file is valid for the duration of the `T::open` call. > > It's valid for the lifespan between open/release. > > > // * There is no active fdget_pos region on the file on this thread. > > - let ptr = match T::open(unsafe { File::from_raw_file(file) }) { > > + let file = unsafe { File::from_raw_file(file) }; > > + > > + let ptr = match T::open(file, misc) { > > Ok(ptr) => ptr, > > Err(err) => return err.to_errno(), > > }; > > > > + // This overwrites the private data from above. It makes sense to not hold on to the misc > > + // pointer since the `struct miscdevice` can get unregistered as soon as we return from this > > + // call, so the misc pointer might be dangling on future file operations. > > + // > > Wait, what are we overwriting this here with? Now private data points > to the misc device when before it was the file structure. No other code > needed to be changed because of that? Can't we enforce this pointer > type somewhere so that any casts in any read/write/ioctl also "knows" it > has the right type? This feels "dangerous" to me. Ultimately, when interfacing with C code using void pointers, Rust is going to need a pointer cast somewhere to assert what the type is. With the current design, that place is the fops_* functions. We need to get the pointer casts right there, but anywhere else the types are enforced. > > // SAFETY: The open call of a file owns the private data. > > unsafe { (*file).private_data = ptr.into_foreign().cast_mut() }; > > Is this SAFETY comment still correct? Well, it could probably be worded better at least. The point is that nobody else is going to touch this field and we can do what we want with it. Alice