user_copy_rs_kernel_tests/
kernel.rs1#![no_std]
8#![allow(clippy::missing_safety_doc)]
9
10use user_copy::{UserInIovec, UserInOutPtr, UserInPtr, UserOutPtr, UserStringView};
11use zx_status::Status;
12use zx_types::{zx_iovec_t, zx_status_t};
13
14fn status_raw<T>(res: Result<T, Status>) -> zx_status_t {
15 match res {
16 Ok(_) => Status::OK.into_raw(),
17 Err(err) => err.into_raw(),
18 }
19}
20
21#[unsafe(no_mangle)]
24pub unsafe extern "C" fn rust_user_copy_user_out_ptr_write(
25 ptr: UserOutPtr<u32>,
26 val: u32,
27) -> zx_status_t {
28 status_raw(ptr.write(val))
29}
30
31#[unsafe(no_mangle)]
34pub unsafe extern "C" fn rust_user_copy_user_in_ptr_read(
35 ptr: UserInPtr<u32>,
36 out_val: *mut u32,
37) -> zx_status_t {
38 match ptr.read() {
39 Ok(val) => unsafe {
41 *out_val = val;
42 Status::OK.into_raw()
43 },
44 Err(err) => err.into_raw(),
45 }
46}
47
48#[unsafe(no_mangle)]
51pub unsafe extern "C" fn rust_user_copy_user_in_ptr_copy_from_user(
52 ptr: UserInPtr<u32>,
53 out_val: *mut u32,
54) -> zx_status_t {
55 let mut uninit = core::mem::MaybeUninit::uninit();
56 match ptr.copy_from_user(&mut uninit) {
57 Ok(val_ref) => unsafe {
59 *out_val = *val_ref;
60 Status::OK.into_raw()
61 },
62 Err(err) => err.into_raw(),
63 }
64}
65
66#[unsafe(no_mangle)]
69pub unsafe extern "C" fn rust_user_copy_user_in_ptr_copy_slice_from_user(
70 ptr: UserInPtr<u32>,
71 dst: *mut u32,
72 dst_len: usize,
73) -> zx_status_t {
74 let slice = unsafe {
76 core::slice::from_raw_parts_mut(dst.cast::<core::mem::MaybeUninit<u32>>(), dst_len)
77 };
78 status_raw(ptr.copy_slice_from_user(slice))
79}
80
81#[unsafe(no_mangle)]
84pub unsafe extern "C" fn rust_user_copy_user_in_iovec_get_total_capacity(
85 ptr: UserInPtr<zx_iovec_t>,
86 count: usize,
87 out_capacity: *mut usize,
88) -> zx_status_t {
89 let iovec = UserInIovec::new(ptr, count);
90 match iovec.get_total_capacity() {
91 Ok(cap) => unsafe {
93 *out_capacity = cap;
94 Status::OK.into_raw()
95 },
96 Err(err) => err.into_raw(),
97 }
98}
99
100#[unsafe(no_mangle)]
103pub unsafe extern "C" fn rust_user_copy_user_in_iovec_for_each(
104 ptr: UserInPtr<zx_iovec_t>,
105 count: usize,
106 out_product: *mut usize,
107) -> zx_status_t {
108 let iovec = UserInIovec::new(ptr, count);
109 let mut product = 2usize;
110 let status = iovec.for_each(|_buf, cap| {
111 product = product.wrapping_mul(cap);
112 Ok(())
113 });
114 match status {
115 Ok(()) => unsafe {
117 *out_product = product;
118 Status::OK.into_raw()
119 },
120 Err(err) => err.into_raw(),
121 }
122}
123
124#[unsafe(no_mangle)]
127pub unsafe extern "C" fn rust_user_copy_user_string_view_copy_slice_from_user(
128 ptr: UserInPtr<u8>,
129 length: usize,
130 dst: *mut u8,
131 dst_len: usize,
132) -> zx_status_t {
133 let sv = UserStringView { data: ptr, length };
134 let slice = unsafe {
136 core::slice::from_raw_parts_mut(dst.cast::<core::mem::MaybeUninit<u8>>(), dst_len)
137 };
138 status_raw(sv.copy_slice_from_user(slice))
139}
140
141#[unsafe(no_mangle)]
142pub extern "C" fn rust_user_copy_test_offsets() -> zx_status_t {
143 let base = 0x1000 as *mut u32;
144
145 let in_ptr = UserInPtr::new(base as *const u32);
147 if in_ptr.byte_offset(8).as_ptr() != (0x1008 as *const u32) {
148 return Status::INTERNAL.into_raw();
149 }
150 if in_ptr.byte_offset(-4).as_ptr() != (0x0ffc as *const u32) {
151 return Status::INTERNAL.into_raw();
152 }
153 if in_ptr.element_offset(3).as_ptr() != (0x100c as *const u32) {
154 return Status::INTERNAL.into_raw();
155 }
156 let null_in = UserInPtr::<u32>::new(core::ptr::null());
157 if !null_in.byte_offset(8).is_null() || !null_in.element_offset(3).is_null() {
158 return Status::INTERNAL.into_raw();
159 }
160 let def_in = UserInPtr::<u32>::default();
161 if !def_in.is_null() {
162 return Status::INTERNAL.into_raw();
163 }
164
165 let out_ptr = UserOutPtr::new(base);
167 if out_ptr.byte_offset(8).as_ptr() != (0x1008 as *mut u32) {
168 return Status::INTERNAL.into_raw();
169 }
170 if out_ptr.byte_offset(-4).as_ptr() != (0x0ffc as *mut u32) {
171 return Status::INTERNAL.into_raw();
172 }
173 if out_ptr.element_offset(3).as_ptr() != (0x100c as *mut u32) {
174 return Status::INTERNAL.into_raw();
175 }
176 let null_out = UserOutPtr::<u32>::new(core::ptr::null_mut());
177 if !null_out.byte_offset(8).is_null() || !null_out.element_offset(3).is_null() {
178 return Status::INTERNAL.into_raw();
179 }
180 let def_out = UserOutPtr::<u32>::default();
181 if !def_out.is_null() {
182 return Status::INTERNAL.into_raw();
183 }
184
185 let inout_ptr = UserInOutPtr::new(base);
187 if inout_ptr.byte_offset(8).as_ptr() != (0x1008 as *mut u32) {
188 return Status::INTERNAL.into_raw();
189 }
190 if inout_ptr.byte_offset(-4).as_ptr() != (0x0ffc as *mut u32) {
191 return Status::INTERNAL.into_raw();
192 }
193 if inout_ptr.element_offset(3).as_ptr() != (0x100c as *mut u32) {
194 return Status::INTERNAL.into_raw();
195 }
196 let null_inout = UserInOutPtr::<u32>::new(core::ptr::null_mut());
197 if !null_inout.byte_offset(8).is_null() || !null_inout.element_offset(3).is_null() {
198 return Status::INTERNAL.into_raw();
199 }
200 let def_inout = UserInOutPtr::<u32>::default();
201 if !def_inout.is_null() {
202 return Status::INTERNAL.into_raw();
203 }
204
205 let def_sv = UserStringView::default();
207 if !def_sv.data.is_null() || !def_sv.is_empty() {
208 return Status::INTERNAL.into_raw();
209 }
210
211 Status::OK.into_raw()
212}