|
4 | 4 | #include <linux/seq_file.h> |
5 | 5 | #include <linux/kallsyms.h> |
6 | 6 | #include <linux/rwlock.h> |
| 7 | +#include <asm/uaccess.h> |
7 | 8 |
|
8 | | -#define MOD "[proc-owner]: " |
9 | | - |
10 | | -int (*xlate)(const char *name, struct proc_dir_entry **ret, const char **residual); |
11 | | -struct proc_dir_entry* (*subdir_find)(struct proc_dir_entry *dir, const char *name, unsigned int len); |
12 | | -void* subdir_lock; |
13 | | -const char *(*syms_lookup)(unsigned long addr, unsigned long *symbolsize, unsigned long *offset, char **modname, char *namebuf); |
14 | | -int (*symbol_name)(unsigned long addr, char *symname); |
15 | | - |
16 | | - struct proc_dir_entry { |
17 | | - unsigned int low_ino; |
18 | | - umode_t mode; |
19 | | - nlink_t nlink; |
20 | | - kuid_t uid; |
21 | | - kgid_t gid; |
22 | | - loff_t size; |
23 | | - const struct inode_operations *proc_iops; |
24 | | - const struct file_operations *proc_fops; |
25 | | - struct proc_dir_entry *parent; |
26 | | - struct rb_root subdir; |
27 | | - struct rb_node subdir_node; |
28 | | - void *data; |
29 | | - atomic_t count; /* use count */ |
30 | | - atomic_t in_use; /* number of callers into module in progress; */ |
31 | | - /* negative -> it's going away RSN */ |
32 | | - struct completion *pde_unload_completion; |
33 | | - struct list_head pde_openers; /* who did ->open, but not ->release */ |
34 | | - spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ |
35 | | - u8 namelen; |
36 | | - char name[]; |
| 9 | +#define MOD "[proc-details]: " |
| 10 | + |
| 11 | +static struct { |
| 12 | + char filename[256]; |
| 13 | + struct proc_dir_entry *dir_entry; |
| 14 | + char modname[128]; |
| 15 | + char fops[128]; |
| 16 | + char fops_open[128]; |
| 17 | + char fops_release[128]; |
| 18 | + char fops_read[128]; |
| 19 | + char fops_write[128]; |
| 20 | + char fops_llseek[128]; |
| 21 | +} proc_details; |
| 22 | + |
| 23 | +static int (*xlate)(const char *name, struct proc_dir_entry **ret, const char **residual); |
| 24 | +static struct proc_dir_entry* (*subdir_find)(struct proc_dir_entry *dir, const char *name, unsigned int len); |
| 25 | +static void* subdir_lock; |
| 26 | +static const char *(*syms_lookup)(unsigned long addr, unsigned long *symbolsize, unsigned long *offset, char **modname, char *namebuf); |
| 27 | +static int (*symbol_name)(unsigned long addr, char *symname); |
| 28 | + |
| 29 | +static void get_details(void); |
| 30 | + |
| 31 | + |
| 32 | +// ---------------------------------------------------------------------------------------------------------- |
| 33 | +struct proc_dir_entry { |
| 34 | + unsigned int low_ino; |
| 35 | + umode_t mode; |
| 36 | + nlink_t nlink; |
| 37 | + kuid_t uid; |
| 38 | + kgid_t gid; |
| 39 | + loff_t size; |
| 40 | + const struct inode_operations *proc_iops; |
| 41 | + const struct file_operations *proc_fops; |
| 42 | + struct proc_dir_entry *parent; |
| 43 | + struct rb_root subdir; |
| 44 | + struct rb_node subdir_node; |
| 45 | + void *data; |
| 46 | + atomic_t count; /* use count */ |
| 47 | + atomic_t in_use; /* number of callers into module in progress; */ |
| 48 | + /* negative -> it's going away RSN */ |
| 49 | + struct completion *pde_unload_completion; |
| 50 | + struct list_head pde_openers; /* who did ->open, but not ->release */ |
| 51 | + spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ |
| 52 | + u8 namelen; |
| 53 | + char name[]; |
37 | 54 | }; |
38 | 55 |
|
| 56 | +// ---------------------------------------------------------------------------------------------------------- |
| 57 | +#define BUF 1024 |
| 58 | +#define SHOW_FUNCTION(fnc) if(proc_details.fops_##fnc[0]) snprintf(buf, BUF, "%s .%s = %s,\n", buf, #fnc, proc_details.fops_##fnc); |
| 59 | +static int proc_procreadwrite_show (struct seq_file *m, void *v) { |
| 60 | + size_t i, spacing; |
| 61 | + char buf[BUF]; |
| 62 | + char spacing_left[] = " "; |
| 63 | + const char* padding = " "; |
| 64 | + int pad = 45; |
| 65 | + |
| 66 | + spacing = (60 - strlen(proc_details.filename) - 6) / 2; |
| 67 | + if(spacing < 0 || spacing >= 60) { |
| 68 | + spacing = 0; |
| 69 | + } |
| 70 | + spacing_left[spacing] = 0; |
| 71 | + |
| 72 | + snprintf(buf, BUF, "------------------------------------------------------------\n%s/proc/%s\n------------------------------------------------------------\n", spacing_left, proc_details.filename); |
| 73 | + |
| 74 | + snprintf(buf, BUF, "%s> %s%*.*s : %s\n", buf, "Module ", pad - 8, pad - 8, padding, proc_details.modname); |
| 75 | + snprintf(buf, BUF, "%s> %s%*.*s\n", buf, "Mode "); |
| 76 | + snprintf(buf, BUF, "%s %s%*.*s : %o\n", buf, "Format ", pad - 12, pad - 12, padding, (proc_details.dir_entry->mode & 0170000) / (8*8*8)); |
| 77 | + snprintf(buf, BUF, "%s %s%*.*s : %o\n", buf, "Permissions ", pad - 17, pad - 17, padding, proc_details.dir_entry->mode & 0777); |
| 78 | + snprintf(buf, BUF, "%s> %s%*.*s : %d\n", buf, "Count ", pad - 7, pad - 7, padding, proc_details.dir_entry->count); |
| 79 | + snprintf(buf, BUF, "%s> %s%*.*s : %d\n", buf, "In use ", pad - 8, pad - 8, padding, proc_details.dir_entry->in_use); |
| 80 | + |
| 81 | + snprintf(buf, BUF, "%s> %s%*.*s : %s\n", buf, "File Operations ", pad - 17, pad - 17, padding, proc_details.fops[0] ? "Yes" : "No"); |
| 82 | + if(proc_details.fops[0]) { |
| 83 | + snprintf(buf, BUF, "%s %s = {\n", buf, proc_details.fops); |
| 84 | + SHOW_FUNCTION(open) |
| 85 | + SHOW_FUNCTION(read) |
| 86 | + SHOW_FUNCTION(write) |
| 87 | + SHOW_FUNCTION(release) |
| 88 | + SHOW_FUNCTION(llseek) |
| 89 | + snprintf(buf, BUF, "%s };\n", buf); |
| 90 | + } |
| 91 | + seq_puts(m, buf); |
| 92 | + return 0; |
| 93 | +} |
| 94 | + |
| 95 | + |
| 96 | +// ---------------------------------------------------------------------------------------------------------- |
| 97 | +static int proc_procreadwrite_open (struct inode *inode, struct file *file) { |
| 98 | + return single_open (file, proc_procreadwrite_show, NULL); |
| 99 | +} |
| 100 | + |
39 | 101 |
|
40 | 102 | // ---------------------------------------------------------------------------------------------------------- |
41 | | -static void get_owner(const char* fname) { |
| 103 | +static ssize_t proc_procreadwrite_write (struct file *file, const char * buf, size_t size, loff_t * ppos) { |
| 104 | + size_t len = 255; |
| 105 | + size_t i; |
| 106 | + |
| 107 | + if (len > size) { |
| 108 | + len = size; |
| 109 | + } |
| 110 | + |
| 111 | + if (copy_from_user (proc_details.filename, buf, len)) { |
| 112 | + return -EFAULT; |
| 113 | + } |
| 114 | + |
| 115 | + proc_details.filename[len] = 0; |
| 116 | + for(i = 0; i < len; i++) { |
| 117 | + if(proc_details.filename[i] == '\r' || proc_details.filename[i] == '\n') { |
| 118 | + proc_details.filename[i] = 0; |
| 119 | + break; |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + printk(KERN_INFO MOD "checking module: %s\n", proc_details.filename); |
| 124 | + get_details(); |
| 125 | + return len; |
| 126 | +} |
| 127 | + |
| 128 | + |
| 129 | + |
| 130 | +// ---------------------------------------------------------------------------------------------------------- |
| 131 | +static struct file_operations proc_procreadwrite_operations = { |
| 132 | + .open = proc_procreadwrite_open, |
| 133 | + .read = seq_read, |
| 134 | + .write = proc_procreadwrite_write, |
| 135 | + .llseek = seq_lseek, |
| 136 | + .release = single_release, |
| 137 | +}; |
| 138 | + |
| 139 | + |
| 140 | + |
| 141 | +// ---------------------------------------------------------------------------------------------------------- |
| 142 | +#define GET_FUNCTION(fnc) if(proc_details.dir_entry->proc_fops->fnc) {\ |
| 143 | + symbol_name((size_t)(proc_details.dir_entry->proc_fops->fnc), proc_details.fops_##fnc);\ |
| 144 | + } else {\ |
| 145 | + proc_details.fops_##fnc[0] = 0;\ |
| 146 | + } |
| 147 | + |
| 148 | +static void get_details() { |
42 | 149 | int rv; |
43 | 150 | unsigned int len; |
44 | 151 | unsigned long symbolsize, offset; |
45 | | - const char* fn = fname; |
46 | | - char* modname = NULL, tmpstr; |
| 152 | + const char* fn = proc_details.filename; |
| 153 | + char *tmpstr, *modname = NULL; |
47 | 154 | char namebuf[128]; |
48 | | - struct proc_dir_entry *de = NULL; |
49 | 155 |
|
50 | 156 | spin_lock(subdir_lock); |
51 | | - rv = xlate(fname, &de, &fn); |
| 157 | + rv = xlate(proc_details.filename, &(proc_details.dir_entry), &fn); |
52 | 158 | printk(KERN_INFO MOD "Ret: %d, Residual: %s\n", rv, fn); |
53 | 159 | if(rv != 0) { |
54 | 160 | spin_unlock(subdir_lock); |
55 | 161 | return; |
56 | 162 | } |
57 | 163 | len = strlen(fn); |
58 | | - de = subdir_find(de, fn, len); |
59 | | - if(de) { |
60 | | - printk(KERN_INFO MOD "Name: %s, proc fops: %p\n", de->name, de->proc_fops); |
61 | | - tmpstr = syms_lookup((size_t)(de->proc_fops), &symbolsize, &offset, &modname, namebuf); |
62 | | - printk(KERN_INFO MOD "Modname: %s\n", modname); |
63 | | - symbol_name((size_t)(de->proc_fops), namebuf); |
64 | | - printk(KERN_INFO MOD "Symbol: %s\n", namebuf); |
| 164 | + // find entry in procfs |
| 165 | + proc_details.dir_entry = subdir_find(proc_details.dir_entry, fn, len); |
| 166 | + if(proc_details.dir_entry) { |
| 167 | + printk(KERN_INFO MOD "Name: %s, proc fops: %p\n", proc_details.dir_entry->name, proc_details.dir_entry->proc_fops); |
| 168 | + // get module name |
| 169 | + tmpstr = syms_lookup((size_t)(proc_details.dir_entry->proc_fops), &symbolsize, &offset, &modname, namebuf); |
| 170 | + if(modname) { |
| 171 | + strlcpy(proc_details.modname, modname, 128); |
| 172 | + } else { |
| 173 | + strcpy(proc_details.modname, "N/A"); |
| 174 | + } |
| 175 | + // get file operation struct name |
| 176 | + symbol_name((size_t)(proc_details.dir_entry->proc_fops), proc_details.fops); |
| 177 | + // check which functions are registered |
| 178 | + GET_FUNCTION(open) |
| 179 | + GET_FUNCTION(read) |
| 180 | + GET_FUNCTION(write) |
| 181 | + GET_FUNCTION(release) |
| 182 | + GET_FUNCTION(llseek) |
65 | 183 | } |
66 | 184 | spin_unlock(subdir_lock); |
67 | | - |
68 | 185 | } |
69 | 186 |
|
70 | 187 |
|
71 | | -// ---------------------------------------------------------------------------------------------------------- |
72 | | -static int proc_read(struct seq_file *m, void *v) { |
73 | | - seq_printf(m, "test\n"); |
74 | | - get_owner("kallsyms"); |
75 | | - |
76 | | - return 0; |
77 | | -} |
78 | | - |
79 | | -// ---------------------------------------------------------------------------------------------------------- |
80 | | -static int pm_open(struct inode *i, struct file *f) { |
81 | | - return single_open(f, proc_read, NULL); |
82 | | -} |
83 | | - |
84 | | -// ---------------------------------------------------------------------------------------------------------- |
85 | | -static const struct file_operations temp_proc_fops = { |
86 | | - .owner = THIS_MODULE, |
87 | | - .open = pm_open, |
88 | | - .read = seq_read, |
89 | | - .release = single_release, |
90 | | -}; |
91 | | - |
92 | 188 | // ---------------------------------------------------------------------------------------------------------- |
93 | 189 | static int __init procowner_init(void) |
94 | 190 | { |
95 | | - printk(KERN_INFO MOD "module start\n"); |
96 | | - proc_create("procowner", 0, NULL, &temp_proc_fops); |
97 | | - |
98 | | - xlate = kallsyms_lookup_name("__xlate_proc_name"); |
99 | | - if(!xlate) { |
100 | | - printk(KERN_INFO MOD "__xlate_proc_name not found!\n"); |
101 | | - return -ENODEV; |
102 | | - } |
103 | | - subdir_lock = kallsyms_lookup_name("proc_subdir_lock"); |
104 | | - if(!subdir_lock) { |
105 | | - printk(KERN_INFO MOD "proc_subdir_lock not found!\n"); |
106 | | - return -ENODEV; |
107 | | - } |
108 | | - subdir_find = kallsyms_lookup_name("pde_subdir_find"); |
109 | | - if(!subdir_find) { |
110 | | - printk(KERN_INFO MOD "pde_subdir_find not found!\n"); |
111 | | - return -ENODEV; |
112 | | - } |
113 | | - syms_lookup = kallsyms_lookup_name("kallsyms_lookup"); |
114 | | - if(!syms_lookup) { |
115 | | - printk(KERN_INFO MOD "kallsyms_lookup not found!\n"); |
116 | | - return -ENODEV; |
117 | | - } |
118 | | - symbol_name = kallsyms_lookup_name("lookup_symbol_name"); |
119 | | - if(!symbol_name) { |
120 | | - printk(KERN_INFO MOD "lookup_symbol_name not found!\n"); |
121 | | - return -ENODEV; |
122 | | - } |
| 191 | + printk(KERN_INFO MOD "module start\n"); |
| 192 | + int merr = 0; |
| 193 | + |
| 194 | + proc_create("procdetails", 0666, NULL, &proc_procreadwrite_operations); |
123 | 195 |
|
124 | | - return 0; |
| 196 | + xlate = kallsyms_lookup_name("__xlate_proc_name"); |
| 197 | + if(!xlate) { |
| 198 | + printk(KERN_INFO MOD "__xlate_proc_name not found!\n"); |
| 199 | + return -ENODEV; |
| 200 | + } |
| 201 | + subdir_lock = kallsyms_lookup_name("proc_subdir_lock"); |
| 202 | + if(!subdir_lock) { |
| 203 | + printk(KERN_INFO MOD "proc_subdir_lock not found!\n"); |
| 204 | + return -ENODEV; |
| 205 | + } |
| 206 | + subdir_find = kallsyms_lookup_name("pde_subdir_find"); |
| 207 | + if(!subdir_find) { |
| 208 | + printk(KERN_INFO MOD "pde_subdir_find not found!\n"); |
| 209 | + return -ENODEV; |
| 210 | + } |
| 211 | + syms_lookup = kallsyms_lookup_name("kallsyms_lookup"); |
| 212 | + if(!syms_lookup) { |
| 213 | + printk(KERN_INFO MOD "kallsyms_lookup not found!\n"); |
| 214 | + return -ENODEV; |
| 215 | + } |
| 216 | + symbol_name = kallsyms_lookup_name("lookup_symbol_name"); |
| 217 | + if(!symbol_name) { |
| 218 | + printk(KERN_INFO MOD "lookup_symbol_name not found!\n"); |
| 219 | + return -ENODEV; |
| 220 | + } |
| 221 | + |
| 222 | + return 0; |
125 | 223 | } |
126 | 224 |
|
127 | 225 | // ---------------------------------------------------------------------------------------------------------- |
128 | 226 | static void __exit procowner_exit(void) |
129 | 227 | { |
130 | | - remove_proc_entry("procowner", NULL); |
| 228 | + remove_proc_entry("procdetails", NULL); |
131 | 229 |
|
132 | | - printk(KERN_INFO MOD "module end\n"); |
| 230 | + printk(KERN_INFO MOD "module end\n"); |
133 | 231 | } |
134 | 232 |
|
135 | 233 |
|
|
0 commit comments