mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-22 17:55:57 +01:00
improve memfile a bit with missing slab and dyn_arr_reserve write out of mem error check
And don't do wrong deadlock on write error.
This commit is contained in:
@@ -6,7 +6,8 @@
|
|||||||
#include <linux/kernel.h> /* min */
|
#include <linux/kernel.h> /* min */
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/printk.h> /* printk */
|
#include <linux/printk.h> /* printk */
|
||||||
#include <linux/string.h> /* strcpy */
|
#include <linux/slab.h> /* kvzalloc, kvrealloc, kvfree */
|
||||||
|
#include <linux/string.h> /* memset */
|
||||||
#include <linux/uaccess.h> /* copy_from_user, copy_to_user */
|
#include <linux/uaccess.h> /* copy_from_user, copy_to_user */
|
||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <uapi/linux/stat.h> /* S_IRUSR */
|
#include <uapi/linux/stat.h> /* S_IRUSR */
|
||||||
@@ -43,7 +44,7 @@ int dyn_arr_reserve(dyn_arr_t *a, size_t off, size_t len);
|
|||||||
int dyn_arr_reserve(dyn_arr_t *a, size_t off, size_t len)
|
int dyn_arr_reserve(dyn_arr_t *a, size_t off, size_t len)
|
||||||
{
|
{
|
||||||
size_t new_used, new_size;
|
size_t new_used, new_size;
|
||||||
|
|
||||||
new_used = off + len;
|
new_used = off + len;
|
||||||
if (new_used > a->_size) {
|
if (new_used > a->_size) {
|
||||||
new_size = new_used * 2;
|
new_size = new_used * 2;
|
||||||
@@ -99,10 +100,12 @@ static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off
|
|||||||
ret = min(len, data.used - (size_t)*off);
|
ret = min(len, data.used - (size_t)*off);
|
||||||
if (copy_to_user(buf, data.buf + *off, ret)) {
|
if (copy_to_user(buf, data.buf + *off, ret)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
*off += ret;
|
*off += ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
up_read(&rwsem);
|
up_read(&rwsem);
|
||||||
if (log) pr_info("read ret:=%lld\n", (long long)ret);
|
if (log) pr_info("read ret:=%lld\n", (long long)ret);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -114,15 +117,21 @@ static ssize_t write(struct file *filp, const char __user *buf, size_t len, loff
|
|||||||
|
|
||||||
if (log) pr_info("write len=%zu off=%lld\n", len, (long long)*off);
|
if (log) pr_info("write len=%zu off=%lld\n", len, (long long)*off);
|
||||||
down_write(&rwsem);
|
down_write(&rwsem);
|
||||||
dyn_arr_reserve(&data, *off, len);
|
ret = dyn_arr_reserve(&data, *off, len);
|
||||||
|
if (ret) {
|
||||||
|
ret = -ENOSPC;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (copy_from_user(data.buf + *off, buf, len)) {
|
if (copy_from_user(data.buf + *off, buf, len)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
ret = len;
|
ret = len;
|
||||||
*off += ret;
|
*off += ret;
|
||||||
}
|
}
|
||||||
up_write(&rwsem);
|
out:
|
||||||
if (log) pr_info("write ret:=%lld\n", (long long)ret);
|
if (log) pr_info("write ret:=%lld\n", (long long)ret);
|
||||||
|
up_write(&rwsem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +177,7 @@ static const struct file_operations fops = {
|
|||||||
static int myinit(void)
|
static int myinit(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dyn_arr_init(&data, 1);
|
ret = dyn_arr_init(&data, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user