Re: cvs commit: src/sys/vm vm_unix.c (fwd)

Date view Thread view Subject view Author view

From: Matthew Dillon (dillon@apollo.backplane.com)
Date: Mon Feb 08 1999 - 16:00:57 EST


:>
:> I don't understand your statement about
:> "But once you've executed something in it you cannot write to it again."
:> Of course you can write into it and execute it again.
:>
:
:I just realized that saying "you can write into it and execute it again"
:does not refute your statement.
:
:What I mean is that you can write to the data segment and execute code
:in it arbitrarily.
:
: - Godmar

    Most modern processors have a separate instruction cache. Typically,
    writes to memory are only cached in the data cache, not the instruction
    cache. Thus if you have executed a piece of code ( causing it to be
    brought into the instruction cache ), and then attempt to change
    that code by writing to the memory where said code resides, then execute
    it again, the processor may execute stale instructions from the
    instruction cache instead of the new instructions you wrote into the
    memory.

    So, the rule of thumb is: You can write instructions to newly allocated
    memory but once you've executed them, you can't modify that memory.

    UNIX systems have the notion of three protection bits:
    PROT_READ, PROT_WRITE, and PROT_EXECUTE. Many of today's processor's
    MMU's can only deal with PROT_READ and PROT_WRITE and ignore
    PROT_EXECUTE. Thus, on many of today's processors you can run code
    out of memory that was allocated R+W rather then R+W+X. This leads to
    rather sloppy memory allocation practices in regards to dynamically
    loaded code or JIT code.

    The only way to be absolutely sure is to use mmap(), which allows you
    to properly specify PROT_EXECUTE. If you use sbrk() you do not necessarily
    know what access flags the OS is applying to the memory, and you might
    still be able to run code in it *even* if the OS only mapped the memory
    R+W ( due to limitations with the hardware MMU for the processor in
    question ). Prior to mmap() coming into existance, sbrk() was used
    to allocate memory to hold dynamically loaded code, so the use of
    sbrk() has become a kind of defacto standard. Given the choice,
    though, it is better to use mmap() on systems that support anonymous
    or /dev/zero mmaping.

    The IA32 architecture ( aka intel ) has no notion of execute permissions
    in the MMU proper. It does have a notion of execute permissions in
    the code segment register, but apart from a few hacks one sees here and
    there the code segment register is not useful in a paged memory
    environment and so cannot typically be used to enforce PROT_EXECUTE.

                                        -Matt
                                        Matthew Dillon
                                        <dillon@backplane.com>


Date view Thread view Subject view Author view

This archive was generated by hypermail 2b29 : Sat Sep 23 2000 - 19:58:02 EDT