How to read files in linux kernel after 5.10+ [duplicate] - c

I know all the discussions about why one should not read/write files from kernel, instead how to use /proc or netlink to do that. I want to read/write anyway. I have also read
Driving Me Nuts - Things You Never Should Do in the Kernel.
However, the problem is that 2.6.30 does not export sys_read(). Rather it's wrapped in SYSCALL_DEFINE3. So if I use it in my module, I get the following warnings:
WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!
Obviously insmod cannot load the module because linking does not happen correctly.
Questions:
How to read/write within kernel after 2.6.22 (where sys_read()/sys_open() are not exported)?
In general, how to use system calls wrapped in macro SYSCALL_DEFINEn() from within the kernel?

You should be aware that you should avoid file I/O from within Linux kernel when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:
Includes:
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
Opening a file (similar to open):
struct file *file_open(const char *path, int flags, int rights)
{
struct file *filp = NULL;
mm_segment_t oldfs;
int err = 0;
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open(path, flags, rights);
set_fs(oldfs);
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
return NULL;
}
return filp;
}
Close a file (similar to close):
void file_close(struct file *file)
{
filp_close(file, NULL);
}
Reading data from a file (similar to pread):
int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_read(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Writing data to a file (similar to pwrite):
int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_write(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Syncing changes a file (similar to fsync):
int file_sync(struct file *file)
{
vfs_fsync(file, 0);
return 0;
}
[Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.

Since version 4.14 of Linux kernel, vfs_read and vfs_write functions are no longer exported for use in modules. Instead, functions exclusively for kernel's file access are provided:
# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);
# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos);
Also, filp_open no longer accepts user-space string, so it can be used for kernel access directly (without dance with set_fs).

Related

How do I copy the contents of a file to another one in kernel space? [duplicate]

I know all the discussions about why one should not read/write files from kernel, instead how to use /proc or netlink to do that. I want to read/write anyway. I have also read
Driving Me Nuts - Things You Never Should Do in the Kernel.
However, the problem is that 2.6.30 does not export sys_read(). Rather it's wrapped in SYSCALL_DEFINE3. So if I use it in my module, I get the following warnings:
WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!
Obviously insmod cannot load the module because linking does not happen correctly.
Questions:
How to read/write within kernel after 2.6.22 (where sys_read()/sys_open() are not exported)?
In general, how to use system calls wrapped in macro SYSCALL_DEFINEn() from within the kernel?
You should be aware that you should avoid file I/O from within Linux kernel when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:
Includes:
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
Opening a file (similar to open):
struct file *file_open(const char *path, int flags, int rights)
{
struct file *filp = NULL;
mm_segment_t oldfs;
int err = 0;
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open(path, flags, rights);
set_fs(oldfs);
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
return NULL;
}
return filp;
}
Close a file (similar to close):
void file_close(struct file *file)
{
filp_close(file, NULL);
}
Reading data from a file (similar to pread):
int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_read(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Writing data to a file (similar to pwrite):
int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_write(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Syncing changes a file (similar to fsync):
int file_sync(struct file *file)
{
vfs_fsync(file, 0);
return 0;
}
[Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.
Since version 4.14 of Linux kernel, vfs_read and vfs_write functions are no longer exported for use in modules. Instead, functions exclusively for kernel's file access are provided:
# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);
# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos);
Also, filp_open no longer accepts user-space string, so it can be used for kernel access directly (without dance with set_fs).

How to run write something in a file with android kernel source code? [duplicate]

I know all the discussions about why one should not read/write files from kernel, instead how to use /proc or netlink to do that. I want to read/write anyway. I have also read
Driving Me Nuts - Things You Never Should Do in the Kernel.
However, the problem is that 2.6.30 does not export sys_read(). Rather it's wrapped in SYSCALL_DEFINE3. So if I use it in my module, I get the following warnings:
WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!
Obviously insmod cannot load the module because linking does not happen correctly.
Questions:
How to read/write within kernel after 2.6.22 (where sys_read()/sys_open() are not exported)?
In general, how to use system calls wrapped in macro SYSCALL_DEFINEn() from within the kernel?
You should be aware that you should avoid file I/O from within Linux kernel when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:
Includes:
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
Opening a file (similar to open):
struct file *file_open(const char *path, int flags, int rights)
{
struct file *filp = NULL;
mm_segment_t oldfs;
int err = 0;
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open(path, flags, rights);
set_fs(oldfs);
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
return NULL;
}
return filp;
}
Close a file (similar to close):
void file_close(struct file *file)
{
filp_close(file, NULL);
}
Reading data from a file (similar to pread):
int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_read(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Writing data to a file (similar to pwrite):
int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_write(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Syncing changes a file (similar to fsync):
int file_sync(struct file *file)
{
vfs_fsync(file, 0);
return 0;
}
[Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.
Since version 4.14 of Linux kernel, vfs_read and vfs_write functions are no longer exported for use in modules. Instead, functions exclusively for kernel's file access are provided:
# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);
# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos);
Also, filp_open no longer accepts user-space string, so it can be used for kernel access directly (without dance with set_fs).

How to open an existing file in a custom syscall and write to it [duplicate]

I know all the discussions about why one should not read/write files from kernel, instead how to use /proc or netlink to do that. I want to read/write anyway. I have also read
Driving Me Nuts - Things You Never Should Do in the Kernel.
However, the problem is that 2.6.30 does not export sys_read(). Rather it's wrapped in SYSCALL_DEFINE3. So if I use it in my module, I get the following warnings:
WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!
Obviously insmod cannot load the module because linking does not happen correctly.
Questions:
How to read/write within kernel after 2.6.22 (where sys_read()/sys_open() are not exported)?
In general, how to use system calls wrapped in macro SYSCALL_DEFINEn() from within the kernel?
You should be aware that you should avoid file I/O from within Linux kernel when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:
Includes:
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
Opening a file (similar to open):
struct file *file_open(const char *path, int flags, int rights)
{
struct file *filp = NULL;
mm_segment_t oldfs;
int err = 0;
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open(path, flags, rights);
set_fs(oldfs);
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
return NULL;
}
return filp;
}
Close a file (similar to close):
void file_close(struct file *file)
{
filp_close(file, NULL);
}
Reading data from a file (similar to pread):
int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_read(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Writing data to a file (similar to pwrite):
int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size)
{
mm_segment_t oldfs;
int ret;
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_write(file, data, size, &offset);
set_fs(oldfs);
return ret;
}
Syncing changes a file (similar to fsync):
int file_sync(struct file *file)
{
vfs_fsync(file, 0);
return 0;
}
[Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.
Since version 4.14 of Linux kernel, vfs_read and vfs_write functions are no longer exported for use in modules. Instead, functions exclusively for kernel's file access are provided:
# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);
# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos);
Also, filp_open no longer accepts user-space string, so it can be used for kernel access directly (without dance with set_fs).

I need help in understanding the following kernel module written in C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
As an assignment I need to complete the following C code in order to produce a kernel module able to act as a memory, but from how it's written I can't understand how it works and why many variables are not used but just declared. I have already tried looking on the teaching material they gave me, and it's even more confusing, plus I can't find on the web a good site where to find documentation about these functions.
The code is the following:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "my_device"
#define MAJOR_DEVICE_NUMBER 60
#define MINOR_DEVICE_NUMBER 0
#define BUF_LEN 1024
static char msg[BUF_LEN];
static char *msg_ptr; // I'm pretty sure this should become msg_reading_offset
static int major;
MODULE_AUTHOR("<YOUR NAME>");
MODULE_LICENSE("GPL");
static ssize_t my_read (
struct file *filp, char __user *buf,
size_t length, loff_t *offset);
static ssize_t my_write (
struct file *filp, const char __user *buf,
size_t length, loff_t *offset);
static int my_open (struct inode *inode,
struct file *filp);
static int my_close (struct inode *inode,
struct file *filp);
static int __init my_init (void);
static void __exit my_cleanup (void);
static struct file_operations fops = {
.read = my_read,
.write = my_write,
.open = my_open,
.release = my_close,
};
// I need to implement this function
static int my_open (struct inode *inode,
struct file *filp)
{
return 0;
}
// and this function
static int my_close (struct inode *inode,
struct file *filp)
{
return 0;
}
static ssize_t my_read (
struct file *filp, char __user *buf,
size_t length, loff_t *offset)
{
int nc = 0;
// if no more "valid" bytes can be read, stop
if (*msg_reading_offset == 0) return 0;
// no-negative values allowed
if (length < 0)
return -EINVAL;
// read the whole msg, nothing more
if (length > strlen(msg)) {
length = strlen(msg);
}
nc = copy_to_user(buf, msg_reading_offset, length);
/*
updates the current reading offset pointer so that a
recursive call due to not original
full length will get a 0 (nothing to read)
*/
msg_reading_offset += sizeof(char) * (length-nc);
// returns the number of REAL bytes read.
return length - nc;
}
static ssize_t my_write (
struct file *filp, const char __user *buf,
size_t length, loff_t *offset)
{
int nc = 0;
if (length > BUF_LEN)
return BUF_LEN-length;
nc = copy_from_user(msg,buf,length);
msg_ptr = msg;
return length - nc;
}
static int __init my_init (void)
{
register_chrdev (MAJOR_DEVICE_NUMBER,
DEVICE_NAME,
&fops);
}
module_init(my_init);
static void __exit my_cleanup (void)
{
unregister_chrdev (major, DEVICE_NAME);
}
module_exit(my_cleanup);
At the moment these are my biggest problems:
Where are all the *inode, *filp variables going? Am I supposed to use them?
How is this program even working? I know I need to compile it with a makefile I've been give, but then how am I supposed to access these functions?
Is this supposed to be a real program executed by the kernel or is it just a collections of functions I should use in another C program?
I'm sorry if the questions may seem stupid, but I am at a loss to know how the hell I'm supposed to approach this.
Your Q is a bit broad, but I'll try to give you some hints.
Where are all the *inode, *filp variables going? Am I supposed to use them?
First read an example of how a typical character device is implemented, eg, here.
How is this program even working? I know I need to compile it with a makefile I've been give, but then how am I supposed to access these functions?
Is this supposed to be a real program executed by the kernel or is it just a collections of functions I should use in another C program?
This is NOT a normal executable program. As you are writing a kernel module, you are extending the kernel functionalities. You need to tell the kernel about that, normally via an insmod call. Eg.,
insmod chardev.ko
Then create the corresponding character device:
mknod /dev/chardev c 60 0 # 60 being your MAJOR_DEVICE_NUMBER
Then you can create your own program to read and write to your character device. Alternatively, you can use existing user-space tools:
echo "12345678" > /dev/chardev # write to the device
and,
cat /dev/chardev # read from the device

Errno : 13 on using fopen on proc entry

I am trying to write a /proc file created by a loadable kernel module. I am using fopen() to open the file for write but am getting errno : 13 (permission denied).
FILE *fp;
fp = fopen("/proc/file1","w");
if(fp == NULL){
printf("Errno : %d",errno); // prints 13
}
The LKM contains the following code:
static struct proc_dir_entry *proc_entry;
static ssize_t proc_write(struct file *filp, const char __user *buff, unsigned long len, void *data)
{
// code writes from buffer to local variable
return len;
}
static ssize_t proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
// code for reading file
return 0;
}
int proc_open(struct inode *inode, struct file *file)
{
try_module_get(THIS_MODULE);
return 0;
}
int proc_close(struct inode *inode, struct file *file)
{
module_put(THIS_MODULE);
return 0;
}
Any suggestions on how to overcome this?
Thanks.
The most probable answer is that the procfs node that is created does not have the correct permissions for the user.
When run as root, it bypasses most of the permission checking for the node, so you do not receive an error (there are exceptions; this is the general case).
in the kernel loadable module, where it creates the procfs node (somewhere in the .c file):
create_proc_entry(...)
You need to make sure that the second parameter, the mode is set to something that permits opening for writing by users other than root in order to support your desired open option; e.g. 0666 makes the file globally openable as R/W by anyone.
Generally, nodes in procfs are created with the flags 0444 (i.e. R/O only for all users). Some are created in mode 0644 (R/W by root, R/O for all other users), some are created with permissions 0400 (R/O for root, all others stay away).

Resources