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