1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
other: 0.956
semantic: 0.942
instruction: 0.927
boot: 0.925
mistranslation: 0.912
KVM: 0.911
network: 0.881
[Qemu-devel] [BUG] Inappropriate size of target_sigset_t
Hello, Peter, Laurent,
While working on another problem yesterday, I think I discovered a
long-standing bug in QEMU Linux user mode: our target_sigset_t structure is
eight times smaller as it should be!
In this code segment from syscalls_def.h:
#ifdef TARGET_MIPS
#define TARGET_NSIG 128
#else
#define TARGET_NSIG 64
#endif
#define TARGET_NSIG_BPW TARGET_ABI_BITS
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
typedef struct {
abi_ulong sig[TARGET_NSIG_WORDS];
} target_sigset_t;
... TARGET_ABI_BITS should be replaced by eight times smaller constant (in
fact, semantically, we need TARGET_ABI_BYTES, but it is not defined) (what is
needed is actually "a byte per signal" in target_sigset_t, and we allow "a bit
per signal").
All this probably sounds to you like something impossible, since this code is
in QEMU "since forever", but I checked everything, and the bug seems real. I
wish you can prove me wrong.
I just wanted to let you know about this, given the sensitive timing of current
softfreeze, and the fact that I won't be able to do more investigation on this
in coming weeks, since I am busy with other tasks, but perhaps you can analyze
and do something which you consider appropriate.
Yours,
Aleksandar
Le 03/07/2019 à 21:46, Aleksandar Markovic a écrit :
>
Hello, Peter, Laurent,
>
>
While working on another problem yesterday, I think I discovered a
>
long-standing bug in QEMU Linux user mode: our target_sigset_t structure is
>
eight times smaller as it should be!
>
>
In this code segment from syscalls_def.h:
>
>
#ifdef TARGET_MIPS
>
#define TARGET_NSIG 128
>
#else
>
#define TARGET_NSIG 64
>
#endif
>
#define TARGET_NSIG_BPW TARGET_ABI_BITS
>
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
>
>
typedef struct {
>
abi_ulong sig[TARGET_NSIG_WORDS];
>
} target_sigset_t;
>
>
... TARGET_ABI_BITS should be replaced by eight times smaller constant (in
>
fact, semantically, we need TARGET_ABI_BYTES, but it is not defined) (what is
>
needed is actually "a byte per signal" in target_sigset_t, and we allow "a
>
bit per signal").
TARGET_NSIG is divided by TARGET_ABI_BITS which gives you the number of
abi_ulong words we need in target_sigset_t.
>
All this probably sounds to you like something impossible, since this code is
>
in QEMU "since forever", but I checked everything, and the bug seems real. I
>
wish you can prove me wrong.
>
>
I just wanted to let you know about this, given the sensitive timing of
>
current softfreeze, and the fact that I won't be able to do more
>
investigation on this in coming weeks, since I am busy with other tasks, but
>
perhaps you can analyze and do something which you consider appropriate.
If I compare with kernel, it looks good:
In Linux:
arch/mips/include/uapi/asm/signal.h
#define _NSIG 128
#define _NSIG_BPW (sizeof(unsigned long) * 8)
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t;
_NSIG_BPW is 8 * 8 = 64 on MIPS64 or 4 * 8 = 32 on MIPS
In QEMU:
TARGET_NSIG_BPW is TARGET_ABI_BITS which is TARGET_LONG_BITS which is
64 on MIPS64 and 32 on MIPS.
I think there is no problem.
Thanks,
Laurent
From: Laurent Vivier <address@hidden>
>
If I compare with kernel, it looks good:
>
...
>
I think there is no problem.
Sure, thanks for such fast response - again, I am glad if you are right.
However, for some reason, glibc (and musl too) define sigset_t differently than
kernel. Please take a look. I am not sure if this is covered fine in our code.
Yours,
Aleksandar
>
Thanks,
>
Laurent
On Wed, 3 Jul 2019 at 21:20, Aleksandar Markovic <address@hidden> wrote:
>
>
From: Laurent Vivier <address@hidden>
>
> If I compare with kernel, it looks good:
>
> ...
>
> I think there is no problem.
>
>
Sure, thanks for such fast response - again, I am glad if you are right.
>
However, for some reason, glibc (and musl too) define sigset_t differently
>
than kernel. Please take a look. I am not sure if this is covered fine in our
>
code.
Yeah, the libc definitions of sigset_t don't match the
kernel ones (this is for obscure historical reasons IIRC).
We're providing implementations of the target
syscall interface, so our target_sigset_t should be the
target kernel's version (and the target libc's version doesn't
matter to us). On the other hand we will be using the
host libc version, I think, so a little caution is required
and it's possible we have some bugs in our code.
thanks
-- PMM
>
From: Peter Maydell <address@hidden>
>
>
On Wed, 3 Jul 2019 at 21:20, Aleksandar Markovic <address@hidden> wrote:
>
>
>
> From: Laurent Vivier <address@hidden>
>
> > If I compare with kernel, it looks good:
>
> > ...
>
> > I think there is no problem.
>
>
>
> Sure, thanks for such fast response - again, I am glad if you are right.
>
> However, for some reason, glibc (and musl too) define sigset_t differently
>
> than kernel. Please take a look. I am not sure if this is covered fine in
>
> our code.
>
>
Yeah, the libc definitions of sigset_t don't match the
>
kernel ones (this is for obscure historical reasons IIRC).
>
We're providing implementations of the target
>
syscall interface, so our target_sigset_t should be the
>
target kernel's version (and the target libc's version doesn't
>
matter to us). On the other hand we will be using the
>
host libc version, I think, so a little caution is required
>
and it's possible we have some bugs in our code.
OK, I gather than this is not something that requires our immediate attention
(for 4.1), but we can analyze it later on.
Thanks for response!!
Sincerely,
Aleksandar
>
thanks
>
-- PMM
Le 03/07/2019 à 22:28, Peter Maydell a écrit :
>
On Wed, 3 Jul 2019 at 21:20, Aleksandar Markovic <address@hidden> wrote:
>
>
>
> From: Laurent Vivier <address@hidden>
>
>> If I compare with kernel, it looks good:
>
>> ...
>
>> I think there is no problem.
>
>
>
> Sure, thanks for such fast response - again, I am glad if you are right.
>
> However, for some reason, glibc (and musl too) define sigset_t differently
>
> than kernel. Please take a look. I am not sure if this is covered fine in
>
> our code.
>
>
Yeah, the libc definitions of sigset_t don't match the
>
kernel ones (this is for obscure historical reasons IIRC).
>
We're providing implementations of the target
>
syscall interface, so our target_sigset_t should be the
>
target kernel's version (and the target libc's version doesn't
>
matter to us). On the other hand we will be using the
>
host libc version, I think, so a little caution is required
>
and it's possible we have some bugs in our code.
It's why we need host_to_target_sigset_internal() and
target_to_host_sigset_internal() that translates bits and bytes between
guest kernel interface and host libc interface.
void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s)
{
int i;
target_sigemptyset(d);
for (i = 1; i <= TARGET_NSIG; i++) {
if (sigismember(s, i)) {
target_sigaddset(d, host_to_target_signal(i));
}
}
}
void target_to_host_sigset_internal(sigset_t *d,
const target_sigset_t *s)
{
int i;
sigemptyset(d);
for (i = 1; i <= TARGET_NSIG; i++) {
if (target_sigismember(s, i)) {
sigaddset(d, target_to_host_signal(i));
}
}
}
Thanks,
Laurent
Hi Aleksandar,
On Wed, Jul 3, 2019 at 12:48 PM Aleksandar Markovic
<address@hidden> wrote:
>
#define TARGET_NSIG_BPW TARGET_ABI_BITS
>
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
>
>
typedef struct {
>
abi_ulong sig[TARGET_NSIG_WORDS];
>
} target_sigset_t;
>
>
... TARGET_ABI_BITS should be replaced by eight times smaller constant (in
>
fact,
>
semantically, we need TARGET_ABI_BYTES, but it is not defined) (what is needed
>
is actually "a byte per signal" in target_sigset_t, and we allow "a bit per
>
signal").
Why do we need a byte per target signal, if the functions in linux-user/signal.c
operate with bits?
--
Thanks.
-- Max
>
Why do we need a byte per target signal, if the functions in
>
linux-user/signal.c
>
operate with bits?
Max,
I did not base my findings on code analysis, but on dumping size/offsets of
elements of some structures, as they are emulated in QEMU, and in real systems.
So, I can't really answer your question.
Yours,
Aleksandar
>
--
>
Thanks.
>
-- Max
|