Operating Systems 2019W Lecture 21

From Soma-notes
Jump to navigation Jump to search

Video

The video from the lecture given on April 1, 2019 is now available.

Notes

Lecture 21
----------

A4 Quiz coming out Sunday night, substitue for A4 submission
 - you can still submit A4, but it won't be graded unless you ask for it to because you don't think your answers to the multiple choice questions matches your understanding of the material.  Likely the grading will be in an in-person meeting.

Fine-grained access control
---------------------------
(and alternative ways of doing access control)

When you run with privileges, drop them as soon as you can

If you're in a setuid root context, you can drop privileges by
running seteuid(), change it to process's real UID

assume uid=1000, euid=0
if you run seteuid(1000), then uid=1000, euid=1000

but

you can still run seteuid(0) after doing this!
 - so only worth doing if you know attacker can't take control
   of code (e.g., no code injection vulnerabilities)

You can make the euid change permanent if you then do an execve

But still, this is very coarse - you either can do everything or you can
do almost nothing


Ideally you'd like to split up the powers of root into subsets
 - so you'd only keep the privileges you need

Well, what can root do?
 - access any file
 - mount/unmount filesystems
 - allocate low-numbered ports (<1024)
    http  80
    https 443
    ssh   22
    smtp  25
    auth smtp 465
 - configure networks
 - access block devices
 - set the time
   ...

Linux kernel capabilities allow you to control whether a process can or
cannot do different kinds of privileged operations
 - normally a process starts as roots and then drops capabilities it doesn't need
 - but you can be "setuid" for capabilities using extended attributes
   (on some filesystems)


Why dow we want fine-grained access control?  Is it really better?
 - well, it limits damage when an attacker gets control
 - but it makes the jobs of developers, users, and admins harder

SELinux allows for very fine-grained access control (and more)
 - but mostly people want to disable it, because they don't understand it

Android permissions
 - fine grained in a mostly useless way

Nowadays we do more sandboxing rather than fine-grained access control
 - default deny, limited flexibility rather than arbitrary flexibility

Discretionary versus mandatory access control (DAC vs MAC)
 - discretionary: can change at runtime
 - mandatory: *cannot* change at runtime, must reboot into special mode

MAC limits the power of root
 - root can't change the policies at runtime
 - useful at times but can be very very painful to use, thus
   most common question about systems like SELinux is how to disable it

Sandboxing
 - not a technology, more a hope or goal

a sandbox is an environment for running programs in which the program stays isolated from the outside world (except for "safe" connections)
 - so it is safe to run untrusted code inside of a sandbox

Since more and more code isn't trusted, sandoxes show up everywhere

A process itself is a kind of sandbox - but a very very leaky one

processes have lots of shared state
 - filesystem
 - process list/signals
 - IPC of all kinds

How do you "sandbox" a program?
 A add restrictions to processes
 B add restrictions to the OS
 C implement a "virtual machine" of some kind, run it in there
   (using a language that the native machine can't run directly)
   
A is containers <-- hacks on the OS
B is hardware virtual machines (VMWare, kvm, etc) <-- isolate the OS
C is Java and JavaScript

C can provide the strongest guarantees but has considerable complexity
B is very heavyweight (new kernel per isolated instance)
A is fashionable and not so good

Containers allow a kernel to run multiple, separate userlands
 - potentially each with its own set of users including root and
   its own filesystem structure

WebAssembly

First, there was the JavaScript sandbox
 - limited capabilities (no background processing, no filesystem access,
   very limited network access)
 - then came AJAX  (or just AJ now), so JavaScript became more powerful
 - got full apps in JavaScript, so runtimes had to get faster
 - V8 was so good, was moved to the server (node.js)

Javascript is everywhere, is fast, can do sandboxing, but not everyone likes it

Emscripten came along - allow you to compile arbitrary languages to Javascript

Mozilla came up with asm.js - subset of JS as a target for Emscripten

Google came up with NaCl - native client, subset of x86 for browsers

asm.js + NaCL => WebAssembly