top | item 47017831

(no title)

rep_lodsb | 16 days ago

Nitpick (footnote 3): "64-bit kernels can run 32-bit userspace processes, but 64-bit and 32-bit code can’t be mixed in the same process. ↩"

That isn't true on any operating system I'm aware of. If both modes are supported at all, there will be a ring 3 code selector defined in the GDT for each, and I don't think there would be any security benefit to hiding the "inactive" one. A program could even use the LAR instruction to search for them.

At least on Linux, the kernel is perfectly fine with being called from either mode. FASM example code (with hardcoded selector, works on my machine):

    format elf executable at $1_0000
    entry start
    
    segment readable executable
    
    start:  mov     eax,4                   ;32-bit syscall# for write
            mov     ebx,1                   ;handle
            mov     ecx,Msg1                ;pointer
            mov     edx,Msg1.len            ;length
            int     $80
    
            call    $33:demo64
    
            mov     eax,4
            mov     ebx,1
            mov     ecx,Msg3
            mov     edx,Msg3.len
            int     $80
            mov     eax,1                   ;exit
            xor     ebx,ebx                 ;status
            int     $80
    
    use64
    demo64: mov     eax,1                   ;64-bit syscall# for write
            mov     edi,1                   ;handle
            lea     rsi,[Msg2]              ;pointer
            mov     edx,Msg2.len            ;length
            syscall
            retfd                           ;return to caller in 32 bit mode

    Msg1    db      "Hello from 32-bit mode",10
    .len=$-Msg1
    
    Msg2    db      "Now in 64-bit mode",10
    .len=$-Msg2
    
    Msg3    db      "Back to 32 bits",10
    .len=$-Msg3

discuss

order

bonzini|16 days ago

Isn't it how recent Wine runs 32-bit programs?

josephh|16 days ago

Much like there is 64-bit "code", there is also 32-bit "code" that can only be executed in the 32-bit (protected) mode, namely all the BCD, segment-related, push/pop-all instructions that will trigger an invalid opcode exception (#UD) when executed under long mode. In that strictest sense, "64-bit and 32-bit code can’t be mixed".

jcranmer|16 days ago

x86 has (not counting the system-management mode stuff) 4 major modes: real mode, protected mode, virtual 8086 mode, and IA-32e mode. Protected mode and IA-32e mode rely on the bits within the code segment's descriptor to figure out whether or not it is 16-bit, 32-bit, or 64-bit. (For extra fun, you can also have "wrong-size" stack segments, e.g., 32-bit code + 16-bit stack segment!)

16-bit and 32-bit code segments work almost exactly in IA-32e mode (what Intel calls "compatibility mode") as they do in protected mode; I think the only real difference is that the task management stuff doesn't work in IA-32e mode (and consequently features that rely on task management--e.g., virtual-8086 mode--don't work either). It's worth pointing out that if you're running a 64-bit kernel, then all of your 32-bit applications are running in IA-32e mode and not in protected mode. This also means that it's possible to have a 32-bit application that runs 64-bit code!

But I can run the BCD instructions, the crazy segment stuff, etc. all within a 16-bit or 32-bit code segment of a 64-bit executable. I have the programs to prove it.