-
Notifications
You must be signed in to change notification settings - Fork 141
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
Potential unsoundness in libbpf-cargo generated code #589
Comments
Perhaps the most sensible solution is to wrap all |
|
The |
Certain Rust types that we use in our generated skeleton are not valid for all bit patterns. Bools, for example, are defined to be one byte in size, but their representation allows only for 0 and 1 values to be used in said byte -- everything else is undefined behavior. Enums have similar problems, in that not the entire space of the backing type is necessarily used by variants. The result is an unsoundness issue in our generated skeletons, because C code could accidentally set an enum to an invalid value and Rust code would exhibit undefined behavior. This change fixes this problem by wrapping the corresponding attributes in MaybeUninit. In so doing users have to be explicit when accessing them and make sure that the current representation is indeed valid. Closes: libbpf#589 Signed-off-by: Daniel Müller <[email protected]>
Certain Rust types that we use in our generated skeleton are not valid for all bit patterns. Bools, for example, are defined to be one byte in size, but their representation allows only for 0 and 1 values to be used in said byte -- everything else is undefined behavior. Enums have similar problems, in that not the entire space of the backing type is necessarily used by variants. The result is an unsoundness issue in our generated skeletons, because C code could accidentally set an enum to an invalid value and Rust code would exhibit undefined behavior. This change fixes this problem by wrapping the corresponding attributes in MaybeUninit. In so doing users have to be explicit when accessing them and make sure that the current representation is indeed valid. Closes: libbpf#589 Signed-off-by: Daniel Müller <[email protected]>
Certain Rust types that we use in our generated skeleton are not valid for all bit patterns. Bools, for example, are defined to be one byte in size, but their representation allows only for 0 and 1 values to be used in said byte -- everything else is undefined behavior. Enums have similar problems, in that not the entire space of the backing type is necessarily used by variants. The result is an unsoundness issue in our generated skeletons, because C code could accidentally set an enum to an invalid value and Rust code would exhibit undefined behavior. This change fixes this problem by wrapping the corresponding attributes in MaybeUninit. In so doing users have to be explicit when accessing them and make sure that the current representation is indeed valid. Closes: #589 Signed-off-by: Daniel Müller <[email protected]>
I think there is possibility of unsoundness in the generated code, depending on what C code does. E.g., in the
capable
example we have thetool_config
struct, which contains theuniqueness
enumeration:libbpf-rs/examples/capable/src/bpf/capable.bpf.c
Lines 13 to 18 in cb4186d
libbpf-rs/examples/capable/src/bpf/capable.h
Lines 21 to 23 in cb4186d
Once we generate the skeleton we end up with:
and
That cast, however, is anything but safe. Rust's
uniqueness
requires that it has only any of the variant values 0, 1, or 2. But in C code it is fine to assign, say,0xff
to theenum
object (without triggering UB, I believe). The result would be UB in Rust.A similar thing can be observed for
bool
, though it may be that both languages have the samebool
representation (questionable, because C leaves binary representation mostly undefined, I believe, but if it's all LLVM we probably luck out).My reading is that this is basically a variant of rust-lang/rust#36927 (though I haven't gone through the issue in its entirety).
So at the very least we should make
rodata
(and similar methods)unsafe
and document that it's on users. The better approach is probably to translateenum
s to constants on the Rust side, which I understand is done for a lot of foreign function interfaces.The text was updated successfully, but these errors were encountered: