Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access data from proc file within kernel module

I need to access some proc files in a module on Android kernel. Basically i need the info shown in cat command, like cat /proc/uptime. However i need to do it programmatically.

I tried work with proc_fs functions, but it was just a little fuzzy for me, usually the examples are to create a proc file then read it and that is it. I need to actually use the data from proc files.

I also tred the good fopen, but it does not seems to work on modules.

How can i do that? i'm really newbie on this. I'm working on goldfish Android kernel.

Thanks.

like image 231
douglasd3 Avatar asked Oct 03 '22 02:10

douglasd3


2 Answers

Procfs is an in-memory file system. It is an interface for the userspace to fetch info and put (config) info into the kernel data structures. In other words, procfs enables userspace to interact and look into the kernel data structures the way they exist during runtime.

Hence, any file inside /proc is not meant to be read from inside a kernel or a kernel module. And why would one want to do that? In a monolithic kernel like Linux, you can access the data structures of one subsystem in the kernel through another directly or through a pre-defined function.

The following function call might help:

struct timespec uptime;

do_posix_clock_monotonic_gettime(&uptime);

You can refer to the /proc/uptime implementation at the link below, it is essentially a seq_file.

http://lxr.free-electrons.com/source/fs/proc/uptime.c

like image 195
user31986 Avatar answered Oct 07 '22 18:10

user31986


I'm responding to the original question, how can a kernel module access files in the procfs.

How a Kernel Module Accesses Files in Special Filesystems

I found the following to be a useful reference: https://elixir.bootlin.com/linux/latest/source/fs/proc/proc_sysctl.c#L1790

I think it's setting sysctl values from the kernel command line. The sequence appears to be as follows:

A. Mount the procfs filesystem

  1. proc_fs_type = get_fs_type("proc");
  2. *proc_mnt = kern_mount(proc_fs_type);

B. Open the file at a path relative to the root of the procfs

  1. file = file_open_root((*proc_mnt)->mnt_root, *proc_mnt, path, O_WRONLY, 0);

C. Read/Write the file

  1. int kernel_read_file(struct file *file, loff_t offset, void **buf, size_t buf_size, size_t *file_size, enum kernel_read_file_id id)
  2. wret = kernel_write(file, val, len, &pos);

D. Close the file

  1. err = filp_close(file, NULL);

D. Cleanup the filesystem mount

  1. kern_unmount(proc_mnt);
  2. put_filesystem(proc_fs_type);

Should a Kernel Module Access Files in Special Filesystems

Yes, procfs mostly provides user space with read/write access to kernel-level data. Since a kernel module runs in the kernel, if a more direct sequence of API calls exist that allow the module to access such data, use of such API would be preferred as it is likely much cleaner, less code, and more efficient.

However, a dynamically-loaded kernel module doesn't have (clean) direct access to all symbols (or data structures) in the kernel.

A kernel module can only access functions and variables that are

  • defined entirely in a header file that can be included in the kernel-module source

  • or explicitly exposed to kernel modules through one of the macros in /include/asm-generic/export.h:

    • EXPORT_SYMBOL
    • EXPORT_SYMBOL_GPL
    • EXPORT_DATA_SYMBOL
    • EXPORT_DATA_SYMBOL_GPL

Cases where a kernel module needs to access data that is not exposed through such EXPORTED API but accessible through files in procfs or any other special filesystem seem like legitimate cases for accessing such files from kernel modules.

As a general design principle, it is my understanding, that the kernel aims to implement mechanisms without forcing a particular policy. Any feature implemented in a way that forces a policy where user-space has access to data, but a kernel module does not is poorly designed.

Kernel module code, by design, run at the same privilege level as the rest of the kernel. There is no fool-proof way to deny a kernel module access to any data that any other part of the kernel can access. Any such attempts can be circumvented with beautifully ugly hacks.

As an extreme example, on x86 machines, the kernel module can use in-line assembly to directly access control registers, walk page tables, and have it's way with any region of memory it so desires. The same goes for interrupt and exception handlers.

like image 39
Safayet Ahmed Avatar answered Oct 07 '22 17:10

Safayet Ahmed