Skip to content

Commit

Permalink
add talk
Browse files Browse the repository at this point in the history
  • Loading branch information
ezrizhu committed Oct 24, 2023
1 parent e3e99db commit 5a7f080
Show file tree
Hide file tree
Showing 40 changed files with 163 additions and 105 deletions.
Binary file added assets/files/try.pdf
Binary file not shown.
Binary file added assets/img/talks/try/slide0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide17.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide18.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide21.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide22.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide23.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide24.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide25.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide26.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide27.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide28.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide29.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide30.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/talks/try/slide4.png
Binary file added assets/img/talks/try/slide5.png
Binary file added assets/img/talks/try/slide6.png
Binary file added assets/img/talks/try/slide7.png
Binary file added assets/img/talks/try/slide8.png
Binary file added assets/img/talks/try/slide9.png
Binary file added assets/img/talks/try/try_demo.gif
80 changes: 44 additions & 36 deletions content/talks/20231022-try.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
---
Title: Tool: Try(1)
Title: Try(1)
Description: Inspect a command’s effects before modifying your live system
Tags:
- golang
- hypervisor
- pash
- shell
- linux

---

This was a talk.
A video recording of this talk is available [here](https://not-a.link/7odvmye.mp4).

[Slide 1]
The full slides pdf is available [here](/files/try.pdf).

![Slide 0](/assets/img/talks/try/slide0.png)

This talk was given at the third PaSh workshop, I would like to first thank
Nikos Vasilakis for organizing this. This was also my first talk, so apologies
for the cringy bits.

[Slide 2]
![Slide 1](/assets/img/talks/try/slide1.png)

Try is a higher order command that lets you run a command or a script, including
a shell, in a sandbox looks exactly like your live system, and inspect it’s
Expand All @@ -34,15 +37,15 @@ This is a collaboration effort in the PaSh team, so I’d like to thank Michael
Greenberg, Konstantinos Kallas, Georgios Liargkovas and the rest of the PaSh
team on making this happen.

[Slide 3]
![Slide 2](/assets/img/talks/try/slide2.png)

We will first start by going over why we made try and how it integrates with our
research. We will then go over overlayfs, one of the main drivers of try. After
that, we will examine how we’re using linux namespaces via unshare to support
mounting in the userspace. Lastly, we will explore some of the essential code
snippets of try that makes it work.

[Slide 4]
![Slide 3](/assets/img/talks/try/slide3.png)

First, let’s go over why we built try in the first place. Our research hs is
mainly about parallelizing the shell via speculative execution. To do that, we
Expand All @@ -52,7 +55,7 @@ have to merge the different outputs of a command. And in order to utilize
overlayfs in the userspace, we will be taking advantage of Linux namespaces via
the unshare command.

[Slide 5]
![Slide 4](/assets/img/talks/try/slide4.png)

Here is a quick example of a shell script that we will execute via our out of
order execution engine ‘hs’. You can read more about hs on the HotOS 2023 paper.
Expand All @@ -64,7 +67,7 @@ once. However, we know that if we call all three commands at once, there is a
chance that the message “It’s sunny”, gets written before the date, and that
wouldn’t make much sense.

[Slide 6]
![Slide 5](/assets/img/talks/try/slide5.png)

So, hs will first send the script to our preprocessor PaSh, which in this case
will just extract the three lines from the script, in some more complex cases it
Expand All @@ -75,7 +78,7 @@ sure whether these command runs will be correct, we call that speculation. We
use riker to monitor these command’s changes to the filesystem, and intercept
network calls, since we don’t wish to make network calls in speculation.

[Slide 7]
![Slide 6](/assets/img/talks/try/slide6.png)

After these commands finish, the scheduler will find that command B does not
read or write to anything that its previous command has written, so we know that
Expand All @@ -86,26 +89,26 @@ that command B has also written to, realizing that the speculative run of
command C is incorrect, because command C is a dependency of command B due to
the editing of the file “report”.

[Slide 8]
![Slide 7](/assets/img/talks/try/slide7.png)

So, we have established that command A and B are ready to be merged into the
filesystem. After that’s done, the scheduler will re-run command C and commit
the changes to the filesystem.

[Slide 9]
![Slide 8](/assets/img/talks/try/slide8.png)

As a result, we have created a tool that writes a program’s filesystem changes
to a separate sandbox, allowing you to inspect its effects before committing it
to your machine.

[Slide 10]
![Slide 9](/assets/img/talks/try/slide9.png)

One major driver of try is the Linux overlayfs. Overlayfs allows us to mount a
directory somewhere, and capture the changes to the mounted directory and put
them somewhere else. However, to the underlying program making these changes, it
will look like the changes were just written to the real filesystem.

[Slide 11]
![Slide 10](/assets/img/talks/try/slide10.png)

Overlayfs at minimum uses four directories, a lowerdir, an upperdir, a workdir,
and a directory to mount the merged views to.
Expand All @@ -119,7 +122,7 @@ and a directory to mount the merged views to.
- Workdir is where overlay stage changes to as it is copying files up from
lowerdir to upperdir.

[Slide 12]
![Slide 11](/assets/img/talks/try/slide11.png)

For example, here we have two directories, lowerdir 1, and lowerdir 2.

Expand All @@ -132,14 +135,14 @@ one for the workdir, and one to mount the overlay view to. After overlayfs is
mounted to the overlay view, you are able to see the four files from the two
lower directories in the overlay view.

[Slide 13]
![Slide 12](/assets/img/talks/try/slide12.png)

Here we’ll make a new file called file 5, and we will edit file 1. As you can
see, overlayfs writes the updated file 1, and creates file 5 in the upperdir,
leaving the lowerdirs alone. However, the changes are reflected in the overlay
view.

[Slide 14]
![Slide 13](/assets/img/talks/try/slide13.png)

Now, we will delete file two. For file deletions, overlayfs will write a
character device at the location of the file that it is removing, and the file
Expand All @@ -148,24 +151,24 @@ will disappear from the overlay view.
This is basically how overlayfs works, we use it to stash changes to the
filesystem elsewhere, and then commit them later on if we want to.

[Slide 15]
![Slide 14](/assets/img/talks/try/slide14.png)

And this is how you start an overlay mount.

[Slide 16]
![Slide 15](/assets/img/talks/try/slide15.png)

This is also how docker works, when you build a container, each line in the
dockerfile is being written to it’s own upperdir, with everything preceding are
just lowerdirs in a merged view. When you pull a docker image and run it, each
layer is just a lowerdir, and your container is mounted on the overlay view.

[Slide 17]
![Slide 16](/assets/img/talks/try/slide16.png)

But if we try to mount an overlayfs in the userspace, we get a permission error.
Since only root is allowed to mount, but we have a way to work around this via
unshare.

[Slide 18]
![Slide 17](/assets/img/talks/try/slide17.png)

This is your computer, a program usually have access to all of these system
resources provided by the Kernel. And you can access them via system calls.
Expand All @@ -180,7 +183,7 @@ to reverse proxy the webapp because they both share a network namespace. Then
the webapp is able to communicate with the postgres database via a socket, as
they both share the IPC namespace.

[Slide 19]
![Slide 18](/assets/img/talks/try/slide18.png)

Here is an example of linux namespaces being used in the real world.

Expand All @@ -190,7 +193,7 @@ linux network namespaces. He then spawns a browser in each of the three
namespaces, where he will work on different things. This allows him to have
three different IP addresses on the browser.

[Slide 20]
![Slide 19](/assets/img/talks/try/slide19.png)

But in our case, we will focus mainly on mount namespaces. Here we have two
mount namespaces, one has /fs1/ mounted at mount, and one has /fs2/ mounted at
Expand All @@ -199,13 +202,13 @@ mount, and a different value in fs1/file, and fs2/file.
Then if we start a shell in the two amespaces and open mount/file, we will get
different results.

[Slide 21]
![Slide 20](/assets/img/talks/try/slide20.png)

This demo reproduces what we just went over. Feel free to copy them to your
computer and try it yourself. (Make sure the second unshare is not executed
within the first unshare, and you want to type ‘exit’ to exit the unshare.)

[Slide 22]
![Slide 21](/assets/img/talks/try/slide21.png)

Alright, now let’s walk through some important snippets of our tool try. I have
edited some commands to make them a bit more readable. If you don’t supply try
Expand All @@ -219,28 +222,28 @@ You can also use -D to tell it to just run the command in a sandbox, and you can
use the summary and commit subcommands later. There’s also the explore
subcommand, this will pop you into a shell in a sandbox.

[Slide 23]
![Slide 22](/assets/img/talks/try/slide22.png)

Here, try will create three directories, an upperdir, a workdir, and a temproot.
Then for each mountpoint, we will create the directories within the three that
we just made. We then get all the top level directories, and all the mountpoints
in the system, and perform deduplication.

[Slide 24]
![Slide 23](/assets/img/talks/try/slide23.png)

Here, we have the flag mount so we can mount and unmount overlayfs without
affecting the rest of the system. We also have map-root-user so that we are
allowed to mount. We also create a new PID namespace, and fork is necessary if
we do PID.

[Slide 25]
![Slide 24](/assets/img/talks/try/slide24.png)

Here, we will define the function and make an overlay, we’re also enabling
extended user attributes so we see less errors in dmesg. We also mapped out the
devices that we want to mount, we don’t want to mount all our devices in case
some script starts writing zeros to your drives.

[Slide 26]
![Slide 25](/assets/img/talks/try/slide25.png)

Now, we will create the overlayfs mount for each of the top level directories,
as well as the mountpoints that were already in the system. Sometimes, which is
Expand All @@ -251,18 +254,23 @@ Lastly, after we have mounted everything in it’s overlayfs, we will pop into o
second unshare, this case we will be entering our entirely overlayfs backed
system.

[Slide 27]
![Slide 26](/assets/img/talks/try/slide26.png)

And here, we will mount the prof filesystem, and run the script or command that
we called try with.

INSERT DEMO HERE
![Slide 27](/assets/img/talks/try/slide27.png)

gif courtesy of Georgios.
![Try Demo](/assets/img/talks/try/try_demo.gif)

![Slide 30](/assets/img/talks/try/slide30.png)

Future plans

* We plan on allowing the user to specify the namespace that they want to be
- We plan on allowing the user to specify the namespace that they want to be
isolated (such as networking)
* Finalize support for UID/GID mapping (currently being worked on the [future
- Finalize support for UID/GID mapping (currently being worked on the [future
branch])
* Speed up summary process
* And more, and we’re tracking them on our issues page.
- Speed up summary process
- And more, and we’re tracking them on our issues page.
14 changes: 13 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ async fn health() -> Html<String> {
Html(String::from("OK"))
}

enum PageType {
Blog,
Project,
Talk
}

#[derive(Clone)]
pub struct SiteState {
css: Vec<css::Css>,
Expand All @@ -28,6 +34,7 @@ pub struct SiteState {
news: String,
projects: Vec<post::Post>,
blog: Vec<post::Post>,
talks: Vec<post::Post>,
sitemap: Vec<u8>,
webring: Vec<webring::Node>,
}
Expand All @@ -47,6 +54,7 @@ async fn main() {
now: utils::path_to_html(&"content/now.md"),
projects: post::init(&"content/projects"),
blog: post::init(&"content/blog"),
talks: post::init(&"content/talks"),
sitemap: vec![],
webring: webring::fetch().await.unwrap(),
};
Expand Down Expand Up @@ -74,7 +82,11 @@ async fn main() {
.route("/projects/tags", get(site::tags::projects_tags_index))
.route("/projects/tags/", get(site::tags::projects_tags_index))
.route("/projects/tags/:tag", get(site::tags::projects_tags_get))
.route("/talks", get(site::wip::wip))
.route("/talks", get(site::talks::talk_index))
.route("/talks/:name", get(site::post::talk_handler))
.route("/talks/tags", get(site::tags::talks_tags_index))
.route("/talks/tags/", get(site::tags::talks_tags_index))
.route("/talks/tags/:tag", get(site::tags::talks_tags_get))
.route("/blog", get(site::blog::blog_index))
.route("/blog/", get(site::blog::blog_index))
.route("/blog/:name", get(site::post::blog_handler))
Expand Down
1 change: 1 addition & 0 deletions src/site/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod contact;
pub mod news;
pub mod projects;
pub mod blog;
pub mod talks;
pub mod not_found;
pub mod wip;
pub mod post;
Expand Down
31 changes: 21 additions & 10 deletions src/site/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,62 @@ use axum::{
http::StatusCode
};
use super::base;
use crate::PageType;

pub async fn blog_handler(Path(name): Path<String>, State(state): State<SiteState>) -> (StatusCode, Markup) {
if let Some(blog) = get(state.blog.clone(), &name) {
(StatusCode::OK, post(blog, state, true))
(StatusCode::OK, post(blog, state, PageType::Blog))
} else {
return not_found().await
}
}

pub async fn project_handler(Path(name): Path<String>, State(state): State<SiteState>) -> (StatusCode, Markup) {
if let Some(project) = get(state.projects.clone(), &name) {
(StatusCode::OK, post(project, state, false))
(StatusCode::OK, post(project, state, PageType::Project))
} else {
not_found().await
}
}

fn post(post: Post, state: SiteState, is_blog: bool) -> Markup {
let tags = post.tags.iter().map(|x| x.to_string()).collect::<Vec<_>>();
let mut url = format!("https://ericz.me/blog/{}", post.slug);
if !is_blog {
url = format!("https://ericz.me/projects/{}", post.slug);
pub async fn talk_handler(Path(name): Path<String>, State(state): State<SiteState>) -> (StatusCode, Markup) {
if let Some(talk) = get(state.talks.clone(), &name) {
(StatusCode::OK, post(talk, state, PageType::Talk))
} else {
not_found().await
}
}

fn post(post: Post, state: SiteState, page_type: PageType) -> Markup {
let tags = post.tags.iter().map(|x| x.to_string()).collect::<Vec<_>>();
let page_name = match page_type {
PageType::Blog => "blog",
PageType::Project => "projects",
PageType::Talk => "talks",
};

let content = html! {
article class="h-entry" {
h1 class="p-name" { (post.title) };
div class="byline" {
p {
"by " a class="p-author h-card" href="https://ericz.me" target="_blank" { "Eric" }
@if is_blog {
@if matches!(page_type, PageType::Blog) {
@let date_str = post.date.format("%B %d, %Y").to_string();
@let date_rfc3339 = post.date.to_rfc3339();
" on " time class="dt-published" datetime=(date_rfc3339) { (date_str) }
}
br;
"tags: "
@for tag in tags {
a class="p-category" href=(format!("/blog/tags/{}", tag)) { (tag) } " "
a class="p-category" href=(format!("/{}/tags/{}", page_name, tag)) { (tag) } " "
}
}
}
div class="e-content" {
p { (PreEscaped(post.body)) };
}
a style="display: none;" class="u-url" href=(url) { "Permalink" }
a style="display: none;" class="u-url" href=(format!("https://ericz.me/{}/{}", page_name, post.slug)) { "Permalink" }
}
hr;
p { "If you have any questions, want to change my mind, or literally anything else, please " a href="mailto:[email protected]" {"reach out"} "!" };
Expand Down
Loading

0 comments on commit 5a7f080

Please sign in to comment.