Add preliminary support for more recent kernel (~4.15)

It is currently building with a Debian 4.15.11-1, but hasn't been tested
and is expecting to crash really hard. Do no try unless you are ready to
hard crash your system. It should support most version between the
~2.6.32 and this 4.15.11.
This commit is contained in:
Godzil 2018-05-08 15:39:51 +01:00
parent 1afa952fb0
commit 48264ec40a
2 changed files with 92 additions and 15 deletions

View File

@ -6,12 +6,16 @@ FUSD: A Linux Framework for User-Space Devices
This is FUSD snapshot 20110401, released 18 January 2012. This fork is based
on the found on the xiph.org SVN tracker. ( http://svn.xiph.org/trunk/fusd )
They seems to no longuer update this tool (since 11 January 2007) and since it
longuer compile with recent Linux kernel (at around 2.6.21) and since I need
it in personal project, I ported it to newer version (current version is 2.6.32)
They seems to no longer update this tool (since 11 January 2007) and since it
longer compile with recent Linux kernel (at around 2.6.21) and since I need
it in personal project, I ported it to newer version (current version is 2.6.32).
It is currently no officialy supporting newer kernel, but changes are currently
going on to support newer kernel up to 4.15. It is currently building under this
line, but don't expect it to work.
Some feature are still missing missing or buggy form the Xiph version (due to
changes on the kernel source tree), but it's completly useable.
changes on the kernel source tree), but it is still usable.
The official URL for this fork is:
@ -53,7 +57,7 @@ include the following rule:
5. Verify the fusd devices /dev/fusd/status and /dev/fusd/control
exist. If the modprobe succeeds but no fusd devices appear,
doublecheck the udev rule config change and make sure udevd restarted
double-check the udev rule config change and make sure udevd restarted
successfully. The kfusd kernel module must be inserted after udev has
been correctly configured and restarted.

View File

@ -78,6 +78,10 @@
#include <linux/device.h>
#include <linux/highmem.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/signal.h>
#endif
#include <asm/atomic.h>
#include <asm/uaccess.h>
#include <asm/ioctl.h>
@ -132,6 +136,23 @@
# define CLASS_DEVICE_DESTROY(a, b) device_destroy(a, b)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
//result = GET_USER_PAGES(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm,
// mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
#define GET_USER_PAGES(t,m,s,n,w,f,p,v) get_user_pages_remote(t,m,s,n,(w?FOLL_WRITE:0)|(f?FOLL_FORCE:0),p,v, NULL)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
#define GET_USER_PAGES(t,m,s,n,w,f,p,v) get_user_pages_remote(t,m,s,n,w,f,p,v)
#else
#define GET_USER_PAGES(t,m,s,n,w,f,p,v) get_user_pages(t,m,s,n,w,f,p,v)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
#define FULL_NAME_HASH(a, b) full_name_hash(0, a, b)
#else
#define FULL_NAME_HASH(a, b) full_name_hash(a, b)
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
struct sysfs_elem_dir
@ -847,7 +868,7 @@ STATIC int fusd_fops_call_send (fusd_file_t *fusd_file_arg,
/* fill the rest of the structure */
fusd_msg->parm.fops_msg.pid = current->pid;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
fusd_msg->parm.fops_msg.uid = current_uid();
fusd_msg->parm.fops_msg.gid = current_gid();
#endif
@ -1149,7 +1170,7 @@ int fusd_dev_add_file (struct file *file, fusd_dev_t *fusd_dev, fusd_file_t **fu
init_waitqueue_head(&fusd_file->file_wait);
init_waitqueue_head(&fusd_file->poll_wait);
INIT_LIST_HEAD(&fusd_file->transactions);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
init_MUTEX(&fusd_file->file_sem);
init_MUTEX(&fusd_file->transactions_sem);
#else
@ -1711,11 +1732,14 @@ static void fusd_client_mm_open (struct vm_area_struct * vma);
static void fusd_client_mm_close (struct vm_area_struct * vma);
/* int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)
static int fusd_client_fault (struct vm_fault *vmf);
#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf);
#else
static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type);
#endif
static struct vm_operations_struct fusd_remap_vm_ops ={
.open = fusd_client_mm_open,
.close = fusd_client_mm_close,
@ -1783,7 +1807,7 @@ static int fusd_client_mmap (struct file *file, struct vm_area_struct * vma)
}
/* and wait for the reply */
/* todo: store and retrieve the transid from the interrupted messsage */
/* todo: store and retrieve the transid from the interrupted message */
retval = fusd_fops_call_wait(fusd_file, &reply, transaction);
mmap_instance =
@ -1800,7 +1824,11 @@ static int fusd_client_mmap (struct file *file, struct vm_area_struct * vma)
vma->vm_private_data = mmap_instance;
vma->vm_ops = &fusd_remap_vm_ops;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
#else
vma->vm_flags |= VM_RESERVED;
#endif
fusd_client_mm_open(vma);
@ -1817,24 +1845,36 @@ invalid_file:
return -EPIPE;
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
static int fusd_client_fault (struct vm_fault *vmf)
#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf)
#else
static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type)
#endif
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
struct vm_area_struct *vma = vmf->vma;
#endif
struct fusd_mmap_instance* mmap_instance = (struct fusd_mmap_instance*) vma->vm_private_data;
unsigned long offset;
struct page *page = NULL;
int result;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
offset = ( (unsigned long) vmf->address - vma->vm_start ) + ( vma->vm_pgoff << PAGE_SHIFT );
#else
offset = ( (unsigned long) vmf->virtual_address - vma->vm_start ) + ( vma->vm_pgoff << PAGE_SHIFT );
#endif
// todo: worry about size
if ( offset > mmap_instance->size )
goto out;
down_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
result = get_user_pages(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm, mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
result = GET_USER_PAGES(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm,
mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
up_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
@ -2207,8 +2247,11 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
if ( sysfs )
{
/* Get FS superblock */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
sb = sget(sysfs, systest, NULL, 0, NULL);
#else
sb = sget(sysfs, systest, NULL, NULL);
#endif
/* because put_filesystem isn't exported */
module_put(sysfs->owner);
@ -2224,7 +2267,8 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
/* Search for directory "class" in the root of this filesystem */
name.name = "class";
name.len = 5;
name.hash = full_name_hash(name.name, name.len);
name.hash = FULL_NAME_HASH(name.name, name.len);
classdir = d_lookup(root, &name);
if ( classdir )
@ -2232,7 +2276,7 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
/* Found, now search for class wanted name */
name.name = register_msg.clazz;
name.len = strlen(name.name);
name.hash = full_name_hash(name.name, name.len);
name.hash = FULL_NAME_HASH(name.name, name.len);
classdir2 = d_lookup(classdir, &name);
if ( classdir2 )
@ -2659,6 +2703,31 @@ STATIC ssize_t fusd_writev (struct file *file,
iov[0].iov_base, iov[0].iov_len,
iov[1].iov_base, iov[1].iov_len);
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
ssize_t fusd_write_iter (struct kiocb *iocb, struct iov_iter *iov)
{
unsigned long count = iov_iter_count(iov);
char *msg, *data;
size_t msg_len, data_len;
if ( count != 2 )
{
RDEBUG(2, "fusd_writev: got illegal iov count of %ld", count);
return -EINVAL;
}
msg = iov->iov->iov_base + iov->iov_offset;
msg_len = iov_iter_single_seg_count(iov);
iov_iter_advance(iov, msg_len);
data = iov->iov->iov_base + iov->iov_offset;
data_len = iov_iter_single_seg_count(iov);
return fusd_process_write(iocb->ki_filp,
msg, msg_len,
data, data_len);
}
#else
STATIC ssize_t fusd_aio_write (struct kiocb *iocb,
const struct iovec *iov,
@ -2685,8 +2754,8 @@ STATIC long fusd_unlocked_ioctl (struct file *file,
unsigned int cmd, unsigned long arg)
#endif
{
void __user *argp = (void __user *) arg;
#if 0
void __user *argp = (void __user *) arg;
struct iovec iov;
if ( ( argp != NULL ) && ( cmd == 0xb16b00b5 ) )
@ -2914,7 +2983,11 @@ STATIC struct file_operations fusd_fops = {
.open = fusd_open,
.read = fusd_read,
.write = fusd_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
.write_iter = fusd_write_iter,
#else
.aio_write = fusd_aio_write,
#endif
.unlocked_ioctl = fusd_unlocked_ioctl,
.release = fusd_release,
.poll = fusd_poll,