From 122e401d65ccd947d2367eb82181294b131dd5ca Mon Sep 17 00:00:00 2001 From: Geoffrey Thomas Date: Sat, 17 Aug 2019 17:39:45 -0400 Subject: [PATCH] Add the json-sysctl demo from the LSSNA talk --- tests/json-sysctl/Cargo.toml | 21 ++++++++ tests/json-sysctl/src/lib.rs | 86 ++++++++++++++++++++++++++++++++ tests/json-sysctl/tests/tests.rs | 22 ++++++++ 3 files changed, 129 insertions(+) create mode 100644 tests/json-sysctl/Cargo.toml create mode 100644 tests/json-sysctl/src/lib.rs create mode 100644 tests/json-sysctl/tests/tests.rs diff --git a/tests/json-sysctl/Cargo.toml b/tests/json-sysctl/Cargo.toml new file mode 100644 index 00000000..11ad8eac --- /dev/null +++ b/tests/json-sysctl/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "json-sysctl-tests" +version = "0.1.0" +authors = ["Alex Gaynor "] +edition = "2018" + +[lib] +crate-type = ["staticlib"] +test = false + +[features] +default = ["linux-kernel-module"] + +[dependencies] +linux-kernel-module = { path = "../..", optional = true } +serde = { version = "1", default-features = false , features = ["derive"] } +serde-json-core = "0.1" +typenum = "1" + +[dev-dependencies] +kernel-module-testlib = { path = "../../testlib" } diff --git a/tests/json-sysctl/src/lib.rs b/tests/json-sysctl/src/lib.rs new file mode 100644 index 00000000..04f5f987 --- /dev/null +++ b/tests/json-sysctl/src/lib.rs @@ -0,0 +1,86 @@ +#![no_std] + +use core::cmp::min; +use core::convert::TryInto; +use core::sync::atomic::{AtomicBool, Ordering}; + +use serde::Serialize; + +use linux_kernel_module::cstr; +use linux_kernel_module::sysctl::Sysctl; +use linux_kernel_module::Mode; + +static A: AtomicBool = AtomicBool::new(false); +static B: AtomicBool = AtomicBool::new(false); +static C: AtomicBool = AtomicBool::new(false); + +struct JsonChrdev; + +impl linux_kernel_module::file_operations::FileOperations for JsonChrdev { + const VTABLE: linux_kernel_module::file_operations::FileOperationsVtable = + linux_kernel_module::file_operations::FileOperationsVtable::builder::() + .read() + .build(); + + fn open() -> linux_kernel_module::KernelResult { + Ok(JsonChrdev) + } +} + +impl linux_kernel_module::file_operations::Read for JsonChrdev { + fn read( + &self, + _file: &linux_kernel_module::file_operations::File, + buf: &mut linux_kernel_module::user_ptr::UserSlicePtrWriter, + offset: u64, + ) -> linux_kernel_module::KernelResult<()> { + let o = Output { + a: A.load(Ordering::Relaxed), + b: B.load(Ordering::Relaxed), + c: C.load(Ordering::Relaxed), + }; + let mut s = serde_json_core::to_vec::(&o) + .map_err(|_| linux_kernel_module::Error::ENOMEM)?; + s.push(b'\n') + .map_err(|_| linux_kernel_module::Error::ENOMEM)?; + let start = min(offset.try_into()?, s.len()); + let end = min(start + buf.len(), s.len()); + buf.write(&s[start..end])?; + Ok(()) + } +} + +struct JsonSysctlModule { + _a: Sysctl<&'static AtomicBool>, + _b: Sysctl<&'static AtomicBool>, + _c: Sysctl<&'static AtomicBool>, + _chrdev_registration: linux_kernel_module::chrdev::Registration, +} + +#[derive(Serialize)] +struct Output { + a: bool, + b: bool, + c: bool, +} + +impl linux_kernel_module::KernelModule for JsonSysctlModule { + fn init() -> linux_kernel_module::KernelResult { + let chrdev_registration = linux_kernel_module::chrdev::builder(cstr!("json"), 0..1)? + .register_device::() + .build()?; + Ok(JsonSysctlModule { + _a: Sysctl::register(cstr!("json-sysctl"), cstr!("a"), &A, Mode::from_int(0o666))?, + _b: Sysctl::register(cstr!("json-sysctl"), cstr!("b"), &B, Mode::from_int(0o666))?, + _c: Sysctl::register(cstr!("json-sysctl"), cstr!("c"), &C, Mode::from_int(0o666))?, + _chrdev_registration: chrdev_registration, + }) + } +} + +linux_kernel_module::kernel_module!( + JsonSysctlModule, + author: b"Fish in a Barrel Contributors", + description: b"Use JSON serialization in kernelspace", + license: b"GPL" +); diff --git a/tests/json-sysctl/tests/tests.rs b/tests/json-sysctl/tests/tests.rs new file mode 100644 index 00000000..2f54461c --- /dev/null +++ b/tests/json-sysctl/tests/tests.rs @@ -0,0 +1,22 @@ +use std::fs; + +use kernel_module_testlib::*; + +#[test] +fn test_json() { + with_kernel_module(|| { + let device_number = get_device_major_number("json"); + let p = temporary_file_path(); + let _u = mknod(&p, device_number, 0); + + assert_eq!( + std::str::from_utf8(&fs::read(&p).unwrap()).unwrap(), + "{\"a\":false,\"b\":false,\"c\":false}\n" + ); + fs::write("/proc/sys/json-sysctl/a", "1").unwrap(); + assert_eq!( + std::str::from_utf8(&fs::read(&p).unwrap()).unwrap(), + "{\"a\":true,\"b\":false,\"c\":false}\n" + ); + }); +}