starnix_core/bpf/
context.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::power::EbpfSuspendGuard;
6use crate::task::CurrentTask;
7use ebpf_api::{CurrentTaskContext, Map, MapValueRef, MapsContext};
8use starnix_sync::{EbpfStateLock, Locked};
9use starnix_uapi::{gid_t, pid_t, uid_t};
10
11enum SuspendLockState<'a> {
12    NotLocked(&'a mut Locked<EbpfStateLock>),
13
14    #[allow(dead_code)]
15    Locked(EbpfSuspendGuard<'a>),
16}
17
18pub struct EbpfRunContextImpl<'a> {
19    current_task: &'a CurrentTask,
20
21    // Must precede `map_refs` to ensure it's dropped after `base`.
22    suspend_lock_state: SuspendLockState<'a>,
23
24    map_refs: Vec<MapValueRef<'a>>,
25}
26
27impl<'a> EbpfRunContextImpl<'a> {
28    pub fn new(locked: &'a mut Locked<EbpfStateLock>, current_task: &'a CurrentTask) -> Self {
29        Self {
30            current_task,
31            suspend_lock_state: SuspendLockState::NotLocked(locked),
32            map_refs: vec![],
33        }
34    }
35}
36
37impl<'a> MapsContext<'a> for EbpfRunContextImpl<'a> {
38    fn on_map_access(&mut self, map: &Map) {
39        if map.uses_locks() && matches!(self.suspend_lock_state, SuspendLockState::NotLocked(_)) {
40            replace_with::replace_with(&mut self.suspend_lock_state, |state| {
41                let SuspendLockState::NotLocked(locked) = state else { unreachable!() };
42                SuspendLockState::Locked(
43                    self.current_task
44                        .kernel()
45                        .suspend_resume_manager
46                        .acquire_ebpf_suspend_lock(locked),
47                )
48            });
49        }
50    }
51
52    fn add_value_ref(&mut self, map_ref: MapValueRef<'a>) {
53        self.map_refs.push(map_ref)
54    }
55}
56
57impl<'a> CurrentTaskContext for EbpfRunContextImpl<'a> {
58    fn get_uid_gid(&self) -> (uid_t, gid_t) {
59        self.current_task.with_current_creds(|creds| (creds.uid, creds.gid))
60    }
61
62    fn get_tid_tgid(&self) -> (pid_t, pid_t) {
63        let task = &self.current_task.task;
64        (task.get_tid(), task.get_pid())
65    }
66}