fishinabarrel / linux-kernel-module-rust

Framework for writing Linux kernel modules in safe Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Teach bindgen about sparse annotations

geofft opened this issue · comments

In include/linux/compiler_types.h there are annotations for the Sparse static type checker like

#ifdef __CHECKER__
# define __user         __attribute__((noderef, address_space(1)))
# define __kernel       __attribute__((address_space(0)))
# define __must_hold(x) __attribute__((context(x,1,1)))
# define __acquires(x)  __attribute__((context(x,0,1)))
# define __releases(x)  __attribute__((context(x,1,0)))
# define __percpu       __attribute__((noderef, address_space(3)))
# define __rcu          __attribute__((noderef, address_space(4)))
# define __private      __attribute__((noderef))

They're used in ways like

struct task_struct {
        struct task_struct __rcu        *parent;
};
struct file_operations {
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
};

It would be awesome if we could #define them in a way that bindgen could pass to Rust, such that you couldn't dereference a __rcu or __user pointer directly (note the noderef definition in sparse) and ideally so that there's a defined constructor from an __rcu raw pointer to an Rcu<T> or whatever but not from other raw pointers.

I'm also curious about the locking stuff, though that seems to be for what locks are expected to be held/acquired/released when you call a function, not for describing locks on data.

Apparently Clang supports __attribute__((annotate("some arbitrary text here"))) and assigns no meaning of it. If that gets through to the level that bindgen is looking at, we can probably teach bindgen to newtype the user/percpu/rcu/private pointers so they can't be dereferenced.