Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust/cargo apparmor profile #621

Closed
bf opened this issue Dec 7, 2024 · 6 comments
Closed

rust/cargo apparmor profile #621

bf opened this issue Dec 7, 2024 · 6 comments

Comments

@bf
Copy link

bf commented Dec 7, 2024

I noticed that that rust/cargo provides basically unrestricted access for third-party modules from crates.io not only at compile time but also when doing things like cargo doc.

Therefore I'm building an apparmor profile for cargo/cargo-fmt/cargo-clippy/rustc/rustfmt/rustdoc binaries.

Do you think this is in scope for this project? Should I create pull request for this?

@bf
Copy link
Author

bf commented Dec 8, 2024

Here's the profile for rust/cargo

# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2024 Alexandre Pujol <[email protected]>
# SPDX-License-Identifier: GPL-2.0-only

abi <abi/4.0>,   
# abi <kernel>,

include <tunables/global>

# profile @{bin}/rustdoc flags=(kill) {
profile @{bin}/rustdoc flags=(attach_disconnected)  {
deny userns, 

  include <abstractions/base>
  include <abstractions/consoles>

  audit deny network,

  @{bin}/rustdoc mr,
  owner @{HOME}/src/*.rs r,
  owner @{HOME}/src/**.rs r,
  owner @{HOME}/src/**/target/*/** rm,
  owner @{HOME}/src/**/target/doc/** rw,
  owner @{HOME}/src/**/target/doc/.lock rwk,
  owner @{HOME}/.cargo/registry/** r,

  @{PROC}/@{pid}/cgroup r,
  @{PROC}/@{pid}/statm r,
  /sys/kernel/mm/**/* r,
  /sys/fs/**/cpu.max r,

  @{bin}/rustc px,
}

profile @{bin}/{cargo-fmt,rustfmt} flags=(attach_disconnected)  {
#profile @{bin}/{cargo-fmt,rustfmt} flags=(kill) {
deny userns, 

  audit deny network,
  include <abstractions/base>
  include <abstractions/consoles>

  @{bin}/{cargo-fmt,rustfmt} mr,

  owner @{HOME}/.local/share/gnome-shell/session.gvdb rw,
  owner @{HOME}/src/*.rs rw,

  /usr/share/terminfo/** r,
}

#profile @{bin}/rustc flags=(kill) {
profile @{bin}/rustc flags=(attach_disconnected) {
deny userns, 

  @{bin}/rustc mr,

  include <abstractions/base>
  include <abstractions/consoles>

  # network (create, setattr, getattr, send) unix seqpacket,
  network unix seqpacket,
  signal (send,receive),

  capability fsetid,
  capability mknod,
  capability chown,

  owner @{HOME}/src/**/target/** rw,

  /usr/lib/** mrl,

  owner @{HOME}/.cargo/registry/** rw,
  owner @{HOME}/.local/share/gnome-shell/session.gvdb rw,
    
  owner @{HOME}/src/**.rs r,
  # owner @{HOME}/src/**/*.rs r,
  owner @{HOME}/src/*/target{,-install}/** rwklwm,
  # owner @{HOME}/src/**/target/**/* rmw,
  # owner @{HOME}/src/**/target/**/*.o rwlk,
  # owner @{HOME}/src/**/target/**/*.lock rwk,
  # owner @{HOME}/src/**/target/**/*.so rwkm,
  # owner @{HOME}/src/**/target/**/*.bin rwlm,
  # owner @{HOME}/src/**/target/**/.cargo-lock rwk,
  # owner @{HOME}/src/**/target/**/.fingerprint/** rwk,

  @{PROC}/@{pid}/cgroup r,
  @{PROC}/@{pid}/statm r,
  /sys/kernel/mm/**/* r,
  /sys/fs/**/cpu.max r,

  /etc/ld.so.{preload,cache} r,


  # rustc wants to access cargo folder
  owner @{HOME}/.cargo/registry/** r,

  @{bin}/gcc Pixlr,
  @{bin}/cc Pixlr,
  @{bin}/ld Pixlr,

  # rustc temp folder
  /tmp/{rustc,cargo-install}??????/{,**} Cixrwlk,

  # cc output file
  /tmp/cc* rw,
  /usr/lib/gcc/**/collect2 Cix,
  /usr/lib/gcc/**/cc1 Cix,
}

# profile @{bin}/cargo flags=(kill,audit) {
profile @{bin}/cargo flags=(attach_disconnected) {
  deny userns, 
  owner @{HOME}/.local/share/gnome-shell/session.gvdb rw,

  include <abstractions/base>
  include <abstractions/consoles>
  include <abstractions/nameservice-strict>
  include <abstractions/ssl_certs>

  capability fsetid,
  capability mknod,
  capability chown,

  @{bin}/cargo mrPx,

  # /run/systemd/resolve/io.systemd.Resolve rw,
  # unix (connect, send, receive) type=stream peer=(label=/run/systemd/resolve/io.systemd.Resolve),

  # see https://gitlab.com/apparmor/apparmor/-/blob/master/parser/apparmor.d.pod

  #  audit deny network,
  #   audit deny unix,
  network inet  tcp,
  network inet6 tcp,
  network inet  udp,
  network inet6 udp,
  network netlink raw,
  # network (create, setattr, getattr, send) unix seqpacket,
  network unix seqpacket,
  signal (send,receive),

 #    allow network (create, setattr, getattr) inet udp,
  #   allow network (create, setattr, getattr) inet tcp,

  #    allow network  inet tcp peer=(port=443),
  #allow network inet6 peer=(port=443),
  #allow network ( connect, send, receive, receive ) inet dgram peer=(port=53),
  #allow network ( connect, send, receive ) inet6 dgram peer=(port=53),

  # owner @{HOME}/.cargo/.crates.toml rwk,
  owner @{HOME}/.cargo/{,**} rkw,
  owner @{HOME}/.cargo/bin/** ixrw,
  # owner @{HOME}/.cargo/**/.cargo-ok rw,
  # owner @{HOME}/.cargo/.global-cache rwk,
  # owner @{HOME}/.cargo/.package-cache rwk,
  # owner @{HOME}/.cargo/.package-cache-mutate rwk,
  
  owner @{HOME}/.gitconfig r,

  # # for cargo check cargo will try to create a target?????? temp older
  # # for cargo install udeps it will try to create a target-install?????? temp older
  # owner @{HOME}/src/*/target{,-install}/**/.cargo-lock rwk,
  # owner @{HOME}/src/*/target{,-install}{,??????}/{,**} rwk,
  owner @{HOME}/src/** r,
  owner @{HOME}/src/*/src/**.rs rw,
  owner @{HOME}/src/*/.git/** r,
  owner @{HOME}/src/*/Cargo.toml rw,
  owner @{HOME}/src/*/Cargo.lock rwk,
  
  # owner @HOME/src/*/target/debug/build/crossbeam-utils-8baf432b752f5fbe/build-script-build Pix,

  owner @{HOME}/src/*/target{,-install}{,??????}/{,**} ixrwklm,

  # owner @{HOME}/src/*/target{,-install}{,??????}/{,**} rwklm,

  /usr/lib/rustlib/src/rust/library/Cargo.lock k,


  # build scripts from deps
  # owner @{HOME}/src/*/target{,-install}/**/build[-_]script[-_]* ixrwklm,
  #  @{HOME}/src/*/target{,-install}/**/build[-_]script[-_]* ixrwklm,
  

  # for cargo remove foo cargo will try to create Cargo.toml?????? temp file,

  owner @{HOME}/src/**/Cargo.toml?????? rw,

  @{PROC}/@{pid}/cgroup r,
  /sys/fs/**/cpu.max r,

  # cargo install folder
  /tmp/{rustc,cargo-install}??????/{,**} Cixrwlk,

  # cargo build stuff
  /tmp/cc* rw,
  /usr/lib/gcc/**/collect2 Cix,
  /usr/lib/gcc/**/cc1 Cix,

  /usr/lib/** rm,
  /etc/ld.so.{preload,cache} r,

  @{bin}/gcc Pixlr,
  @{bin}/cc Pixlr,
  @{bin}/ld Pixlr,
  @{bin}/as Pixlr,
  @{bin}/ar Pixlr,
  @{bin}/pkgconf Pixlr,

  # for cc1
  /usr/include/** r,

  @{bin}/rustc px,
  @{bin}/rustfmt px,
  @{bin}/rustdoc px,
  @{bin}/rust-analyzer ix,
}


# vim:syntax=apparmor

Updated version will be hosted at https://github.com/bf/rust-security-problems/blob/main/apparmor-cargo.conf

@roddhjav
Copy link
Owner

This program (and by extension any building program) are a program that usually should not be confined using MAC policies.

To sum up:

  • Usage of development commands varies a lot depending on project to build and target.
  • They can usually start any other developer command
  • The resulting profile would break a lot of dev process
  • Sandboxing your full development process is a better/easier solution

@beroal
Copy link
Contributor

beroal commented Jan 1, 2025

I need Rust utilities too and created a very rough profile for them.

My take on the situation is that there are different ways to isolate programs and processes (as opposed to user isolation which is already in Unix) on Linux. Since the issue is young, it's hard to tell the shape of the future system.

The current version of AppArmor has limitations comparing to user namespaces (example). But user namespaces aren't widely deployed. Another issue is that source and target code paths can only be defined by the root. You defined them for yourself. I don't have

owner @{HOME}/src/** r,
owner @{HOME}/src/*/.git/** r,

Actually, there were a couple of discussions. Hence Alex restricts what goes into this repository. You'll need your own repository if you believe in this application of AppArmor.

@bf
Copy link
Author

bf commented Jan 2, 2025

Yeah, I'd need to fork this repo because there are so many oddities around chromium/thunderbird profiles for which I had to customize apparmor.d rules. Obviously we all fight the apparmor.d restrictions (e.g. umlaut handling...) so we're all trying to do what we can.

The cargo rules actually work quite well at this point, and the malicious payloads I've showcased for rust can be mitigated with this approach. Feel free to look at https://github.com/bf/rust-security-problems/blob/main/apparmor-cargo.conf if you're interested.

I'm a bit allergic to this "if it's not 100% secure we wont bother implementing it" approach because we're talking about a single layer in a defense-in-depth approach here to catch the most basic malware.

While linux is very robust out of the box, the security controls for everyday users can be improved quite a bit :)

Closing this issue because maintainers won't implement. Thanks for your input!

@bf bf closed this as completed Jan 2, 2025
@roddhjav
Copy link
Owner

roddhjav commented Jan 9, 2025

I'm a bit allergic to this "if it's not 100% secure we wont bother implementing it"

This is not my approach at all (I will expand more on this once the full security model will be out).

My main concern here is that:

  • To not break someone else workstation because they use special locations/tools/extensions/providers/technologies that would break a build with a profile too generic,
  • Not a priority (Still a one-person project)

owner @{HOME}/src/** r,
owner @{HOME}/src/*/.git/** r,

This can be easily fixed thanks to the use of the @{user_projects_dirs} variable.

I'd need to fork this repo because there are so many oddities around chromium/thunderbird profiles for which I had to customize apparmor.d rules.

Can you tell us more?

@roddhjav
Copy link
Owner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants