Skip to content

Commit 0a898c3

Browse files
committed
uapi: Generate and test 64-bit and 32-bit bindings
Until now, we only used 64-bit architecture, but here are the changes to use this crate on 32-bit architecture as well. Add the bindgen.sh script to make update simple: ./src/uapi/bindgen.sh .../linux-6.12 Target x86_64-unknown-linux-gnu was already the default but make it explicit wrt i686. Closes: #110 Signed-off-by: Mickaël Salaün <mic@digikod.net>
1 parent 229f152 commit 0a898c3

File tree

5 files changed

+301
-7
lines changed

5 files changed

+301
-7
lines changed

.github/workflows/rust.yml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,21 +131,31 @@ jobs:
131131
- name: Get MSRV
132132
run: sed -n 's/^rust-version = "\([0-9.]\+\)"$/RUST_TOOLCHAIN=\1/p' Cargo.toml >> $GITHUB_ENV
133133

134+
- name: Install 32-bit development libraries
135+
run: |
136+
sudo apt update
137+
sudo apt install gcc-multilib libc6-dev-i386
138+
134139
- name: Install Rust MSRV
135140
run: |
136141
rm ~/.cargo/bin/{cargo-fmt,rustfmt} || :
137142
rustup self update
138143
rustup default ${{ env.RUST_TOOLCHAIN }}
139144
rustup update ${{ env.RUST_TOOLCHAIN }}
145+
rustup target add i686-unknown-linux-gnu
146+
rustup target add x86_64-unknown-linux-gnu
140147
141-
- name: Build
142-
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo build --verbose
148+
- name: Build (x86_64)
149+
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo build --target x86_64-unknown-linux-gnu --verbose
143150

144-
- name: Build tests
145-
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo build --tests --verbose
151+
- name: Build (x86)
152+
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo build --target i686-unknown-linux-gnu --verbose
146153

147-
- name: Run tests against the local kernel (Landlock ABI ${{ env.LANDLOCK_CRATE_TEST_ABI }})
148-
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo test --verbose
154+
- name: Run tests against the local kernel (Landlock ABI ${{ env.LANDLOCK_CRATE_TEST_ABI }} on x86_64)
155+
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo test --target x86_64-unknown-linux-gnu --verbose
156+
157+
- name: Run tests against the local kernel (Landlock ABI ${{ env.LANDLOCK_CRATE_TEST_ABI }} on x86)
158+
run: rustup run ${{ env.RUST_TOOLCHAIN }} cargo test --target i686-unknown-linux-gnu --verbose
149159

150160
- name: Run tests against Linux 6.1
151161
run: CARGO="rustup run ${{ env.RUST_TOOLCHAIN }} cargo" ./landlock-test-tools/test-rust.sh linux-6.1 2

src/uapi/bindgen.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
set -u -e -o pipefail
5+
6+
if [[ $# -ne 1 ]]; then
7+
echo "usage $(basename -- "${BASH_SOURCE[0]}") <kernel-source>" >&2
8+
exit 1
9+
fi
10+
11+
LANDLOCK_H="$(readlink -f -- "$1")/include/uapi/linux/landlock.h"
12+
13+
if [[ ! -f "${LANDLOCK_H}" ]]; then
14+
echo "File not found: ${LANDLOCK_H}" >&2
15+
exit 1
16+
fi
17+
18+
cd "$(dirname "${BASH_SOURCE[0]}")"
19+
20+
MSRV="$(sed -n 's/^rust-version = "\(.*\)"/\1/p' ../../Cargo.toml)"
21+
22+
for ARCH in x86_64 i686; do
23+
bindgen \
24+
--rust-target "${MSRV}" \
25+
--ctypes-prefix="::std::os::raw" \
26+
-o "landlock_${ARCH}.rs" \
27+
"${LANDLOCK_H}" \
28+
-- \
29+
--target="${ARCH}-linux-gnu"
30+
done

src/uapi/landlock_i686.rs

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/* automatically generated by rust-bindgen 0.72.0 */
2+
3+
pub const __BITS_PER_LONG: u32 = 32;
4+
pub const __BITS_PER_LONG_LONG: u32 = 64;
5+
pub const __FD_SETSIZE: u32 = 1024;
6+
pub const LANDLOCK_CREATE_RULESET_VERSION: u32 = 1;
7+
pub const LANDLOCK_ACCESS_FS_EXECUTE: u32 = 1;
8+
pub const LANDLOCK_ACCESS_FS_WRITE_FILE: u32 = 2;
9+
pub const LANDLOCK_ACCESS_FS_READ_FILE: u32 = 4;
10+
pub const LANDLOCK_ACCESS_FS_READ_DIR: u32 = 8;
11+
pub const LANDLOCK_ACCESS_FS_REMOVE_DIR: u32 = 16;
12+
pub const LANDLOCK_ACCESS_FS_REMOVE_FILE: u32 = 32;
13+
pub const LANDLOCK_ACCESS_FS_MAKE_CHAR: u32 = 64;
14+
pub const LANDLOCK_ACCESS_FS_MAKE_DIR: u32 = 128;
15+
pub const LANDLOCK_ACCESS_FS_MAKE_REG: u32 = 256;
16+
pub const LANDLOCK_ACCESS_FS_MAKE_SOCK: u32 = 512;
17+
pub const LANDLOCK_ACCESS_FS_MAKE_FIFO: u32 = 1024;
18+
pub const LANDLOCK_ACCESS_FS_MAKE_BLOCK: u32 = 2048;
19+
pub const LANDLOCK_ACCESS_FS_MAKE_SYM: u32 = 4096;
20+
pub const LANDLOCK_ACCESS_FS_REFER: u32 = 8192;
21+
pub const LANDLOCK_ACCESS_FS_TRUNCATE: u32 = 16384;
22+
pub const LANDLOCK_ACCESS_FS_IOCTL_DEV: u32 = 32768;
23+
pub const LANDLOCK_ACCESS_NET_BIND_TCP: u32 = 1;
24+
pub const LANDLOCK_ACCESS_NET_CONNECT_TCP: u32 = 2;
25+
pub const LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: u32 = 1;
26+
pub const LANDLOCK_SCOPE_SIGNAL: u32 = 2;
27+
pub type __s8 = ::std::os::raw::c_schar;
28+
pub type __u8 = ::std::os::raw::c_uchar;
29+
pub type __s16 = ::std::os::raw::c_short;
30+
pub type __u16 = ::std::os::raw::c_ushort;
31+
pub type __s32 = ::std::os::raw::c_int;
32+
pub type __u32 = ::std::os::raw::c_uint;
33+
pub type __s64 = ::std::os::raw::c_longlong;
34+
pub type __u64 = ::std::os::raw::c_ulonglong;
35+
#[repr(C)]
36+
#[derive(Debug, Copy, Clone)]
37+
pub struct __kernel_fd_set {
38+
pub fds_bits: [::std::os::raw::c_ulong; 32usize],
39+
}
40+
#[test]
41+
fn bindgen_test_layout___kernel_fd_set() {
42+
const UNINIT: ::std::mem::MaybeUninit<__kernel_fd_set> = ::std::mem::MaybeUninit::uninit();
43+
let ptr = UNINIT.as_ptr();
44+
assert_eq!(
45+
::std::mem::size_of::<__kernel_fd_set>(),
46+
128usize,
47+
"Size of __kernel_fd_set"
48+
);
49+
assert_eq!(
50+
::std::mem::align_of::<__kernel_fd_set>(),
51+
4usize,
52+
"Alignment of __kernel_fd_set"
53+
);
54+
assert_eq!(
55+
unsafe { ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize },
56+
0usize,
57+
"Offset of field: __kernel_fd_set::fds_bits"
58+
);
59+
}
60+
pub type __kernel_sighandler_t =
61+
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
62+
pub type __kernel_key_t = ::std::os::raw::c_int;
63+
pub type __kernel_mqd_t = ::std::os::raw::c_int;
64+
pub type __kernel_mode_t = ::std::os::raw::c_ushort;
65+
pub type __kernel_ipc_pid_t = ::std::os::raw::c_ushort;
66+
pub type __kernel_uid_t = ::std::os::raw::c_ushort;
67+
pub type __kernel_gid_t = ::std::os::raw::c_ushort;
68+
pub type __kernel_old_dev_t = ::std::os::raw::c_ushort;
69+
pub type __kernel_long_t = ::std::os::raw::c_long;
70+
pub type __kernel_ulong_t = ::std::os::raw::c_ulong;
71+
pub type __kernel_ino_t = __kernel_ulong_t;
72+
pub type __kernel_pid_t = ::std::os::raw::c_int;
73+
pub type __kernel_suseconds_t = __kernel_long_t;
74+
pub type __kernel_daddr_t = ::std::os::raw::c_int;
75+
pub type __kernel_uid32_t = ::std::os::raw::c_uint;
76+
pub type __kernel_gid32_t = ::std::os::raw::c_uint;
77+
pub type __kernel_old_uid_t = __kernel_uid_t;
78+
pub type __kernel_old_gid_t = __kernel_gid_t;
79+
pub type __kernel_size_t = ::std::os::raw::c_uint;
80+
pub type __kernel_ssize_t = ::std::os::raw::c_int;
81+
pub type __kernel_ptrdiff_t = ::std::os::raw::c_int;
82+
#[repr(C)]
83+
#[derive(Debug, Copy, Clone)]
84+
pub struct __kernel_fsid_t {
85+
pub val: [::std::os::raw::c_int; 2usize],
86+
}
87+
#[test]
88+
fn bindgen_test_layout___kernel_fsid_t() {
89+
const UNINIT: ::std::mem::MaybeUninit<__kernel_fsid_t> = ::std::mem::MaybeUninit::uninit();
90+
let ptr = UNINIT.as_ptr();
91+
assert_eq!(
92+
::std::mem::size_of::<__kernel_fsid_t>(),
93+
8usize,
94+
"Size of __kernel_fsid_t"
95+
);
96+
assert_eq!(
97+
::std::mem::align_of::<__kernel_fsid_t>(),
98+
4usize,
99+
"Alignment of __kernel_fsid_t"
100+
);
101+
assert_eq!(
102+
unsafe { ::std::ptr::addr_of!((*ptr).val) as usize - ptr as usize },
103+
0usize,
104+
"Offset of field: __kernel_fsid_t::val"
105+
);
106+
}
107+
pub type __kernel_off_t = __kernel_long_t;
108+
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
109+
pub type __kernel_old_time_t = __kernel_long_t;
110+
pub type __kernel_time_t = __kernel_long_t;
111+
pub type __kernel_time64_t = ::std::os::raw::c_longlong;
112+
pub type __kernel_clock_t = __kernel_long_t;
113+
pub type __kernel_timer_t = ::std::os::raw::c_int;
114+
pub type __kernel_clockid_t = ::std::os::raw::c_int;
115+
pub type __kernel_caddr_t = *mut ::std::os::raw::c_char;
116+
pub type __kernel_uid16_t = ::std::os::raw::c_ushort;
117+
pub type __kernel_gid16_t = ::std::os::raw::c_ushort;
118+
pub type __le16 = __u16;
119+
pub type __be16 = __u16;
120+
pub type __le32 = __u32;
121+
pub type __be32 = __u32;
122+
pub type __le64 = __u64;
123+
pub type __be64 = __u64;
124+
pub type __sum16 = __u16;
125+
pub type __wsum = __u32;
126+
pub type __poll_t = ::std::os::raw::c_uint;
127+
#[doc = " struct landlock_ruleset_attr - Ruleset definition.\n\n Argument of sys_landlock_create_ruleset().\n\n This structure defines a set of *handled access rights*, a set of actions on\n different object types, which should be denied by default when the ruleset is\n enacted. Vice versa, access rights that are not specifically listed here are\n not going to be denied by this ruleset when it is enacted.\n\n For historical reasons, the %LANDLOCK_ACCESS_FS_REFER right is always denied\n by default, even when its bit is not set in @handled_access_fs. In order to\n add new rules with this access right, the bit must still be set explicitly\n (cf. `Filesystem flags`_).\n\n The explicit listing of *handled access rights* is required for backwards\n compatibility reasons. In most use cases, processes that use Landlock will\n *handle* a wide range or all access rights that they know about at build time\n (and that they have tested with a kernel that supported them all).\n\n This structure can grow in future Landlock versions."]
128+
#[repr(C)]
129+
#[derive(Debug, Copy, Clone)]
130+
pub struct landlock_ruleset_attr {
131+
#[doc = " @handled_access_fs: Bitmask of handled filesystem actions\n (cf. `Filesystem flags`_)."]
132+
pub handled_access_fs: __u64,
133+
#[doc = " @handled_access_net: Bitmask of handled network actions (cf. `Network\n flags`_)."]
134+
pub handled_access_net: __u64,
135+
#[doc = " @scoped: Bitmask of scopes (cf. `Scope flags`_)\n restricting a Landlock domain from accessing outside\n resources (e.g. IPCs)."]
136+
pub scoped: __u64,
137+
}
138+
#[test]
139+
fn bindgen_test_layout_landlock_ruleset_attr() {
140+
const UNINIT: ::std::mem::MaybeUninit<landlock_ruleset_attr> =
141+
::std::mem::MaybeUninit::uninit();
142+
let ptr = UNINIT.as_ptr();
143+
assert_eq!(
144+
::std::mem::size_of::<landlock_ruleset_attr>(),
145+
24usize,
146+
"Size of landlock_ruleset_attr"
147+
);
148+
assert_eq!(
149+
::std::mem::align_of::<landlock_ruleset_attr>(),
150+
4usize,
151+
"Alignment of landlock_ruleset_attr"
152+
);
153+
assert_eq!(
154+
unsafe { ::std::ptr::addr_of!((*ptr).handled_access_fs) as usize - ptr as usize },
155+
0usize,
156+
"Offset of field: landlock_ruleset_attr::handled_access_fs"
157+
);
158+
assert_eq!(
159+
unsafe { ::std::ptr::addr_of!((*ptr).handled_access_net) as usize - ptr as usize },
160+
8usize,
161+
"Offset of field: landlock_ruleset_attr::handled_access_net"
162+
);
163+
assert_eq!(
164+
unsafe { ::std::ptr::addr_of!((*ptr).scoped) as usize - ptr as usize },
165+
16usize,
166+
"Offset of field: landlock_ruleset_attr::scoped"
167+
);
168+
}
169+
#[doc = " @LANDLOCK_RULE_PATH_BENEATH: Type of a &struct\n landlock_path_beneath_attr ."]
170+
pub const landlock_rule_type_LANDLOCK_RULE_PATH_BENEATH: landlock_rule_type = 1;
171+
#[doc = " @LANDLOCK_RULE_NET_PORT: Type of a &struct\n landlock_net_port_attr ."]
172+
pub const landlock_rule_type_LANDLOCK_RULE_NET_PORT: landlock_rule_type = 2;
173+
#[doc = " enum landlock_rule_type - Landlock rule type\n\n Argument of sys_landlock_add_rule()."]
174+
pub type landlock_rule_type = ::std::os::raw::c_uint;
175+
#[doc = " struct landlock_path_beneath_attr - Path hierarchy definition\n\n Argument of sys_landlock_add_rule()."]
176+
#[repr(C, packed)]
177+
#[derive(Debug, Copy, Clone)]
178+
pub struct landlock_path_beneath_attr {
179+
#[doc = " @allowed_access: Bitmask of allowed actions for this file hierarchy\n (cf. `Filesystem flags`_)."]
180+
pub allowed_access: __u64,
181+
#[doc = " @parent_fd: File descriptor, preferably opened with ``O_PATH``,\n which identifies the parent directory of a file hierarchy, or just a\n file."]
182+
pub parent_fd: __s32,
183+
}
184+
#[test]
185+
fn bindgen_test_layout_landlock_path_beneath_attr() {
186+
const UNINIT: ::std::mem::MaybeUninit<landlock_path_beneath_attr> =
187+
::std::mem::MaybeUninit::uninit();
188+
let ptr = UNINIT.as_ptr();
189+
assert_eq!(
190+
::std::mem::size_of::<landlock_path_beneath_attr>(),
191+
12usize,
192+
"Size of landlock_path_beneath_attr"
193+
);
194+
assert_eq!(
195+
::std::mem::align_of::<landlock_path_beneath_attr>(),
196+
1usize,
197+
"Alignment of landlock_path_beneath_attr"
198+
);
199+
assert_eq!(
200+
unsafe { ::std::ptr::addr_of!((*ptr).allowed_access) as usize - ptr as usize },
201+
0usize,
202+
"Offset of field: landlock_path_beneath_attr::allowed_access"
203+
);
204+
assert_eq!(
205+
unsafe { ::std::ptr::addr_of!((*ptr).parent_fd) as usize - ptr as usize },
206+
8usize,
207+
"Offset of field: landlock_path_beneath_attr::parent_fd"
208+
);
209+
}
210+
#[doc = " struct landlock_net_port_attr - Network port definition\n\n Argument of sys_landlock_add_rule()."]
211+
#[repr(C)]
212+
#[derive(Debug, Copy, Clone)]
213+
pub struct landlock_net_port_attr {
214+
#[doc = " @allowed_access: Bitmask of allowed network actions for a port\n (cf. `Network flags`_)."]
215+
pub allowed_access: __u64,
216+
#[doc = " @port: Network port in host endianness.\n\n It should be noted that port 0 passed to :manpage:`bind(2)` will bind\n to an available port from the ephemeral port range. This can be\n configured with the ``/proc/sys/net/ipv4/ip_local_port_range`` sysctl\n (also used for IPv6).\n\n A Landlock rule with port 0 and the ``LANDLOCK_ACCESS_NET_BIND_TCP``\n right means that requesting to bind on port 0 is allowed and it will\n automatically translate to binding on the related port range."]
217+
pub port: __u64,
218+
}
219+
#[test]
220+
fn bindgen_test_layout_landlock_net_port_attr() {
221+
const UNINIT: ::std::mem::MaybeUninit<landlock_net_port_attr> =
222+
::std::mem::MaybeUninit::uninit();
223+
let ptr = UNINIT.as_ptr();
224+
assert_eq!(
225+
::std::mem::size_of::<landlock_net_port_attr>(),
226+
16usize,
227+
"Size of landlock_net_port_attr"
228+
);
229+
assert_eq!(
230+
::std::mem::align_of::<landlock_net_port_attr>(),
231+
4usize,
232+
"Alignment of landlock_net_port_attr"
233+
);
234+
assert_eq!(
235+
unsafe { ::std::ptr::addr_of!((*ptr).allowed_access) as usize - ptr as usize },
236+
0usize,
237+
"Offset of field: landlock_net_port_attr::allowed_access"
238+
);
239+
assert_eq!(
240+
unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize },
241+
8usize,
242+
"Offset of field: landlock_net_port_attr::port"
243+
);
244+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* automatically generated by rust-bindgen 0.71.1 */
1+
/* automatically generated by rust-bindgen 0.72.0 */
22

33
pub const __BITS_PER_LONG: u32 = 64;
44
pub const __BITS_PER_LONG_LONG: u32 = 64;

src/uapi/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44
#[allow(non_camel_case_types)]
55
#[allow(non_snake_case)]
66
#[allow(non_upper_case_globals)]
7+
#[cfg(target_arch = "x86_64")]
8+
#[path = "landlock_x86_64.rs"]
9+
mod landlock;
10+
11+
#[allow(dead_code)]
12+
#[allow(non_camel_case_types)]
13+
#[allow(non_snake_case)]
14+
#[allow(non_upper_case_globals)]
15+
#[cfg(target_arch = "x86")]
16+
#[path = "landlock_i686.rs"]
717
mod landlock;
818

919
#[rustfmt::skip]

0 commit comments

Comments
 (0)