1#![allow(non_upper_case_globals)]
7
8use crate::bpf::attachments::{BpfAttachAttr, bpf_prog_attach, bpf_prog_detach};
9use crate::bpf::fs::{BpfFsDir, BpfHandle, get_bpf_object, resolve_pinned_bpf_object};
10use crate::bpf::map::{self, BpfMap, BpfMapHandle};
11use crate::bpf::program::{Program, ProgramInfo};
12use crate::mm::{MemoryAccessor, MemoryAccessorExt};
13use crate::security;
14use crate::task::CurrentTask;
15use crate::vfs::socket::{Socket, ZxioBackedSocket};
16use crate::vfs::{Anon, FdFlags, FdNumber, LookupContext, OutputBuffer, UserBuffersOutputBuffer};
17use ebpf::{EbpfInstruction, MapFlags, MapSchema};
18use ebpf_api::{MapKey, ProgramType};
19use smallvec::smallvec;
20use starnix_logging::{log_error, log_trace, log_warn, track_stub};
21use starnix_syscalls::{SUCCESS, SyscallResult};
22use starnix_types::user_buffer::UserBuffer;
23use starnix_uapi::auth::CAP_SYS_ADMIN;
24use starnix_uapi::errors::Errno;
25use starnix_uapi::open_flags::OpenFlags;
26use starnix_uapi::user_address::{UserAddress, UserCString, UserRef};
27use starnix_uapi::{
28 BPF_F_RDONLY, BPF_F_WRONLY, bpf_attr__bindgen_ty_1, bpf_attr__bindgen_ty_2,
29 bpf_attr__bindgen_ty_4, bpf_attr__bindgen_ty_5, bpf_attr__bindgen_ty_8, bpf_attr__bindgen_ty_9,
30 bpf_attr__bindgen_ty_10, bpf_attr__bindgen_ty_12, bpf_cmd, bpf_cmd_BPF_BTF_GET_FD_BY_ID,
31 bpf_cmd_BPF_BTF_GET_NEXT_ID, bpf_cmd_BPF_BTF_LOAD, bpf_cmd_BPF_ENABLE_STATS,
32 bpf_cmd_BPF_ITER_CREATE, bpf_cmd_BPF_LINK_CREATE, bpf_cmd_BPF_LINK_DETACH,
33 bpf_cmd_BPF_LINK_GET_FD_BY_ID, bpf_cmd_BPF_LINK_GET_NEXT_ID, bpf_cmd_BPF_LINK_UPDATE,
34 bpf_cmd_BPF_MAP_CREATE, bpf_cmd_BPF_MAP_DELETE_BATCH, bpf_cmd_BPF_MAP_DELETE_ELEM,
35 bpf_cmd_BPF_MAP_FREEZE, bpf_cmd_BPF_MAP_GET_FD_BY_ID, bpf_cmd_BPF_MAP_GET_NEXT_ID,
36 bpf_cmd_BPF_MAP_GET_NEXT_KEY, bpf_cmd_BPF_MAP_LOOKUP_AND_DELETE_BATCH,
37 bpf_cmd_BPF_MAP_LOOKUP_AND_DELETE_ELEM, bpf_cmd_BPF_MAP_LOOKUP_BATCH,
38 bpf_cmd_BPF_MAP_LOOKUP_ELEM, bpf_cmd_BPF_MAP_UPDATE_BATCH, bpf_cmd_BPF_MAP_UPDATE_ELEM,
39 bpf_cmd_BPF_OBJ_GET, bpf_cmd_BPF_OBJ_GET_INFO_BY_FD, bpf_cmd_BPF_OBJ_PIN,
40 bpf_cmd_BPF_PROG_ATTACH, bpf_cmd_BPF_PROG_BIND_MAP, bpf_cmd_BPF_PROG_DETACH,
41 bpf_cmd_BPF_PROG_GET_FD_BY_ID, bpf_cmd_BPF_PROG_GET_NEXT_ID, bpf_cmd_BPF_PROG_LOAD,
42 bpf_cmd_BPF_PROG_QUERY, bpf_cmd_BPF_PROG_RUN, bpf_cmd_BPF_RAW_TRACEPOINT_OPEN,
43 bpf_cmd_BPF_TASK_FD_QUERY, bpf_cmd_BPF_TOKEN_CREATE, bpf_map_info,
44 bpf_map_type_BPF_MAP_TYPE_DEVMAP, bpf_map_type_BPF_MAP_TYPE_DEVMAP_HASH,
45 bpf_map_type_BPF_MAP_TYPE_SK_STORAGE, bpf_prog_info, errno, error,
46};
47use zerocopy::{FromBytes, IntoBytes};
48
49fn read_attr<Attr: FromBytes>(
54 current_task: &CurrentTask,
55 attr_addr: UserAddress,
56 attr_size: u32,
57) -> Result<Attr, Errno> {
58 let mut attr_size = attr_size as usize;
59 let sizeof_attr = std::mem::size_of::<Attr>();
60
61 if attr_size > sizeof_attr {
63 let tail_addr = attr_addr.checked_add(sizeof_attr).ok_or_else(|| errno!(EFAULT))?;
64 let tail = current_task.read_memory_to_vec(tail_addr, attr_size - sizeof_attr)?;
65 if tail.into_iter().any(|byte| byte != 0) {
66 return error!(E2BIG);
67 }
68
69 attr_size = sizeof_attr;
70 }
71
72 current_task.read_object_partial(UserRef::new(attr_addr), attr_size)
75}
76
77fn reopen_bpf_fd(
78 current_task: &CurrentTask,
79 handle: BpfHandle,
80 open_flags: OpenFlags,
81) -> Result<SyscallResult, Errno> {
82 let name = handle.type_name();
85 let file = Anon::new_private_file(
86 current_task,
87 Box::new(handle),
88 open_flags | OpenFlags::CLOEXEC,
89 name,
90 );
91 Ok(current_task.add_file(file, FdFlags::CLOEXEC)?.into())
92}
93
94fn install_bpf_fd(
95 current_task: &CurrentTask,
96 obj: impl Into<BpfHandle>,
97) -> Result<SyscallResult, Errno> {
98 let handle: BpfHandle = obj.into();
99 handle.security_check_open_fd(current_task, None)?;
100 let name = handle.type_name();
101
102 let file = Anon::new_private_file(
104 current_task,
105 Box::new(handle),
106 OpenFlags::RDWR | OpenFlags::CLOEXEC,
107 name,
108 );
109 Ok(current_task.add_file(file, FdFlags::CLOEXEC)?.into())
110}
111
112#[derive(Debug, Clone)]
113pub struct BpfTypeFormat {
114 #[allow(dead_code)]
115 data: Vec<u8>,
116}
117
118fn read_map_key(
119 current_task: &CurrentTask,
120 addr: UserAddress,
121 map: &BpfMapHandle,
122) -> Result<MapKey, Errno> {
123 let key_size = map.schema.key_size as usize;
124 let mut key = current_task.read_objects_to_smallvec(UserRef::<u8>::new(addr), key_size)?;
125
126 if map.schema.map_type == bpf_map_type_BPF_MAP_TYPE_SK_STORAGE {
128 let fd = FdNumber::from_raw(
129 i32::read_from_bytes(&key[..]).expect("invalid key size in sk_storage map"),
130 );
131 let file = current_task.files().get(fd)?;
132 let socket = Socket::get_from_file(&file)?;
133 let socket = socket.downcast_socket::<ZxioBackedSocket>().ok_or_else(|| errno!(EINVAL))?;
134 let cookie = socket.get_socket_cookie()?;
135 key = MapKey::from_slice(cookie.as_bytes());
136 }
137
138 Ok(key)
139}
140
141fn validate_bpf_name(name: &[u8]) -> Result<&str, Errno> {
142 let name = std::ffi::CStr::from_bytes_until_nul(name)
143 .map_err(|_| errno!(EINVAL))?
144 .to_str()
145 .map_err(|_| errno!(EINVAL))?;
146 if !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.') {
149 return error!(EINVAL);
150 }
151 Ok(name)
152}
153
154pub fn sys_bpf(
155 current_task: &CurrentTask,
156 cmd: bpf_cmd,
157 attr_addr: UserAddress,
158 attr_size: u32,
159) -> Result<SyscallResult, Errno> {
160 match cmd {
168 bpf_cmd_BPF_MAP_CREATE => {
170 let map_attr: bpf_attr__bindgen_ty_1 = read_attr(current_task, attr_addr, attr_size)?;
171 log_trace!("BPF_MAP_CREATE {:?}", map_attr);
172 security::check_bpf_access(current_task, cmd, &map_attr, attr_size)?;
173
174 let map_type = map_attr.map_type;
175 let mut flags =
176 MapFlags::from_bits(map_attr.map_flags).ok_or_else(|| errno!(EINVAL))?;
177 if map_type == bpf_map_type_BPF_MAP_TYPE_DEVMAP
182 || map_type == bpf_map_type_BPF_MAP_TYPE_DEVMAP_HASH
183 {
184 flags |= MapFlags::ProgReadOnly;
185 }
186
187 let schema = MapSchema {
188 map_type,
189 key_size: map_attr.key_size,
190 value_size: map_attr.value_size,
191 max_entries: map_attr.max_entries,
192 flags,
193 };
194
195 let name = validate_bpf_name(map_attr.map_name.as_bytes())?;
196 let map =
197 BpfMap::new(current_task, schema, name, security::bpf_map_alloc(current_task))?;
198 install_bpf_fd(current_task, map)
199 }
200
201 bpf_cmd_BPF_MAP_LOOKUP_ELEM => {
202 let elem_attr: bpf_attr__bindgen_ty_2 = read_attr(current_task, attr_addr, attr_size)?;
203 log_trace!("BPF_MAP_LOOKUP_ELEM");
204 security::check_bpf_access(current_task, cmd, &elem_attr, attr_size)?;
205 let map_fd = FdNumber::from_raw(elem_attr.map_fd as i32);
206 let map = get_bpf_object(current_task, map_fd)?;
207 let map = map.as_map()?;
208
209 if map.schema.flags.contains(MapFlags::SyscallWriteOnly) {
210 return error!(EPERM);
211 }
212
213 let key = read_map_key(current_task, UserAddress::from(elem_attr.key), map)?;
214
215 let user_value = UserAddress::from(unsafe { elem_attr.__bindgen_anon_1.value });
218
219 let _suspend_lock =
220 current_task.kernel().suspend_resume_manager.acquire_ebpf_suspend_lock();
221
222 let value = map.load(&key).ok_or_else(|| errno!(ENOENT))?;
223 current_task.write_memory(user_value, &value)?;
224
225 Ok(SUCCESS)
226 }
227
228 bpf_cmd_BPF_MAP_UPDATE_ELEM => {
230 let elem_attr: bpf_attr__bindgen_ty_2 = read_attr(current_task, attr_addr, attr_size)?;
231 log_trace!("BPF_MAP_UPDATE_ELEM");
232 security::check_bpf_access(current_task, cmd, &elem_attr, attr_size)?;
233 let map_fd = FdNumber::from_raw(elem_attr.map_fd as i32);
234 let map = get_bpf_object(current_task, map_fd)?;
235 let map = map.as_map()?;
236
237 let frozen = map.frozen();
239
240 if *frozen || map.schema.flags.contains(MapFlags::SyscallReadOnly) {
241 return error!(EPERM);
242 }
243
244 let flags = elem_attr.flags;
245 let key = read_map_key(current_task, UserAddress::from(elem_attr.key), map)?;
246
247 let user_value = UserAddress::from(unsafe { elem_attr.__bindgen_anon_1.value });
250 let mut value =
251 current_task.read_memory_to_vec(user_value, map.schema.value_size as usize)?;
252
253 let _suspend_lock =
254 current_task.kernel().suspend_resume_manager.acquire_ebpf_suspend_lock();
255
256 map.update(&key[..], value.as_mut_bytes().into(), flags)
257 .map_err(map::map_error_to_errno)?;
258 Ok(SUCCESS)
259 }
260
261 bpf_cmd_BPF_MAP_DELETE_ELEM => {
262 let elem_attr: bpf_attr__bindgen_ty_2 = read_attr(current_task, attr_addr, attr_size)?;
263 log_trace!("BPF_MAP_DELETE_ELEM");
264 security::check_bpf_access(current_task, cmd, &elem_attr, attr_size)?;
265 let map_fd = FdNumber::from_raw(elem_attr.map_fd as i32);
266 let map = get_bpf_object(current_task, map_fd)?;
267 let map = map.as_map()?;
268
269 let frozen = map.frozen();
271
272 if *frozen || map.schema.flags.contains(MapFlags::SyscallReadOnly) {
273 return error!(EPERM);
274 }
275
276 let key = read_map_key(current_task, UserAddress::from(elem_attr.key), map)?;
277
278 let _suspend_lock =
279 current_task.kernel().suspend_resume_manager.acquire_ebpf_suspend_lock();
280
281 map.delete(&key).map_err(map::map_error_to_errno)?;
282 Ok(SUCCESS)
283 }
284
285 bpf_cmd_BPF_MAP_GET_NEXT_KEY => {
288 let elem_attr: bpf_attr__bindgen_ty_2 = read_attr(current_task, attr_addr, attr_size)?;
289 log_trace!("BPF_MAP_GET_NEXT_KEY");
290 security::check_bpf_access(current_task, cmd, &elem_attr, attr_size)?;
291 let map_fd = FdNumber::from_raw(elem_attr.map_fd as i32);
292 let map = get_bpf_object(current_task, map_fd)?;
293 let map = map.as_map()?;
294
295 if map.schema.flags.contains(MapFlags::SyscallWriteOnly) {
296 return error!(EPERM);
297 }
298
299 let key = if elem_attr.key != 0 {
300 Some(read_map_key(current_task, UserAddress::from(elem_attr.key), map)?)
301 } else {
302 None
303 };
304
305 let next_key =
306 map.get_next_key(key.as_ref().map(|k| &k[..])).map_err(map::map_error_to_errno)?;
307
308 let user_next_key = UserAddress::from(unsafe { elem_attr.__bindgen_anon_1.next_key });
311 current_task.write_memory(user_next_key, &next_key)?;
312
313 Ok(SUCCESS)
314 }
315
316 bpf_cmd_BPF_PROG_LOAD => {
319 let prog_attr: bpf_attr__bindgen_ty_4 = read_attr(current_task, attr_addr, attr_size)?;
320 log_trace!("BPF_PROG_LOAD");
321 security::check_bpf_access(current_task, cmd, &prog_attr, attr_size)?;
322
323 let user_code = UserRef::<EbpfInstruction>::new(UserAddress::from(prog_attr.insns));
324 let code = current_task.read_objects_to_vec(user_code, prog_attr.insn_cnt as usize)?;
325
326 let mut log_buffer = if prog_attr.log_buf != 0 && prog_attr.log_size > 1 {
327 UserBuffersOutputBuffer::unified_new(
328 current_task,
329 smallvec![UserBuffer {
330 address: prog_attr.log_buf.into(),
331 length: (prog_attr.log_size - 1) as usize
332 }],
333 )?
334 } else {
335 UserBuffersOutputBuffer::unified_new(current_task, smallvec![])?
336 };
337 let name = validate_bpf_name(prog_attr.prog_name.as_bytes())?;
338 let info = ProgramInfo::try_from(&prog_attr)?;
339 let program_type = info.program_type;
340 let program = Program::new(current_task, info, &mut log_buffer, code);
341 let program_or_stub = match (program, program_type) {
342 (Ok(program), _) => BpfHandle::Program(program),
343
344 (Err(e), ProgramType::SockOps | ProgramType::SchedCls | ProgramType::Kprobe)
347 if !current_task.kernel().features.bpf_v2 =>
348 {
349 log_warn!(
350 "Creating a stub for eBPF program {name}, type={program_type:?}: {e:?}"
351 );
352 BpfHandle::ProgramStub(prog_attr.prog_type)
353 }
354
355 (Err(e), _) => {
356 log_error!("Unable to load eBPF program {name}, type={program_type:?}: {e:?}");
357 return Err(e.into());
358 }
359 };
360 log_buffer.write(b"\0")?;
362 install_bpf_fd(current_task, program_or_stub)
363 }
364
365 bpf_cmd_BPF_PROG_ATTACH => {
367 let attach_attr: BpfAttachAttr = read_attr(current_task, attr_addr, attr_size)?;
368 security::check_bpf_access(current_task, cmd, &attach_attr, attr_size)?;
369 bpf_prog_attach(current_task, attach_attr)
370 }
371
372 bpf_cmd_BPF_PROG_QUERY => {
374 let mut prog_attr: bpf_attr__bindgen_ty_10 =
375 read_attr(current_task, attr_addr, attr_size)?;
376 log_trace!("BPF_PROG_QUERY");
377 security::check_bpf_access(current_task, cmd, &prog_attr, attr_size)?;
378 track_stub!(TODO("https://fxbug.dev/322873416"), "Bpf::BPF_PROG_QUERY");
379 current_task.write_memory(UserAddress::from(prog_attr.prog_ids), 1.as_bytes())?;
380 prog_attr.__bindgen_anon_2.prog_cnt = std::mem::size_of::<u64>() as u32;
381 current_task.write_memory(attr_addr, prog_attr.as_bytes())?;
382 Ok(SUCCESS)
383 }
384
385 bpf_cmd_BPF_OBJ_PIN => {
388 let pin_attr: bpf_attr__bindgen_ty_5 = read_attr(current_task, attr_addr, attr_size)?;
389 log_trace!("BPF_OBJ_PIN {:?}", pin_attr);
390 security::check_bpf_access(current_task, cmd, &pin_attr, attr_size)?;
391 let bpf_fd = FdNumber::from_raw(pin_attr.bpf_fd as i32);
392 let object = get_bpf_object(current_task, bpf_fd)?;
393 let path_addr = UserCString::new(current_task, UserAddress::from(pin_attr.pathname));
394 let pathname = current_task.read_path(path_addr)?;
395 let (parent, basename) = current_task.lookup_parent_at(
396 &mut LookupContext::default(),
397 FdNumber::AT_FDCWD,
398 pathname.as_ref(),
399 )?;
400 let bpf_dir =
401 parent.entry.node.downcast_ops::<BpfFsDir>().ok_or_else(|| errno!(EINVAL))?;
402 bpf_dir.register_pin(current_task, &parent, basename, object)?;
403 Ok(SUCCESS)
404 }
405
406 bpf_cmd_BPF_OBJ_GET => {
408 let path_attr: bpf_attr__bindgen_ty_5 = read_attr(current_task, attr_addr, attr_size)?;
409 log_trace!("BPF_OBJ_GET {:?}", path_attr);
410 security::check_bpf_access(current_task, cmd, &path_attr, attr_size)?;
411 let path_addr = UserCString::new(current_task, UserAddress::from(path_attr.pathname));
412 let open_flags = match path_attr.file_flags {
413 BPF_F_RDONLY => OpenFlags::RDONLY,
414 BPF_F_WRONLY => OpenFlags::WRONLY,
415 0 => OpenFlags::RDWR,
416 _ => return error!(EINVAL),
417 };
418 let pathname = current_task.read_path(path_addr)?;
419 let handle = resolve_pinned_bpf_object(current_task, pathname.as_ref(), open_flags)?;
420 reopen_bpf_fd(current_task, handle, open_flags)
421 }
422
423 bpf_cmd_BPF_OBJ_GET_INFO_BY_FD => {
425 let mut get_info_attr: bpf_attr__bindgen_ty_9 =
426 read_attr(current_task, attr_addr, attr_size)?;
427 log_trace!("BPF_OBJ_GET_INFO_BY_FD {:?}", get_info_attr);
428 security::check_bpf_access(current_task, cmd, &get_info_attr, attr_size)?;
429 let bpf_fd = FdNumber::from_raw(get_info_attr.bpf_fd as i32);
430 let object = get_bpf_object(current_task, bpf_fd)?;
431
432 let mut info = match object {
433 BpfHandle::Map(map) => bpf_map_info {
434 type_: map.schema.map_type,
435 id: map.id(),
436 key_size: map.schema.key_size,
437 value_size: map.schema.value_size,
438 max_entries: map.schema.max_entries,
439 map_flags: map.schema.flags.bits(),
440 ..Default::default()
441 }
442 .as_bytes()
443 .to_owned(),
444 BpfHandle::Program(prog) => {
445 #[allow(unknown_lints, clippy::unnecessary_struct_initialization)]
446 bpf_prog_info {
447 type_: prog.info.program_type.into(),
448 id: prog.id(),
449 jited_prog_len: 1,
451 ..Default::default()
452 }
453 .as_bytes()
454 .to_owned()
455 }
456 BpfHandle::ProgramStub(type_) => {
457 #[allow(unknown_lints, clippy::unnecessary_struct_initialization)]
458 bpf_prog_info {
459 type_,
460 jited_prog_len: 1,
462 ..Default::default()
463 }
464 .as_bytes()
465 .to_owned()
466 }
467 _ => {
468 return error!(EINVAL);
469 }
470 };
471
472 info.truncate(get_info_attr.info_len as usize);
477 get_info_attr.info_len = info.len() as u32;
478 current_task.write_memory(UserAddress::from(get_info_attr.info), &info)?;
479 current_task.write_memory(attr_addr, get_info_attr.as_bytes())?;
480 Ok(SUCCESS)
481 }
482
483 bpf_cmd_BPF_BTF_LOAD => {
487 let btf_attr: bpf_attr__bindgen_ty_12 = read_attr(current_task, attr_addr, attr_size)?;
488 log_trace!("BPF_BTF_LOAD {:?}", btf_attr);
489 security::check_bpf_access(current_task, cmd, &btf_attr, attr_size)?;
490 let data = current_task
491 .read_memory_to_vec(UserAddress::from(btf_attr.btf), btf_attr.btf_size as usize)?;
492 install_bpf_fd(current_task, BpfTypeFormat { data })
493 }
494 bpf_cmd_BPF_PROG_DETACH => {
495 let attach_attr: BpfAttachAttr = read_attr(current_task, attr_addr, attr_size)?;
496 security::check_bpf_access(current_task, cmd, &attach_attr, attr_size)?;
497 bpf_prog_detach(current_task, attach_attr)
498 }
499 bpf_cmd_BPF_PROG_RUN => {
500 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_PROG_RUN");
501 error!(EINVAL)
502 }
503 bpf_cmd_BPF_PROG_GET_NEXT_ID => {
504 security::check_task_capable(current_task, CAP_SYS_ADMIN)?;
505 let mut get_next_attr: bpf_attr__bindgen_ty_8 =
506 read_attr(current_task, attr_addr, attr_size)?;
507 let start_id = unsafe { get_next_attr.__bindgen_anon_1.start_id };
509 get_next_attr.next_id = current_task
510 .kernel()
511 .ebpf_state
512 .get_next_program_id(start_id)
513 .ok_or_else(|| errno!(ENOENT))?;
514 current_task.write_object(UserRef::new(attr_addr), &get_next_attr)?;
515 Ok(SUCCESS)
516 }
517 bpf_cmd_BPF_MAP_GET_NEXT_ID => {
518 security::check_task_capable(current_task, CAP_SYS_ADMIN)?;
519 let mut get_next_attr: bpf_attr__bindgen_ty_8 =
520 read_attr(current_task, attr_addr, attr_size)?;
521 let start_id = unsafe { get_next_attr.__bindgen_anon_1.start_id };
523 get_next_attr.next_id = current_task
524 .kernel()
525 .ebpf_state
526 .get_next_map_id(start_id)
527 .ok_or_else(|| errno!(ENOENT))?;
528 current_task.write_object(UserRef::new(attr_addr), &get_next_attr)?;
529 Ok(SUCCESS)
530 }
531 bpf_cmd_BPF_PROG_GET_FD_BY_ID => {
532 security::check_task_capable(current_task, CAP_SYS_ADMIN)?;
533 let get_by_id_attr: bpf_attr__bindgen_ty_8 =
534 read_attr(current_task, attr_addr, attr_size)?;
535 let prog_id = unsafe { get_by_id_attr.__bindgen_anon_1.prog_id };
537 let prog = current_task
538 .kernel()
539 .ebpf_state
540 .get_program_by_id(prog_id)
541 .ok_or_else(|| errno!(ENOENT))?;
542 install_bpf_fd(current_task, prog)
543 }
544 bpf_cmd_BPF_MAP_GET_FD_BY_ID => {
545 security::check_task_capable(current_task, CAP_SYS_ADMIN)?;
546 let get_by_id_attr: bpf_attr__bindgen_ty_8 =
547 read_attr(current_task, attr_addr, attr_size)?;
548 let map_id = unsafe { get_by_id_attr.__bindgen_anon_1.map_id };
550 let map = current_task
551 .kernel()
552 .ebpf_state
553 .get_map_by_id(map_id)
554 .ok_or_else(|| errno!(ENOENT))?;
555 install_bpf_fd(current_task, map)
556 }
557 bpf_cmd_BPF_RAW_TRACEPOINT_OPEN => {
558 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_RAW_TRACEPOINT_OPEN");
559 error!(EINVAL)
560 }
561 bpf_cmd_BPF_BTF_GET_FD_BY_ID => {
562 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_BTF_GET_FD_BY_ID");
563 error!(EINVAL)
564 }
565 bpf_cmd_BPF_TASK_FD_QUERY => {
566 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_TASK_FD_QUERY");
567 error!(EINVAL)
568 }
569 bpf_cmd_BPF_MAP_LOOKUP_AND_DELETE_ELEM => {
570 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_MAP_LOOKUP_AND_DELETE_ELEM");
571 error!(EINVAL)
572 }
573 bpf_cmd_BPF_MAP_FREEZE => {
574 let elem_attr: bpf_attr__bindgen_ty_2 = read_attr(current_task, attr_addr, attr_size)?;
575 log_trace!("BPF_MAP_FREEZE");
576 let map_fd = FdNumber::from_raw(elem_attr.map_fd as i32);
577 let map = get_bpf_object(current_task, map_fd)?;
578 let map = map.as_map()?;
579 map.freeze()?;
580 Ok(SUCCESS)
581 }
582 bpf_cmd_BPF_BTF_GET_NEXT_ID => {
583 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_BTF_GET_NEXT_ID");
584 error!(EINVAL)
585 }
586 bpf_cmd_BPF_MAP_LOOKUP_BATCH => {
587 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_MAP_LOOKUP_BATCH");
588 error!(EINVAL)
589 }
590 bpf_cmd_BPF_MAP_LOOKUP_AND_DELETE_BATCH => {
591 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_MAP_LOOKUP_AND_DELETE_BATCH");
592 error!(EINVAL)
593 }
594 bpf_cmd_BPF_MAP_UPDATE_BATCH => {
595 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_MAP_UPDATE_BATCH");
596 error!(EINVAL)
597 }
598 bpf_cmd_BPF_MAP_DELETE_BATCH => {
599 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_MAP_DELETE_BATCH");
600 error!(EINVAL)
601 }
602 bpf_cmd_BPF_LINK_CREATE => {
603 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_LINK_CREATE");
604 error!(EINVAL)
605 }
606 bpf_cmd_BPF_LINK_UPDATE => {
607 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_LINK_UPDATE");
608 error!(EINVAL)
609 }
610 bpf_cmd_BPF_LINK_GET_FD_BY_ID => {
611 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_LINK_GET_FD_BY_ID");
612 error!(EINVAL)
613 }
614 bpf_cmd_BPF_LINK_GET_NEXT_ID => {
615 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_LINK_GET_NEXT_ID");
616 error!(EINVAL)
617 }
618 bpf_cmd_BPF_ENABLE_STATS => {
619 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_ENABLE_STATS");
620 error!(EINVAL)
621 }
622 bpf_cmd_BPF_ITER_CREATE => {
623 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_ITER_CREATE");
624 error!(EINVAL)
625 }
626 bpf_cmd_BPF_LINK_DETACH => {
627 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_LINK_DETACH");
628 error!(EINVAL)
629 }
630 bpf_cmd_BPF_PROG_BIND_MAP => {
631 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_PROG_BIND_MAP");
632 error!(EINVAL)
633 }
634 bpf_cmd_BPF_TOKEN_CREATE => {
635 track_stub!(TODO("https://fxbug.dev/322874055"), "BPF_TOKEN_CREATE");
636 error!(EINVAL)
637 }
638 _ => {
639 track_stub!(TODO("https://fxbug.dev/322874055"), "bpf", cmd);
640 error!(EINVAL)
641 }
642 }
643}
644
645#[cfg(target_arch = "aarch64")]
647mod arch32 {
648 pub use super::sys_bpf as sys_arch32_bpf;
649}
650
651#[cfg(target_arch = "aarch64")]
652pub use arch32::*;