% vim: set filetype=tex fileencoding=utf8 et sw=2 ts=2 sts=2 tw=80 :
% © 2025 Ali Polatel <alip@hexsys.org>
% Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported Lisansı ile yayınlanmıştır.

\documentclass[aspectratio=169]{beamer}
\usepackage[english]{babel}

\usepackage{fontspec}
\usepackage{unicode-math}
\defaultfontfeatures{Ligatures=TeX}
\setmainfont[Ligatures=TeX,
Extension=.otf,
BoldFont=*-bold,
UprightFont=*-regular,
ItalicFont=*-italic,
BoldItalicFont=*-bolditalic,
SmallCapsFeatures={Letters=SmallCaps}]{texgyretermes}
\setmathfont[Ligatures=TeX]{texgyretermes-math.otf}
\setsansfont[Ligatures=TeX,
Extension=.otf,
BoldFont=*-bold,
UprightFont=*-regular,
ItalicFont=*-italic,
BoldItalicFont=*-bolditalic,
SmallCapsFeatures={Letters=SmallCaps}]{texgyreheros}

\usepackage{graphicx}
\DeclareGraphicsExtensions{.jpg,.png}

\usepackage{fontawesome5}
\usepackage{marvosym}

\usepackage{booktabs}
\usepackage{enumerate}
\usepackage{multicol}
\usepackage{pdfpages}
\usepackage{color}
\usepackage[xspace]{ellipsis}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows.meta, positioning, fit, calc}
\tikzset{
  startstop/.style = {
    rectangle, rounded corners,
    minimum height=0.5cm,
    text centered, text width=2.0cm, align=center,
    draw=black, fill=red!20, inner sep=2pt
  },
  process/.style = {
    rectangle,
    minimum height=0.5cm,
    text centered, text width=2.1cm, align=center,
    draw=black, fill=orange!20, inner sep=2pt
  },
  decision/.style = {
    diamond, aspect=2,
    minimum height=0.5cm,
    text width=1.9cm, align=center,
    draw=black, fill=green!20, inner xsep=2pt, inner ysep=1pt
  },
  arrow/.style = {-{Stealth}, shorten >=1pt, line width=0.6pt}
}

\definecolor{Brown}{cmyk}{0,0.81,1,0.60}
\definecolor{OliveGreen}{cmyk}{0.64,0,0.95,0.40}
\definecolor{CadetBlue}{cmyk}{0.62,0.57,0.23,0}
\definecolor{lightlightgray}{gray}{0.9}
\usepackage{listings}
\lstset{
  inputencoding=utf8,
  extendedchars=\false,
  escapeinside={\%*}{*)},
  language=Python,
  basicstyle=\scriptsize\ttfamily,
  stringstyle=\scriptsize\ttfamily,
  keywordstyle=\color{OliveGreen},
  commentstyle=\color{gray},
  numbers=left,
  numberstyle=\tiny,
  stepnumber=1,
  numbersep=5pt,
  backgroundcolor=\color{lightlightgray},
  frame=none,
  tabsize=2,
  captionpos=t,
  breaklines=true,
  breakatwhitespace=false,
  showspaces=false,
  showstringspaces=false,
  showtabs=false,
  columns=flexible
}

\usetheme{Warsaw}
\usecolortheme[snowy]{owl}
%\setbeamertemplate{itemize/enumerate body begin}{\footnotesize}
%\setbeamertemplate{itemize/enumerate subbody begin}{\scriptsize}
%\setbeamertemplate{itemize/enumerate subsubbody begin}{\tiny}

\author{Ali Polatel}
\title{Syd}
\subtitle{Advanced Introduction to Secure Application Sandboxing}
\institute{
  \noindent
  \includegraphics[height=0.2\textheight,width=0.2\textwidth]{zebrapig}
  \hspace{0.1\textwidth}
  \includegraphics[height=0.2\textheight,width=0.2\textwidth]{syd}
  \hspace{0.1\textwidth}
  \includegraphics[height=0.2\textheight,width=0.2\textwidth]{sydbox}
}
\date{BalCCon2k25}

\usepackage{hyperref}
\hypersetup{%
    hyperfootnotes=true,
    breaklinks=true,
    colorlinks=true,
    urlcolor=black,
    citecolor=black,
    linkcolor=black,
    pdftitle={Syd},
    pdfauthor={Ali Polatel},
    pdfsubject={Ali Polatel, Syd},
    pdflang={en},
    pdfkeywords={Linux, Sandboxing},
    pdfproducer={LuaLaTeX, BibTeX, hyperref, memoir},
    pdfpagelabels=true
    pdfborder={0 0 0},
}

\begin{document}

\frame{\titlepage}

\begin{frame}
  \frametitle{whoami}
  \framesubtitle{Shine on you crazy diamond.}

  \begin{itemize}
    \item Exherbo Linux dev, ex-Gentoo dev
    \item Main author of Sydbox
    \item Chess trainer, Co-founder of \url{chesswob.org}
    \item Interests: Linux, BSD, Sandboxing, Security, Board games, Translation
    \item E-mail: \url{alip@chesswob.org}
    \item Looking for a job :-)
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Outline}
  \framesubtitle{You pick the place and I'll choose the time.}

  \begin{itemize}
    \item History
    \item Threat model
    \item Features
    \item Hardenings
    \item Design
    \item Demo
    \item Q\&A
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{History}
  \framesubtitle{And the echo of a distant time.}

  \begin{itemize}
    \item Gentoo sandbox: C, \texttt{LD\_PRELOAD}
    \item sydbox-1: C, \texttt{ptrace(2)}, default on Exherbo since 2008
    \item sydbox-2: C, \texttt{ptrace(2)} \& \texttt{seccomp(2)}
    \item sydbox-3: aka Syd, Rust, \texttt{seccomp\_unotify(2)} \& \texttt{ptrace(2)}
  \end{itemize}

\end{frame}

\begin{frame}
  \frametitle{Threat model}
  \framesubtitle{Dogs of war don't negotiate.}

  \begin{itemize}
    \item Trusted: Linux kernel + Syd
    \item Untrusted: All sandboxed apps (arbitrary code assumed)
    \item Goal: Restrict syscall surface; mediate FS/net; audit violations
    \item Out of scope: External network/physical attacks
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Threat model (cont.)}
  \framesubtitle{Us and them, and after all we're only ordinary men.}

  \begin{itemize}
    \item Unprivileged: No \texttt{SETUID}, \texttt{EBPF}, or \texttt{LKM}
    \item Multilayered: \texttt{seccomp(2)}, \texttt{ptrace(2)}, \texttt{landlock(7)}, \texttt{PR\_SET\_MDWE(2const)}
    \item General purpose: Secure by default with toggles for each hardening
    \item Sandbox lock and dynamic configuration:
      \begin{description}
        \item[\texttt{lock:on}] Default, made immutable with \texttt{mseal(2)} after setup
        \item[\texttt{lock:off}] All processes can configure, must lock after setup
        \item[\texttt{lock:exec}] Initial thread can configure, used by \texttt{esandbox} on Exherbo
        \item[\texttt{lock:ipc}] Configure sandbox through a UNIX socket
      \end{description}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Features: Path sandboxing}
  \framesubtitle{All in all you're just another brick in the wall.}

  \begin{itemize}
    \item Path sandboxing with refined categories: read, write, exec, ioctl, ...
    \item OpenBSD \texttt{pledge(2)} like category sets: rpath, wpath, cpath, inet, ...
    \item ``Last matching rule wins'' semantics simplifies stacking rules \& profiles!
  \end{itemize}

  \centering
  \includegraphics[height=0.7\textheight]{examples/example-1}

\end{frame}

\begin{frame}
  \frametitle{Features: Path hiding}
  \framesubtitle{There's someone in my head but it's not me.}

  \begin{itemize}
    \item Path hiding: covers directory listings and path traversals
  \end{itemize}

  \centering
  \includegraphics[height=0.7\textheight]{examples/example-2}

\end{frame}

\begin{frame}
  \frametitle{Features: Path masking}
  \framesubtitle{Wearing the inside out.}

  \begin{itemize}
    \item Replace files and directories on the fly
    \item Like bind mounts but unprivileged!
  \end{itemize}

  \centering
  \includegraphics[height=0.7\textheight]{examples/example-3}

\end{frame}

\begin{frame}
  \frametitle{Features: Network sandboxing}
  \framesubtitle{We're just two lost souls swimming in a fish bowl.}

  \begin{itemize}
    \item Network sandboxing with rules based on address and port
  \end{itemize}

  \centering
  \includegraphics[height=0.7\textheight]{examples/example-4}

\end{frame}

\begin{frame}
  \frametitle{Features: Learning mode}
  \framesubtitle{When I was a child I caught a fleeting glimpse.}

  \begin{itemize}
    \item Flexible config interface: \texttt{glob(3p)}, \texttt{CIDR}, \texttt{ioctl(2)} matching
    \item Learning mode with \texttt{pandora(1)} to automatically build profiles
  \end{itemize}

  \centering
  \includegraphics[height=0.75\textheight]{examples/example-5}

\end{frame}

\begin{frame}
  \frametitle{Features: \texttt{landlock(7)}}
  \framesubtitle{Set the controls for the heart of the sun.}

  \begin{itemize}
    \item Lock sandboxing: Use \texttt{landlock(7)} to build multilayered sandboxes
    \item Use \texttt{syd-lock(1)} CLI to build lightweight sandboxes
    \item Support up to Landlock ABI 7 (current, Linux>=6.15)
  \end{itemize}

  \centering
  \includegraphics[height=0.53\textheight]{examples/example-6}

\end{frame}

\begin{frame}
  \frametitle{Features: \texttt{Memory-Deny-Write-Execute} (W\^{}X)}
  \framesubtitle{I have become comfortably numb.}

  \begin{itemize}
    \item Deny writable-executable memory with \texttt{PR\_SET\_MDWE(2const)}
    \item Harden W\^{}X boundary with \texttt{seccomp(2)}
      \begin{itemize}
        \item Deny \texttt{READ\_IMPLIES\_EXEC} \texttt{personality(2)}
        \item Deny \texttt{PROT\_READ|PROT\_EXEC} mappings backed by writable files
          \begin{itemize}
            \item Linux \#219227, HardenedBSD \#107
          \end{itemize}
      \end{itemize}
    \item \texttt{syd-mdwe(1)} CLI to build lightweight sandboxes coupled with \texttt{syd-lock(1)}
  \end{itemize}

  \centering
  \includegraphics[height=0.3\textheight]{examples/example-7}

\end{frame}

\begin{frame}
  \frametitle{Features: Crypt sandboxing}
  \framesubtitle{Careful with that axe, Eugene.}

  \begin{itemize}
    \item AES-CTR + HMAC-SHA256 via AF\_ALG sockets
      \begin{itemize}
        \item Do not roll your own crypto, roll \texttt{socket(2)}s with \texttt{pipe(2)}s!
      \end{itemize}
    \item Transparent \& concurrent with Linux OFD locks (included in POSIX 2024)
  \end{itemize}

  \centering
  \includegraphics[height=0.7\textheight]{examples/example-8}

\end{frame}

\begin{frame}
  \frametitle{Features: Crypt sandboxing (cont.)}
  \framesubtitle{But the sun is eclipsed by the moon.}

  \begin{itemize}
    \item Zero-copy with \texttt{splice(2)} and \texttt{pipe(2)}s:
      \begin{itemize}
        \item Plaintext doesn't leak into Syd's address space!
      \end{itemize}
    \item HMAC authentication detects corrupt data, returns \texttt{EBADMSG}!
  \end{itemize}

  \centering
  \includegraphics[height=0.75\textheight]{examples/example-9}

\end{frame}

\begin{frame}
  \frametitle{Features (cont.)}
  \framesubtitle{Haven't you heard it's a battle of words?}

  \begin{itemize}
    \item Force sandboxing: Verify checksums at \texttt{exec(3)}, \texttt{mmap(2)} boundary
    \item Memory \& PID sandboxing: Simple, unprivileged alternatives to cgroups
    \item Proxy sandboxing: Isolate network with a single exit through SOCKS5 proxy
    \item PTY sandboxing: Isolate TTY with zero-copy and unsafe ops \texttt{TIOCSTI} denied
    \item SafeSetID: Safely change UID/GID through predefined transition rules
    \item Ghost mode: Detach sandbox process from \texttt{syd}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Hardenings}
  \framesubtitle{Run like hell.}

  \begin{itemize}
    \item Analysis-friendly: \texttt{ptrace(2)} made a no-op;
      \texttt{PR\_SET\_NAME} made a no-op with optional logging;
      \texttt{proc\_pid\_status(5)} normalized to prevent detection.
    \item Exec \& memory: MDWE (W\^{}X), PIE \& non-exec stack enforced;
      secure-execution mode with AT\_SECURE;
      SegvGuard/TPE for safe execution with crash throttling;
      ROP/SROP guards raising the bar for exploitation.
    \item /proc \& devices: Hide other PIDs;
      block magic links of other processes;
      deny device-node creation/open.
    \item Signals \& IPC: Guests cannot signal or interfere with the sandbox;
      remote-memory APIs denied;
      unsafe TTY ioctls blocked.
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Design}
  \framesubtitle{You rearrange me 'til I'm sane.}

  \centering
  \begin{tikzpicture}[x=1cm, y=1cm, font=\scriptsize]

    % Top boxes, evenly gapped.
    \node (linux) [process] at (0.2,4.7) {Linux};
    \node (proc)   [process] at (4.0,4.7) {/proc};
    \node (usock)  [process] at (8.0,4.7) {IPC socket};

    % Legend.
    \draw[dashed, draw=blue, line width=1.3pt] (-1.5,5.2) -- +(-0.5,0) node[left]{\texttt{seccomp\_unotify(2)}};
    \draw[dotted, draw=orange, line width=1.3pt] (-1.5,4.8) -- +(-0.5,0) node[left]{\texttt{ptrace(2)}};
    \draw[dotted, draw=CadetBlue, line width=1.3pt] (-1.5,4.4) -- +(-0.5,0) node[left]{\texttt{landlock(7)}};
    \draw[dashdotted, draw=OliveGreen, line width=0.9pt] (-1.5,4.0) -- +(-0.5,0) node[left]{\texttt{PR\_SET\_MDWE}};
    \draw[dashed, draw=red!70!black, line width=0.9pt] (-1.5,3.5) -- +(-0.5,0) node[left]{\texttt{unshare(FS|FILES)}};
    \draw[dashdotted, draw=purple!70!black, line width=0.9pt] (-1.5,3.0) -- +(-0.5,0) node[left]{per-thread \texttt{seccomp(2)}};

    % Large Syd container
    \draw[rounded corners, draw=black, fill=lightlightgray] (-1.0,4.0) rectangle (9.5,-1.0);

    % Syd internal grid
    \node (sydemu) [process, minimum width=1.1cm, minimum height=0.43cm] at (0.6,3.2) {\texttt{syd\_emu} $\times$Y};
    \node (sydipc)  [process, minimum width=1.1cm, minimum height=0.43cm] at (7.8,3.2) {\texttt{syd\_ipc}};
    \node (sydmon)  [process, minimum width=1.1cm, minimum height=0.43cm] at (0.6,1.3) {\texttt{syd\_mon}};
    \node (policy)  [process, minimum width=1.1cm, minimum height=0.43cm] at (4.2,1.3) {policy};
    \node (sydint)  [process, minimum width=1.1cm, minimum height=0.43cm] at (7.8,1.3) {\texttt{syd\_int}};
    \node (sydmain)  [process, minimum width=1.1cm, minimum height=0.43cm] at (0.6,-0.2) {\texttt{syd\_main}};
    \node (sydaes)  [process, minimum width=1.1cm, minimum height=0.43cm] at (7.8,-0.2) {\texttt{syd\_aes}};

    % Subtitle for Syd container + syd-{pty,tor}
    \node (sydpty) [startstop] at (0.2,-1.5) {\texttt{syd-pty}};
    \node (sydtor) [startstop] at (4.2,-1.5) {\texttt{syd-tor}};
    \node at (4.2,-0.5) {\scriptsize Syd};

    % Entry point under legend. Bottom left corner.
    \node (syd) [startstop] at (-3.5,-1.5) {\$ \texttt{syd}};

    % Exec child and sandbox processes
    \node (sbx)   [startstop] at (-3.5,-0.2) {sandbox process$\times$X};

    % Security boundaries
    \foreach \N in {sydmain, sydmon, sydemu, sydipc, sydint, sydaes, sydpty, sydtor, sbx}
      \node[draw=CadetBlue, line width=1.3pt, dotted, rounded corners, fit=(\N), inner sep=1.2pt] {};
    \foreach \N in {sydmain, sydmon, sydemu, sydipc, sydint, sydaes, sydpty, sydtor, sbx}
      \node[draw=OliveGreen, line width=0.9pt, dashdotted, rounded corners, fit=(\N), inner sep=1.4pt] {};
    \foreach \N in {sydmain, sydmon, sydemu, sydipc, sydint, sydaes, sydpty, sydtor}
      \node[draw=red!70!black, line width=0.9pt, dashed, rounded corners, fit=(\N), inner sep=1.5pt] {};
    \foreach \N in {sydmain, sydmon, sydemu, sydipc, sydint, sydaes, sydpty, sydtor}
      \node[draw=purple!70!black, line width=0.9pt, dashdotted, rounded corners, fit=(\N), inner sep=1.7pt] {};
    \foreach \N in {sbx}
      \node[draw=blue, line width=1.3pt, dashed, rounded corners, fit=(\N), inner sep=1.9pt] {};
    \foreach \N in {sbx}
      \node[draw=orange, line width=1.3pt, dotted, rounded corners, fit=(\N), inner sep=2.1pt] {};

    % ARROWS
    % ipc socket to sydipc (straight, label "cmd")
    \draw[arrow] (usock.south) -- node[right, yshift=-2]{cmd} (sydipc.north);

    % sydipc to policy (curly, over policy, label "cmd")
    \draw[arrow,dotted,thick] (sydipc.south) .. controls +(0,-1.1) and +(3.8,0.7) .. node[below right=1.2 and -0.4]{} (policy.north);

    % syd_int to /proc (straight, label "status")
    \draw[arrow] (sydint.north) -- node[left]{status} (proc.south);

    % syd_int to syd_emu (straight, label "SIGALRM")
    \draw[arrow] (sydint.north) -- node[above]{SIGALRM} (sydemu.south);

    % syd_main to syd_mon (straight, label "spawn")
    \draw[arrow] (sydmain.north) -- node[right]{spawn} (sydmon.south);

    % syd_mon to syd_emu (straight, label "spawn")
    \draw[arrow] (sydmon.north) -- node[right]{spawn} (sydemu.south);

    % syd_main to syd-pty (straight, label "exec")
    \draw[arrow] (sydmain.south) -- node[right]{exec} (sydpty.north);

    % syd_main to syd-tor (straight, label "exec")
    \draw[arrow] (sydmain.south) -- node[right]{exec} (sydtor.north);

    % syd_main to policy (straight, label "setup")
    \draw[arrow] (sydmain.north east) -- node[right]{setup} (policy.south west);

    % syd to sydmain (straight, label "exec")
    \draw[arrow] (syd.north east) -- node[below]{exec} (sydmain.south west);

    % sydmain to sbx straight, label "exec")
    \draw[arrow] (sydmain.west) -- node[below]{exec} (sbx.east);

    % sandbox process to Linux, label "syscalls"
    \draw[arrow] (sbx.north east) -- node[left]{syscalls} (linux.south west);

    % linux to syd_emu, label "notify"
    \draw[arrow] (linux.south) -- node[above]{notify} (sydemu.north);

  % Curly arrow from linux to syd_main, label "ptrace"
  \draw[arrow, dashed, draw=orange, line width=1.3pt]
    (linux.south east) .. controls +(1.8,-0.5) and +(0,1.3) ..
    node[above, yshift=30]{ptrace} (sydmain.north east);
  % Straight arrow from syd_emu to sandbox process, label "sysret"
  \draw[arrow] (sydemu.west) -- node[below,yshift=-5]{sysret} (sbx.east);

  % Straight arrow from syd_emu to policy, label "check"
  \draw[arrow] (sydemu.north east) -- node[right, yshift=-12]{check} (policy.north west);

  % Straight arrow from policy to syd_aes, label "encrypt"
  \draw[arrow] (policy.south east) -- node[right]{encrypt} (sydaes.north west);
  \end{tikzpicture}
\end{frame}

\begin{frame}
  \frametitle{DEMO TIME!}
  \framesubtitle{Free games for May, see Emily play!}

  \begin{itemize}
    \item Sacrifice a knight on f7 for DemoGods!
    \item Reproducible under
      \texttt{syd.git/doc/talks/2025-Syd-BalCCon/examples}
    \item Too easy? Try the CTF: \url{https://ctftime.org/event/2178}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Thanks for watching! Questions?}
  \framesubtitle{Wish you were here.}

  \begin{itemize}
    \item Gitlab: \url{https://gitlab.exherbo.org/sydbox/sydbox.git}
    \item Manual: \url{https://man.exherbo.org}
    \item IRC: \#sydbox at Libera
    \item Matrix: \#sydbox:mailstation.de
  \end{itemize}

\end{frame}

\end{document}
