Assignment 2, due Feb 7 (date changed due to snow)

Part of the homework for 22C:169, Spring 2011
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Always, on every assignment, please write your name legibly as it appears on your University ID and on the class list! All assignments will be due at the start of class on the day indicated (usually a Friday), and unless there is what insurance companies call "an act of God" - something outside your control; the only exceptions to this rule will be by advance arrangement.

  1. Background: The Unix operating system does not include any explicit mechanism to enlarge the stack segment. Initially, the stack segment is just big enough to hold the initial stack (the values pushed by the exec system call that launches an application).

    A Problem: Given that there is no explicit system call "make my stack bigger", how can the system possibly know when to enlarge the stack. (1.0 points)

  2. Background: Suppose the system always loads programs at a random virtual address each time an application is launched. This prevents exploiting a buffer overflow to force execution of some specific subroutine. The buffer overflow can still cause random actions.

    On Unix, the above defense must be modified somewhat because whenever there are multiple processes running the same application, the code segment is shared.

    a) On most machines, a shared code segment must be at the same virtual address in all processes that share it. Why? This is a question about computer architecture. Knowledge of assembly language programming is essential to answering it. (0.5 points)

    b) Assume that shared code is seen to be in the same virtual address by all processes that share that code, but that the load address is randomized each time the code is loaded -- that is, when nobody was using it and then someone launched it, what could an attacker do that would not work if code was not shared between processes and each execution of a program involved loading it again? (0.5 points)

  3. Background: Consider a process on a Unix system. Each process in this system has a code segment that always starts at virtual address zero, a stack segment that grows down from the highest virtual address, a and a static segment. Executable object files can be executed by directly copying them into code segment.

    a) Explain what part of the function of execve() on this system could be implemented using the semantics of unmap() and mmap(). (0.5 points)

    b) What, if anything, does mmap() do that shmat() does not do, and visa versa. (Note: These two Unix kernel services exist entirely because there were separate independent streams of development that each produced shared memory models. Both models are supported in modern Linux systems. More evidence of "intelligent" design.) (0.5 points)

  4. A Problem: Empirically determine, for example, by writing some small C programs, using a debugger, or by other means, the organization of the address space of a user program on the Linux system of your choice. What system did you use, and on that system, Note that your code from the first homework assignment for printing out the value of a pointer will be immensely valuable in solving this problem. (1 point)

  5. A Problem: On most modern CPU architectures, all of the address space is one virtual address space, so incrementing or decrementing an address in the stack segment by an appropriate amount will produce a value in the code segment, the static segment, or elsewhere. In effect, pointers have no type, so while we may think of code pointers as a different type from data pointers, the hardware is unable to enforce the difference.

    a) How can the MMU be used to prevent, for example, a stack overflow into the static segment? (0.5 points) b) How can the MMU be used to prevent, for example, accidental execution of data on the stack, or accidental modification of code in the program segment? (0.5 points)