1 #include <linux/module.h>
2 #include <linux/pagemap.h>
3 #include <linux/sched.h>
4 #include <linux/version.h>
6 enum ksplice_state_enum
{
7 KSPLICE_PREPARING
, KSPLICE_APPLIED
, KSPLICE_REVERSED
10 struct ksplice_reloc
{
12 char *blank_sect_name
;
32 struct ksplice_patch
{
44 enum ksplice_state_enum state
;
45 struct ksplice_reloc
*primary_relocs
;
46 struct ksplice_size
*primary_sizes
;
47 struct ksplice_reloc
*helper_relocs
;
48 struct ksplice_size
*helper_sizes
;
49 struct ksplice_patch
*patches
;
50 struct list_head
*reloc_addrmaps
;
51 struct list_head
*reloc_namevals
;
52 struct list_head
*safety_records
;
55 struct reloc_nameval
{
56 struct list_head list
;
59 enum { NOVAL
, TEMP
, VAL
} status
;
62 struct reloc_addrmap
{
63 struct list_head list
;
67 struct reloc_nameval
*nameval
;
71 static inline int virtual_address_mapped(long addr
)
80 if (addr
> init_mm
.start_code
&& addr
< init_mm
.end_code
)
83 pgd
= pgd_offset_k(addr
);
88 pud
= pud_offset(pgd
, addr
);
89 pmd
= pmd_offset(pud
, addr
);
91 pmd
= pmd_offset(pgd
, addr
);
96 ptep
= pte_offset_map(pmd
, addr
);
97 if (!pte_present(*ptep
)) {
106 struct reloc_nameval
*find_nameval(struct module_pack
*pack
, char *name
,
108 struct reloc_addrmap
*find_addrmap(struct module_pack
*pack
, long addr
);
109 int handle_myst_reloc(long pre_addr
, int *pre_z
, long run_addr
,
110 int *run_z
, struct reloc_addrmap
*map
, int rerun
);
112 struct safety_record
{
113 struct list_head list
;
119 struct candidate_val
{
120 struct list_head list
;
124 #define singular(list) (!list_empty(list) && (list)->next->next == (list))
125 #define failed_to_find(sym_name) \
126 printk(KERN_ERR "ksplice: Failed to find symbol %s at %s:%d\n", \
127 sym_name, __FILE__, __LINE__)
129 static inline void print_abort(const char *str
)
131 printk(KERN_ERR
"ksplice: Aborted. (%s)\n", str
);
134 #define ksplice_debug(level, fmt, ...) \
135 do { if (debug >= (level)) printk(fmt, ## __VA_ARGS__); } while (0)
137 int process_ksplice_relocs(struct module_pack
*pack
,
138 struct ksplice_reloc
*relocs
);
139 int process_reloc(struct module_pack
*pack
, struct ksplice_reloc
*r
);
140 int compute_address(struct module_pack
*pack
, char *sym_name
,
141 struct list_head
*vals
);
143 #ifndef KSPLICE_STANDALONE
144 int accumulate_matching_names(void *data
, const char *sym_name
, long sym_val
);
147 #ifdef CONFIG_KALLSYMS
148 #if defined KSPLICE_STANDALONE && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
149 long ksplice_kallsyms_expand_symbol(unsigned long off
, char *result
);
151 int kernel_lookup(const char *name_wlabel
, struct list_head
*vals
);
152 int other_module_lookup(const char *name_wlabel
, struct list_head
*vals
,
153 const char *ksplice_name
);
154 int ksplice_mod_find_sym(struct module
*m
, const char *name
,
155 struct list_head
*vals
);
158 int add_candidate_val(struct list_head
*vals
, long val
);
159 void release_vals(struct list_head
*vals
);
160 void set_temp_myst_relocs(struct module_pack
*pack
, int status_val
);
161 int starts_with(const char *str
, const char *prefix
);
162 int ends_with(const char *str
, const char *suffix
);
163 int label_offset(const char *sym_name
);
164 const char *dup_wolabel(const char *sym_name
);
166 #define clear_list(head, type, member) \
168 struct list_head *_pos, *_n; \
169 list_for_each_safe(_pos, _n, head) { \
171 kfree(list_entry(_pos, type, member)); \
175 int init_module(void);
176 void cleanup_module(void);
177 int init_ksplice_module(struct module_pack
*pack
);
178 void cleanup_ksplice_module(struct module_pack
*pack
);
181 int activate_primary(struct module_pack
*pack
);
182 int resolve_patch_symbols(struct module_pack
*pack
);
183 int procfile_read(char *buffer
, char **buffer_location
, off_t offset
,
184 int buffer_length
, int *eof
, void *data
);
185 int procfile_write(struct file
*file
, const char *buffer
,
186 unsigned long count
, void *data
);
187 int __apply_patches(void *packptr
);
188 int __reverse_patches(void *packptr
);
189 int check_each_task(struct module_pack
*pack
);
190 int check_task(struct module_pack
*pack
, struct task_struct
*t
);
191 int check_stack(struct module_pack
*pack
, struct thread_info
*tinfo
,
193 int check_address_for_conflict(struct module_pack
*pack
, long addr
);
194 int valid_stack_ptr(struct thread_info
*tinfo
, void *p
);
197 int activate_helper(struct module_pack
*pack
);
198 int search_for_match(struct module_pack
*pack
, struct ksplice_size
*s
);
199 int try_addr(struct module_pack
*pack
, struct ksplice_size
*s
, long run_addr
,
200 long pre_addr
, int create_nameval
);
202 #ifdef KSPLICE_STANDALONE
203 void *ksplice_kcalloc(int size
);
204 void brute_search_all_mods(struct module_pack
*pack
, struct ksplice_size
*s
);
206 static inline int brute_search(struct module_pack
*pack
, struct ksplice_size
*s
,
207 void *start
, long len
)
212 for (addr
= (long)start
; addr
< (long)start
+ len
; addr
++) {
213 if (addr
% 100000 == 0)
216 if (!virtual_address_mapped(addr
))
219 run
= *(unsigned char *)(addr
);
220 pre
= *(unsigned char *)(s
->thismod_addr
);
225 if (addr
== s
->thismod_addr
)
228 if (try_addr(pack
, s
, addr
, s
->thismod_addr
, 1))
234 #endif /* KSPLICE_STANDALONE */