removed data
This commit is contained in:
15
bi0sctf23/pow_solver.py
Normal file
15
bi0sctf23/pow_solver.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from time import time
|
||||||
|
def solve_pow(s, debug=False):
|
||||||
|
start = time()
|
||||||
|
g = int(s.split("^")[0])
|
||||||
|
p = int(s.split("mod ")[1].split(" == ")[0])
|
||||||
|
target = int(s.split(" == ")[1])
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
if pow(g, i, p) == target:
|
||||||
|
if debug: print(f'Time taken: {time()-start}')
|
||||||
|
return i
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
# Pass the PoW line given by the challenge to this function
|
||||||
|
print(solve_pow(input(), debug=True))
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
CONFIG_SLUB=y
|
|
||||||
CONFIG_SLAB_FREELIST_RANDOM=y
|
|
||||||
CONFIG_SLAB_FREELIST_HARDENED=y
|
|
||||||
CONFIG_SLUB_CPU_PARTIAL=y
|
|
||||||
CONFIG_RANDOM_KMALLOC_CACHES=y
|
|
||||||
|
|
||||||
CONFIG_STATIC_USERMODEHELPER=y
|
|
||||||
CONFIG_STATIC_USERMODEHELPER_PATH=""
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
qemu-system-x86_64 \
|
|
||||||
-m 64M \
|
|
||||||
-cpu kvm64,+smep,+smap \
|
|
||||||
-kernel bzImage \
|
|
||||||
-drive file=rootfs.ext3,format=raw \
|
|
||||||
-drive file=exploit,format=raw \
|
|
||||||
-snapshot \
|
|
||||||
-nographic \
|
|
||||||
-monitor /dev/null \
|
|
||||||
-no-reboot \
|
|
||||||
-append "root=/dev/sda rw init=/init console=ttyS0 kaslr kpti=1 loglevel=0 oops=panic panic=-1"
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
#include "linux/random.h"
|
|
||||||
#include "palindromatic_util.c"
|
|
||||||
|
|
||||||
char *temp_buffer;
|
|
||||||
unsigned long magic;
|
|
||||||
queue_t incoming_queue;
|
|
||||||
queue_t outgoing_queue;
|
|
||||||
bool sanitized = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copy request from user and add to start of queue
|
|
||||||
*/
|
|
||||||
static noinline long pm_add_request(arg_t *arg)
|
|
||||||
{
|
|
||||||
long idx = -1;
|
|
||||||
request_t *req = kmem_cache_zalloc(pm_cache, GFP_KERNEL);
|
|
||||||
if(!req) goto end;
|
|
||||||
|
|
||||||
req->type = RAW;
|
|
||||||
req->magic = magic;
|
|
||||||
if(copy_from_user(req->str, arg->buffer, STRING_SZ))
|
|
||||||
{
|
|
||||||
kfree(req);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
idx = pm_queue_enqueue(&incoming_queue, req);
|
|
||||||
|
|
||||||
end:
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Accept characters only in [A-Z|a-z] and translate to [A-Z]
|
|
||||||
Only 1 sanitize is allowed
|
|
||||||
*/
|
|
||||||
static noinline long pm_sanitize_request(void)
|
|
||||||
{
|
|
||||||
long idx = -1;
|
|
||||||
|
|
||||||
request_t *req = pm_queue_peek(&incoming_queue);
|
|
||||||
if(!req) goto end;
|
|
||||||
if(req->type == SANITIZED) goto end;
|
|
||||||
|
|
||||||
memset(temp_buffer, 0x0, STRING_SZ);
|
|
||||||
|
|
||||||
int ptr = 0;
|
|
||||||
for(int i = 0; i < STRING_SZ; i++)
|
|
||||||
{
|
|
||||||
if(!req->str[i]) break;
|
|
||||||
|
|
||||||
if(req->str[i] > 0x60 && req->str[i] < 0x7b)
|
|
||||||
temp_buffer[ptr++] = req->str[i]-0x20;
|
|
||||||
|
|
||||||
else if(req->str[i] > 0x40 && req->str[i] < 0x5b)
|
|
||||||
temp_buffer[ptr++] = req->str[i];
|
|
||||||
|
|
||||||
else continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_buffer[ptr] = 0;
|
|
||||||
strcpy(req->sanstr, temp_buffer);
|
|
||||||
req->type = SANITIZED;
|
|
||||||
|
|
||||||
idx = pm_queue_enqueue(&incoming_queue, pm_queue_dequeue(&incoming_queue));
|
|
||||||
|
|
||||||
end:
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If request is raw, remove it
|
|
||||||
else, set it to raw and send it back to start of the queue
|
|
||||||
*/
|
|
||||||
static noinline long pm_reset_request(void)
|
|
||||||
{
|
|
||||||
request_t *req = pm_queue_dequeue(&incoming_queue);
|
|
||||||
if(!req) return -1;
|
|
||||||
|
|
||||||
if(req->type != RAW)
|
|
||||||
{
|
|
||||||
req->type = RAW;
|
|
||||||
memset(req->sanstr, 0x0, sizeof(req->sanstr));
|
|
||||||
pm_queue_enqueue(&incoming_queue, req);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kfree(req);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if it is a palindrome or not and set type accordingly
|
|
||||||
Remove from incoming queue and add to outgoing queue
|
|
||||||
*/
|
|
||||||
static noinline long pm_process_request(void)
|
|
||||||
{
|
|
||||||
long idx = -1;
|
|
||||||
|
|
||||||
request_t *req = pm_queue_peek(&incoming_queue);
|
|
||||||
if(!req) goto end;
|
|
||||||
if(req->magic != magic) goto end;
|
|
||||||
int len = req->type==SANITIZED?strlen(req->sanstr):strlen(req->str);
|
|
||||||
if(!len) goto end;
|
|
||||||
idx = pm_queue_enqueue(&outgoing_queue, req);
|
|
||||||
if(idx < 0) goto end;
|
|
||||||
|
|
||||||
memset(temp_buffer, 0x0, STRING_SZ);
|
|
||||||
if(req->type == RAW)
|
|
||||||
{
|
|
||||||
for(int i = (len/2)-1; i > -1; i--)
|
|
||||||
{
|
|
||||||
if(req->str[i] < 0x41 || req->str[i] > 0x5a) break;
|
|
||||||
temp_buffer[i] = req->str[i];
|
|
||||||
}
|
|
||||||
temp_buffer[len/2] = 0;
|
|
||||||
|
|
||||||
if(strcmp(temp_buffer, &req->str[len/2]+len%2)) req->type = NONPALINDROME;
|
|
||||||
else req->type = PALINDROME;
|
|
||||||
pm_queue_dequeue(&incoming_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(req->type == SANITIZED)
|
|
||||||
{
|
|
||||||
for(int i = (len/2)-1; i > -1; i--) temp_buffer[i] = req->sanstr[i];
|
|
||||||
temp_buffer[len/2] = 0;
|
|
||||||
|
|
||||||
if(strcmp(temp_buffer, &req->sanstr[len/2]+len%2)) req->type = NONPALINDROME;
|
|
||||||
else req->type = PALINDROME;
|
|
||||||
pm_queue_dequeue(&incoming_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get result of first request in outgoing queue
|
|
||||||
*/
|
|
||||||
static noinline long pm_reap_request(void)
|
|
||||||
{
|
|
||||||
request_t *req = pm_queue_dequeue(&outgoing_queue);
|
|
||||||
if(!req) return -1;
|
|
||||||
if(req->magic != magic) return -1;
|
|
||||||
|
|
||||||
long ret = req->type==PALINDROME?1:0;
|
|
||||||
kfree(req);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get the available slots in both queues
|
|
||||||
*/
|
|
||||||
static noinline long pm_query_capacity(void)
|
|
||||||
{
|
|
||||||
long ret = (QUEUE_SZ-pm_queue_count(&outgoing_queue))<<16
|
|
||||||
| (QUEUE_SZ-pm_queue_count(&incoming_queue));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static long pm_ioctl(struct file *file, unsigned int cmd, unsigned long uarg)
|
|
||||||
{
|
|
||||||
arg_t arg;
|
|
||||||
long ret = -1;
|
|
||||||
mutex_lock(&lock);
|
|
||||||
|
|
||||||
switch(cmd)
|
|
||||||
{
|
|
||||||
case QUEUE:
|
|
||||||
if(copy_from_user(&arg, (void *)uarg, sizeof(arg_t))) goto end;
|
|
||||||
ret = pm_add_request(&arg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SANITIZE:
|
|
||||||
if(sanitized) goto end;
|
|
||||||
sanitized = true;
|
|
||||||
ret = pm_sanitize_request();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RESET:
|
|
||||||
ret = pm_reset_request();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROCESS:
|
|
||||||
ret = pm_process_request();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REAP:
|
|
||||||
ret = pm_reap_request();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QUERY:
|
|
||||||
ret = pm_query_capacity();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
mutex_unlock(&lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int __init init_palindromatic(void)
|
|
||||||
{
|
|
||||||
if(misc_register(&pm_device) < 0) goto err;
|
|
||||||
|
|
||||||
pm_cache = kmem_cache_create("palindromatic", TARGET_SZ, __alignof__(request_t),
|
|
||||||
SLAB_ACCOUNT | SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NO_MERGE, NULL);
|
|
||||||
if(!pm_cache) goto err;
|
|
||||||
|
|
||||||
temp_buffer = kzalloc(TARGET_SZ, GFP_KERNEL);
|
|
||||||
if(!temp_buffer) goto err;
|
|
||||||
|
|
||||||
get_random_bytes(&magic, sizeof(magic));
|
|
||||||
pm_queue_init(&incoming_queue);
|
|
||||||
pm_queue_init(&outgoing_queue);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
|
||||||
if(pm_cache) kmem_cache_destroy(pm_cache);
|
|
||||||
printk(KERN_ALERT "[-] Failed to register pipeparty");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void __exit exit_palindromatic(void)
|
|
||||||
{
|
|
||||||
kfree(temp_buffer);
|
|
||||||
kmem_cache_destroy(pm_cache);
|
|
||||||
misc_deregister(&pm_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(init_palindromatic);
|
|
||||||
module_exit(exit_palindromatic);
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#include <linux/compiler.h>
|
|
||||||
#include <linux/kobject.h>
|
|
||||||
#include <asm/page_types.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/uaccess.h>
|
|
||||||
#include <linux/miscdevice.h>
|
|
||||||
#include <linux/gfp.h>
|
|
||||||
#include <linux/random.h>
|
|
||||||
#include <linux/gfp_types.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
|
|
||||||
MODULE_AUTHOR("k1R4");
|
|
||||||
MODULE_DESCRIPTION("\"palindromatic\" - bi0s CTF 2023");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
enum : unsigned int
|
|
||||||
{
|
|
||||||
QUEUE = 0xb10500a,
|
|
||||||
SANITIZE,
|
|
||||||
RESET,
|
|
||||||
PROCESS,
|
|
||||||
REAP,
|
|
||||||
QUERY
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum ptype : unsigned long
|
|
||||||
{
|
|
||||||
RAW = 0x1337,
|
|
||||||
SANITIZED,
|
|
||||||
PALINDROME,
|
|
||||||
NONPALINDROME
|
|
||||||
} ptype;
|
|
||||||
|
|
||||||
#define TARGET_SZ 0x400
|
|
||||||
#define STRING_SZ ((TARGET_SZ-2*sizeof(unsigned long))/2)
|
|
||||||
|
|
||||||
typedef struct request_t
|
|
||||||
{
|
|
||||||
ptype type;
|
|
||||||
unsigned long magic;
|
|
||||||
char str[STRING_SZ];
|
|
||||||
char sanstr[STRING_SZ];
|
|
||||||
} request_t;
|
|
||||||
|
|
||||||
typedef struct arg_t
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
} arg_t;
|
|
||||||
|
|
||||||
#define QUEUE_SZ 0x100
|
|
||||||
|
|
||||||
typedef struct queue_t
|
|
||||||
{
|
|
||||||
int front;
|
|
||||||
int rear;
|
|
||||||
request_t *reqs[QUEUE_SZ];
|
|
||||||
} queue_t;
|
|
||||||
|
|
||||||
DEFINE_MUTEX(lock);
|
|
||||||
struct kmem_cache *pm_cache;
|
|
||||||
|
|
||||||
static noinline long pm_ioctl(struct file *file, unsigned int cmd, unsigned long uarg);
|
|
||||||
|
|
||||||
static struct file_operations pm_fops = { .unlocked_ioctl = pm_ioctl };
|
|
||||||
|
|
||||||
struct miscdevice pm_device = {
|
|
||||||
.minor = MISC_DYNAMIC_MINOR,
|
|
||||||
.name = "palindromatic",
|
|
||||||
.fops = &pm_fops,
|
|
||||||
};
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#include "palindromatic.h"
|
|
||||||
|
|
||||||
static void pm_queue_init(queue_t *queue)
|
|
||||||
{
|
|
||||||
queue->front = queue->rear = -1;
|
|
||||||
for(int i = 0; i<QUEUE_SZ; i++) queue->reqs[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static long pm_queue_enqueue(queue_t *queue, request_t *req)
|
|
||||||
{
|
|
||||||
if((queue->front == 0 && queue->rear == QUEUE_SZ-1) || (queue->rear+1)%QUEUE_SZ == queue->front) return -1;
|
|
||||||
|
|
||||||
else if(queue->front == -1)
|
|
||||||
{
|
|
||||||
queue->front = queue->rear = 0;
|
|
||||||
queue->reqs[queue->rear] = req;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(queue->rear == QUEUE_SZ-1 && queue->front != 0)
|
|
||||||
{
|
|
||||||
queue->rear = 0;
|
|
||||||
queue->reqs[queue->rear] = req;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
queue->rear++;
|
|
||||||
queue->reqs[queue->rear] = req;
|
|
||||||
}
|
|
||||||
|
|
||||||
return queue->rear;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static request_t *pm_queue_dequeue(queue_t *queue)
|
|
||||||
{
|
|
||||||
if(queue->front == -1) return NULL;
|
|
||||||
|
|
||||||
request_t *req = queue->reqs[queue->front];
|
|
||||||
queue->reqs[queue->front] = NULL;
|
|
||||||
|
|
||||||
if(queue->front == queue->rear) queue->front = queue->rear = -1;
|
|
||||||
else if(queue->front == QUEUE_SZ-1) queue->front = 0;
|
|
||||||
else queue->front++;
|
|
||||||
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static request_t *pm_queue_peek(queue_t *queue)
|
|
||||||
{
|
|
||||||
if(queue->front == -1) return NULL;
|
|
||||||
else return queue->reqs[queue->front];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int pm_queue_count(queue_t *queue)
|
|
||||||
{
|
|
||||||
if(queue->front == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
else if(queue->rear >= queue->front)
|
|
||||||
return queue->rear-queue->front+1;
|
|
||||||
|
|
||||||
else
|
|
||||||
return QUEUE_SZ - queue->front + queue->rear + 1;
|
|
||||||
}
|
|
||||||
3
bi0sctf23/pwn/virtio-note/.gitignore
vendored
Normal file
3
bi0sctf23/pwn/virtio-note/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
./linux/
|
||||||
|
./files/
|
||||||
|
linux-6.7.2.tar.xz
|
||||||
1
bi0sctf23/pwn/virtio-note/exploit/.Module.symvers.cmd
Normal file
1
bi0sctf23/pwn/virtio-note/exploit/.Module.symvers.cmd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
savedcmd_/home/cato/CTF/bi0sctf23/pwn/virtio-note/exploit/Module.symvers := scripts/mod/modpost -M -o /home/cato/CTF/bi0sctf23/pwn/virtio-note/exploit/Module.symvers -T /home/cato/CTF/bi0sctf23/pwn/virtio-note/exploit/modules.order -i Module.symvers -e
|
||||||
1
bi0sctf23/pwn/virtio-note/exploit/.modules.order.cmd
Normal file
1
bi0sctf23/pwn/virtio-note/exploit/.modules.order.cmd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
savedcmd_/home/cato/CTF/bi0sctf23/pwn/virtio-note/exploit/modules.order := { echo /home/cato/CTF/bi0sctf23/pwn/virtio-note/exploit/malicious_driver.o; :; } > /home/cato/CTF/bi0sctf23/pwn/virtio-note/exploit/modules.order
|
||||||
7
bi0sctf23/pwn/virtio-note/exploit/Makefile
Normal file
7
bi0sctf23/pwn/virtio-note/exploit/Makefile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
obj-m += malicious_driver.o
|
||||||
|
|
||||||
|
all:
|
||||||
|
make -C ../linux M=$(PWD) modules
|
||||||
|
|
||||||
|
clean:
|
||||||
|
make -C ../linux M=$(PWD) clean
|
||||||
95
bi0sctf23/pwn/virtio-note/exploit/malicious_driver.c
Normal file
95
bi0sctf23/pwn/virtio-note/exploit/malicious_driver.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include <linux/virtio.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h> /* io map */
|
||||||
|
#include <linux/dma-mapping.h> /* DMA */
|
||||||
|
#include <linux/kernel.h> /* kstrtoint() func */
|
||||||
|
#include <linux/virtio_config.h> /* find_single_vq() func */
|
||||||
|
|
||||||
|
#include "../files/src/virtio-note.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define VIRTIO_NOTE_ID 42
|
||||||
|
|
||||||
|
static void virtio_note_store(struct device *dev, const char *buf, size_t count){
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_dummy_recv_cb(struct virtqueue *vq)
|
||||||
|
{
|
||||||
|
struct virtio_dummy_dev *dev = vq->vdev->priv;
|
||||||
|
char *buf;
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) {
|
||||||
|
pr_info("%s\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virtio_dummy_probe(struct virtio_device *vdev)
|
||||||
|
{
|
||||||
|
struct virtio_dummy_dev *dev = NULL;
|
||||||
|
|
||||||
|
/* initialize device data */
|
||||||
|
dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL);
|
||||||
|
if (!dev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* the device has a single virtqueue */
|
||||||
|
dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, "input");
|
||||||
|
if (IS_ERR(dev->vq)) {
|
||||||
|
kfree(dev);
|
||||||
|
return PTR_ERR(dev->vq);
|
||||||
|
|
||||||
|
}
|
||||||
|
vdev->priv = dev;
|
||||||
|
|
||||||
|
/* from this point on, the device can notify and get callbacks */
|
||||||
|
virtio_device_ready(vdev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_dummy_remove(struct virtio_device *vdev)
|
||||||
|
{
|
||||||
|
struct virtio_dummy_dev *dev = vdev->priv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* disable vq interrupts: equivalent to
|
||||||
|
* vdev->config->reset(vdev)
|
||||||
|
*/
|
||||||
|
virtio_reset_device(vdev);
|
||||||
|
|
||||||
|
char *buf;
|
||||||
|
/* detach unused buffers */
|
||||||
|
while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) {
|
||||||
|
kfree(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove virtqueues */
|
||||||
|
vdev->config->del_vqs(vdev);
|
||||||
|
|
||||||
|
kfree(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct virtio_device_id id_table[] = {
|
||||||
|
{ VIRTIO_NOTE_ID, VIRTIO_DEV_ANY_ID },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct virtio_driver virtio_dummy_driver = {
|
||||||
|
.driver.name = KBUILD_MODNAME,
|
||||||
|
.driver.owner = THIS_MODULE,
|
||||||
|
.id_table = id_table,
|
||||||
|
.probe = virtio_dummy_probe,
|
||||||
|
.remove = virtio_dummy_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_virtio_driver(virtio_dummy_driver);
|
||||||
|
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||||
|
MODULE_DESCRIPTION("Dummy virtio driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
Reference in New Issue
Block a user