From 91f519c63866bb40872b762ed3ac8b01e1c9c05b Mon Sep 17 00:00:00 2001 From: Gioh Kim Date: Sun, 1 Oct 2023 20:57:55 +0900 Subject: [PATCH] ch04: kernel panic when openning proc_create returns non-null pointer but open generates null-pointer panic. I checked the panic address. That is a code calling open. / # insmod share/rust_proc.ko [ 22.202776] rust_proc: module verification failed: signature and/or required key missing - tainting kernel [ 22.204453] rust_proc: rust_proc is loaded [ 22.205103] rust_proc: succeeded to create a proc entry: 0xffff8880054696c0 / # cat /proc/rust_demo/rust_proc_fs [ 26.663960] kernel tried to execute NX-protected page - exploit attempt? (uid: 0) [ 26.665132] BUG: unable to handle page fault for address: ffff888005492a00 [ 26.666141] #PF: supervisor instruction fetch in kernel mode [ 26.666674] #PF: error_code(0x0011) - permissions violation [ 26.666674] PGD 3a01067 P4D 3a01067 PUD 3a02067 PMD 80000000054001e3 [ 26.666674] Oops: 0011 [#1] PREEMPT SMP NOPTI [ 26.666674] CPU: 0 PID: 120 Comm: cat Tainted: G E 6.3.0+ #18 [ 26.666674] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 [ 26.666674] RIP: 0010:0xffff888005492a00 [ 26.666674] Code: 00 00 60 11 e0 81 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 [ 26.666674] RSP: 0018:ffff8880056c7e00 EFLAGS: 00010286 [ 26.666674] RAX: ffff8880056c7918 RBX: 0000000000000000 RCX: ffff8880056c7ef0 [ 26.666674] RDX: 0000000000001000 RSI: 00007ffc8b3ba048 RDI: ffff888005721400 [ 26.666674] RBP: ffff8880056c7e48 R08: 00007ffc8b3ba048 R09: 0000000000000000 [ 26.666674] R10: 0000000000000000 R11: ffff888005492a00 R12: ffff8880054696c0 [ 26.666674] R13: ffff888005721400 R14: 0000000000000001 R15: 0000000000000000 [ 26.666674] FS: 000000000249a3c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 [ 26.666674] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 26.666674] CR2: ffff888005492a00 CR3: 00000000054c6000 CR4: 00000000000006f0 [ 26.666674] Call Trace: [ 26.666674] [ 26.666674] ? proc_reg_read+0xe8/0x150 [ 26.666674] vfs_read+0xb4/0x260 [ 26.666674] ? do_sendfile+0x1cf/0x3f0 [ 26.666674] ksys_read+0x5f/0xb0 [ 26.666674] __x64_sys_read+0x1b/0x20 [ 26.666674] do_syscall_64+0x35/0x50 [ 26.666674] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 26.666674] RIP: 0033:0x4ad272 [ 26.666674] Code: 31 c0 e9 b1 fe ff ff 50 48 8d 3d c1 80 17 00 e8 54 8e 00 00 0f 1f 40 00 f3 0f 1e fa 64 8b 04 25 18 00 00 04 [ 26.666674] RSP: 002b:00007ffc8b3b9fe8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 [ 26.666674] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00000000004ad272 [ 26.666674] RDX: 0000000000001000 RSI: 00007ffc8b3ba048 RDI: 0000000000000003 [ 26.666674] RBP: 00007ffc8b3ba048 R08: 0000000000000001 R09: 0000000000000000 [ 26.666674] R10: 0000000001000000 R11: 0000000000000246 R12: 0000000000001000 [ 26.666674] R13: 000000000249a3a0 R14: 0000000000000000 R15: 0000000000000001 [ 26.666674] [ 26.666674] Modules linked in: rust_proc(E) [ 26.666674] CR2: ffff888005492a00 [ 26.666674] ---[ end trace 0000000000000000 ]--- [ 26.666674] RIP: 0010:0xffff888005492a00 [ 26.666674] Code: 00 00 60 11 e0 81 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 [ 26.666674] RSP: 0018:ffff8880056c7e00 EFLAGS: 00010286 [ 26.666674] RAX: ffff8880056c7918 RBX: 0000000000000000 RCX: ffff8880056c7ef0 [ 26.666674] RDX: 0000000000001000 RSI: 00007ffc8b3ba048 RDI: ffff888005721400 [ 26.666674] RBP: ffff8880056c7e48 R08: 00007ffc8b3ba048 R09: 0000000000000000 [ 26.666674] R10: 0000000000000000 R11: ffff888005492a00 R12: ffff8880054696c0 [ 26.666674] R13: ffff888005721400 R14: 0000000000000001 R15: 0000000000000000 [ 26.666674] FS: 000000000249a3c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000 [ 26.666674] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 26.666674] CR2: ffff888005492a00 CR3: 00000000054c6000 CR4: 00000000000006f0 [ 26.666674] note: cat[120] exited with irqs disabled Killed --- samples/rust/rust_proc.rs | 50 +++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/samples/rust/rust_proc.rs b/samples/rust/rust_proc.rs index 5455539fbe8751..fa1d8809cd554d 100644 --- a/samples/rust/rust_proc.rs +++ b/samples/rust/rust_proc.rs @@ -7,6 +7,7 @@ //! make LLVM=1 M=samples/rust // core is from Rust compiler, not from kernel +use core::marker::PhantomPinned; use core::ptr; use kernel::bindings; @@ -26,8 +27,10 @@ module! { } struct RustProc { + ops: bindings::proc_ops, parent: *mut bindings::proc_dir_entry, _entry: *mut bindings::proc_dir_entry, + _pin: PhantomPinned, } impl RustProc { @@ -55,9 +58,13 @@ impl RustProc { pr_info!("proc_open is invoked\n"); pr_info!("proc_open is invoked\n"); pr_info!("proc_open is invoked\n"); - pr_info!("proc_open is invoked\n"); - pr_info!("proc_open is invoked\n"); - pr_info!("proc_open is invoked\n"); + pr_err!("proc_open is invoked\n"); + pr_err!("proc_open is invoked\n"); + pr_err!("proc_open is invoked\n"); + + while true { + pr_info!("proc_open is invoked\n"); + } unsafe { let ret = bindings::single_open(_file, Some(Self::proc_show), ptr::null_mut()); @@ -79,22 +86,28 @@ impl kernel::Module for RustProc { let dir_name = CString::try_from_fmt(fmt!("{}", SUB_DIR_NAME))?; let parent = bindings::proc_mkdir(dir_name.as_char_ptr(), ptr::null_mut()); - let proc_ops = bindings::proc_ops { - proc_flags: 0, // mandatory to prevent build error - proc_get_unmapped_area: None, // mandatory to prevent build error - proc_read_iter: None, // mandatory to prevent build error - proc_open: Some(Self::proc_open), - proc_read: None, - proc_write: None, - proc_lseek: None, - proc_release: None, - proc_poll: None, - proc_ioctl: None, - proc_mmap: None, + let ret = Self { + parent, + ops: bindings::proc_ops { + proc_flags: 0, // mandatory to prevent build error + proc_get_unmapped_area: None, // mandatory to prevent build error + proc_read_iter: None, // mandatory to prevent build error + proc_open: Some(Self::proc_open), + proc_read: None, + proc_write: None, + proc_lseek: None, + proc_release: None, + proc_poll: None, + proc_ioctl: None, + proc_mmap: None, + }, + _entry: ptr::null_mut(), + _pin: PhantomPinned, }; + let entry_name = CString::try_from_fmt(fmt!("{}", PROC_FS_NAME))?; let entry: *mut bindings::proc_dir_entry = - bindings::proc_create(entry_name.as_char_ptr(), 0o644, parent, &proc_ops); + bindings::proc_create(entry_name.as_char_ptr(), 0o644, parent, &ret.ops); // How to check entry? if entry.is_null() { pr_info!("failed to create a proc entry\n"); @@ -102,10 +115,7 @@ impl kernel::Module for RustProc { pr_info!("succeeded to create a proc entry: {:p}\n", entry); } - Ok(RustProc { - parent, - _entry: entry, - }) + Ok(ret) } } }