1 |
On Sat, Jun 9, 2018 at 8:56 AM Alexander Kapshuk |
2 |
<alexander.kapshuk@×××××.com> wrote: |
3 |
> |
4 |
> |
5 |
> |
6 |
> On Sat, Jun 9, 2018, 07:34 Ian Zimmerman <itz@××××××××××××.org> wrote: |
7 |
>> |
8 |
>> On 2018-06-08 22:38, Alexander Kapshuk wrote: |
9 |
>> |
10 |
>> > On Fri, Jun 8, 2018, 22:30 Ian Zimmerman <itz@××××××××××××.org> wrote: |
11 |
>> > |
12 |
>> > > On 2018-06-08 22:00, Alexander Kapshuk wrote: |
13 |
>> > > |
14 |
>> > > > What's the output of: |
15 |
>> > > > uname -r |
16 |
>> > > > strings /path/to/your/module.ko | grep vermagic= |
17 |
>> > > |
18 |
>> > > Here are the results for 4.9.105 (working): |
19 |
>> > > |
20 |
>> > > matica!6 ~$ uname -r |
21 |
>> > > 4.9.105 |
22 |
>> > > matica!7 ~$ strings |
23 |
>> > > /lib64/modules/4.9.105/kernel/drivers/video/console/fbcon.ko | |
24 |
>> > > fgrep -e 'vermagic=' |
25 |
>> > > vermagic=4.9.105 SMP |
26 |
>> > > |
27 |
>> > > Let me know if you need to see the ones for the broken kernel ... |
28 |
>> > > |
29 |
>> > |
30 |
>> > Yes, we want to make sure the vermagic of the modules you're trying to load |
31 |
>> > matches the output of uname -r of the running kernel. |
32 |
>> |
33 |
>> Ok, here: |
34 |
>> |
35 |
>> Script started on 2018-06-08 21:11:04-0700 |
36 |
>> matica!501 ~# ls -l /lib64/modules/4.9.107/kernel/drivers/video/console/fbcon.ko |
37 |
>> -rw-r--r-- 1 root root 54280 Jun 8 20:57 /lib64/modules/4.9.107/kernel/drivers/video/console/fbcon.ko |
38 |
>> matica!502 ~# uname -r |
39 |
>> 4.9.107 |
40 |
>> matica!503 ~# strings /lib64/modules/4.9.107/kernel/drivers/video/console/fbcon |
41 |
>> .ko | fgrep -e 'vermagic=' |
42 |
>> vermagic=4.9.107 SMP |
43 |
>> matica!504 ~# modprobe fbcon |
44 |
>> modprobe: ERROR: could not insert 'fbcon': Exec format error |
45 |
>> matica!505 ~# exit |
46 |
>> |
47 |
>> Script done on 2018-06-08 21:14:46-0700 |
48 |
>> |
49 |
>> Sorry to ruin the low-hanging hypothesis :-P |
50 |
>> |
51 |
> |
52 |
> Did dmesg have anything useful to say other than exec format error? |
53 |
> Have you tried insmod'ing the modules instead of modprobe'ing them? |
54 |
>> |
55 |
>> |
56 |
>> -- |
57 |
|
58 |
I had a look at the source code for kmod-25. If I read it right, dmesg |
59 |
should have records along the lines of: |
60 |
kmod-25/libkmod/libkmod-module.c:886: INFO(mod->ctx, "Failed |
61 |
to insert module '%s': %m\n", path); |
62 |
|
63 |
modprobe returns Exec format error. |
64 |
|
65 |
errno -l | grep 'Exec format error' |
66 |
ENOEXEC 8 Exec format error |
67 |
|
68 |
/usr/include/asm-generic/errno-base.h: |
69 |
#define ENOEXEC 8 /* Exec format error */ |
70 |
|
71 |
Here's the execution path I've been able to follow: |
72 |
insmod()->kmod_module_probe_insert_module()->kmod_module_insert_module()->init_module()->copy_module_from_user(); |
73 |
|
74 |
init_module(2): |
75 |
http://man7.org/linux/man-pages/man2/init_module.2.html |
76 |
ENOEXEC |
77 |
The binary image supplied in module_image is not an ELF image, |
78 |
or is an ELF image that is invalid or for a different |
79 |
architecture. |
80 |
|
81 |
(1). kmod-25/tools/modprobe.c |
82 |
ENOEXEC returned by kmod_module_probe_insert_module(). |
83 |
static int insmod(struct kmod_ctx *ctx, const char *alias, |
84 |
const char *extra_options) |
85 |
{ |
86 |
... |
87 |
kmod_list_foreach(l, list) { |
88 |
... |
89 |
if (lookup_only) |
90 |
printf("%s\n", kmod_module_get_name(mod)); |
91 |
else { |
92 |
err = kmod_module_probe_insert_module(mod, flags, |
93 |
extra_options, NULL, NULL, show); |
94 |
} |
95 |
|
96 |
if (err >= 0) |
97 |
/* ignore flag return values such as a mod being blacklisted */ |
98 |
err = 0; |
99 |
else { |
100 |
switch (err) { |
101 |
... |
102 |
default: |
103 |
ERR("could not insert '%s': %s\n", <- the error message reported by modprobe |
104 |
kmod_module_get_name(mod), |
105 |
strerror(-err)); |
106 |
break; |
107 |
} |
108 |
} |
109 |
|
110 |
(2). kmod-25/libkmod/libkmod-module.c |
111 |
KMOD_EXPORT int kmod_module_probe_insert_module(struct kmod_module *mod, |
112 |
unsigned int flags, const char *extra_options, |
113 |
int (*run_install)(struct kmod_module *m, |
114 |
const char *cmd, void *data), |
115 |
const void *data, |
116 |
void (*print_action)(struct kmod_module *m, |
117 |
bool install, |
118 |
const char *options)) |
119 |
{ |
120 |
... |
121 |
if (!(flags & KMOD_PROBE_DRY_RUN)) |
122 |
err = kmod_module_insert_module(m, flags, |
123 |
options); |
124 |
} |
125 |
... |
126 |
} |
127 |
|
128 |
(3). KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod, |
129 |
unsigned int flags, |
130 |
const char *options) |
131 |
{ |
132 |
... |
133 |
size = kmod_file_get_size(mod->file); <- the size of your modules elf file |
134 |
... |
135 |
err = init_module(mem, size, args); |
136 |
... |
137 |
} |
138 |
|
139 |
(4). [init_module syscall] |
140 |
kernel/module.c |
141 |
SYSCALL_DEFINE3(init_module, void __user *, umod, |
142 |
unsigned long, len, const char __user *, uargs) |
143 |
{ |
144 |
int err; |
145 |
struct load_info info = { }; |
146 |
|
147 |
err = may_init_module(); |
148 |
if (err) |
149 |
return err; |
150 |
|
151 |
pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n", |
152 |
umod, len, uargs); |
153 |
|
154 |
err = copy_module_from_user(umod, len, &info); |
155 |
if (err) |
156 |
return err; |
157 |
|
158 |
return load_module(&info, uargs, 0); |
159 |
} |
160 |
|
161 |
(5). kernel/module.c |
162 |
/* Sets info->hdr and info->len. */ |
163 |
static int copy_module_from_user(const void __user *umod, unsigned long len, |
164 |
struct load_info *info) |
165 |
{ |
166 |
int err; |
167 |
|
168 |
info->len = len; |
169 |
if (info->len < sizeof(*(info->hdr))) <- here, size of your |
170 |
module'e elf file is being compared against the size of the ELF header |
171 |
as defined for your architecture. See below. |
172 |
return -ENOEXEC; |
173 |
... |
174 |
} |
175 |
|
176 |
kernel/module.c:310,313 |
177 |
struct load_info { |
178 |
const char *name; |
179 |
Elf_Ehdr *hdr; <- ELF header used in comparison above. |
180 |
unsigned long len; |
181 |
|
182 |
Elf_Ehdr is effected by CONFIG_X86_32 set in: |
183 |
arch/x86/um/asm/module.h:14:#define Elf_Ehdr Elf32_Ehdr |
184 |
arch/x86/um/asm/module.h:20:#define Elf_Ehdr Elf64_Ehdr |
185 |
|
186 |
And CONFIG_64BIT defined in: |
187 |
include/asm-generic/module.h:20:#define Elf_Ehdr Elf64_Ehdr |
188 |
include/asm-generic/module.h:37:#define Elf_Ehdr Elf32_Ehdr |
189 |
|
190 |
Example of ELF header sizes for 32/64 bit: |
191 |
readelf -h ./kernel/fs/udf/udf.ko |
192 |
ELF Header: |
193 |
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |
194 |
Class: ELF32 |
195 |
... |
196 |
Machine: Intel 80386 |
197 |
... |
198 |
Size of this header: 52 (bytes) |
199 |
|
200 |
readelf -h ./kernel/fs/udf/udf.ko |
201 |
ELF Header: |
202 |
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |
203 |
Class: ELF64 |
204 |
... |
205 |
Machine: Advanced Micro Devices X86-64 |
206 |
Size of this header: 64 (bytes) |
207 |
|
208 |
Now, if my understanding of the source code above is right, you either |
209 |
have CONFIG_X86_32 set in your kernel, e.i. your Elf_Ehdr is set to |
210 |
Elf32_Ehdr, or the module's header is for the architecture that is |
211 |
different from what is expected by the kernel. |