Skip to content

Commit

Permalink
tests: Add tests for Rust bindings
Browse files Browse the repository at this point in the history
Add the regression tests for the libseccomp crate that is Rust
language bindings for the libseccomp library.

You can run the tests as follows.

```sh
$ cd tests
$ make check-build
$ ./regression -m rust
```

If you do not want to build Rust test programs, set
`RUST_BINDINGS_TEST=no` as follows.

```sh
$ make check-build RUST_BINDINGS_TEST=no
```

Signed-off-by: Manabu Sugimoto <[email protected]>
  • Loading branch information
ManaSugi committed Jan 3, 2022
1 parent a792221 commit 90d23a8
Show file tree
Hide file tree
Showing 18 changed files with 761 additions and 1 deletion.
4 changes: 4 additions & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
*.bpf
*.bpfd
*.pfc
*.log
*.stats
__pycache__/
miniseq
util.pyc
Expand Down Expand Up @@ -64,3 +66,5 @@ util.pyc
56-basic-iterate_syscalls
57-basic-rawsysrc
58-live-tsync_notify
!/rust/*
/rust/target
20 changes: 20 additions & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ miniseq_LDADD =

TESTS = regression

RUST_BINDINGS_TEST = yes

This comment has been minimized.

Copy link
@drakenclimber

drakenclimber Jan 3, 2022

I need to think about this some more, but we may need to make ./configure aware of the rust stuff as well.

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

Thank you for the review. Yes, I'll prepare for the configure.

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

I fixed it by using configure.
185718a

The tests for rust bindings can be enabled as follows:

$ ./configure --enable-rust
rust_TESTS_DIR = ./rust
rust_LINK_TYPE = dylib
rust_LIBSECCOMP_LIBRARY_DIR = ../src/.libs
rust_cargo = $(shell command -v cargo 2>/dev/null)

This comment has been minimized.

Copy link
@drakenclimber

drakenclimber Jan 3, 2022

silly nitpick - I get this warning when I run ./autogen.sh

tests/Makefile.am:41: warning: shell command -v cargo 2>/dev/null: non-POSIX variable name
tests/Makefile.am:41: (probably a GNU make extension)

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

Oh, sorry. I fixe it temporarily, but this will be changed by configure


define build_rust_bindings
echo "Build test programs for rust bindings"; \
export LIBSECCOMP_LINK_TYPE=$(rust_LINK_TYPE); \
export LIBSECCOMP_LIB_PATH=$(rust_LIBSECCOMP_LIBRARY_DIR); \
$(MAKE) -C $(rust_TESTS_DIR) && $(MAKE) -C $(rust_TESTS_DIR) install;
endef

check_PROGRAMS = \
miniseq \
01-sim-allow \
Expand Down Expand Up @@ -234,6 +247,13 @@ EXTRA_PROGRAMS = 00-test

check-build:
${MAKE} ${AM_MAKEFLAGS} ${check_PROGRAMS}
@if [ "$(RUST_BINDINGS_TEST)" = "yes" ]; then \
if [ -z "$(rust_cargo)" ]; then \
echo "ERROR: command cargo not found. Please install it." >&2; exit 1; \
fi; \
$(call build_rust_bindings) \
fi

clean-local:
${RM} -f 00-test *.pyc
$(MAKE) -C $(rust_TESTS_DIR) clean
9 changes: 8 additions & 1 deletion tests/regression
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ GLBL_SYS_RESOLVER="../tools/scmp_sys_resolver"
GLBL_SYS_SIM="../tools/scmp_bpf_sim"
GLBL_SYS_API="../tools/scmp_api_level"

RUST_TESTS_BIN="./rust/bin"

####
# functions

Expand Down Expand Up @@ -100,7 +102,7 @@ optional arguments:
-h show this help message and exit
-j JOBS run up to JOBS test jobs in parallel
can also be set via LIBSECCOMP_TSTCFG_JOBS env variable
-m MODE specified the test mode [c (default), python]
-m MODE specified the test mode [c (default), python, rust]
can also be set via LIBSECCOMP_TSTCFG_MODE_LIST env variable
-a specifies all tests are to be run
-b BATCH_NAME specifies batch of tests to be run
Expand Down Expand Up @@ -262,6 +264,8 @@ function run_test_command() {
else
cmd="$cmd /usr/bin/env python ${srcdir}/$2.py $3"
fi
elif [[ $mode == "rust" ]]; then
cmd="${RUST_TESTS_BIN}/$2 $3"
else
cmd="$2 $3"
fi
Expand Down Expand Up @@ -1111,6 +1115,9 @@ while getopts "ab:gj:l:m:s:t:T:vh" opt; do
verify_deps python
mode_list="$mode_list python"
;;
rust)
mode_list="$mode_list rust"
;;
*)
usage
exit 1
Expand Down
14 changes: 14 additions & 0 deletions tests/rust/01-sim-allow/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "sim-allow"
version = "0.1.0"

This comment has been minimized.

Copy link
@drakenclimber

drakenclimber Jan 3, 2022

I'm afraid of the copy-pasta nature of this Cargo file. Having to copy-paste this 58 (and counting!) times seems inefficient.

One random solution - we could use automake to populate these variables. Then when we want to roll to a new version of libseccomp-rs, it's a one-line change and all of the tests are updated.

This comment has been minimized.

Copy link
@rusty-snake

rusty-snake Jan 3, 2022

@ManaSugi am I missing something or could we just put the test programs in libseccomp/tests/*.rs?

tests
|- Cargo.toml
|- 01-sim-allow.rs
|- 02-sim-basic.rs
...

Cargo.toml:

[package]
name = "rust-tests"
version = "0.0.0"
edition = "2018"

[dependencies]
anyhow = "1"
libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git" }

[[bin]]
name = "01-sim-allow"
path = "01-sim-allow.rs"

[[bin]]
name = "02-sim-basic"
path = "02-sim-basic.rs"

...

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

@drakenclimber @rusty-snake Thank you for your review.
The current design is not good, so I fixed it as follows.

rust
├── 01-sim-allow.rs            
├── 02-sim-basic.rs            
├── 03-sim-basic_chains.rs     
├── 04-sim-multilevel_chains.rs
├── 05-sim-long_jumps.rs       
├── Cargo.lock                 
├── Cargo.toml                 
├── Makefile                   
└── utils                            
    ├── Cargo.toml             
    └── src                    
        └── lib.rs             

@rusty-snake
IMO, it would be better to put these test programs in the upstream libseccomp repo for centralizing the tests.
But, I'm also not sure what the right answer as @drakenclimber mentioned in the comment.

This comment has been minimized.

Copy link
@rusty-snake

rusty-snake Jan 4, 2022

└── utils                            
    ├── Cargo.toml             
    └── src                    
        └── lib.rs       

Can also be a utils.rs.

Either via

mod utils;

or

[lib]
name = "utils"
path = "utils.rs"

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

Thank you for the suggestion.
I updated it as follows and fixed Makefile to use cargo install.

rust                             
├── 01-sim-allow.rs            
├── 02-sim-basic.rs            
├── 03-sim-basic_chains.rs     
├── 04-sim-multilevel_chains.rs
├── 05-sim-long_jumps.rs       
├── Cargo.lock                 
├── Cargo.toml                 
├── Makefile                   
└── utils.rs                   

This comment has been minimized.

Copy link
@drakenclimber

drakenclimber Jan 4, 2022

Works for me. Thanks for removing the copy-pasta; that wouldn't have been fun to maintain

authors = ["Manabu Sugimoto <[email protected]>"]
edition = "2018"

[dependencies]
libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git" }
utils = { path = "../utils" }
anyhow = "1.0.51"

[[bin]]
name = "01-sim-allow"
path = "src/main.rs"
17 changes: 17 additions & 0 deletions tests/rust/01-sim-allow/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0 or MIT

This comment has been minimized.

Copy link
@drakenclimber

drakenclimber Jan 3, 2022

What license should these files be since they will reside in the libseccomp github repo? Is Apache correct, or should they be LGPL?

Oh, and thanks for spurring discussion on SPDX. We've been wanting to move to it for a while.

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

Sorry, I forgot to modify the license after the copy-pasta.
IMO, in the case of the test programs, it is more appropriate to publish them under LGPL because they reside in the upstream repo. Hence, I modified the SPDX identifier for the test code to LGPL-2.1-only (The license in the Cargo.toml was also fixed).

//
// Copyright 2021 Sony Group Corporation
//
// Seccomp Library test program
//

use anyhow::Result;
use libseccomp::*;
use utils::*;

fn main() -> Result<()> {
let opts = util_getopt();
let ctx = ScmpFilterContext::new_filter(ScmpAction::Allow)?;

util_filter_output(&opts, &ctx)
}
14 changes: 14 additions & 0 deletions tests/rust/02-sim-basic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "sim-basic"
version = "0.1.0"
authors = ["Manabu Sugimoto <[email protected]>"]
edition = "2018"

[dependencies]
libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git" }
utils = { path = "../utils"}
anyhow = "1.0.51"

[[bin]]
name = "02-sim-basic"
path = "src/main.rs"
28 changes: 28 additions & 0 deletions tests/rust/02-sim-basic/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: Apache-2.0 or MIT
//
// Copyright 2021 Sony Group Corporation
//
// Seccomp Library test program
//

use anyhow::Result;
use libseccomp::*;
use utils::*;

fn main() -> Result<()> {

This comment has been minimized.

Copy link
@drakenclimber

drakenclimber Jan 3, 2022

I like how clean the libseccomp-rs API turned out. Even if you don't know rust that well, these tests are clear and concise

This comment has been minimized.

Copy link
@ManaSugi

ManaSugi Jan 4, 2022

Author Owner

I'm glad to hear that. Thank you. In addition, the get_syscall_from_name function will be fixed to be more clean by the PR.

let opts = util_getopt();
let mut ctx = ScmpFilterContext::new_filter(ScmpAction::KillThread)?;

ctx.add_rule_exact(ScmpAction::Allow, get_syscall_from_name("read", None)?)?;

ctx.add_rule_exact(ScmpAction::Allow, get_syscall_from_name("write", None)?)?;

ctx.add_rule_exact(ScmpAction::Allow, get_syscall_from_name("close", None)?)?;

ctx.add_rule_exact(
ScmpAction::Allow,
get_syscall_from_name("rt_sigreturn", None)?,
)?;

util_filter_output(&opts, &ctx)
}
14 changes: 14 additions & 0 deletions tests/rust/03-sim-basic_chains/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "sim-basic_chains"
version = "0.1.0"
authors = ["Manabu Sugimoto <[email protected]>"]
edition = "2018"

[dependencies]
libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git" }
utils = { path = "../utils"}
anyhow = "1.0.51"

[[bin]]
name = "03-sim-basic_chains"
path = "src/main.rs"
55 changes: 55 additions & 0 deletions tests/rust/03-sim-basic_chains/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: Apache-2.0 or MIT
//
// Copyright 2021 Sony Group Corporation
//
// Seccomp Library test program
//

use anyhow::Result;
use libseccomp::*;
use std::os::unix::io::AsRawFd;
use utils::*;

fn main() -> Result<()> {
let opts = util_getopt();
let mut ctx = ScmpFilterContext::new_filter(ScmpAction::KillThread)?;

ctx.add_rule_conditional_exact(
ScmpAction::Allow,
get_syscall_from_name("read", None)?,
&[ScmpArgCompare::new(
0,
ScmpCompareOp::Equal,
std::io::stdin().as_raw_fd() as u64,
)],
)?;

ctx.add_rule_conditional_exact(
ScmpAction::Allow,
get_syscall_from_name("write", None)?,
&[ScmpArgCompare::new(
0,
ScmpCompareOp::Equal,
std::io::stdout().as_raw_fd() as u64,
)],
)?;

ctx.add_rule_conditional_exact(
ScmpAction::Allow,
get_syscall_from_name("write", None)?,
&[ScmpArgCompare::new(
0,
ScmpCompareOp::Equal,
std::io::stderr().as_raw_fd() as u64,
)],
)?;

ctx.add_rule_exact(ScmpAction::Allow, get_syscall_from_name("close", None)?)?;

ctx.add_rule_exact(
ScmpAction::Allow,
get_syscall_from_name("rt_sigreturn", None)?,
)?;

util_filter_output(&opts, &ctx)
}
15 changes: 15 additions & 0 deletions tests/rust/04-sim-multilevel_chains/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "sim-multilevel_chains"
version = "0.1.0"
authors = ["Manabu Sugimoto <[email protected]>"]
edition = "2018"

[dependencies]
libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git" }
utils = { path = "../utils" }
anyhow = "1.0.51"
libc = "0.2.109"

[[bin]]
name = "04-sim-multilevel_chains"
path = "src/main.rs"
67 changes: 67 additions & 0 deletions tests/rust/04-sim-multilevel_chains/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: Apache-2.0 or MIT
//
// Copyright 2021 Sony Group Corporation
//
// Seccomp Library test program
//

use anyhow::Result;
use libseccomp::*;
use std::os::unix::io::AsRawFd;
use utils::*;

fn main() -> Result<()> {
let opts = util_getopt();
let mut ctx = ScmpFilterContext::new_filter(ScmpAction::KillThread)?;

ctx.add_rule(ScmpAction::Allow, get_syscall_from_name("openat", None)?)?;

ctx.add_rule(ScmpAction::Allow, get_syscall_from_name("close", None)?)?;

ctx.add_rule_conditional(
ScmpAction::Allow,
get_syscall_from_name("read", None)?,
&[
ScmpArgCompare::new(0, ScmpCompareOp::Equal, std::io::stdin().as_raw_fd() as u64),
ScmpArgCompare::new(1, ScmpCompareOp::NotEqual, 0),
ScmpArgCompare::new(2, ScmpCompareOp::Less, libc::ssize_t::MAX as u64),
],
)?;

ctx.add_rule_conditional(
ScmpAction::Allow,
get_syscall_from_name("write", None)?,
&[
ScmpArgCompare::new(
0,
ScmpCompareOp::Equal,
std::io::stdout().as_raw_fd() as u64,
),
ScmpArgCompare::new(1, ScmpCompareOp::NotEqual, 0),
ScmpArgCompare::new(2, ScmpCompareOp::Less, libc::ssize_t::MAX as u64),
],
)?;

ctx.add_rule_conditional(
ScmpAction::Allow,
get_syscall_from_name("write", None)?,
&[
ScmpArgCompare::new(
0,
ScmpCompareOp::Equal,
std::io::stderr().as_raw_fd() as u64,
),
ScmpArgCompare::new(1, ScmpCompareOp::NotEqual, 0),
ScmpArgCompare::new(2, ScmpCompareOp::Less, libc::ssize_t::MAX as u64),
],
)?;

ctx.add_rule(ScmpAction::Allow, get_syscall_from_name("close", None)?)?;

ctx.add_rule(
ScmpAction::Allow,
get_syscall_from_name("rt_sigreturn", None)?,
)?;

util_filter_output(&opts, &ctx)
}
15 changes: 15 additions & 0 deletions tests/rust/05-sim-long_jumps/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "sim-long_jumps"
version = "0.1.0"
authors = ["Manabu Sugimoto <[email protected]>"]
edition = "2018"

[dependencies]
libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git" }
utils = { path = "../utils" }
anyhow = "1.0.51"
libc = "0.2.109"

[[bin]]
name = "05-sim-long_jumps"
path = "src/main.rs"
56 changes: 56 additions & 0 deletions tests/rust/05-sim-long_jumps/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SPDX-License-Identifier: Apache-2.0 or MIT
//
// Copyright 2021 Sony Group Corporation
//
// Seccomp Library test program
//

use anyhow::Result;
use libseccomp::*;
use utils::*;

fn main() -> Result<()> {
let opts = util_getopt();
let mut ctx = ScmpFilterContext::new_filter(ScmpAction::KillThread)?;

ctx.add_rule(ScmpAction::Allow, get_syscall_from_name("brk", None)?)?;

// same syscall, many chains
for iter in 0..100 {
ctx.add_rule_conditional(
ScmpAction::Allow,
get_syscall_from_name("chdir", None)?,
&[
ScmpArgCompare::new(0, ScmpCompareOp::Equal, iter),
ScmpArgCompare::new(1, ScmpCompareOp::NotEqual, 0),
ScmpArgCompare::new(2, ScmpCompareOp::Less, libc::ssize_t::MAX as u64),
],
)?;
}

// many syscalls, same chain
let mut ctr = 0;
for iter in 0..10000 {
if ctr >= 100 {
break;
}

if iter == get_syscall_from_name("chdir", None)? {
continue;
}

if get_syscall_name_from_arch(ScmpArch::Native, iter).is_ok() {
ctx.add_rule_conditional(
ScmpAction::Allow,
iter,
&[ScmpArgCompare::new(0, ScmpCompareOp::NotEqual, 0)],
)?;

ctr += 1;
}
}

ctx.add_rule(ScmpAction::Allow, get_syscall_from_name("close", None)?)?;

util_filter_output(&opts, &ctx)
}
Loading

0 comments on commit 90d23a8

Please sign in to comment.