···4455#mol-chapter("Introduction")
6677+Twizzler is a research operating system focused on new programming paradigms
88+possible via NVM (Non-Volatile Memory)@twizzler. It gives programmers direct
99+access to underlying data by removing the kernel from the datapath, which
1010+results in huge performance gains, while using NVM to make that data persistent
1111+across power cycles. However this reimagining of an operating system leaves many
1212+questions for how security is undertaken.
1313+714// talk about the standard unix abstractions
88-In mainstream operating systems, an
99-omnicient and all-powerful kernel enforces security policy at runtime.
1010-// what am i trying to say here.
1111-It acts as the bodyguard, holding all I/O and data hostage unless the
1212-requesting party has the authorization to access some resource. This tight
1313-coupling of security policy and access mechanisms works well since any access
1414-must be done through the kernel, so why not perform security checks
1515-alongside accesses?
16151616+In mainstream operating systems, an omnicient and all-powerful kernel enforces
1717+security policy at runtime. It acts as the bodyguard, holding all I/O and data
1818+hostage unless the requesting party has the authorization to access some
1919+resource. This tight coupling of security policy and access mechanisms works
2020+well since any access must be done through the kernel, so why not perform
2121+security checks alongside accesses? This coupling gets challenged as soon as one
2222+tries to decouple access mechanisms from the kernel, as we see in Twizzler.
17231818-This coupling gets challenged as soon as one tries to decouple access mechanisms
1919-from the kernel, as we see in Twizzler.
2020-Twizzler is a research operating system focused on new programming paradigms
2424+== Data-Centric Operating Systems
21252222-However,
2323-the enforcement of security policy starts getting complicated when we try
2424-to separate the access mechanisms from the kernel.
2626+Twizzler defines itself as a data-centric operating system, meaning
2727+it is built upon two key principles @twizzler:
25282626-// TODO: maybe give a brief introduction to twizzler?
2929+ + Providing direct, kernel-free, access to data.
27303131+ + Pointers are tied to the data they represent.
28322929-3030-3131-//TODO: explain why this happens?
3232-== Data-Centric Operating Systems
3333-3434-3535-//TODO: daniel feedback
3633// I would add a paragraph motivating the data-centric approach
3734// like why would i want the kernel out of the way?
3535+These principiles emerge from treating persistent data as a first class citizen.
3636+Since NVM removes the necessity of the kernel to serialize and deserialize
3737+data from storage devices and memory, it only makes sense for it to be removed
3838+from the access path. If applications want to utilize memory as truly
3939+persisent, they require a persistent way to access that memory, leading to a
4040+notion of persistent pointers.
38413939-Data-centric operating systems are defined by two principles @twizzler:
4040-4141- + They provide direct, kernel-free, access to data.
4242-4343- + They have a notion of pointers that are tied to the data they represent.
4242+// this talks about why this kind of access rights is a secuirty issue.
4343+With the decoupling of the kernel and access methods, we have to rethink
4444+how security policy for objects is enforced. While the kernel doesn't manage
4545+the connection between applications and data, its still responsible for
4646+creating that connection. This provides one area of enforcement, where
4747+the kernel can check access rights before granting the application access
4848+to the object, and then stay out of the way after. Twizzler programs
4949+the MMU, per thread, to grant access rights, allowing for a point of enforcement; more
5050+detail can be found in section 4.2. Now we have to build the underlying system that
5151+must be enforced.
44524545-By defenition, they require the removal of the kernel from the access path.
4646-This is desirable since it would remove the kernel overhead for data accesses,
4747-resulting in pure performance gains for heavy I/O applications.
4848-4949-// then this paragrapch can focus on why removing the kernel
5050-// from the access path is a security probjem
5151-// maybe worth discussing how the access is tied to the mmu as well.
5252-//
5353-Mainstream operating systems fail to classify as data-centric operating
5454-systems, as they rely on the kernel for all data access, and use virtualized
5555-pointers per process to represent underlying data. The benefit of this "class"
5656-of operating systems comes from the low overhead for data manipulation, due to the lack
5757-of kernel involvement. However, the mainstream security model fails to operate
5858-here as, by definition, the kernel cannot be in front of access to data. So,
5959-something new must be investigated.
60536154== Capability Based Security Systems
6262-6363-6464-6565-Capability-based security systems have a rich history in research, and offer
6666-an alternative approach to security, in opposition to the Access Control Lists of prevalent OS's @linux_security.
6767-Boiled down, a capability is a token of authority, holding at minimum some
6868-permissions and a unique identifier to which "thing" those permissions apply
6969-to @cap-book. This simple approach of having a "token", allows for a separation
7070-of the kernel's involvement in the creation and management of security policy.
7171-In a well-designed system, as we see in @twizsec and described later, this allows
7272-users to completely create and manage security policy while the kernel is left to enforce
7373-it.
5555+Capability-based security systems have a rich history in research, and offer an
5656+alternative approach to security, in opposition to the Access Control Lists of
5757+prevalent OS's @linux_security. Boiled down, a capability is a token of
5858+authority, holding at minimum some permissions and a unique identifier to which
5959+"thing" those permissions apply to @cap-book. There are some
6060+additions we make to this basic defenition in order to apply capabilities in Twizzler,
6161+most notablity the addition of a cryptograhic signature. Since capabilities
6262+are stored on-disk, the kernel needs a way to ensure the policy its enforcing
6363+is coming from a trusted entity. If this weren't the case, it would be trivial
6464+for a bad actor to manipulate capabilties, and the kernel would be
6565+none-the-wiser as it goes to enforce it. Thus we have this construciton of an
6666+cryptographically signed capability, in which the kernel only enforces after it
6767+verifies the signature to be authentic.
74687575-//TODO: how? (via mmu + pagetable mappings programmed via the kernel) (which is still kernel-free for most data accesses)
7669This paradigm permits kernel-free access of data, while also guaranteeing
7777-security.
7878-7979-//TODO: maybe add a bit about "unforgeable" tokens, cryptographic operations, why they are needed
8080-8181-8282-8383-7070+security by enforcing it right before the point of access through the MMU.
84718572== Our Contributions
8686-8773In this thesis, I detail the fundamentals of security in the Twizzler
8874operating system, and discuss how I implement and refine some of the high
8975level ideas described in Twizzler @twizzler and an early draft of a Twizzler security
9076paper @twizsec. Additionally, we evaluate these systems inside kernel and user space, using
9177Alice/Bob scenarios and microbenchmarks.
9292-Code can be found in this
7878+7979+A list of merged PR's to Twizzler:
8080++ #link("https://github.com/twizzler-operating-system/twizzler/pull/267")[Old Security Port to Main]
8181+ - Implementation of SigningKey and VerifyingKey mentioned in seciton 2.
8282+ - Implementation of Capabilities mentioned in section 3.
8383+ - Support to compile twizzler-security for the kernel and userspace
8484+8585++ #link("https://github.com/twizzler-operating-system/twizzler/pull/273")[Adds creation of SigningKey / Verifying object pairs.]
8686+ - Implementation of the keypair objects containing singing and verifying keys, mentioned in section 2.
8787+ - Userspace tests for keypair creation and usage of signing / verifying keys.
8888+8989++ #link("https://github.com/twizzler-operating-system/twizzler/pull/275")[Security Contexts and Benchmarking]
9090+ - Implements Security Contexts for kernel and userspace, as described in section 4.
9191+ - A benchmarking framework for the kernel.
9292+ - Benchmarks for cryptographic operations inside the kernel, and can be viewed in seciton 5.
9393+ - Userspace benchmarks of security policy creation, as shown in section 5.
9494+9595+More details can be found in this
9396#link("https://github.com/twizzler-operating-system/twizzler/issues/268")[Github
9497tracking issue].
9595-9696-//TODO: list pr's with a short summary of what each one accomplishes?
97989899#load-bib(read("refs.bib"))
+22-24
2-keypair.typ
···44#mol-chapter("Key Pairs")
5566// what are keypair objects ?
77-// TODO: fix this fuckin sentence
88-Key pairs in Twizzler are representation of the cryptographic signing
99-schemes used to create a signed capability, as discussed in 3.1.
77+Key-Pairs in Twizzler are two objects, one containing a signing key, and the
88+other having a verifying key. The signing key is used to form the signature when
99+creating a capability, while the verifying key is used by the kernel to validate
1010+a capability before granting access rights. More detail can be found about
1111+capability signatures in section 3.1.
101211131212-We design
1313-the keypair objects to be agnostic towards the underlying scheme to allow for
1414-multiple schemes, as described in @twizzler. This also helps with backwards
1515-compatibilty when adding new, more secure schemes, in the future. The keys
1616-are stored inside of objects, allowing for persistent or volatile
1717-storage depending on object specification, and allows for keys themselves to
1818-be treated as any other object and have security policy applied to them. This
1919-allows for powerful primitives and rich expressiveness for describing secruity
2020-//NOTE: elaborate or point forward to later
2121-policy, while also being intuitive enough to construct basic policy easily.
1414+They keys are represented as follows:
22151616+```rust
1717+struct Key {
1818+ key: [u8; MAX_KEY_SIZE],
1919+ len: u64,
2020+ scheme: SigningScheme,
2121+}
2222+```
2323+Since the underlying data is just a byte array, the keys themselves are
2424+scheme-agnostic, enabling support for multiple cryptograhic schemes, as
2525+described in @twizzler. This also makes backward compatibility trivial when
2626+adding new signing schemes.The keys are stored inside of objects, allowing for
2727+persistent or volatile storage depending on object specification, and allows for
2828+keys themselves to be treated as any other object and have security policy
2929+applied to them.
23302431== Abstraction
2525-2626-The `SigningKey` struct is a fixed length byte array with a length field
2727-and an enum specifying what algorithm that key should be interpreted as.
2832Currently we use the Elliptic Curve Digital Signature Algorithm (ECDSA) @ecdsa
2929-//TODO: why are we talkin about the simplistic data representation without
3030-// actually explaining the representation. maybe having a diagram would be useful?
3133to sign capabilities and verify them, but the simplistic data representation
3234allows for any arbitrary algorithm to be used as long as the key can be
3335represented as bytes.
34363535-Additionally this specification allows for backward compatibility, allowing
3636-for an outdated signing scheme to be used in support of older programs /
3737-files. An existing drawback for backward compatibility is the maximum size
3737+An existing drawback for backward compatibility is the maximum size
3838of the buffer we store the key in. Currently we set the maximum size as 256
3939bytes, meaning if a future cryptographic signing scheme was to be created with
4040a key size larger than 256 bytes, we would have to drop backwards
4141compatibility. While this can be prevented now by setting the maximum size to
4242something larger, it ends up being tradeoff between possible cryptographic schemes
4343-vs the real on-disk cost of larger buffers.
4343+vs the real on-disk cost of larger buffers, something we plan to investigate in future work.
44444545== Compartmentalization
4646// how they can be used to sign multiple objects (compartmentalization)
···6262the involvement of the kernel.
63636464// nice, we should talk more about this
6565-6666-6765#load-bib(read("refs.bib"))
+5-1
3-cap.typ
···6060We hope for future work to develop more expressive ways of using capabilities, i.e. Decentralized Information Flow Control, as specified in
61616.1.
62626363-//TODO: maybe worth discussing delegations if only to describe how they could be
6363+// maybe worth discussing delegations if only to describe how they could be
6464// extended from capabilities (as a future work ofc)
6565+//
6666+// lowkey tuah lazy to do dis rn, so maybe later, plus i havent talked about
6767+// them at all so im sure daniel is just recomending this as a way to add
6868+// content here, so ill see.
656966706771#load-bib(read("refs.bib"))
+17-12
4-secctx.typ
···2828the relevant security context implementations for kernel and userspace to
2929parse security context objects. Implicitly, the kernel uses
3030this map for lookup while the user interacts with this map to indicate the insertion, removal, or modification of
3131-a capability.
3131+a capability. The `Map` type here and for `masks` is a flat data-structure, and stores
3232+offsets into the object where capabilities can be found for a target object.
32333333-//TODO: talk about the map in memory, and about how its flat, might be worth discussing in the context
3434-// of not storing virtual address pointers.
35343635=== Masks
3736Masks act as a restraint on the permissions this context can provide for some targeted object.
···6160they switch @twizzler. To manage these threads, the kernel assigns a Security Context Manager,
6261which holds onto security context references that a thread has.
63626464-The enforcement of security policy in Twizzler happens on page fault when trying to access
6565-a new object @twizzler. Upon fault, the kernel inspects the target object and identifies the
6363+There exists only 1 point of enforcement for security policy if we wish
6464+to keep the kernel out of the access path; the creation of the path itself!
6565+On page fault, the point in which a process requests the kernel to map an object in is
6666+when we have access to the security policy we seek to enforce (the signed capabilities inside the security context), the
6767+target object, and most importantly, kernel execution! Its the only time
6868+we can program the mmu according to the desired protections, and transfer control
6969+of enforcement to the hardware @twizzler.
7070+7171+Upon page fault, the kernel inspects the target object and identifies the
6672default permissions of that object. Then the kernel checks if the currently active
6773security context for the accessing thread has either cached or capabilities that provide
6874permissions. If default permissions + the active context permissions arent enough to
···7278was found. If it fails all of these, then the kernel terminates the process, citing inadequate
7379permissions.
74807575-Since the security context can have a mask per object, while also having a global_mask to
7676-the protections it can grant, the kernel also takes this into account while determining if
7777-a process has the permissions for access.
78817979-The original Twizzler paper @twizzler, and the following security paper
8080-go into more detail about the philosophy behind why enforcement works this way, such as the
8181-performance benefits of letting programs access objects directly without kernel involvement, etc.
82828383-//TODO: may be worth summarizing a few more bits here
8383+8484+8585+8686+// why should enforcement work this way?
8787+8888+// may be worth summarizing a few more bits here
8489// doesnt have to be super detailed or anything but its better to havea ... thing tie together
8590// than and a parathere with "etc"
8691//
+11-13
5-results.typ
···11#import "template.typ": *
2233+#show link: it => underline(text(fill:blue)[#it])
44+35#import "@preview/unify:0.7.1"
46#mol-chapter("Results")
57···3234== Micro Benchmarks
3335Additionally, we have microbenchmarks of core security operations in Twizzler. All
3436benchmarks were run with a Ryzen 5 2600, with Twizzler virtualized in QEMU. Unfortunately
3535-//TODO: do not say they they should be the same :sob:, instead say that finding
3636-// the difference between virtualized performance and actual performance is future work
3737-I ran out of time to perform benchmarks on bare metal, but they should be the same, if
3838-not more, performant.
3737+I ran out of time to perform benchmarks on bare metal, but hope to find
3838+any discrepencies between virtualized and actual performance in future work.
39394040=== Kernel
4141+4242+The kernel benchmarking framework takes a closure ( a block of code we want to benchmark ),
4343+runs it atleast 100 times, and scales the number of iterations to reach 2 seconds of total runtime, and stores
4444+the time it takes for each run. Then it computes the average, and the standard deviation from the timings.
4545+4146There a couple of things we benchmark inside the kernel, including core cryptographic
4247operations like signature generation and verification, as well as the total time it takes
4348to verify a capability.
44494545-//TODO: is this with SIMD in kernel? maybe worth discussing this nuance
4646-//
4747-// how many times did you run the experimnt and how were the stats calculated.
4848-//
4949-// could be interesting to compare signature verification cost as the amount of data
5050-// to verify goes up
5151-// my_note: (wouldnt this only be applicable towards delegations though since others are always
5252-// done properly)
5353-//
5450#figure(
5551table(
5652 columns: (auto, auto),
···104100capability creation only takes place in user space.
105101106102=== UserSpace
103103+Userspace benchmarks were calculated using rust's built in
104104+#link("https://doc.rust-lang.org/cargo/commands/cargo-bench.html")[benchmarking tool].
107105108106In userspace, we benchmark keypair and capability creation, as these operations are core to
109107creating a security policy.
+35-9
6-conclusion.typ
···2233#mol-chapter("Conclusion")
4455-//TODO: So, this is more a summary. Which is good to have here, but
55+//So, this is more a summary. Which is good to have here, but
66// you'll want to have some conclusions -- e.g. What did you learn (e.g. about the
77// cost of the operations)
88In short we provide a general overview of the critical security
···1111security policy can be expressed and verifies that the kernel is enforcing as
1212programmed. Lastly we go over microbenchmarks to show and explain the cost of these operations.
13131414+The results affirm our intuition that performance would be greatly improved via
1515+caching. The cost of verifying a signature everytime a new page from an object
1616+had to be mapped into a process's memory space would be redundant. Additionally,
1717+the performance of the kernel verifying signatures is bottlenecked by the
1818+performance of the cryptograhpic scheme, meaning its a good plan to allow for
1919+the addition of new schemes while allowing for backwards compatibility since
2020+adopting a more performant scheme would lead to pure performance gains.
14211515-== Future Works
2222+== Future Work
16231717-// TODO: Maybe go into more detail here. There's a number of things that are discussed
2424+// Maybe go into more detail here. There's a number of things that are discussed
1825// as future work throughout that could use a couple sentences each here.
1919-In the future I hope to take the primitives created during my thesis, and apply them towards
2020-the implementation of Decentralized Information Flow Control, as described in @flume, into
2121-the Twizzler security model. Additionally I would love to see how the current security model
2222-evolves once we start adding distributed computing support to Twizzler, as described in
2323-the orignal paper @twizzler.
2626+2727+There are a number of things I hope to achieve in future work, listed as follows.
2828+2929+- Perform a cost-benefit analysis between key sizes and performance, trying
3030+ to optimimze for a future proof key size in order to maximize backwards
3131+ compatibility.
3232+3333+- Program the kernel to perform access rights checks with a processes secuirty
3434+ context
3535+ during a page fault. I was hoping to get this completed before the end of this
3636+ quarter, but we ran into some bugs and were unable to resolve them in time.
3737+ Once this is hooked up, we plan to design scenarios that test the degress of
3838+ expressivity allowed by our secuirty model to ensure it operates as expected.
3939+4040+- Investigate areas of the secuirty model that could be extended to support
4141+ Decentralized
4242+ Information Flow Control, inspired by the work done in FLUME @flume.
4343+4444+- Create a onboarding process that allows new students to learn the essentials
4545+ of the Twizzler operating system, to foster an environment for increased
4646+ student contributions to the project.
4747+4848+- Clear code documentation so that users wanting to interface with the library
4949+ have an easier time integrating it with their applications.
245025512652== Acknowledgements
2753I couldn't have done the work for this thesis and for Twizzler if it wasn't for the
2854support I've recieved from my advisor Owen Arden and my technical mentor Daniel Bittman! I
2929-owe both of you so much, not just for the class credit but also for how much I've learned in
5555+owe both of you so much, not just for this thesis but also for how much I've learned in
3056this endeavor. Thanks guys!
31573258
+1-49
refs.bib
···7171@inproceedings{twizsec,
7272 author = {Daniel Bittman and Peter Alvaro and Pankaj Mehra and Darrell D. E.
7373 Long and Ethan L. Miller},
7474- title = {Twizzler: a {Data-Centric} {OS} for {Non-Volatile} Memory},
7575- booktitle = {2020 USENIX Annual Technical Conference (USENIX ATC 20)},
7676- year = {2020},
7474+ title = {A Data Centric Model for OS Security},
7775 isbn = {978-1-939133-14-4},
7876 pages = {65--80},
7977 url = {https://www.usenix.org/conference/atc20/presentation/bittman},
···128126129127130128131131-@inproceedings{10.1145/1294261.1294293,
132132- author = {Krohn, Maxwell and Yip, Alexander and Brodsky, Micah and Cliffer,
133133- Natan and Kaashoek, M. Frans and Kohler, Eddie and Morris, Robert},
134134- title = {Information flow control for standard OS abstractions},
135135- year = {2007},
136136- isbn = {9781595935915},
137137- publisher = {Association for Computing Machinery},
138138- address = {New York, NY, USA},
139139- url = {https://doi.org/10.1145/1294261.1294293},
140140- doi = {10.1145/1294261.1294293},
141141- abstract = {Decentralized Information Flow Control (DIFC) is an approach to
142142- security that allows application writers to control how data
143143- flows between the pieces of an application and the outside world.
144144- As applied to privacy, DIFC allows untrusted software to compute
145145- with private data while trusted security code controls the
146146- release of that data. As applied to integrity, DIFC allows
147147- trusted code to protect untrusted software from unexpected
148148- malicious inputs. In either case, only bugs in the trusted code,
149149- which tends to be small and isolated, can lead to security
150150- violations.We present Flume, a new DIFC model that applies at the
151151- granularity of operating system processes and standard OS
152152- abstractions (e.g., pipes and file descriptors). Flume was
153153- designed for simplicity of mechanism, to ease DIFC's use in
154154- existing applications, and to allow safe interaction between
155155- conventional and DIFC-aware processes. Flume runs as a user-level
156156- reference monitor onLinux. A process confined by Flume cannot
157157- perform most system calls directly; instead, an interposition
158158- layer replaces system calls with IPCto the reference monitor,
159159- which enforces data flowpolicies and performs safe operations on
160160- the process's behalf. We ported a complex web application
161161- (MoinMoin Wiki) to Flume, changingonly 2\% of the original code.
162162- Performance measurements show a 43\% slowdown on read
163163- workloadsand a 34\% slowdown on write workloads, which aremostly
164164- due to Flume's user-level implementation.},
165165- booktitle = {Proceedings of Twenty-First ACM SIGOPS Symposium on Operating
166166- Systems Principles},
167167- pages = {321–334},
168168- numpages = {14},
169169- keywords = {web services, system call interposition, reference monitor,
170170- endpoints, decentralized information flow control, DIFC},
171171- location = {Stevenson, Washington, USA},
172172- series = {SOSP '07},
173173-}
174174-175175-176176-
thesis.pdf
This is a binary file and will not be displayed.
-1
thesis.typ
···1515 /* Only one supervisor? The singleton array ("Dr Jack Smith",) needs the
1616 trailing comma. */
1717 supervisors: ("Owen B. Arden",),
1818- //TODO: fix these
1918 committee: (
2019 "Dr. Peter Alvaro",
2120 "Dr. Andi Quinn",