Passing kernel space data buffer where userspace is expected.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi All,

I want to encrypt the data before it is written to the disk and decrypt is after it is being read from the disk. so copied the ext2 source code in my directory.

Then modified the ext2 file_operations structure to invoke my read and write functions instead of do_sync_read/write

const struct file_operations ext2_file_operations = {
    .llseek     = generic_file_llseek,
    .read       = my_read,                   /* do_sync_read  */   <<<<<<<<<<<<<<<<<<<<<<<<
    .write      = my_write,                  /* do_sync_write */   <<<<<<<<<<<<<<<<<<<<<<<<
    .aio_read   = generic_file_aio_read,
    .aio_write  = generic_file_aio_write,
    .unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl   = ext2_compat_ioctl,
#endif
    .mmap       = generic_file_mmap,
    .open       = generic_file_open,
    .release    = ext2_release_file,
    .fsync      = ext2_sync_file,
    .splice_read    = generic_file_splice_read,
    .splice_write   = generic_file_splice_write,
};


For time being i used simplest encryption XOR 5
int encrypt_data(char *data, size_t len)
{
    int i;
    for(i=0; i < len; i++)
        data[i] ^= 5;

    return 0;
}

int decrypt_data(char *data, size_t len)
{
    int i;
    for(i=0; i < len; i++)
        data[i] ^= 5;

    return 0;
}

ssize_t my_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
    size_t ret;
    char *data = "" GFP_KERNEL);

    ret = do_sync_read(filp, data, len, ppos);
    decrypt_data(data, len);
    copy_to_user(buf, data, len);

    kfree(data);
    return ret;
}

In write I am supposed to encrypt the data before it is written to the disk, ie encrypt the data before it is passed to the do_sync_write.
But, the data is in the buf which is passed from the user process and has the type             const char *buf       so      I can't modify the     buf

I thought of  copying data from the      (userland)   buf     to some variable in the kernelspace and then encrypt it and pass to do_sync_write()

This is what I did

ssize_t my_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
    size_t ret;
    char *data = "" GFP_KERNEL);

    copy_from_user(data, buf, len);
    encrypt_data(data, len);
    ret = do_sync_write(filp, data, len, ppos);

    kfree(data);
    return ret;
}

After running the code and writing data to the file using echo "test" > /mnt_pt/file    I am getting bad address error

Is it because do_sync_write() also expects buf pointer from the userspace?
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)

But, the only thing do_sync_write should be concerned with whether it can access the data pointer or not. So, if the data pointer is valid and kernel is able to access the location why so worry about userspace pointer?

Thanks and Regards,
Prasad

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux