Available from March 30, 2022 until September 30, 2022

Course: CS4280 Edition: 2021-2022

About the Course

Security vulnerabilities often arise due to programming errors in the source code of an application. Recent programming errors with severe security implications include Heartbleed (buffer over-read), Shellshock (code injection), and goto-fail (ill-formated code). Rather than hunt for individual vulnerabilities in programs, a more structural approach to improve security is to improve the programming language. This is the goal of language-based security: to rule out whole classes of potential security vulnerabilities in one go.

This course studies various security properties and program analysis techniques for enforcing these properties at the level of the programming language to improve software security. In particular, we will study the following properties:

  • Memory safety: prevent buffer overflows and overreads
  • Type safety: prevent undefined behaviour
  • Information flow control: prevent data leaks and code injection attacks

We will study techniques to address these problems at the language level through dynamic analysis, static analysis, and language design. To facilitate a precise study and comparison, we will define the above techniques formally in class. To facilitate student experimentation and exploration of trade-offs, students will implement the above techniques in homework assignments.

Latest Announcements

Error in last assignment for Week 2

Dear all,

I am sorry to say that there is a mistake in the description of the last assignment for Week 2: the question suggests to use a set of locations to keep track of which locations in the heap have been freed, but this is not actually sufficient to ensure memory safety. In particular, this does not allow you to pass the following spec test:

  it should "when accessing freed memory with assign cause the termination of the program" in {
    val compiler = new ArrayCompiler()
    val prog: Program = program(
      NewArrayStmt("x", Lit(Num(3))),
      DeleteArrayStmt("x"),
      NewArrayStmt("y", Lit(Num(3))),
      AssignArrayStmt("x", Lit(Num(1)), Lit(Num(42))),
      ReadArrayStmt("res", "y", Lit(Num(1)))
    )

    val (_, _) = compiler.compile(prog)
    an [RuntimeException] should be thrownBy SafeArrayRuntime.run(compiler,prog)
  }

The problem here is that the memory of the freed array x is reused for the array y, which means that the variable x then no longer points to freed memory but instead becomes an alias to y. This can be fixed by setting the pointer x to 0 when it is freed; however that does not respect aliases of x. Hence there is no way (that I know of) to fix both problems at once by making use of just a set of freed locations, you need to keep track of more data.

Since the question was very misleading, I will change the grading scheme for this question so that you get a full grade with 3/4 spec tests. However, I still invite you to think about how to fix both problems (reuse of memory and aliasing) in a single solution.

at Mon, May 9, 2022 18:33:15

View all announcements