1use std::collections::HashMap;
7
8use super::{
9 CallbackCategory, DetectionPattern, HeaderStubs, OpsFieldDef, OpsStructDef, PlatformModule,
10};
11
12pub struct LinuxPlatform {
14 header_stubs: HeaderStubs,
15 ops_structs: Vec<OpsStructDef>,
16 call_normalizations: HashMap<&'static str, &'static str>,
17}
18
19impl LinuxPlatform {
20 pub fn new() -> Self {
21 let mut platform = Self {
22 header_stubs: HeaderStubs::new(),
23 ops_structs: Vec::new(),
24 call_normalizations: HashMap::new(),
25 };
26 platform.init_header_stubs();
27 platform.init_ops_structs();
28 platform.init_call_normalizations();
29 platform
30 }
31
32 fn init_header_stubs(&mut self) {
33 self.header_stubs.add(
35 "linux/types.h",
36 r#"
37typedef unsigned char u8;
38typedef unsigned short u16;
39typedef unsigned int u32;
40typedef unsigned long long u64;
41typedef signed char s8;
42typedef signed short s16;
43typedef signed int s32;
44typedef signed long long s64;
45typedef u8 __u8;
46typedef u16 __u16;
47typedef u32 __u32;
48typedef u64 __u64;
49typedef s8 __s8;
50typedef s16 __s16;
51typedef s32 __s32;
52typedef s64 __s64;
53typedef u16 __le16;
54typedef u32 __le32;
55typedef u64 __le64;
56typedef u16 __be16;
57typedef u32 __be32;
58typedef u64 __be64;
59typedef unsigned long size_t;
60typedef long ssize_t;
61typedef long long loff_t;
62typedef int bool;
63typedef unsigned int gfp_t;
64typedef unsigned int fmode_t;
65typedef unsigned short umode_t;
66typedef unsigned int dev_t;
67typedef int pid_t;
68typedef unsigned int uid_t;
69typedef unsigned int gid_t;
70typedef long long ktime_t;
71typedef unsigned long phys_addr_t;
72typedef unsigned long long dma_addr_t;
73typedef unsigned long long resource_size_t;
74typedef unsigned long uintptr_t;
75typedef long intptr_t;
76typedef long ptrdiff_t;
77"#,
78 );
79
80 self.header_stubs.add(
82 "linux/kernel.h",
83 r#"
84#define NULL ((void *)0)
85#define true 1
86#define false 0
87#define KERN_EMERG ""
88#define KERN_ALERT ""
89#define KERN_CRIT ""
90#define KERN_ERR ""
91#define KERN_WARNING ""
92#define KERN_NOTICE ""
93#define KERN_INFO ""
94#define KERN_DEBUG ""
95#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
96#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
97#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
98extern int printk(const char *fmt, ...);
99extern void panic(const char *fmt, ...);
100extern void *ERR_PTR(long error);
101extern long PTR_ERR(const void *ptr);
102extern int IS_ERR(const void *ptr);
103"#,
104 );
105
106 self.header_stubs.add(
108 "linux/init.h",
109 r#"
110#define __init
111#define __exit
112#define __initdata
113#define __exitdata
114#define __initconst
115#define __devinit
116#define __devexit
117#define module_init(x) int init_module(void) { return x(); }
118#define module_exit(x) void cleanup_module(void) { x(); }
119#define late_initcall(fn)
120#define subsys_initcall(fn)
121#define fs_initcall(fn)
122#define device_initcall(fn)
123#define arch_initcall(fn)
124#define core_initcall(fn)
125#define postcore_initcall(fn)
126"#,
127 );
128
129 self.header_stubs.add(
131 "linux/module.h",
132 r#"
133#define MODULE_LICENSE(license)
134#define MODULE_AUTHOR(author)
135#define MODULE_DESCRIPTION(desc)
136#define MODULE_VERSION(version)
137#define MODULE_ALIAS(alias)
138#define MODULE_DEVICE_TABLE(type, name)
139#define MODULE_FIRMWARE(fw)
140#define MODULE_INFO(tag, info)
141#define MODULE_PARM_DESC(parm, desc)
142#define EXPORT_SYMBOL(sym)
143#define EXPORT_SYMBOL_GPL(sym)
144#define EXPORT_SYMBOL_NS(sym, ns)
145#define EXPORT_SYMBOL_NS_GPL(sym, ns)
146#define THIS_MODULE ((struct module *)0)
147struct module;
148"#,
149 );
150
151 self.header_stubs.add(
153 "linux/fs.h",
154 r#"
155struct file;
156struct inode;
157struct dentry;
158struct super_block;
159struct file_operations {
160 struct module *owner;
161 loff_t (*llseek)(struct file *, loff_t, int);
162 ssize_t (*read)(struct file *, char *, size_t, loff_t *);
163 ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
164 int (*open)(struct inode *, struct file *);
165 int (*release)(struct inode *, struct file *);
166 long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
167 int (*mmap)(struct file *, struct vm_area_struct *);
168 unsigned int (*poll)(struct file *, struct poll_table_struct *);
169 int (*fsync)(struct file *, loff_t, loff_t, int);
170 int (*flush)(struct file *, void *);
171};
172struct inode_operations {
173 int (*create)(struct inode *, struct dentry *, umode_t, bool);
174 struct dentry * (*lookup)(struct inode *, struct dentry *, unsigned int);
175 int (*link)(struct dentry *, struct inode *, struct dentry *);
176 int (*unlink)(struct inode *, struct dentry *);
177 int (*mkdir)(struct inode *, struct dentry *, umode_t);
178 int (*rmdir)(struct inode *, struct dentry *);
179};
180extern int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops);
181extern void unregister_chrdev(unsigned int major, const char *name);
182"#,
183 );
184
185 self.header_stubs.add(
187 "linux/device.h",
188 r#"
189struct device;
190struct device_driver;
191struct class;
192struct bus_type;
193extern int device_register(struct device *dev);
194extern void device_unregister(struct device *dev);
195extern struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
196extern void device_destroy(struct class *cls, dev_t devt);
197extern int dev_err(const struct device *dev, const char *fmt, ...);
198extern int dev_warn(const struct device *dev, const char *fmt, ...);
199extern int dev_info(const struct device *dev, const char *fmt, ...);
200extern int dev_dbg(const struct device *dev, const char *fmt, ...);
201"#,
202 );
203
204 self.header_stubs.add(
206 "linux/pci.h",
207 r#"
208struct pci_dev;
209struct pci_device_id {
210 u32 vendor, device;
211 u32 subvendor, subdevice;
212 u32 class, class_mask;
213 unsigned long driver_data;
214};
215struct pci_driver {
216 const char *name;
217 const struct pci_device_id *id_table;
218 int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
219 void (*remove)(struct pci_dev *dev);
220 int (*suspend)(struct pci_dev *dev, pm_message_t state);
221 int (*resume)(struct pci_dev *dev);
222 void (*shutdown)(struct pci_dev *dev);
223 struct device_driver driver;
224};
225extern int pci_register_driver(struct pci_driver *drv);
226extern void pci_unregister_driver(struct pci_driver *drv);
227extern int pci_enable_device(struct pci_dev *dev);
228extern void pci_disable_device(struct pci_dev *dev);
229extern void pci_set_master(struct pci_dev *dev);
230extern int pci_request_regions(struct pci_dev *dev, const char *name);
231extern void pci_release_regions(struct pci_dev *dev);
232extern void *pci_ioremap_bar(struct pci_dev *dev, int bar);
233extern int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val);
234extern int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val);
235extern int pci_read_config_dword(const struct pci_dev *dev, int where, u32 *val);
236extern int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val);
237extern int pci_write_config_word(const struct pci_dev *dev, int where, u16 val);
238extern int pci_write_config_dword(const struct pci_dev *dev, int where, u32 val);
239#define PCI_DEVICE(vend, dev) .vendor = (vend), .device = (dev)
240#define module_pci_driver(drv)
241"#,
242 );
243
244 self.header_stubs.add(
246 "linux/slab.h",
247 r#"
248#define GFP_KERNEL 0
249#define GFP_ATOMIC 1
250#define GFP_DMA 2
251#define GFP_NOWAIT 4
252extern void *kmalloc(size_t size, gfp_t flags);
253extern void *kzalloc(size_t size, gfp_t flags);
254extern void *kcalloc(size_t n, size_t size, gfp_t flags);
255extern void *krealloc(void *p, size_t new_size, gfp_t flags);
256extern void kfree(const void *objp);
257extern void *vmalloc(unsigned long size);
258extern void vfree(const void *addr);
259extern void *kvmalloc(size_t size, gfp_t flags);
260extern void kvfree(const void *addr);
261extern struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *));
262extern void kmem_cache_destroy(struct kmem_cache *s);
263extern void *kmem_cache_alloc(struct kmem_cache *s, gfp_t flags);
264extern void kmem_cache_free(struct kmem_cache *s, void *objp);
265"#,
266 );
267
268 self.header_stubs.add(
270 "linux/mutex.h",
271 r#"
272struct mutex {
273 int count;
274};
275#define DEFINE_MUTEX(name) struct mutex name = { .count = 1 }
276#define mutex_init(mutex) do { (mutex)->count = 1; } while(0)
277extern void mutex_lock(struct mutex *lock);
278extern int mutex_trylock(struct mutex *lock);
279extern void mutex_unlock(struct mutex *lock);
280extern int mutex_is_locked(struct mutex *lock);
281"#,
282 );
283
284 self.header_stubs.add(
286 "linux/spinlock.h",
287 r#"
288typedef struct {
289 int lock;
290} spinlock_t;
291typedef struct {
292 int lock;
293} rwlock_t;
294#define DEFINE_SPINLOCK(name) spinlock_t name = { .lock = 0 }
295#define DEFINE_RWLOCK(name) rwlock_t name = { .lock = 0 }
296#define spin_lock_init(lock) do { (lock)->lock = 0; } while(0)
297extern void spin_lock(spinlock_t *lock);
298extern void spin_unlock(spinlock_t *lock);
299extern void spin_lock_irq(spinlock_t *lock);
300extern void spin_unlock_irq(spinlock_t *lock);
301extern void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
302extern void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
303extern int spin_trylock(spinlock_t *lock);
304extern void read_lock(rwlock_t *lock);
305extern void read_unlock(rwlock_t *lock);
306extern void write_lock(rwlock_t *lock);
307extern void write_unlock(rwlock_t *lock);
308"#,
309 );
310
311 self.header_stubs.add(
313 "linux/wait.h",
314 r#"
315struct wait_queue_head {
316 spinlock_t lock;
317};
318typedef struct wait_queue_head wait_queue_head_t;
319#define DECLARE_WAIT_QUEUE_HEAD(name) wait_queue_head_t name
320#define init_waitqueue_head(wq) do { } while(0)
321extern void wake_up(wait_queue_head_t *wq);
322extern void wake_up_interruptible(wait_queue_head_t *wq);
323extern void wake_up_all(wait_queue_head_t *wq);
324#define wait_event(wq, condition) do { } while(0)
325#define wait_event_interruptible(wq, condition) 0
326#define wait_event_timeout(wq, condition, timeout) 0
327"#,
328 );
329
330 self.header_stubs.add(
332 "linux/interrupt.h",
333 r#"
334typedef int irqreturn_t;
335#define IRQ_NONE 0
336#define IRQ_HANDLED 1
337#define IRQ_WAKE_THREAD 2
338#define IRQF_SHARED 0x00000080
339#define IRQF_TRIGGER_RISING 0x00000001
340#define IRQF_TRIGGER_FALLING 0x00000002
341typedef irqreturn_t (*irq_handler_t)(int, void *);
342extern int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);
343extern void free_irq(unsigned int irq, void *dev_id);
344extern int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags, const char *name, void *dev);
345extern void disable_irq(unsigned int irq);
346extern void enable_irq(unsigned int irq);
347extern void local_irq_disable(void);
348extern void local_irq_enable(void);
349"#,
350 );
351
352 self.header_stubs.add(
354 "linux/dma-mapping.h",
355 r#"
356enum dma_data_direction {
357 DMA_BIDIRECTIONAL = 0,
358 DMA_TO_DEVICE = 1,
359 DMA_FROM_DEVICE = 2,
360 DMA_NONE = 3,
361};
362extern void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag);
363extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
364extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, enum dma_data_direction dir);
365extern void dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir);
366extern int dma_set_mask(struct device *dev, u64 mask);
367extern int dma_set_coherent_mask(struct device *dev, u64 mask);
368#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
369"#,
370 );
371
372 self.header_stubs.add(
374 "linux/io.h",
375 r#"
376extern void *ioremap(phys_addr_t offset, size_t size);
377extern void iounmap(void *addr);
378extern u8 readb(const volatile void *addr);
379extern u16 readw(const volatile void *addr);
380extern u32 readl(const volatile void *addr);
381extern u64 readq(const volatile void *addr);
382extern void writeb(u8 value, volatile void *addr);
383extern void writew(u16 value, volatile void *addr);
384extern void writel(u32 value, volatile void *addr);
385extern void writeq(u64 value, volatile void *addr);
386extern u8 ioread8(const void *addr);
387extern u16 ioread16(const void *addr);
388extern u32 ioread32(const void *addr);
389extern void iowrite8(u8 value, void *addr);
390extern void iowrite16(u16 value, void *addr);
391extern void iowrite32(u32 value, void *addr);
392"#,
393 );
394
395 self.header_stubs.add(
397 "linux/errno.h",
398 r#"
399#define EPERM 1
400#define ENOENT 2
401#define EIO 5
402#define ENXIO 6
403#define ENOMEM 12
404#define EACCES 13
405#define EFAULT 14
406#define EBUSY 16
407#define EEXIST 17
408#define ENODEV 19
409#define EINVAL 22
410#define ENOSPC 28
411#define ERANGE 34
412#define EOPNOTSUPP 95
413#define ETIMEDOUT 110
414#define ERESTARTSYS 512
415"#,
416 );
417
418 self.header_stubs.add(
420 "linux/netdevice.h",
421 r#"
422struct net_device;
423struct sk_buff;
424struct net_device_stats;
425typedef u16 netdev_features_t;
426struct net_device_ops {
427 int (*ndo_open)(struct net_device *dev);
428 int (*ndo_stop)(struct net_device *dev);
429 int (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev);
430 void (*ndo_set_rx_mode)(struct net_device *dev);
431 int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
432 int (*ndo_validate_addr)(struct net_device *dev);
433 int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
434 int (*ndo_change_mtu)(struct net_device *dev, int new_mtu);
435 void (*ndo_tx_timeout)(struct net_device *dev, unsigned int txqueue);
436 struct net_device_stats *(*ndo_get_stats)(struct net_device *dev);
437};
438struct ethtool_ops {
439 int (*get_link)(struct net_device *dev);
440 int (*get_link_ksettings)(struct net_device *dev, struct ethtool_link_ksettings *cmd);
441 int (*set_link_ksettings)(struct net_device *dev, const struct ethtool_link_ksettings *cmd);
442};
443extern struct net_device *alloc_etherdev(int sizeof_priv);
444extern void free_netdev(struct net_device *dev);
445extern int register_netdev(struct net_device *dev);
446extern void unregister_netdev(struct net_device *dev);
447extern void *netdev_priv(const struct net_device *dev);
448"#,
449 );
450
451 self.header_stubs.add(
453 "linux/uaccess.h",
454 r#"
455extern unsigned long copy_from_user(void *to, const void *from, unsigned long n);
456extern unsigned long copy_to_user(void *to, const void *from, unsigned long n);
457extern int get_user(int x, int *ptr);
458extern int put_user(int x, int *ptr);
459extern int access_ok(int type, const void *addr, unsigned long size);
460#define VERIFY_READ 0
461#define VERIFY_WRITE 1
462"#,
463 );
464
465 self.header_stubs.add(
467 "linux/string.h",
468 r#"
469extern void *memset(void *s, int c, size_t n);
470extern void *memcpy(void *dest, const void *src, size_t n);
471extern void *memmove(void *dest, const void *src, size_t n);
472extern int memcmp(const void *s1, const void *s2, size_t n);
473extern size_t strlen(const char *s);
474extern char *strcpy(char *dest, const char *src);
475extern char *strncpy(char *dest, const char *src, size_t n);
476extern int strcmp(const char *s1, const char *s2);
477extern int strncmp(const char *s1, const char *s2, size_t n);
478extern char *strcat(char *dest, const char *src);
479extern char *strchr(const char *s, int c);
480extern char *strstr(const char *haystack, const char *needle);
481"#,
482 );
483
484 self.header_stubs.add(
486 "linux/workqueue.h",
487 r#"
488struct work_struct;
489struct delayed_work;
490struct workqueue_struct;
491typedef void (*work_func_t)(struct work_struct *work);
492#define DECLARE_WORK(n, f) struct work_struct n
493#define DECLARE_DELAYED_WORK(n, f) struct delayed_work n
494#define INIT_WORK(work, func) do { } while(0)
495#define INIT_DELAYED_WORK(dwork, func) do { } while(0)
496extern struct workqueue_struct *create_workqueue(const char *name);
497extern void destroy_workqueue(struct workqueue_struct *wq);
498extern int queue_work(struct workqueue_struct *wq, struct work_struct *work);
499extern int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay);
500extern int schedule_work(struct work_struct *work);
501extern int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay);
502extern int cancel_work_sync(struct work_struct *work);
503extern int cancel_delayed_work_sync(struct delayed_work *dwork);
504extern void flush_workqueue(struct workqueue_struct *wq);
505"#,
506 );
507
508 self.header_stubs.add(
510 "linux/timer.h",
511 r#"
512struct timer_list {
513 unsigned long expires;
514 void (*function)(struct timer_list *);
515 unsigned long data;
516};
517#define DEFINE_TIMER(name, func) struct timer_list name
518extern void timer_setup(struct timer_list *timer, void (*callback)(struct timer_list *), unsigned int flags);
519extern int mod_timer(struct timer_list *timer, unsigned long expires);
520extern int del_timer(struct timer_list *timer);
521extern int del_timer_sync(struct timer_list *timer);
522extern unsigned long jiffies;
523#define HZ 100
524#define msecs_to_jiffies(m) ((m) * HZ / 1000)
525"#,
526 );
527
528 self.header_stubs.add(
530 "linux/completion.h",
531 r#"
532struct completion {
533 unsigned int done;
534 wait_queue_head_t wait;
535};
536#define DECLARE_COMPLETION(name) struct completion name
537#define init_completion(x) do { (x)->done = 0; } while(0)
538extern void wait_for_completion(struct completion *x);
539extern int wait_for_completion_timeout(struct completion *x, unsigned long timeout);
540extern int wait_for_completion_interruptible(struct completion *x);
541extern void complete(struct completion *x);
542extern void complete_all(struct completion *x);
543extern void reinit_completion(struct completion *x);
544"#,
545 );
546
547 self.header_stubs.add(
549 "linux/atomic.h",
550 r#"
551typedef struct {
552 int counter;
553} atomic_t;
554typedef struct {
555 long long counter;
556} atomic64_t;
557#define ATOMIC_INIT(i) { (i) }
558#define atomic_read(v) ((v)->counter)
559#define atomic_set(v, i) ((v)->counter = (i))
560extern void atomic_inc(atomic_t *v);
561extern void atomic_dec(atomic_t *v);
562extern int atomic_inc_return(atomic_t *v);
563extern int atomic_dec_return(atomic_t *v);
564extern int atomic_dec_and_test(atomic_t *v);
565extern int atomic_add_return(int i, atomic_t *v);
566extern int atomic_sub_return(int i, atomic_t *v);
567extern int atomic_cmpxchg(atomic_t *v, int old, int new);
568"#,
569 );
570
571 self.header_stubs.add(
573 "linux/list.h",
574 r#"
575struct list_head {
576 struct list_head *next, *prev;
577};
578#define LIST_HEAD_INIT(name) { &(name), &(name) }
579#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
580#define INIT_LIST_HEAD(ptr) do { (ptr)->next = (ptr); (ptr)->prev = (ptr); } while (0)
581extern void list_add(struct list_head *new, struct list_head *head);
582extern void list_add_tail(struct list_head *new, struct list_head *head);
583extern void list_del(struct list_head *entry);
584extern void list_del_init(struct list_head *entry);
585extern int list_empty(const struct list_head *head);
586#define list_entry(ptr, type, member) container_of(ptr, type, member)
587#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)
588#define list_for_each_safe(pos, n, head) for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)
589"#,
590 );
591 }
592
593 fn init_ops_structs(&mut self) {
594 self.ops_structs.push(OpsStructDef {
596 struct_name: "file_operations".to_string(),
597 fields: vec![
598 OpsFieldDef {
599 name: "open".to_string(),
600 category: CallbackCategory::Open,
601 },
602 OpsFieldDef {
603 name: "release".to_string(),
604 category: CallbackCategory::Close,
605 },
606 OpsFieldDef {
607 name: "read".to_string(),
608 category: CallbackCategory::Read,
609 },
610 OpsFieldDef {
611 name: "write".to_string(),
612 category: CallbackCategory::Write,
613 },
614 OpsFieldDef {
615 name: "unlocked_ioctl".to_string(),
616 category: CallbackCategory::Ioctl,
617 },
618 OpsFieldDef {
619 name: "compat_ioctl".to_string(),
620 category: CallbackCategory::Ioctl,
621 },
622 OpsFieldDef {
623 name: "mmap".to_string(),
624 category: CallbackCategory::Mmap,
625 },
626 OpsFieldDef {
627 name: "poll".to_string(),
628 category: CallbackCategory::Poll,
629 },
630 OpsFieldDef {
631 name: "llseek".to_string(),
632 category: CallbackCategory::Other,
633 },
634 OpsFieldDef {
635 name: "fsync".to_string(),
636 category: CallbackCategory::Other,
637 },
638 ],
639 });
640
641 self.ops_structs.push(OpsStructDef {
643 struct_name: "pci_driver".to_string(),
644 fields: vec![
645 OpsFieldDef {
646 name: "probe".to_string(),
647 category: CallbackCategory::Probe,
648 },
649 OpsFieldDef {
650 name: "remove".to_string(),
651 category: CallbackCategory::Remove,
652 },
653 OpsFieldDef {
654 name: "suspend".to_string(),
655 category: CallbackCategory::Suspend,
656 },
657 OpsFieldDef {
658 name: "resume".to_string(),
659 category: CallbackCategory::Resume,
660 },
661 OpsFieldDef {
662 name: "shutdown".to_string(),
663 category: CallbackCategory::Cleanup,
664 },
665 ],
666 });
667
668 self.ops_structs.push(OpsStructDef {
670 struct_name: "net_device_ops".to_string(),
671 fields: vec![
672 OpsFieldDef {
673 name: "ndo_open".to_string(),
674 category: CallbackCategory::Open,
675 },
676 OpsFieldDef {
677 name: "ndo_stop".to_string(),
678 category: CallbackCategory::Close,
679 },
680 OpsFieldDef {
681 name: "ndo_start_xmit".to_string(),
682 category: CallbackCategory::Write,
683 },
684 OpsFieldDef {
685 name: "ndo_set_rx_mode".to_string(),
686 category: CallbackCategory::Other,
687 },
688 OpsFieldDef {
689 name: "ndo_set_mac_address".to_string(),
690 category: CallbackCategory::Other,
691 },
692 OpsFieldDef {
693 name: "ndo_do_ioctl".to_string(),
694 category: CallbackCategory::Ioctl,
695 },
696 OpsFieldDef {
697 name: "ndo_tx_timeout".to_string(),
698 category: CallbackCategory::Timer,
699 },
700 ],
701 });
702
703 self.ops_structs.push(OpsStructDef {
705 struct_name: "platform_driver".to_string(),
706 fields: vec![
707 OpsFieldDef {
708 name: "probe".to_string(),
709 category: CallbackCategory::Probe,
710 },
711 OpsFieldDef {
712 name: "remove".to_string(),
713 category: CallbackCategory::Remove,
714 },
715 OpsFieldDef {
716 name: "suspend".to_string(),
717 category: CallbackCategory::Suspend,
718 },
719 OpsFieldDef {
720 name: "resume".to_string(),
721 category: CallbackCategory::Resume,
722 },
723 ],
724 });
725 }
726
727 fn init_call_normalizations(&mut self) {
728 self.call_normalizations.insert("kmalloc", "MemAlloc");
730 self.call_normalizations.insert("kzalloc", "MemAlloc");
731 self.call_normalizations.insert("kcalloc", "MemAlloc");
732 self.call_normalizations.insert("krealloc", "MemRealloc");
733 self.call_normalizations.insert("vmalloc", "MemAlloc");
734 self.call_normalizations.insert("kvmalloc", "MemAlloc");
735 self.call_normalizations
736 .insert("kmem_cache_alloc", "MemAlloc");
737 self.call_normalizations
738 .insert("dma_alloc_coherent", "DmaAlloc");
739
740 self.call_normalizations.insert("kfree", "MemFree");
742 self.call_normalizations.insert("vfree", "MemFree");
743 self.call_normalizations.insert("kvfree", "MemFree");
744 self.call_normalizations
745 .insert("kmem_cache_free", "MemFree");
746 self.call_normalizations
747 .insert("dma_free_coherent", "DmaFree");
748
749 self.call_normalizations.insert("memcpy", "MemCopy");
751 self.call_normalizations.insert("memmove", "MemCopy");
752 self.call_normalizations.insert("memset", "MemSet");
753
754 self.call_normalizations
756 .insert("copy_from_user", "CopyFromUser");
757 self.call_normalizations.insert("get_user", "CopyFromUser");
758 self.call_normalizations
759 .insert("copy_to_user", "CopyToUser");
760 self.call_normalizations.insert("put_user", "CopyToUser");
761
762 self.call_normalizations.insert("mutex_lock", "LockAcquire");
764 self.call_normalizations.insert("spin_lock", "LockAcquire");
765 self.call_normalizations
766 .insert("spin_lock_irq", "LockAcquire");
767 self.call_normalizations
768 .insert("spin_lock_irqsave", "LockAcquire");
769 self.call_normalizations.insert("read_lock", "LockAcquire");
770 self.call_normalizations.insert("write_lock", "LockAcquire");
771 self.call_normalizations
772 .insert("mutex_unlock", "LockRelease");
773 self.call_normalizations
774 .insert("spin_unlock", "LockRelease");
775 self.call_normalizations
776 .insert("spin_unlock_irq", "LockRelease");
777 self.call_normalizations
778 .insert("spin_unlock_irqrestore", "LockRelease");
779 self.call_normalizations
780 .insert("read_unlock", "LockRelease");
781 self.call_normalizations
782 .insert("write_unlock", "LockRelease");
783
784 self.call_normalizations
786 .insert("wait_for_completion", "WaitEvent");
787 self.call_normalizations
788 .insert("wait_event_interruptible", "WaitEvent");
789 self.call_normalizations.insert("complete", "SignalEvent");
790 self.call_normalizations
791 .insert("complete_all", "SignalEvent");
792 self.call_normalizations.insert("wake_up", "SignalEvent");
793 self.call_normalizations
794 .insert("wake_up_interruptible", "SignalEvent");
795
796 self.call_normalizations.insert("ioremap", "IoRemap");
798 self.call_normalizations
799 .insert("pci_ioremap_bar", "IoRemap");
800 self.call_normalizations.insert("iounmap", "IoUnmap");
801
802 self.call_normalizations.insert("readb", "IoRead");
804 self.call_normalizations.insert("readw", "IoRead");
805 self.call_normalizations.insert("readl", "IoRead");
806 self.call_normalizations.insert("readq", "IoRead");
807 self.call_normalizations.insert("ioread8", "IoRead");
808 self.call_normalizations.insert("ioread16", "IoRead");
809 self.call_normalizations.insert("ioread32", "IoRead");
810 self.call_normalizations.insert("writeb", "IoWrite");
811 self.call_normalizations.insert("writew", "IoWrite");
812 self.call_normalizations.insert("writel", "IoWrite");
813 self.call_normalizations.insert("writeq", "IoWrite");
814 self.call_normalizations.insert("iowrite8", "IoWrite");
815 self.call_normalizations.insert("iowrite16", "IoWrite");
816 self.call_normalizations.insert("iowrite32", "IoWrite");
817
818 self.call_normalizations.insert("dma_map_single", "DmaMap");
820 self.call_normalizations
821 .insert("dma_unmap_single", "DmaUnmap");
822
823 self.call_normalizations
825 .insert("request_irq", "InterruptRegister");
826 self.call_normalizations
827 .insert("request_threaded_irq", "InterruptRegister");
828 self.call_normalizations
829 .insert("free_irq", "InterruptUnregister");
830 self.call_normalizations
831 .insert("disable_irq", "InterruptDisable");
832 self.call_normalizations
833 .insert("enable_irq", "InterruptEnable");
834
835 self.call_normalizations
837 .insert("pci_register_driver", "DeviceRegister");
838 self.call_normalizations
839 .insert("register_netdev", "DeviceRegister");
840 self.call_normalizations
841 .insert("register_chrdev", "DeviceRegister");
842 self.call_normalizations
843 .insert("device_register", "DeviceRegister");
844 self.call_normalizations
845 .insert("pci_unregister_driver", "DeviceUnregister");
846 self.call_normalizations
847 .insert("unregister_netdev", "DeviceUnregister");
848 self.call_normalizations
849 .insert("unregister_chrdev", "DeviceUnregister");
850 self.call_normalizations
851 .insert("device_unregister", "DeviceUnregister");
852
853 self.call_normalizations.insert("printk", "Log");
855 self.call_normalizations.insert("pr_info", "Log");
856 self.call_normalizations.insert("pr_err", "Log");
857 self.call_normalizations.insert("pr_warn", "Log");
858 self.call_normalizations.insert("pr_debug", "Log");
859 self.call_normalizations.insert("dev_info", "Log");
860 self.call_normalizations.insert("dev_err", "Log");
861 self.call_normalizations.insert("dev_warn", "Log");
862 self.call_normalizations.insert("dev_dbg", "Log");
863 }
864}
865
866impl Default for LinuxPlatform {
867 fn default() -> Self {
868 Self::new()
869 }
870}
871
872impl PlatformModule for LinuxPlatform {
873 fn id(&self) -> &'static str {
874 "linux"
875 }
876
877 fn name(&self) -> &'static str {
878 "Linux Kernel"
879 }
880
881 fn detection_patterns(&self) -> Vec<DetectionPattern> {
882 vec![
883 DetectionPattern::include("linux/", 3.0),
885 DetectionPattern::include("asm/", 1.5),
886 DetectionPattern::include("uapi/", 1.5),
887 DetectionPattern::macro_pattern("MODULE_LICENSE", 4.0),
889 DetectionPattern::macro_pattern("MODULE_AUTHOR", 2.0),
890 DetectionPattern::macro_pattern("MODULE_DESCRIPTION", 2.0),
891 DetectionPattern::macro_pattern("module_init", 3.0),
892 DetectionPattern::macro_pattern("module_exit", 3.0),
893 DetectionPattern::macro_pattern("EXPORT_SYMBOL", 2.5),
894 DetectionPattern::macro_pattern("EXPORT_SYMBOL_GPL", 2.5),
895 DetectionPattern::macro_pattern("__init", 2.0),
896 DetectionPattern::macro_pattern("__exit", 2.0),
897 DetectionPattern::macro_pattern("CONFIG_", 1.0),
898 DetectionPattern::macro_pattern("KERN_INFO", 1.5),
899 DetectionPattern::macro_pattern("KERN_ERR", 1.5),
900 DetectionPattern::macro_pattern("GFP_KERNEL", 2.0),
901 DetectionPattern::function_call("printk", 2.0),
903 DetectionPattern::function_call("kmalloc", 2.0),
904 DetectionPattern::function_call("kfree", 2.0),
905 DetectionPattern::function_call("kzalloc", 2.0),
906 DetectionPattern::function_call("copy_from_user", 2.5),
907 DetectionPattern::function_call("copy_to_user", 2.5),
908 DetectionPattern::type_name("spinlock_t", 1.5),
910 DetectionPattern::type_name("atomic_t", 1.5),
911 DetectionPattern::type_name("wait_queue_head_t", 1.5),
912 ]
913 }
914
915 fn header_stubs(&self) -> &HeaderStubs {
916 &self.header_stubs
917 }
918
919 fn attributes_to_strip(&self) -> &[&'static str] {
920 &[
921 "__init",
923 "__exit",
924 "__initdata",
925 "__exitdata",
926 "__initconst",
927 "__devinit",
928 "__devexit",
929 "__cold",
931 "__hot",
932 "__pure",
933 "__const",
934 "__noreturn",
935 "__malloc",
936 "__weak",
937 "__alias",
938 "__always_inline",
939 "__noinline",
940 "noinline",
941 "inline",
942 "__inline",
943 "__inline__",
944 "__section",
945 "__visible",
946 "__flatten",
947 "__user",
949 "__kernel",
950 "__iomem",
951 "__percpu",
952 "__rcu",
953 "__force",
954 "__bitwise",
955 "__safe",
956 "__maybe_unused",
958 "__always_unused",
959 "__unused",
960 "__packed",
962 "__aligned",
963 "__cacheline_aligned",
964 "__cacheline_aligned_in_smp",
965 "__page_aligned_data",
966 "__page_aligned_bss",
967 "__deprecated",
969 "__deprecated_for_modules",
970 "__must_check",
972 "__must_hold",
973 "__acquires",
974 "__releases",
975 "__acquire",
976 "__release",
977 "__cond_lock",
978 "__read_mostly",
980 "__ro_after_init",
981 "asmlinkage",
983 "fastcall",
984 "regparm",
985 ]
986 }
987
988 fn ops_structs(&self) -> &[OpsStructDef] {
989 &self.ops_structs
990 }
991
992 fn call_normalizations(&self) -> &HashMap<&'static str, &'static str> {
993 &self.call_normalizations
994 }
995}
996
997#[cfg(test)]
998mod tests {
999 use super::*;
1000 use crate::platform::DetectionKind;
1001
1002 #[test]
1003 fn test_linux_platform_id() {
1004 let platform = LinuxPlatform::new();
1005 assert_eq!(platform.id(), "linux");
1006 assert_eq!(platform.name(), "Linux Kernel");
1007 }
1008
1009 #[test]
1010 fn test_linux_header_stubs() {
1011 let platform = LinuxPlatform::new();
1012 let stubs = platform.header_stubs();
1013
1014 assert!(stubs.has_stub("linux/types.h"));
1015 assert!(stubs.has_stub("linux/kernel.h"));
1016 assert!(stubs.has_stub("linux/module.h"));
1017 assert!(stubs.has_stub("linux/fs.h"));
1018 assert!(stubs.has_stub("linux/pci.h"));
1019 assert!(stubs.has_stub("linux/slab.h"));
1020 }
1021
1022 #[test]
1023 fn test_linux_stubs_content() {
1024 let platform = LinuxPlatform::new();
1025 let stubs = platform.header_stubs();
1026
1027 let source = "#include <linux/types.h>\n#include <linux/kernel.h>";
1028 let stub_content = stubs.get_for_includes(source);
1029
1030 assert!(stub_content.contains("typedef unsigned int u32"));
1032 assert!(stub_content.contains("typedef unsigned long long u64"));
1033
1034 assert!(stub_content.contains("extern int printk"));
1036 }
1037
1038 #[test]
1039 fn test_linux_detection_patterns() {
1040 let platform = LinuxPlatform::new();
1041 let patterns = platform.detection_patterns();
1042
1043 let include_patterns: Vec<_> = patterns
1045 .iter()
1046 .filter(|p| p.kind == DetectionKind::Include)
1047 .collect();
1048 assert!(!include_patterns.is_empty());
1049
1050 let macro_patterns: Vec<_> = patterns
1052 .iter()
1053 .filter(|p| p.kind == DetectionKind::Macro)
1054 .collect();
1055 assert!(!macro_patterns.is_empty());
1056
1057 let module_license = patterns
1059 .iter()
1060 .find(|p| p.pattern == "MODULE_LICENSE")
1061 .unwrap();
1062 assert!(module_license.weight >= 3.0);
1063 }
1064
1065 #[test]
1066 fn test_linux_attributes_to_strip() {
1067 let platform = LinuxPlatform::new();
1068 let attrs = platform.attributes_to_strip();
1069
1070 assert!(attrs.contains(&"__init"));
1071 assert!(attrs.contains(&"__exit"));
1072 assert!(attrs.contains(&"__user"));
1073 assert!(attrs.contains(&"__iomem"));
1074 assert!(attrs.contains(&"__must_check"));
1075 }
1076
1077 #[test]
1078 fn test_linux_ops_structs() {
1079 let platform = LinuxPlatform::new();
1080 let ops = platform.ops_structs();
1081
1082 let file_ops = ops.iter().find(|o| o.struct_name == "file_operations");
1084 assert!(file_ops.is_some());
1085 let file_ops = file_ops.unwrap();
1086
1087 let open_field = file_ops.fields.iter().find(|f| f.name == "open");
1089 assert!(open_field.is_some());
1090 assert_eq!(open_field.unwrap().category, CallbackCategory::Open);
1091
1092 let pci_driver = ops.iter().find(|o| o.struct_name == "pci_driver");
1094 assert!(pci_driver.is_some());
1095 }
1096
1097 #[test]
1098 fn test_linux_call_normalizations() {
1099 let platform = LinuxPlatform::new();
1100 let norms = platform.call_normalizations();
1101
1102 assert_eq!(norms.get("kmalloc"), Some(&"MemAlloc"));
1103 assert_eq!(norms.get("kfree"), Some(&"MemFree"));
1104 assert_eq!(norms.get("copy_from_user"), Some(&"CopyFromUser"));
1105 assert_eq!(norms.get("mutex_lock"), Some(&"LockAcquire"));
1106 assert_eq!(norms.get("printk"), Some(&"Log"));
1107 }
1108}