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

Implement THIS_MODULE equivalent #15

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions rust/kernel/src/chrdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Builder {
self
}

pub fn build(self) -> KernelResult<Registration> {
pub fn build(self, this_module: *mut bindings::module) -> KernelResult<Registration> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a safer wrapper around this, otherwise passing the raw ptr makes this interface unsafe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing the address is not unsafe on its own. I agree that it could look better (e.g. a struct ThisModule as I mentioned in the message above).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this will deref the ptr, and creating a raw ptr is safe, the impact is that this is unsound :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is definitely unsound, but the interface isn't unsafe due to the pointer passing on its own -- i.e. if we could check the pointer (somehow), then the function wouldn't need to be unsafe to be sound.

Related: at some point we will have to establish some guidelines in the docs (before Rust code starts growing quickly with people calling kernel APIs directly etc.) on "how much soundness-correct" we want to be (see similar discussions in e.g. cxx).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but there's no way to check if the pointer is correct :-)

In general, safe interfaces can't really take raw pointers for this reason.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, that is why I said "somehow" :-)

I think in my first reply you understood I was disagreeing about the function needing to be marked unsafe or having a proper abstraction -- I was only (pedantically) pointing out that it is not the passing but what we do with the pointer that makes the function unsafe.

let mut dev: bindings::dev_t = 0;
let res = unsafe {
bindings::alloc_chrdev_region(
Expand All @@ -58,8 +58,7 @@ impl Builder {
for (i, file_op) in self.file_ops.iter().enumerate() {
unsafe {
bindings::cdev_init(&mut cdevs[i], *file_op);
// TODO: proper `THIS_MODULE` handling
cdevs[i].owner = core::ptr::null_mut();
cdevs[i].owner = this_module;
let rc = bindings::cdev_add(&mut cdevs[i], dev + i as bindings::dev_t, 1);
if rc != 0 {
// Clean up the ones that were allocated.
Expand Down
16 changes: 14 additions & 2 deletions rust/module/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ pub fn module(ts: TokenStream) -> TokenStream {
#[used]
static __{name}_{param_name}_struct: __{name}_{param_name}_RacyKernelParam = __{name}_{param_name}_RacyKernelParam(kernel::bindings::kernel_param {{
name: __{name}_{param_name}_name,
// TODO: `THIS_MODULE`
mod_: core::ptr::null_mut(),
mod_: THIS_MODULE.0,
ops: unsafe {{ &kernel::bindings::param_ops_{param_kernel_type} }} as *const kernel::bindings::kernel_param_ops,
perm: {permissions},
level: -1,
Expand All @@ -269,6 +268,19 @@ pub fn module(ts: TokenStream) -> TokenStream {
"
static mut __MOD: Option<{type_}> = None;

struct __THIS_MODULE(*mut kernel::bindings::module);

unsafe impl Sync for __THIS_MODULE {{
}}

// TODO: provide a better abstraction to avoid passing around
// `THIS_MODULE.0`, i.e. `this_module: *mut bindings::module` parameters.
#[cfg(MODULE)]
static THIS_MODULE: __THIS_MODULE = __THIS_MODULE(unsafe {{ &kernel::bindings::__this_module }} as *const _ as *mut kernel::bindings::module);

#[cfg(not(MODULE))]
static THIS_MODULE: __THIS_MODULE = __THIS_MODULE(core::ptr::null_mut());

// Loadable modules need to export the `{{init,cleanup}}_module` identifiers
#[cfg(MODULE)]
#[no_mangle]
Expand Down