I'm trying to code an encryption driver in Linux, but when I encrypt the string and copy it into the buffer by using copy_from_user()
it doesn't work and the k value is the number of chars in the string
If I change the temp
in copy_from_user
to buf
it work fine
ssize_t encdec_write_caesar(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
char *temp ;
temp = kmalloc(memory_size * sizeof(char),GFP_USER);
memset(temp, 0, memory_size);
int i , k ;
k = ((encdec_private_date *)(filp->private_data))->key;
for(i = 0; i < count; i++)
{
temp[i] = (buf[i] + k) % 128;
}
k = copy_from_user ( caesar_Buf , temp , count);
printk("write-> %d\n" ,k);
kfree(temp);
return 0;
}
this is part of the code
#include <linux/ctype.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include "encdec.h"
#define MODULE_NAME "encdec"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("YOUR NAME");
int encdec_open(struct inode *inode, struct file *filp);
int encdec_release(struct inode *inode, struct file *filp);
int encdec_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
ssize_t encdec_read_caesar( struct file *filp, char *buf, size_t count, loff_t *f_pos );
ssize_t encdec_write_caesar(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
int memory_size = 0;
MODULE_PARM(memory_size, "i");
int major = 0;
char *caesar_Buf = NULL;
struct file_operations fops_caesar = {
.open = encdec_open,
.release = encdec_release,
.read = encdec_read_caesar,
.write = encdec_write_caesar,
.llseek = NULL,
.ioctl = encdec_ioctl,
.owner = THIS_MODULE
};
// Implemetation suggestion:
// -------------------------
// Use this structure as your file-object's private data structure
typedef struct {
unsigned char key;
int read_state;
} encdec_private_date;
int init_module(void)
{
major = register_chrdev(major, MODULE_NAME, &fops_caesar);
if(major < 0)
{
return major;
}
caesar_Buf = (char *)kmalloc(memory_size * sizeof(char),GFP_KERNEL);
return 0;
}
You should be using copy_from_user
instead of accessing buf
directly (inside the loop, not when accessing temp
(which is in kernel-space memory.)
copy_from_user
is intended to ensure that to accesses in a user context only access user-space data -- i.e., that someone doesn't pass a pointer to kernel memory in a syscall and leaks data from the kernel somehow.