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).
Related
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 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 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 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'm trying to use filp_open() within the kernel to open the file "/proc/.../mynode". The file opens issue-free when it is opened using the O_RDONLY flag, however; when I attempt to open the same file, using the same function, but change the flag to O_RDWR or O_WRONLY, my device's boot sequence breaks.
Does anyone know how to solve this issue?
My Code:
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;
}
The following method is called:
struct file *fp = NULL;
fp = file_open("/proc/.../mynode", O_WRONLY,0);
I could not understand why're you turning on address conversion before error checking. You've called filp_open in kernel address space(i assume get_ds takes you there) and hence it's practice to do error checks in same space. This might be the reason filp gets translated to some random address and why device boot sequence is breaking. If issue persists even after this has been looked into, target file-sys might not be having write permission on this file.