1. Suppose you want to build a sandbox in order to protect your system from malicious user-level access operations. What are the main operations you can think of? List at least 5. The process of sandboxing is used in order to safely run untrusted programs. If you have a multi-threaded system and on each thread you want to run a given program, how would you design your sandbox in order to prevent untrusted code to get access to your system? 2. How would you use CFI and/or SFI to build a system that ensures that an untrusted module returns control to trusted module within a certain amount of time? 3. In proof-carrying code, once the user has verified the proof, he may run the untrusted code without any run-time checks. In model-carrying code, the user still needs to run the untrusted code inside a sandbox, even after verifying the model. Why? 4. In class, there was some debagte as to whether client puzzles really enable legitimate users to reach a server under a TLS DoS attack. What is your conclusion, and why? 5. Describe a timing attack against the following function. Your goal is to recover the real_passwd. You can call the function repeatedly, specifying the user and passwd arguments, and you can observe its return value and execution time. int check_password(char *user, char *passwd) { char *real_passwd = lookup_real_passwd(user); int i; for (i = 0; real_passwd[i] && passwd[i]; i++) if (passwd[i] != real_passwd[i]) return -1; return 0; }