diff mbox

improve emulation correctness

Message ID 209441398413635@web22g.yandex.ru
State New
Headers show

Commit Message

Dmitry Poletaev April 25, 2014, 8:13 a.m. UTC
There is a set of test, that checks QEMU CPU for similar behavior with real hardware (http://roberto.greyhats.it/projects/pills.html). Test reg/pill2579.c can detect, that program is execute in emulated environment. It is related with behavior of rcl instruction. If the number of shifted bits more than 1, OF of eflags become undefined. Real CPUs does not change OF, if it is undefined. QEMU do it anyway.
Emulated program can execute that test and after that can understand environment not real.

Signed-off-by: Dmitry Poletaev <poletaev-qemu@yandex.ru>


This patch improve correctness of emulator behavior.

Comments

Richard Henderson April 25, 2014, 5:09 p.m. UTC | #1
On 04/25/2014 01:13 AM, Dmitry Poletaev wrote:
> There is a set of test, that checks QEMU CPU for similar behavior with real hardware (http://roberto.greyhats.it/projects/pills.html). Test reg/pill2579.c can detect, that program is execute in emulated environment. It is related with behavior of rcl instruction. If the number of shifted bits more than 1, OF of eflags become undefined. Real CPUs does not change OF, if it is undefined. QEMU do it anyway.
> Emulated program can execute that test and after that can understand environment not real.
> 
> Signed-off-by: Dmitry Poletaev <poletaev-qemu@yandex.ru>
> 
> diff --git a/target-i386/shift_helper_template.h b/target-i386/shift_helper_template.h
> index cf91a2d..d5bd321 100644
> --- a/target-i386/shift_helper_template.h
> +++ b/target-i386/shift_helper_template.h
> @@ -64,8 +64,10 @@ target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0,
>          }
>          t0 = res;
>          env->cc_src = (eflags & ~(CC_C | CC_O)) |
> -            (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
>              ((src >> (DATA_BITS - count)) & CC_C);
> +        if (count == 1) {
> +            env->cc_src |= (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O);
> +        }

This doesn't do what you say it does.  It doesn't leave O unchanged,
it always resets it to 0, and only sets it back to 1 if count == 1.


r~
Peter Maydell April 25, 2014, 5:24 p.m. UTC | #2
On 25 April 2014 09:13, Dmitry Poletaev <poletaev-qemu@yandex.ru> wrote:
> There is a set of test, that checks QEMU CPU for similar behavior with real hardware (http://roberto.greyhats.it/projects/pills.html). Test reg/pill2579.c can detect, that program is execute in emulated environment. It is related with behavior of rcl instruction. If the number of shifted bits more than 1, OF of eflags become undefined. Real CPUs does not change OF, if it is undefined. QEMU do it anyway.

It would be helpful if you could be more precise
with your subject lines. "improve emulation correctness"
is so vague it could apply to almost any part of QEMU.
We usually have a format of "area or file: change", so
in this case perhaps
 "target-i386: fix handling of OF in rcl instruction".

That said,

> Emulated program can execute that test and after that
> can understand environment not real.

It is always going to be possible to determine that you're
running on an emulator rather than real hardware, so changing
QEMU behaviour just for this is uninteresting. If QEMU
behaves differently from the specification (in this case
the x86 hardware and architecture manuals) that's an interesting
bug. If we just happen to choose a different undefined
behaviour from that which hardware does, that is not in
my opinion a problem.

thanks
-- PMM
Michael Tokarev April 27, 2014, 4:46 p.m. UTC | #3
25.04.2014 21:24, Peter Maydell wrote:
> On 25 April 2014 09:13, Dmitry Poletaev <poletaev-qemu@yandex.ru> wrote:
> 
>> Emulated program can execute that test and after that
>> can understand environment not real.
> 
> It is always going to be possible to determine that you're
> running on an emulator rather than real hardware, so changing
> QEMU behaviour just for this is uninteresting. If QEMU
> behaves differently from the specification (in this case
> the x86 hardware and architecture manuals) that's an interesting
> bug. If we just happen to choose a different undefined
> behaviour from that which hardware does, that is not in
> my opinion a problem.

Actually it might be a problem.  We know a ton of examples where
hardware had bugs and software had to compensate and actually
_expect_ buggy behavour.  Or when software depends on (reliable
repeating) certain behavour in undocumented parts, and hell
breaks when this (undocumented!) behavour changes.

Thanks,

/mjt
Peter Maydell April 27, 2014, 4:59 p.m. UTC | #4
On 27 April 2014 17:46, Michael Tokarev <mjt@tls.msk.ru> wrote:
> 25.04.2014 21:24, Peter Maydell wrote:
>> It is always going to be possible to determine that you're
>> running on an emulator rather than real hardware, so changing
>> QEMU behaviour just for this is uninteresting. If QEMU
>> behaves differently from the specification (in this case
>> the x86 hardware and architecture manuals) that's an interesting
>> bug. If we just happen to choose a different undefined
>> behaviour from that which hardware does, that is not in
>> my opinion a problem.
>
> Actually it might be a problem.  We know a ton of examples where
> hardware had bugs and software had to compensate and actually
> _expect_ buggy behavour.  Or when software depends on (reliable
> repeating) certain behavour in undocumented parts, and hell
> breaks when this (undocumented!) behavour changes.

Yes, sometimes you get that sort of thing. But we should only
put that kind of change in when we actually need it (ie when
there's real guest code that hits it, not just silly test programs
deliberately looking for undefined behaviour), and comment
why it's there so people who need to maintain that bit of code
in future know that it's deliberate and not just accidental.

I should perhaps have said "that is not inherently a problem".

thanks
-- PMM
Dmitry Poletaev April 28, 2014, 1:41 p.m. UTC | #5
27.04.2014, 20:59, "Peter Maydell" <peter.maydell@linaro.org>:

>  On 27 April 2014 17:46, Michael Tokarev <mjt@tls.msk.ru> wrote:
>>   25.04.2014 21:24, Peter Maydell wrote:
>>>   It is always going to be possible to determine that you're
>>>   running on an emulator rather than real hardware, so changing
>>>   QEMU behaviour just for this is uninteresting. If QEMU
>>>   behaves differently from the specification (in this case
>>>   the x86 hardware and architecture manuals) that's an interesting
>>>   bug. If we just happen to choose a different undefined
>>>   behaviour from that which hardware does, that is not in
>>>   my opinion a problem.
>>   Actually it might be a problem.  We know a ton of examples where
>>   hardware had bugs and software had to compensate and actually
>>   _expect_ buggy behavour.  Or when software depends on (reliable
>>   repeating) certain behavour in undocumented parts, and hell
>>   breaks when this (undocumented!) behavour changes.
>  Yes, sometimes you get that sort of thing. But we should only
>  put that kind of change in when we actually need it (ie when
>  there's real guest code that hits it, not just silly test programs
>  deliberately looking for undefined behaviour), and comment
>  why it's there so people who need to maintain that bit of code
>  in future know that it's deliberate and not just accidental.
>
>  I should perhaps have said "that is not inherently a problem".
>
>  thanks
>  -- PMM

Let's imagine we analyse a program(may be a malware) and so run it in emulator. Malware can execute that test and understand that it run in an emulator. After that malware can make decision, that someone analyse it and alter its behavior with a view to make analysis more complicated. 

So it makes sense to apply that patch.

Of course that little fix can't absolutely break a chance to detect emulation, but can make it more difficult.
Peter Maydell April 28, 2014, 1:49 p.m. UTC | #6
On 28 April 2014 14:41, Dmitry Poletaev <poletaev-qemu@yandex.ru> wrote:
> Let's imagine we analyse a program(may be a malware) and so
> run it in emulator. Malware can execute that test and understand
> that it run in an emulator. After that malware can make decision,
> that someone analyse it and alter its behavior with a view to
> make analysis more complicated.

I understand this theory. I think it's misguided to think that
it's possible to avoid the problem.

> So it makes sense to apply that patch.

I disagree with this, because we can never make QEMU behave
exactly identically to the hardware (timing effects, weird
choices of QEMU devices, etc). We cannot offer this guarantee,
so there is no point in attempting to make changes purely
to try to provide the guarantee in some areas.

(Just to pick a fairly easy way guest malware can
detect QEMU TCG, it can run timing tests that probe for
the size of L1 cache by looking for the point where memory
access time falls off a cliff. QEMU will never be able to
emulate caches with the same sort of memory timing profile.)

thanks
-- PMM
Dmitry Poletaev April 28, 2014, 2:32 p.m. UTC | #7
I'm understand your position.

But why in TCG undefined flags obviously change to zero in some cases? 
For example: 
af = 0; /* undefined */

It is not a part of Intel specification, what reason was apply that convention?

28.04.2014, 17:49, "Peter Maydell" <peter.maydell@linaro.org>:
> On 28 April 2014 14:41, Dmitry Poletaev <poletaev-qemu@yandex.ru> wrote:
>
>>  Let's imagine we analyse a program(may be a malware) and so
>>  run it in emulator. Malware can execute that test and understand
>>  that it run in an emulator. After that malware can make decision,
>>  that someone analyse it and alter its behavior with a view to
>>  make analysis more complicated.
>
> I understand this theory. I think it's misguided to think that
> it's possible to avoid the problem.
>
>>  So it makes sense to apply that patch.
>
> I disagree with this, because we can never make QEMU behave
> exactly identically to the hardware (timing effects, weird
> choices of QEMU devices, etc). We cannot offer this guarantee,
> so there is no point in attempting to make changes purely
> to try to provide the guarantee in some areas.
>
> (Just to pick a fairly easy way guest malware can
> detect QEMU TCG, it can run timing tests that probe for
> the size of L1 cache by looking for the point where memory
> access time falls off a cliff. QEMU will never be able to
> emulate caches with the same sort of memory timing profile.)
>
> thanks
> -- PMM
Richard Henderson April 28, 2014, 4 p.m. UTC | #8
On 04/28/2014 07:32 AM, Dmitry Poletaev wrote:
> I'm understand your position.
> 
> But why in TCG undefined flags obviously change to zero in some cases? 
> For example: 
> af = 0; /* undefined */
> 
> It is not a part of Intel specification, what reason was apply that convention?

Because it's simple, correct, and makes for the smallest fastest qemu binary.


r~
diff mbox

Patch

diff --git a/target-i386/shift_helper_template.h b/target-i386/shift_helper_template.h
index cf91a2d..d5bd321 100644
--- a/target-i386/shift_helper_template.h
+++ b/target-i386/shift_helper_template.h
@@ -64,8 +64,10 @@  target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0,
         }
         t0 = res;
         env->cc_src = (eflags & ~(CC_C | CC_O)) |
-            (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
             ((src >> (DATA_BITS - count)) & CC_C);
+        if (count == 1) {
+            env->cc_src |= (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O);
+        }
     }
     return t0;
}