Piyush Piyush - 2 months ago 12
Linux Question

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.

Answer
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)