System Call write - c

The system call write it's defined as follow:
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count)
{
struct file *file;
ssize_t ret = -EBADF;
int fput_needed;
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
ret = vfs_write(file, buf, count, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
}
return ret;
}
I'd like to copy the variable buf to modify your content and
then use this new variable at:
vfs_write(file, new_buf, count, &pos);
I've tried to allocate memory to a char pointer variable with kmalloc and then I've used copy_from_user() to do the copy. Finally I've used the new variable at vfs_write(). After recompile the kernel and reboot the system I've got kernel panic error message.
Here is my implementation that generates a kernel panic error message:
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count){
struct file *file;
ssize_t ret = -EBADF;
int fput_needed;
char *data;
data = kmalloc(count, GFP_KERNEL);
if(!data)
return ret;
copy_from_user(data, buf, count);
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
ret = vfs_write(file, data, count, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
}
return ret;
}
How can I do this copy in kernel mode?
I'm using Linux Mint 12 - Kernel version: 3.0.30

You should probably also post your code. I.e. the changes you made to the write system call to be certain where the error is.
That said, there are checks in place that don't allow you to use kernel memory for system calls. You either need to allocate your buffer in user address space for the process (bad) or disable the checks (not as bad).
I'm not as familiar with the 3.0 kernel but this answer looks promising:
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
/* Your syscall here */
set_fs(old_fs);

Related

Linux kernel module making a proc entry does not print on reading the proc entry to user

In the book Operating System Concepts: 10th edition, there's a programming project to log some information about a process by providing its pid echo'd to the /proc entry made while initializing the module, namely here, /proc/pid.
/**
* This function is called each time the /proc/pid is read.
*
* This function is called repeatedly until it returns 0, so
* there must be logic that ensures it ultimately returns 0
* once it has collected the data that is to go into the
* corresponding /proc file.
*/
static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos)
{
int rv = 0;
char buffer[BUFFER_SIZE];
static int completed = 0;
struct task_struct *tsk = NULL;
if (completed) {
completed = 0;
return 0;
}
/* l_pid is a global that gets set properly when the proc entry is read. */
tsk = pid_task(find_vpid(l_pid), PIDTYPE_PID);
if (tsk == NULL) {
rv = -1;
return rv;
}
completed = 1;
rv = sprintf(buffer, "pid = [%d], command = [%s], state = [%ld]\n",
tsk->pid, tsk->comm, tsk->state);
if (copy_to_user(usr_buf, buffer, rv)) {
rv = -1;
}
return rv;
}
My problem is with the proc_read function. The way I understand it (as explained in the book) is that rv has to be 0 eventually because the function specified as the .read field in the file_operations struct keeps getting called till returning 0.
The problem is that I do not understand the necessity of having all this "complete" logic. If I change the code to be like this:
static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos)
{
int rv = 0;
char buffer[BUFFER_SIZE];
struct task_struct *tsk = NULL;
/* l_pid is a global that gets set properly when the proc entry is read. */
tsk = pid_task(find_vpid(l_pid), PIDTYPE_PID);
if (tsk == NULL) {
rv = -1;
return rv;
}
int num_bytes = sprintf(buffer, "pid = [%d], command = [%s], state = [%ld]\n",
tsk->pid, tsk->comm, tsk->state);
if (copy_to_user(usr_buf, buffer, num_bytes)) {
rv = -1;
}
return rv;
}
To my understanding, when the proc entry is read, this function will get called, either returning -1 (if tsk == NULL or could not copy from buffer to usr_buf) and thus get called again. Or it will return 0 on success.
The problem with this change (of course) is that it does not work. It does not print anything to the console when issuing cat /proc/pid. However, by printking the string inside buffer, it appears to be correct (at least in the kernel log buffer).

Writing a file in /proc continuouly floods the dmesg

I am trying to read/Write a variable in the linux kernel module using /proc file entry facility.
Kernel module compiles successfully but when tried writing it via
echo 1 > My_file
This operation didn't finish.
Also, dmesg console is continuously flooded with some random value.
[ 1171.481231] proc_write_flag New_Flag 1124646486
[ 1171.481245] proc_write_flag New_Flag 1124646486
[ 1171.481259] proc_write_flag New_Flag 1124646486
[ 1171.481271] proc_write_flag New_Flag 1124646486
[ 1171.481473] ^C
I am new to linux device drivers and trying to use /proc facility provided by the linux kernel. I tried removing the this kernel module, but again, the operation didn't finish.
what is causing this behaviour and how can i rectify it?
Here is the code:
int my_flag;
static struct proc_dir_entry *pdir = NULL;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("GPL");
static ssize_t proc_read_flag(struct file* page,char __user * data, size_t count, loff_t *offset);
static ssize_t proc_write_flag(struct file *file, const char __user* ubuf, size_t count, loff_t* offset);
static struct file_operations myops =
{
.owner = THIS_MODULE,
.read = proc_read_flag,
.write= proc_write_flag,
};
//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//Updated Read function after the reply.
static ssize_t proc_read_flag(struct file* page,char __user * data, size_t count,loff_t *offset)
{
int ret;
if( count >my_flag) //my_flag holds the count of chars received by write function.
count = my_flag;
ret = copy_to_user(data, my_buf, my_flag );
printk("%s: ret = %d ,my_flag %d\n",__FUNCTION__, ret, my_flag);
return ( my_flag - ret );
}
//ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//Updated Write function After the reply.
static ssize_t proc_write_flag(struct file *file, const char __user* ubuf, size_t count, loff_t* offset)
{
if( copy_from_user(my_buf,ubuf,count) ){ //Returns No. of bytes could not copy
return -EFAULT;
}
my_flag = count;
printk("%s New_Flag %d Data: %s\n",__FUNCTION__,my_flag,my_buf);
return count;
}
int init_module(void)
{
struct proc_dir_entry *pfile = NULL;
pdir = proc_mkdir("My_dir",NULL);
if(!pdir){
return -ENOMEM;
}
pfile = proc_create("My_file", 0666, pdir, &myops);
if(!pfile)
return -ENOMEM;
printk("Proc_entry Created Successfully, Module initialized\n");
return 0;
}
void cleanup_function(void)
{
remove_proc_entry("My_file", pdir);
remove_proc_entry("My_dir", NULL);
printk("Removing Proc_entry!!!");
}
The write function should return the number of bytes you processed.
In your case, 'proc_write_flag' function is returning 'ret' which is 0.
which means it will be invoked repeatedly until you process 'count' number of bytes from 'ubuf'
Similarly, 'proc_read_flag' should return the number of bytes you wrote into 'data'. In your case it is returning 0 (len)
There are other problems in 'proc_write_flag' function.
'buf' array isn't initialize and casting 'buf'(address) to int will not give you the expected answer.
Start with this http://tuxthink.blogspot.com/2013/12/creating-directory-under-proc-in-kernel.html
Then look into kstrtol() function.

Reading in kernel second time overrides first instance

I have written a read function to read a file into buffer in Kernel space.
int readfile(const char *filename, void *buf, int len, int offset)
{
struct file *filp;
mm_segment_t oldfs;
int bytes;
filp = NULL;
filp = filp_open(filename, O_RDONLY, 0);
if(!filp || IS_ERR(filp)) {
printk(" Error in reading file %s. Error = %d\n", filename, \
(int) PTR_ERR(filp));
return -1;
}
filp->f_pos = offset;
oldfs = get_fs();
set_fs(get_ds());
bytes = vfs_read(filp, buf, len, &filp->f_pos);
set_fs(oldfs);
filp_close(filp, NULL);
return bytes;
}
Now, this function works really well and I am able to read contents of filename into buf by calling this function from my system call
char *firstbuffer;
firstbuffer = kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL);
bytesread = readfile(firstfile, firstbuffer, len, 0);
// Null terminate read string
firstbuffer[bytesread] = '\0';
printk("first buffer = %s\n",firstbuffer);
Then, I am calling this function again to read contents of secondfile into secondbuffer.
char *secondbuffer;
secondbuffer = kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL);
bytesread2 = readfile(secondfile, secondbuffer, len, 0);
// Null terminate read string
secondbuffer[bytesread2] = '\0';
printk("second buffer %s", secondbuffer);
The problem is that after calling the read function on secondfile, the contents of my firstbuffer are getting overridden with contents of secondbuffer.
For example: if the contents of firstfile are
A
B
C
and contents of secondfile are
X
Y
Z
then after first read file call, the content of firstbuffer is:
A
B
C
and then after second read file call, the content of firstbuffer is:
A
X
Y
Z
Now, I am not sure what is going wrong here, but after second read function call, contents of firstbuffer is getting merged with contents of secondbuffer. How do I fix this?
Disclaimer:
I know we shouldn't do file I/O in Kernel space. This is purely to learn how read functions work in Kernel space.
kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL)
This allocates sizeof(PAGE_SIZE) bytes. Now, PAGE_SIZE is an integer, so it's probably 4 bytes long, so you allocate 4 bytes.
If you wanted to allocate PAGE_SIZE bytes, use:
kmalloc(PAGE_SIZE, GFP_KERNEL)

Newline characters not showing up in proc file

So I'm writing a linux kernel module that involves writing to a proc file. Unfortunately something is going wrong with the newline character. If I open it with vim, it shows as "num^#num^#num^#". If I cat it, it says "numnumnum". It should go to a new line at the end of each "num".
My code for writing each entry to the proc file admittedly seems kind of hacky.
bufSize = snprintf(str,0,"%lu\n",var);
str = (char*)kmalloc(bufSize*sizeof(char),GFP_KERNEL);
snprintf(str,bufSize,"%lu\n",var);
memcpy(msg+msglen,str,bufSize);
msglen+=(bufSize);
kfree(str);
I don't know how long the string will be, so the first snprintf gets the length needed for the buffer. The buffer is initialized, then snprintf is called again. The string is then copied to msg, which contains the data for the proc file. The pointer is incremented by the length of the existing message.
int procfile_read(char *buffer, char **buffer_location, off_t offset, int
buffer_length, int *eof, void *data) {
int ret;
printk(KERN_INFO "procfile_read (/proc/%s) called\n", PROCFS_NAME);
if (offset > 0) {
/* we have finished to read, return 0 */
ret = 0;
} else {
/* fill the buffer, return the buffer size */
memcpy(buffer, msg, msglen);
ret = msglen;
}
return ret;
This is pretty much copied and pasted from a tutorial.
Thanks!
Buffer size is too small
bufSize = snprintf(str,0,"%lu\n",var);
// + 1
str = (char*)kmalloc((bufSize + 1)*sizeof(char),GFP_KERNEL);
// + 1
snprintf(str,bufSize + 1,"%lu\n",var);
// + 1
memcpy(msg+msglen,str,bufSize + 1);
// no + 1 here
// Note that msglen is the string length. Add 1 for the size needed.
msglen+=(bufSize);
kfree(str);

Read a char string as a virtual file

The question may seems strange but I didn't misspelled it:
I want to decompress some data I downloaded without write them on the HDD. For that, I download it in a dynamically allocated buffer and I'd like to send it to the zlib wrapper I use (miniunzip). The problem is that this implementation is quite long (2-3K lines) and I'd like to avoid to have to rewrite it just for few lines.
I'd like to know if there was any way to read the buffer via a FILE* structure (miniunzip use it's own structure but I found a "fopen()" hiden under the loader). I know its length if it can help.
Thanks in advance and excuse me for my poor grammar.
I'm working on both Windows and UNIX systems (OSX/GNU Linux).
If you're talking about the minizip library that's included with zlib, you could use the unzOpen2 function which allows you to specify a structure containing the I/O functions to use. This should get you started:
struct zmem_data {
char *buf;
size_t length;
};
static voidpf zmemopen(voidpf opaque, const char *filename, int mode) {
if ((mode&ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) return NULL;
uLong *pos = malloc(sizeof(uLong));
*pos = 0;
return pos;
}
static uLong zmemread(voidpf opaque, voidpf stream, void* buf, uLong size) {
struct zmem_data *data = (struct zmem_data*)opaque;
uLong *pos = (uLong*)stream;
uLong remaining = data->length - *pos;
uLong readlength = size < remaining ? size : remaining;
if (*pos > data->length) return 0;
memcpy(buf, data->buf+*pos, readlength);
*pos += readlength;
return readlength;
}
static uLong zmemwrite(voidpf opaque, voidpf stream, const void *buf, uLong size) {
/* no write support for now */
return 0;
}
static int zmemclose(voidpf opaque, voidpf stream) {
free(stream);
return 0;
}
static int zmemerror(voidpf opaque, voidpf stream) {
if (stream == NULL) return 1;
else return 0;
}
static long zmemtell(voidpf opaque, voidpf stream) {
return *(uLong*)stream;
}
static long zmemseek(voidpf opaque, voidpf stream, uLong offset, int origin) {
struct zmem_data *data = (struct zmem_data*)opaque;
uLong *pos = (uLong*)stream;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_SET:
*pos = offset;
break;
case ZLIB_FILEFUNC_SEEK_CUR:
*pos = *pos + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
*pos = data->length + offset;
break;
default:
return -1;
}
return 0;
}
static void init_zmemfile(zlib_filefunc_def *inst, char *buf, size_t length) {
struct zmem_data *data = malloc(sizeof(struct zmem_data));
data->buf = buf;
data->length = length;
inst->opaque = data;
inst->zopen_file = zmemopen;
inst->zread_file = zmemread;
inst->zwrite_file = zmemwrite;
inst->ztell_file = zmemtell;
inst->zseek_file = zmemseek;
inst->zclose_file = zmemclose;
inst->zerror_file = zmemerror;
}
static void destroy_zmemfile(zlib_filefunc_def *inst) {
free(inst->opaque);
inst->opaque = NULL;
}
void example() {
zlib_filefunc_dec fileops;
init_zmemfile(&fileops, buffer, buffer_length);
unzFile zf = unzOpen2(NULL, &fileops);
/* ... process zip file ... */
unzClose(zf);
destroy_zmemfile(&fileops);
}
To summarize your question: You want to provide a FILE* interface for an in-memory buffer. No, you can't do that. The fread(), etc. calls actually end up making system calls that deal with an open file descriptor which you don't have.
You're over-complicating this. Decompression code almost always works from buffers that are in memory. If they have a file interface, certainly that is just a wrapper which handles reading the file into memory and then decompressing (probably in chunks to save memory). You should be able to find a decompression library with calls to decompress a buffer that you give it (just a pointer and a length).
Why you don't want to write the downloaded data to the hard drive is certainly up to you, but I hope this is for good, and not for evil.
The other option would be to open a memory-mapped file, to which you write during download, and read during decompression. There may be a way to specify that the file not be written to disk but of that I am unsure. Also, this would be very different between windows and linux.
These may help:
File Mapping (Windows)
mmap (POSIX)

Resources