capsules_system/syscall_filter/
tbf_header_filter.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2025.
4
5//! Implementations of [`SyscallFilter`] using TBF headers.
6
7use kernel::errorcode;
8use kernel::platform::SyscallFilter;
9use kernel::process;
10use kernel::syscall;
11use tock_tbf::types::CommandPermissions;
12
13/// An allow list system call filter based on the TBF header, with a default
14/// allow all fallback.
15///
16/// This will check if the process has TbfHeaderPermissions specified. If the
17/// process has TbfHeaderPermissions they will be used to determine access
18/// permissions. For details on this see the TockBinaryFormat documentation. If
19/// no permissions are specified the default is to allow the syscall.
20pub struct TbfHeaderFilterDefaultAllow {}
21
22/// Implement default SyscallFilter trait for filtering based on the TBF header.
23impl SyscallFilter for TbfHeaderFilterDefaultAllow {
24    fn filter_syscall(
25        &self,
26        process: &dyn process::Process,
27        syscall: &syscall::Syscall,
28    ) -> Result<(), errorcode::ErrorCode> {
29        match syscall {
30            // Subscribe is allowed if any commands are
31            syscall::Syscall::Subscribe {
32                driver_number,
33                subdriver_number: _,
34                upcall_ptr: _,
35                appdata: _,
36            } => match process.get_command_permissions(*driver_number, 0) {
37                CommandPermissions::NoPermsAtAll => Ok(()),
38                CommandPermissions::NoPermsThisDriver => Err(errorcode::ErrorCode::NODEVICE),
39                CommandPermissions::Mask(_allowed) => Ok(()),
40            },
41
42            syscall::Syscall::Command {
43                driver_number,
44                subdriver_number,
45                arg0: _,
46                arg1: _,
47            } => match process.get_command_permissions(*driver_number, subdriver_number / 64) {
48                CommandPermissions::NoPermsAtAll => Ok(()),
49                CommandPermissions::NoPermsThisDriver => Err(errorcode::ErrorCode::NODEVICE),
50                CommandPermissions::Mask(allowed) => {
51                    if (1 << (subdriver_number % 64)) & allowed > 0 {
52                        Ok(())
53                    } else {
54                        Err(errorcode::ErrorCode::NODEVICE)
55                    }
56                }
57            },
58
59            // Allow is allowed if any commands are
60            syscall::Syscall::ReadWriteAllow {
61                driver_number,
62                subdriver_number: _,
63                allow_address: _,
64                allow_size: _,
65            } => match process.get_command_permissions(*driver_number, 0) {
66                CommandPermissions::NoPermsAtAll => Ok(()),
67                CommandPermissions::NoPermsThisDriver => Err(errorcode::ErrorCode::NODEVICE),
68                CommandPermissions::Mask(_allowed) => Ok(()),
69            },
70
71            // Allow is allowed if any commands are
72            syscall::Syscall::UserspaceReadableAllow {
73                driver_number,
74                subdriver_number: _,
75                allow_address: _,
76                allow_size: _,
77            } => match process.get_command_permissions(*driver_number, 0) {
78                CommandPermissions::NoPermsAtAll => Ok(()),
79                CommandPermissions::NoPermsThisDriver => Err(errorcode::ErrorCode::NODEVICE),
80                CommandPermissions::Mask(_allowed) => Ok(()),
81            },
82
83            // Allow is allowed if any commands are
84            syscall::Syscall::ReadOnlyAllow {
85                driver_number,
86                subdriver_number: _,
87                allow_address: _,
88                allow_size: _,
89            } => match process.get_command_permissions(*driver_number, 0) {
90                CommandPermissions::NoPermsAtAll => Ok(()),
91                CommandPermissions::NoPermsThisDriver => Err(errorcode::ErrorCode::NODEVICE),
92                CommandPermissions::Mask(_allowed) => Ok(()),
93            },
94
95            // Non-filterable system calls
96            syscall::Syscall::Yield { .. }
97            | syscall::Syscall::Memop { .. }
98            | syscall::Syscall::Exit { .. } => Ok(()),
99        }
100    }
101}