Skip to content
This repository has been archived by the owner on Mar 7, 2021. It is now read-only.

Commit

Permalink
Add the json-sysctl demo from the LSSNA talk
Browse files Browse the repository at this point in the history
  • Loading branch information
geofft committed Aug 21, 2020
1 parent 1ccec76 commit 122e401
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 0 deletions.
21 changes: 21 additions & 0 deletions tests/json-sysctl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "json-sysctl-tests"
version = "0.1.0"
authors = ["Alex Gaynor <[email protected]", "Geoffrey Thomas <[email protected]>"]
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" }
86 changes: 86 additions & 0 deletions tests/json-sysctl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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::<Self>()
.read()
.build();

fn open() -> linux_kernel_module::KernelResult<Self> {
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::<typenum::U32, _>(&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<Self> {
let chrdev_registration = linux_kernel_module::chrdev::builder(cstr!("json"), 0..1)?
.register_device::<JsonChrdev>()
.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"
);
22 changes: 22 additions & 0 deletions tests/json-sysctl/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -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"
);
});
}

0 comments on commit 122e401

Please sign in to comment.