throbber
Safe Virtual Execution Using Software Dynamic Translation
`
`Kevin Scott and Jack Davidson
`
`Department of Computer Science, University of Virginia
`Charlottesville, VA 22904
`{kscott, jwd}@cs.virginia.edu
`
`Abstract
`Safe virtual execution (SVE) allows a host computer
`system to reduce the risks associated with running
`untrusted programs. SVE prevents untrusted programs
`from directly accessing system resources, thereby giv-
`ing the host the ability to control how individual
`resources may be used. SVE is used in a variety of
`safety-conscious software systems, including the Java
`Virtual Machine (JVM), software fault isolation (SFI),
`system call interposition layers, and execution moni-
`tors. While SVE is the conceptual foundation for these
`systems, each uses a different implementation technol-
`ogy. The lack of a unifying framework for building SVE
`systems results in a variety of problems: many useful
`SVE systems are not portable and therefore are usable
`only on a limited number of platforms; code reuse
`among different SVE systems is often difficult or impos-
`sible; and building SVE systems from scratch can be
`both time consuming and error prone.
`To address these concerns, we have developed a por-
`table, extensible framework for constructing SVE sys-
`tems. Our framework, called Strata, is based on
`software dynamic translation (SDT), a technique for
`modifying binary programs as they execute. Strata is
`designed to be ported easily to new platforms and to
`date has been targeted to SPARC/Solaris, x86/Linux,
`and MIPS/IRIX. This portability ensures that SVE
`applications implemented in Strata are available to a
`wide variety of host systems. Strata also affords the
`opportunity for code reuse among different SVE appli-
`cations by establishing a common implementation
`framework.
`Strata implements a basic safe virtual execution
`engine using SDT. The base functionality supplied by
`this engine is easily extended to implement specific SVE
`systems. In this paper we describe the organization of
`Strata and demonstrate its extension by building two
`SVE systems: system call interposition and stack-
`smashing prevention. To illustrate the use of the system
`call interposition extensions, the paper presents imple-
`mentations of several useful security policies.
`
`1. Introduction
`
`Today’s software environment is complex. End users
`acquire software from a number of sources, including
`the network, and have very little on which to base their
`trust that the software will correctly perform its
`intended function. Given the size of modern software—
`operating system kernels are comprised of millions of
`lines of source code and application programs are often
`an order of magnitude larger—it is difficult or impossi-
`ble for developers to guarantee that their software is
`worthy of the end user’s trust. Even if developers could
`make such guarantees about the software they distrib-
`ute, hostile entities actively seek to modify that soft-
`ware to perform unanticipated, often harmful functions
`via viruses and Trojan horses.
`In recent years, researchers have developed a variety
`of techniques for managing the execution of untrusted
`code. These techniques can be divided into two orthog-
`onal categories: static and dynamic. Static techniques
`analyze untrusted binaries before execution to deter-
`mine whether or not the program is safe to run. Proof
`carrying code [17] is a good example of the static
`approach—before a program can execute, the runtime
`system must successfully validate a proof that the
`untrusted binary will adhere to a given safety policy.
`Many static approaches, including proof carrying code,
`rely on source code analyses to produce safe binaries
`[5,15,22]. Dynamic techniques, on the other hand, do
`not require access to source code. Rather, dynamic
`techniques prevent violation of safety policies by moni-
`toring and modifying the behavior of untrusted binaries
`as they execute. An example of a dynamic approach is
`execution monitoring [9,18]. Execution monitors termi-
`nate the execution of a program as soon as an imper-
`missible sequence of events (corresponding to a safety
`policy violation) is observed. System call interposition
`layers [11, 12, 13, 14] are similar to execution monitors
`with the additional ability to alter the semantics of
`events, specifically system calls. Yet another similar
`dynamic
`technique, software fault
`isolation (also
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`Symantec 1018
`IPR of U.S. Pat. No. 8,141,154
`
`000001
`
`

`
`known as sandboxing) [23] limits the potential damage
`an untrusted binary can do by preventing loads, stores,
`or jumps outside of a restricted address range.
`In this paper we make the following observation:
`many dynamic trust management systems, including
`the ones mentioned above, can be implemented using a
`technique called safe virtual execution (SVE). SVE
`mediates application execution, virtualizing access to
`sensitive resources in order to prevent untrusted bina-
`ries from causing harm. Despite the fact that SVE pro-
`vides a conceptual framework for the implementation
`of systems such as execution monitors, interposition
`layers, and sandboxing, these systems are frequently
`based on widely differing implementation technologies.
`These systems are often dependent on a specific target
`architecture or on special operating system services,
`hence impeding their widespread use in the modern het-
`erogeneous networked computing environment. In
`addition to non-portability, the use of different imple-
`mentation technology places undue engineering bur-
`dens on the designers of SVE systems. They cannot
`share code and features with similar systems and must
`often endure the time consuming and error-prone chore
`of building their systems from scratch.
`To address these concerns, we have developed a por-
`table, extensible framework for constructing SVE sys-
`tems. Our framework, called Strata, is based on
`software dynamic translation (SDT), a technique for
`modifying binary programs as they execute [1, 2, 3, 6,
`7, 20, 21, 24]. Using SDT, Strata offers a basic safe vir-
`tual execution engine. The base functionality supplied
`by this engine can be extended in order to implement
`specific SVE systems. Using this approach useful SVE
`systems can often be implemented with very few lines
`of new code. Strata is designed to be easily ported to
`new platforms and to date has been targeted to SPARC/
`Solaris, x86/Linux, and MIPS/IRIX. This portability
`ensures that SVE applications implemented in Strata
`are available to a wide variety of host systems. Strata
`also affords the opportunity for code reuse among dif-
`ferent SVE applications by establishing a common
`implementation framework.
`The remainder of this paper is organized as follows.
`Section 2 provides an overview of software dynamic
`translation and Section 3 describes Strata’s organization
`and architecture. Section 4 then describes how Strata is
`used to implement a system call interposition layer and
`how this layer can be used to implement powerful secu-
`rity policies. Section 5 discusses our results while Sec-
`tion 6 discusses related work, and Section 7 provides a
`summary.
`
`2. Software Dynamic Translation
`
`SDT is a technique for dynamically modifying a
`program as it is being executed. Software dynamic
`translation has been used in a variety of different areas:
`binary translation for executing programs on non-native
`CPUs [6, 7, 21]; fast machine simulation [3, 24]; and
`recently, dynamic optimization [1]. In this paper we
`describe how software dynamic translation can be used
`to implement safe virtual execution.
`Most software dynamic translators are organized as
`virtual machines (see Figure 1a). The virtual machine
`fetches instructions, performs an application-specific
`translation to native instructions, and then arranges for
`the translated instructions to be executed. Safe virtual
`execution systems can be viewed as types of virtual
`machines. On a conceptual level, an SVE virtual
`machine prevents untrusted binaries from directly
`manipulating system resources. The difference between
`SVE systems is in how this virtual machine is imple-
`mented. For instance, in the Java Virtual Machine an
`interpreter is used to isolate Java bytecode programs
`from underlying system resources [16]. Systems such
`as SASI [9] and SFI [23] merge the application program
`with the SVE virtual machine, using binary rewriting at
`load time; the virtual machine is in the form of instruc-
`tions that check certain sequences of instructions before
`they are allowed to execute. Systems such as Janus [13]
`and Interposition Agents [14] use special operating sys-
`tem facilities to virtualize the execution of a very spe-
`cific aspect of execution, specifically, system calls.
`In this paper we propose the use of software
`dynamic translation as the basis for implementing safe
`virtual execution systems. Implementing an SVE appli-
`cation in a software dynamic translator is a simple mat-
`ter of overriding the translator’s default behavior. For
`example, an SDT implementation of a software fault
`isolator would
`translate
`load
`instructions
`into a
`sequence of instructions that performs an address check
`before the load executes.
`In order to illustrate our approach in brief, consider
`the task of preventing stack-smashing attacks using
`SDT. Stack-smashing attacks take advantage of unsafe
`buffer manipulation functions (e.g., strcpy from the C
`standard library) to copy, and subsequently execute,
`malicious code from the application stack. The mali-
`cious code is executed with the privileges of the user
`running the program, and in many cases can lead to
`serious security compromises on affected systems
`[4,15].
`A simple way to prevent stack-smashing attacks is to
`make the application stack non-executable. In the
`abscence of operating system support for non-execut-
`able stacks, it is a trivial matter to prevent execution of
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`000002
`
`

`
`SDT Virtual Machine
`
`Application
`
`Context
`Capture
`
`New
`PC
`
`Cached?
`
`Yes
`
`Context
`Switch
`
`Finished?
`
`Yes
`
`Strata Virtual
`
`Machine
`
`Context Management
`
`Linker
`
`Memory Management
`
`Strata Virtual CPU
`
`Cache Management
`Target Interface
`Target Specific Functions
`
`New
`Fragment
`
`Fetch
`
`Decode
`
`Translate
`Next PC
`
`No
`
`Host CPU (Executing Translated Code from Cache)
`
`(a)
`
`Figure 1: Strata Architecture
`
`Host CPU
`
`(b)
`
`code on the stack by using SDT. This task is accom-
`plished by replacing the software dynamic translator’s
`default fetch function with a custom fetch that prevents
`execution of stack resident code.
`The custom fetch function
`
`custom_fetch (Address PC) {
`if (is_on_stack(PC)) {
`fail("Cannot execute code on the
`stack");
`} else {
`return default_fetch(PC);
`
`}
`
`}
`checks the PC against the stack boundaries and termi-
`nates program execution if the instruction being fetched
`is on the stack. If the instruction being fetched is not on
`the stack, it is alright to execute the instruction, and
`consequently the fetch is completed by calling the
`default fetch function.
`
`3. Strata
`
`To facilitate SDT research and the development of
`innovative SDT applications, we have constructed a
`portable, extensible SDT infrastructure called Strata. As
`shown in Figure 1a, Strata is organized as a virtual
`machine. The Strata VM mediates application execu-
`tion by examining and translating instructions before
`they execute on the host CPU. Translated instructions
`are held in a Strata-managed cache. The Strata VM is
`entered by capturing and saving the application context
`(e.g., PC, condition codes, registers, etc.). Following
`context capture, the VM processes the next application
`instruction. If a translation for this instruction has been
`cached, a context switch restores the application context
`
`and begins executing cached translated instructions on
`the host CPU.
`If there is no cached translation for the next applica-
`tion instruction, the Strata VM allocates storage for a
`new fragment of translated instructions. A fragment is a
`sequence of code in which branches may appear only at
`the end. The Strata VM then populates the fragment by
`fetching, decoding, and translating application instruc-
`tions one-by-one until an end-of-fragment condition is
`met. The end-of-fragment condition is dependent on the
`particular software dynamic translator being imple-
`mented. For many translators, the end-of-fragment con-
`dition is met when an application branch instruction is
`encountered. Other translators may form fragments that
`emulate only a single application instruction. In any
`case, when the end-of-fragment condition is met, a con-
`text switch restores the application context and the
`newly translated fragment is executed.
`As the application executes under Strata control,
`more and more of the application’s working set of
`instructions materialize in the fragment cache. This,
`along with certain other techniques—e.g., partial inlin-
`ing of functions and indirect branch elimination—that
`reduce the number and cost of context switches, permits
`Strata to execute applications with little or no measur-
`able overhead [19].
`Figure 1b shows the components of the Strata VM.
`Strata was designed with extensibility and portability in
`mind. Extensibility allows Strata to be used for a vari-
`ety of different purposes; researchers can use Strata to
`build dynamic optimizers, dynamic binary translators,
`fast architecture emulators, as well as safe virtual exe-
`cution systems. Portability allows Strata to be moved to
`new machines easily. To date, Strata has been ported to
`SPARC/Solaris, x86/Linux, and MIPS/IRIX. More
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`000003
`
`

`
`importantly, Strata’s portability means that software
`implemented using Strata’s extensibility features is
`readily available on a wide range of target architectures
`and operating systems.
`To achieve these goals, the Strata virtual machine is
`implemented as a set of target-independent common
`services, a set of target-specific functions, and a recon-
`figurable target interface through which the machine-
`independent and machine-dependent components com-
`municate (see Figure 1b). Implementing a new software
`dynamic translator often requires only a small amount
`of coding and a simple reconfiguration of the target
`interface. Even when the implementation is more
`involved, e.g., when retargeting the VM to a new plat-
`form, the programmer is only obligated to implement
`the target-specific functions required by the target inter-
`face; common services should never have to be reim-
`plemented or modified.
`Strata consists of 5000 lines of C code, roughly half
`of which is target-specific. In Figure 1b, shaded boxes
`show the Strata common services which comprise the
`remaining half of the Strata source. The Strata common
`services are target-independent and implement func-
`tions that may be useful in a variety of Strata-based
`dynamic translators. Features such as context manage-
`ment, memory management, and the Strata virtual CPU
`will most likely be required by any Strata-based
`dynamic translator. The cache manager and the linker
`can be used to improve the performance of Strata-based
`dynamic translators, and are detailed in other work
`[19].
`
`4. Strata and Safe Virtual Execution
`
`In Section 2 we sketched one example that demon-
`strates the process one can use to write a Strata-based
`safe virtual execution system, specifically, a stack-
`smashing inhibitor. In this section we use Strata to
`implement a system call interposition layer. This inter-
`position layer, like all Strata-based applications, is user-
`level software and requires no kernel modifications.
`Our Strata-based system call interposition layer also
`obviates the need for special operating system services
`for interception or redirection of system calls. As a con-
`sequence, our system call interposition layer is more
`flexible and portable than many existing systems.
`SDT’s ability to control and dynamically modify a
`running program provides an ideal mechanism for
`implementing a system call interposition layer. As the
`untrusted binary is virtualized and executed by Strata,
`code is dynamically inserted to intercept system calls
`and potentially redirect those calls to user supplied
`functions. In general though, this process does not need
`to be limited to system calls; all access to host CPU and
`
`operating system resources are explicitly controlled by
`Strata (see Figure 2).
`
`Untrusted
`Binary
`
`Host CPU
`
`Strata SVE Application
`
`Host CPU and OS
`Services
`
`Figure 2: Strata
`
`In this paper, we will use terms and phrases that are
`typically employed when discussing the Unix operating
`system (e.g., “becoming root”, “exec’ing a shell”, “per-
`forming a setuid(0)”, etc.). The actions indicated by
`these terms have analogs in other major operating sys-
`tems (e.g., Windows NT, Windows 2000, Window XP,
`VxWorks, and PSOSystem) and the approaches we
`describe would apply equally well to applications run-
`ning on these systems.
`A simple, but realistic example illustrates our
`approach. Suppose a user wishes to enforce a policy
`that prohibits untrusted applications from reading a file
`that the user normally has permission to read. Let’s call
`this file /etc/passwd (registry.dat, SAM, or sys-
`tem might be equally good choices). Now assume that
`the user receives an untrusted binary called funny and
`wishes to run it. The user invokes funny using the
`Strata loader. The Strata loader locates the entry point
`of the application and inserts a call to the Strata startup
`routine. When the loader begins the execution of the
`application, the call to the Strata startup routine leads to
`the dynamic loading and invocation of Strata.
`As Strata processes funny’s text segment and builds
`fragments to be executed, it locates open system calls
`and replaces them with code that invokes the execution
`steering policy code. When the fragment code is exe-
`cuted, all open system calls are diverted to the policy
`code. It is the policy code’s job to examine the argu-
`ments to the original open system call. If the untrusted
`application is attempting to open /etc/passwd, an
`error message is issued and the execution of the appli-
`cation is terminated. If the file being opened is not /
`etc/passwd, the security policy code performs the
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`000004
`
`

`
`open request, returns the result, and execution contin-
`ues normally (albeit under the control of Strata).
`
`20.
`21. int main(int argc, char *argv[]) {
`22.
`FILE *f;
`
`4.1. A System Call Interposition API
`
`We support system call interposition through an API
`implemented by overriding Strata’s base functionality.
`The API is a simple, efficient mechanism that allows
`the user to specify which operating system calls are to
`be monitored and the code to execute every time the
`operating system call is invoked. Strata’s execution
`steering API consists of four functions. They are:
`void init_syscall();
`watch_syscall(unsigned num, void *callback);
`void strata_policy_begin(unsigned num);
`void strata_policy_end(unsigned num);
`The first function is called on the initial entry to Strata.
`The implementation of this function will contain calls
`to the second API function watch_syscall(). Func-
`tion watch_syscall() specifies an operating system
`call to watch (i.e., num) and the redirected system call to
`execute when that OS call is invoked (i.e., callback).
`The signature of callback should match the signature
`of the operating system call being watched. The final
`two API functions are used to bracket redirected system
`call code. The need for the bracketing functions will be
`explained shortly when we describe how Strata dynam-
`ically injects code into the application.
`
`To illustrate the implementation of Strata’s security
`API, we show the Strata security policy for preventing
`an untrusted application from reading /etc/passwd.
`Following the style used on hacker websites to demon-
`strate the exploitation of security vulnerabilities, we
`give a small demonstration program that exercises the
`policy. The demonstration code is given in Listing 1.
`1. #include <stdio.h>
`2. #include <string.h>
`3. #include <strata.h>
`4. #include <sys/syscall.h>
`
`5. int myopen (const char *path, int oflag) {
`6.
`char absfilename[1024];
`7.
`int fd;
`
`8.
`
`9.
`10.
`11.
`12.
`13.
`
`14.
`
`strata_policy_begin(SYS_open);
`
`makepath_absolute(absfilename,path,1024);
`if (strcmp(absfilename,"/etc/passwd") == 0) {
`strata_fatal("Naughty, naughty!");
`
`}
`fd = syscall(SYS_open, path, oflag);
`
`strata_policy_end(SYS_open);
`
`return fd;
`
`15.
`16. }
`17. void init_syscall() {
`18.
`(*TI.watch_syscall)(SYS_open, myopen);
`19. }
`Listing 1: Code for preventing a file from being
`opened.
`
`23.
`
`24.
`25.
`26.
`
`27.
`
`if (argc < 2 || (f = fopen(argv[1],"r")) ==
`NULL) {
`fprintf(stderr,"Can't open file.\n");
`exit(1);
`
`}
`
`printf("File %s opened.\n",argv[1]);
`
`return 0;
`
`28.
`29. }
`Listing 1: Code for preventing a file from being
`opened.
`
`Before explaining how Strata injects this code into
`an untrusted binary, we review the code at a high level.
`Function init_syscall() at lines 17–19 specifies
`that SYS_open calls should be monitored and that when
`a SYS_open call is to be executed by the application,
`control is to be transferred to the policy routine myo-
`pen().
`Function myopen() (lines 5–16) implements the
`redirected system call. As mentioned previously, invo-
`cations
`of
`strata_policy_begin()
`and
`strata_policy_end() are used to bracket the redi-
`rected system call code and their purpose will be
`explained shortly.
`In function myopen(), the path to be opened is con-
`verted to an absolute pathname by calling the utility
`function makepath_absolute(). The path returned is
`compared to the string /etc/passwd and if it matches,
`an error message is issued and execution is terminated.
`If the file to be opened is not /etc/passwd, then the
`policy code performs the SYS_open system call and
`returns the result to the client application as if the actual
`system call was executed.
`When an untrusted binary is to be executed, the
`Strata loader modifies the application binary so that ini-
`tial control is transferred to Strata’s initialization rou-
`tines. This routine dynamically loads and executes the
`init_syscall() function that sets up a table of sys-
`tem calls to watch and their corresponding callback
`functions.
`After initialization is complete, Strata begins build-
`ing the initial application fragment by fetching, decod-
`ing and translating instructions from the application
`text into the fragment cache. The system call interposi-
`tion API is implemented by overriding the translate
`function that handles trap or interrupt instructions. For
`the SPARC/Solaris platform, less than 20 lines of code
`are required to implement the new translation function-
`ality.
`Strata examines each operating system call site to
`determine if the OS call is one to be monitored. In most
`cases, Strata can determine at translation time which
`operating system call will be invoked at the call site. If
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`000005
`
`

`
`the OS call is one to be monitored, the code to invoke
`the operating system call is replaced with a call to the
`user-supplied code. If the call is not one to be moni-
`tored, no translation action needs to be taken and the
`operating system call code is copied unchanged to the
`fragment cache.
`In some cases, Strata cannot determine which oper-
`ating system call will be invoked at a given call site.
`This can occur, for instance, with indirect operating
`system calls. In these cases, Strata must generate and
`insert code that, when the fragment is executed, will
`test whether the OS call being invoked is one to be
`monitored. If the call is one to be monitored, the
`inserted code must call the appropriate user-supplied
`policy code; otherwise, the OS call is executed.
`In the case where the OS call to be invoked can be
`determined at fragment creation (translation) time,
`Strata treats redirected code just like application code.
`As a result, calls to redirected system call code can
`often be partially inlined [1, 19], thus improving the
`efficiency of the code. However, partially inlining code
`creates a complication. Consider the myopen() code in
`Listing 1. When this code is inlined, the SYS_open OS
`call will be generated. This OS call should not be
`replaced by a callback, as it is the OS call to execute
`when the policy’s conditions are satisfied. To avoid
`infinite recursion, redirected system calls are bracketed
`using
`the
`interposition
`API
`calls
`strata_policy_begin()
`and
`strata_policy_end(). Strata uses
`these “code
`markers” to suspend the translation of operating system
`calls. Thus, we are assuming that the writer of policy
`code is not malicious.
`One further complication exists. A malicious user
`with knowledge of how Strata operates may try to cir-
`cumvent
`Strata
`by
`using
`calls
`to
`strata_policy_begin()
`and
`strata_policy_end() to bracket application code
`that attempts to violate the security policy. To prevent
`this
`avenue
`of
`attack,
`Strata
`permits
`strata_policy_begin()
`and
`strata_policy_end() to execute only from within
`security policy code.
`
`4.2. System Call Interposition at Work
`
`A common security exploit is to arrange to exec a
`shell while in root or super-user mode. This is most
`commonly done by using a buffer overrun attack that
`corrupts the run-time stack. In an earlier paper we
`described how such an attack can be stopped using
`Strata’s target-dependent interfaces [13]. Other types of
`attacks are possible [16]. However, they all rely on
`
`exec’ing a program (usually a shell) while in root or
`super-user mode. Using Strata’s security API, it is very
`simple to write a policy that prohibits exec’ing a pro-
`gram when in super-user mode, yet allows exec’s when
`not in super-user mode. Listing 2 contains the demon-
`stration program.
`1. #include <stdio.h>
`2. #include <string.h>
`3. #include <unistd.h>
`4. #include <strata.h>
`5. #include <sys/syscall.h>
`
`6. static int curuid = -1;
`7. int mysetuid (int uid) {
`8.
`strata_policy_begin(SYS_setuid);
`9.
`curuid = syscall(SYS_setuid, uid);
`10.
`strata_policy_end(SYS_setuid);
`11.
`return curuid;
`12. }
`
`13. int myexecve (const char *path, char *const
`argv[],
`14. char *const envp[]) {
`15.
`int retval;
`16.
`strata_syscallback_begin(SYS_execve);
`17.
`if (curuid == 0)
`18.
`strata_fatal(“Naughty, naughty”);
`19.
`retval = syscall(SYS_execve, path, argv,
`envp);
`strata_syscallback_end(SYS_execve);
`return retval;
`
`20.
`21.
`22. }
`
`23. void init_syscall() {
`24.
`(*TI.watch_syscall)(SYS_execve, myexecve);
`25.
`(*TI.watch_syscall)(SYS_setuid, mysetuid);
`26. }
`
`27. int main (int argc, char *argv[]) {
`28.
`FILE *f;
`29.
`char *args[2] = {“/bin/sh”,0};
`30.
`setuid(0);
`31.
`execv(“/bin/sh”, args);
`32.
`return 0;
`33. }
`Listing 2: Code to prevent exec’s while root.
`
`Two system calls—setuid and execve—must be
`monitored to implement this security policy. We must
`monitor setuid to keep track of the uid of the running
`application. This information is stored in the state vari-
`able curuid. In function myexecve(), exec’s are dis-
`allowd if the program is running in root mode (i.e., the
`uid of the process is 0); otherwise they are allowed.
`This example demonstrates a number of advantages
`of our system call interposition API. It is easy to see
`that the code required to implement the security policy
`using the system call interposition API is simple and
`straightforward. We do not rely on special operating
`system services, compilers, or libraries. The user does
`not have to learn a new domain specific language in
`order to write security policies. Furthermore, the use of
`C as the security policy language does not imply that
`untrusted binaries must be written in C. The security
`policy is compiled to binary code that is processed by
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`000006
`
`

`
`Strata along with the untrusted binary. The security pol-
`icy code is portable to most systems with a native C
`compiler and POSIX compliant system calls. Moreover,
`static source code analysis cannot effectively prevent
`execs while root due to a number of inhibiting factors—
`unavailability of library source code, dynamically gen-
`erated code, self-modifying code, and the inability of
`static analyses to precisely predict dynamic state.
`The third security policy presented implements a
`policy that controls the rate at which an application uses
`a resource. In this example, we will limit the rate at
`which an application can transmit packets over a
`socket. This type of policy could be useful for thwarting
`denial of service attacks where zombie processes
`attempt to flood a server with packets. Listing 3 gives
`the code for the demonstration application.
`1. #include <stdio.h>
`2. #include <stdlib.h>
`3. #include <sys/types.h>
`4. #include <sys/socket.h>
`5. #include <netinet/in.h>
`6. #include <netdb.h>
`7. #include <time.h>
`8. #include <string.h>
`9. #include <strata.h>
`10. #include <sys/syscall.h>
`
`11. #define RATE 10000
`12. #define TOPRATE 10000000
`13. #define DISCARD_PORT 9999
`14. #define PAYLOAD_SIZE 1024
`
`15. void xmit (const char *host, int nbytes);
`
`16. static int socket_fd = -1;
`
`17. /* Compute the delay necessary to maintain */
`18. /* the desired rate */
`19. int limiting_delay (double rate, time_t tbeg,
`20. time_t tend, int last_len, int len);
`
`21. /* Callback for the so_socket call */
`22. int my_so_socket (int a,int b,int c,char *d,int e)
`{
`
`23.
`
`24.
`25.
`26.
`
`27.
`28.
`29. }
`
`strata_policy_begin(SYS_so_socket);
`
`/* Make the system call and */
`/* record the file descriptor */
`socket_fd = syscall(SYS_so_socket,a,b,c,d,e);
`
`strata_policy_end(SYS_so_socket);
`return socket_fd;
`
`30. /* Callback for the write system call */
`31. int my_send (int s, const void *msg, size_t len,
`32. int flags) {
`33.
`int result;
`34.
`time_t now;
`35.
`static int last_len = 0;
`36.
`static time_t last_time = 0;
`
`37.
`
`38.
`39.
`40.
`41.
`42.
`
`strata_policy_begin(SYS_send);
`
`/* Only look at writes to socket_fd */
`if (s == socket_fd) {
`now = time(NULL);
`sleep(limiting_delay(RATE,last_time, now
`len,last_len));
`
`Listing 3: Code to limit the rate of
`transmission over a socket.
`
`43.
`44.
`45.
`46.
`
`47.
`48.
`49. }
`
`last_len = len;
`last_time = now;
`
`}
`result = syscall(SYS_send,s,msg,len,flags);
`
`strata_policy_end(SYS_send);
`return result;
`
`50. void init_syscall() {
`51.
`
`(*TI.watch_syscall)(SYS_so_socket,my_so_socket);
`(*TI.watch_syscall)(SYS_send,my_send);
`
`52.
`53. }
`
`54. main(int argc, char *argv[]) {
`
`55.
`56.
`57.
`58.
`59.
`60. }
`
`if (argc == 3)
`xmit(argv[1],atoi(argv[2]));
`else
`fprintf(stderr,
`”Usage: %s host nbytes\n”,argv[0]);
`
`61. /* Transmit nbytes to discard port (9) on host */
`62. void xmit (const char *host, int nbytes) {
`63.
`int sd, bytes_sent;
`64.
`struct sockaddr_in sin;
`65.
`struct sockaddr_in pin;
`66.
`struct hostent *hp;
`67.
`char *payload[PAYLOAD_SIZE];
`68.
`time_t begin, elapsed;
`69.
`double rate;
`
`70.
`
`/* go find out about the desired host machine
`
`*/
`
`*/
`
`if ((hp = gethostbyname(host)) == 0) {
`perror(“gethostbyname”);
`exit(1);
`
`}
`
`/* fill in the socket structure with host info
`
`memset(&pin, 0, sizeof(pin));
`pin.sin_family = AF_INET;
`pin.sin_addr.s_addr = ((struct in_addr *)
`(hp->h_addr))->s_addr;
`pin.sin_port = htons(DISCARD_PORT);
`
`/* grab an Internet domain socket */
`if ((sd = socket(AF_INET,SOCK_STREAM, 0)) == -
`1) {
`
`perror(“socket”);
`exit(1);
`}
`
`/* connect to PORT on HOST */
`if (connect(sd, (struct sockaddr *) &pin,
`sizeof(pin)) == -1) {
`perror(“connect”);
`exit(1);
`
`}
`
`begin = time(0);
`bytes_sent = 0;
`while(bytes_sent < nbytes) {
`/* send a message to the server PORT */
`/* on machine HOST */
`if (send(sd,payload,sizeof(payload),0) == -
`
`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.
`
`1) {
`
`perror(“send”);
`exit(1);
`
`98.
`99.
`100.
`}
`101.
`bytes_sent += sizeof(payload);
`102.
`printf(“.”);
`103.
`fflush(stdout);
`Listing 3: (Continued)Code to limit the rate of
`transmission over a socket.
`
`Proceedings of the 18th Annual Computer Security Applications Conference (ACSAC(cid:146)02)
`1063-9527/02 $17.00 ' 2002 IEEE
`
`000007
`
`

`
`104.
`105.
`106.
`
`}
`elapsed = time(0) - begin;
`rate = bytes_sent / elapsed;
`
`printf(“\nRate = %8.3f bytes per
`107.
`second.\n”,rate);
`
`close(sd);
`
`108.
`109.}
`Listing 3: (Continued)Code to limit the rate of
`transmission over a socket.
`
`To implement this policy, SYS_so_socket and
`SYS_send system calls must be monito

This document is available on Docket Alarm but you must sign up to view it.


Or .

Accessing this document will incur an additional charge of $.

After purchase, you can access this document again without charge.

Accept $ Charge
throbber

Still Working On It

This document is taking longer than usual to download. This can happen if we need to contact the court directly to obtain the document and their servers are running slowly.

Give it another minute or two to complete, and then try the refresh button.

throbber

A few More Minutes ... Still Working

It can take up to 5 minutes for us to download a document if the court servers are running slowly.

Thank you for your continued patience.

This document could not be displayed.

We could not find this document within its docket. Please go back to the docket page and check the link. If that does not work, go back to the docket and refresh it to pull the newest information.

Your account does not support viewing this document.

You need a Paid Account to view this document. Click here to change your account type.

Your account does not support viewing this document.

Set your membership status to view this document.

With a Docket Alarm membership, you'll get a whole lot more, including:

  • Up-to-date information for this case.
  • Email alerts whenever there is an update.
  • Full text search for other cases.
  • Get email alerts whenever a new case matches your search.

Become a Member

One Moment Please

The filing “” is large (MB) and is being downloaded.

Please refresh this page in a few minutes to see if the filing has been downloaded. The filing will also be emailed to you when the download completes.

Your document is on its way!

If you do not receive the document in five minutes, contact support at support@docketalarm.com.

Sealed Document

We are unable to display this document, it may be under a court ordered seal.

If you have proper credentials to access the file, you may proceed directly to the court's system using your government issued username and password.


Access Government Site

We are redirecting you
to a mobile optimized page.





Document Unreadable or Corrupt

Refresh this Document
Go to the Docket

We are unable to display this document.

Refresh this Document
Go to the Docket