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

Commit fe3c89e

Browse files
committed
Very close now
1 parent 97ae5d7 commit fe3c89e

File tree

7 files changed

+58
-1
lines changed

7 files changed

+58
-1
lines changed

build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ const INCLUDED_FUNCTIONS: &[&str] = &[
1616
"kill_litter_super",
1717
"register_sysctl",
1818
"unregister_sysctl_table",
19+
"access_ok",
1920
];
2021
const INCLUDED_VARS: &[&str] = &[
2122
"EINVAL",
2223
"ENOMEM",
24+
"EFAULT",
2325
"__this_module",
2426
"FS_REQUIRES_DEV",
2527
"FS_BINARY_MOUNTDATA",
@@ -28,6 +30,7 @@ const INCLUDED_VARS: &[&str] = &[
2830
"FS_RENAME_DOES_D_MOVE",
2931
"BINDINGS_GFP_KERNEL",
3032
"KERN_INFO",
33+
"VERIFY_WRITE",
3134
];
3235

3336
fn main() {
@@ -74,6 +77,7 @@ fn main() {
7477
let mut builder = cc::Build::new();
7578
println!("cargo:rerun-if-env-changed=CLANG");
7679
builder.compiler(env::var("CLANG").unwrap_or("clang".to_string()));
80+
builder.warnings(false);
7781
builder.file("src/helpers.c");
7882
for arg in shlex::split(&output).unwrap() {
7983
builder.flag(&arg);

src/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <linux/module.h>
22
#include <linux/fs.h>
33
#include <linux/slab.h>
4+
#include <linux/uaccess.h>
45

56
// Bindgen gets confused at certain things
67
//

src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub struct Error(c_types::c_int);
66
impl Error {
77
pub const EINVAL: Self = Error(-(bindings::EINVAL as i32));
88
pub const ENOMEM: Self = Error(-(bindings::ENOMEM as i32));
9+
pub const EFAULT: Self = Error(-(bindings::EFAULT as i32));
910

1011
pub fn from_kernel_errno(errno: c_types::c_int) -> Error {
1112
return Error(errno);

src/helpers.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <linux/bug.h>
22
#include <linux/printk.h>
3+
#include <linux/uaccess.h>
4+
35

46
int printk_helper(const unsigned char *s, int len)
57
{
@@ -10,3 +12,8 @@ void bug_helper(void)
1012
{
1113
BUG();
1214
}
15+
16+
int access_ok_helper(unsigned int mode, const void __user *addr, unsigned long n)
17+
{
18+
return access_ok(mode, addr, n);
19+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod filesystem;
1313
pub mod printk;
1414
pub mod sysctl;
1515
mod types;
16+
pub mod user_ptr;
1617

1718
pub use alloc::format;
1819
pub use error::{Error, KernelResult};

src/sysctl.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use bindings;
77
use c_types;
88
use error;
99
use types;
10+
use user_ptr::UserSlicePtr;
1011

1112
pub struct Sysctl<T: Sync> {
1213
inner: Box<T>,
@@ -21,7 +22,20 @@ unsafe extern "C" fn proc_handler<T>(
2122
len: *mut usize,
2223
ppos: *mut bindings::loff_t,
2324
) -> c_types::c_int {
24-
unimplemented!();
25+
let data = match UserSlicePtr::new(buffer, *len) {
26+
Ok(ptr) => ptr,
27+
Err(e) => return e.to_kernel_errno(),
28+
};
29+
let storage = (*ctl).data as *mut T as Box<T>;
30+
let (bytes_processed, result) = if write != 0 {
31+
let data = data.read_all()?;
32+
storage.store_value(&data)
33+
} else {
34+
storage.read_value(&data)
35+
};
36+
*len -= bytes_processed;
37+
*ppos += bytes_processed;
38+
return result;
2539
}
2640

2741
impl<T: Sync> Sysctl<T> {

src/user_ptr.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use alloc::Vec;
2+
3+
use bindings;
4+
use c_types;
5+
use error;
6+
7+
extern "C" {
8+
fn access_ok_helper(
9+
mode: c_types::c_uint,
10+
addr: *const c_types::c_void,
11+
len: c_types::c_ulong,
12+
) -> c_types::c_int;
13+
}
14+
15+
pub struct UserSlicePtr(*mut c_types::c_void, usize);
16+
17+
impl UserSlicePtr {
18+
pub fn new(ptr: *mut c_types::c_void, length: usize) -> error::KernelResult<UserSlicePtr> {
19+
if unsafe { access_ok_helper(bindings::VERIFY_WRITE, ptr, length as c_types::c_ulong) } != 0
20+
{
21+
return Err(error::Error::EFAULT);
22+
}
23+
return Ok(UserSlicePtr(ptr, length));
24+
}
25+
26+
pub fn read_all(self) -> error::KernelResult<Vec<u8>> {
27+
unimplemented!();
28+
}
29+
}

0 commit comments

Comments
 (0)