Classic confinement request for Mission Center

Hello :wave:

I am the main developer of the Mission Center monitoring app and would like to ask for an allowance to publish the app under classic confinement.

The application monitors and reports, CPU, memory, disk, network, GPU usage, application state, process state, as well as system services.

In order to facilitate these readings it requires access to the host filesystem, which would partially work (with some tweaking) under strict confinement but also requires access to several D-Bus interfaces such as org.gnome.Settings, org.freedesktop.NetworkManager and org.freedesktop.systemd1; which, to my understanding, cannot be done under strict confinement.

I’ll leave a link to the website and the repository: https://missioncenter.io/ https://gitlab.com/mission-center-devs/mission-center

For the sake of full transparency the app is currently packaged using an alternative format and published on an alternative platform. But I would love to make the Snap version a first-class citizen.

Thank you for your consideration.

Romeo

EDIT: Please let me know what information, if any, I can provide to help.

2 Likes

Regarding the dbus accesses, this is possible through interfaces like desktop, network-manager-observe and system-observe - can you please try plugging these?

Thanks for the suggestions.

I initially started out with strict confinement and used, among others, the plugs you mention and kept getting apparmor DENIED errors.

Let me give it another shot and I’ll post again with the results.

I now have the following plugs listed and connected (via the snap connect command):

  • desktop
  • desktop-legacy
  • wayland
  • x11
  • opengl
  • network-manager-observe
  • network-observe
  • system-observe
  • process-control

And this is what I see in the systemd journal logs:

audit: type=1107 audit(1717568011.841:25411): pid=840 uid=103
auid=4294967295 ses=4294967295 subj=unconfined msg='apparmor="DENIED"
operation="dbus_method_call"  bus="system" path="/org/freedesktop/NetworkManager"
interface="org.freedesktop.NetworkManager" member="GetDeviceByIpIface" mask="send"
name=":1.7" pid=420212 label="snap.mission-center.mission-center" peer_pid=856
peer_label="unconfined"

Ah ok, so that particular method is not provided by network-manager-observe - instead you should use network-manager which allows access to all methods on NetworkManager (which seems perhaps too permissive for this usecase and makes me think we should add this method (GetDeviceByIpIface) to the -observe interface instance in snapd.

Thanks, that fixed it.

Another issue is that in order to be able to start, stop, restart, enable and disable services I also use org.freedesktop.systemd1.Manager.

I tried daemon-notify plug, but that doesn’t seem to work.

As expected I get an apparmor denial:

audit: type=1107 audit(1717577915.882:36539): pid=840 uid=103 auid=4294967295 ses=4294967295
subj=unconfined msg='apparmor="DENIED" operation="dbus_method_call"  bus="system"
path="/org/freedesktop/systemd1" interface="org.freedesktop.systemd1.Manager"
member="StopUnit" mask="send" name="org.freedesktop.systemd1" pid=457670
label="snap.mission-center.mission-center" peer_pid=1 peer_label="unconfined"

Unrelated to the above, another feature the app provides is a list of running apps (not processes).

This is done by reading and parsing .desktop files from the users system, originating from Snap, .deb/.rmp, or even Flatpak to get a list of installed apps.

This feature is also broken using strict confinement even though I enabled read access to the relevant directories. Essentially I get an Permission Denied error whenever trying to open a .desktop file.

I have the following plugs declared in the snapcraft.yaml file:

plugs:         
  snap-desktop-files:
    interface: system-files
    read:              
      - /var/lib/snapd/desktop
                      
  flatpak-desktop-files:
    interface: system-files
    read:            
      - /var/lib/flatpak/exports/share
                             
  system-desktop-files:     
    interface: system-files 
    read:              
      - /usr/share/share/applications
                                  
  system-hicolor-icons:   
    interface: system-files
    read:                     
      - /usr/share/icons/hicolor                                      

  var-log-journal:
    interface: system-files
    read:      
      - /var/log/journal
                     
  run-log-journal:                                                                                                                                                                                    
    interface: system-files
    read:               
      - /run/log/journal      
                                      
  flatpak-user-desktop-files:                                                                                                                                                            
    interface: personal-files                                                                             
    read:                                                                                                            
      - $HOME/.local/share/flatpak/exports/share
                     
  user-desktop-files:                                                                                       
    interface: personal-files                                  
    read:                                                                                                                    
      - $HOME/.local/share/applications                                                                                               

  user-hicolor-icons:
    interface: personal-files
    read:
      - $HOME/.local/share/icons/hicolor

This app uses a lot of other things to show the processes, and there is no such plug/slot where snapcraft allows to get this. I snapped a similar gnome app named Resources and this app seems to be the same. They need access to all the app desktop files under /usr/share/applications and other desktop folders. Also, some more details on the graphic cards aren’t found via the plugs. And this page specifically is completely blank

Those directories are mounted under /var/lib/snapd/hostfs/<folder>. You need change the directories to append this before that, and regarding $HOME/.local, you need to access that via $SNAP_REAL_HOME/.local

Thanks for the hints.

I’ll give it a try :crossed_fingers:

Do I still need the system-files and personal-files plugs then?

@kicsyromy I created this patch and now some works, but I guess you can fix the others.

diff --git a/src/utils/app.rs b/src/utils/app.rs
index 2f06d3b..f8f55dc 100644
--- a/src/utils/app.rs
+++ b/src/utils/app.rs
@@ -26,17 +26,33 @@ static RE_FLATPAK_FILTER: Lazy<Regex> =
 
 // Adapted from Mission Center: https://gitlab.com/mission-center-devs/mission-center/
 static DATA_DIRS: Lazy<Vec<PathBuf>> = Lazy::new(|| {
-    let home = std::env::var("HOME").unwrap_or_else(|_| "/".to_string());
+    let home = std::env::var("SNAP_REAL_HOME").unwrap_or_else(|_| std::env::var("HOME").unwrap_or_else(|_| "/".to_string()));
+
+    let snap_prefix = if std::env::var("SNAP").is_ok() {
+        "/var/lib/snapd/hostfs/"
+    } else {
+        ""
+    };
+
     let mut data_dirs: Vec<PathBuf> = std::env::var("XDG_DATA_DIRS")
-        .unwrap_or_else(|_| format!("/usr/share:{}/.local/share", home))
+        .unwrap_or_else(|_| format!("/usr/share:{home}/.local/share"))
         .split(':')
-        .map(PathBuf::from)
+        .map(|path| {
+            if path == format!("{home}/.local/share") || path == "/var/lib/snapd/desktop" {
+                PathBuf::from(path)
+            } else {
+                PathBuf::from(format!("{}{}", snap_prefix, path))
+            }
+        })
         .collect();
-    data_dirs.push(PathBuf::from(format!("{}/.local/share", home)));
+
+    data_dirs.push(PathBuf::from(format!("{home}/.local/share")));
     data_dirs
 });
 
-// This contains known occurences of processes having a too distinct name from the actual app
+
+
+// This contains known occurrences of processes having a too distinct name from the actual app
 // The HashMap is used like this:
 //   Key: The name of the executable of the process
 //   Value: What it should be replaced with when finding out to which app it belongs
1 Like

@soumyaDghosh Thanks for the hints and the patch. Sadly this doesn’t do much. The Applications section of the app is baren :frowning:

Could you share a link to the snapcraft.yaml for Resources, maybe I can use it as inspiration.

@alexmurray How can we proceed from here? With strict confinement the application is working but in a bad state, not sure what I can do to remedy it.

Thank you for your patience. This is my first snap and I’m still wrapping my head around the terminology and procedures.

Yes, same with resources, I added debug lines and one thing I cannot understand, why is it not taking other snaps into account. It can read the files and it’s reading. Can you add some debugs there?

name: resources
base: core22
adopt-info: resources
grade: stable
confinement: strict
compression: lzo

parts:
  rustup:
    plugin: rust
    source: .
    rust-channel: "1.76"
    override-build: ""
    override-prime: ""

  resources:
    after: [rustup]
    plugin: meson
    source: .
    #source-tag: "v1.3.0"
    #source-depth: 1
    parse-info: [usr/share/metainfo/net.nokyan.Resources.metainfo.xml]
    meson-parameters:
      - --prefix=/snap/resources/current/usr
      - -Dprofile=default
    # override-pull: |
    #   craftctl default
    #   echo "Patching."
    #   patch -p1 < $CRAFT_PROJECT_DIR/app.patch
    build-environment:
      - PATH: ${HOME}/.cargo/bin:${PATH}
    organize:
      snap/resources/current: .

  deps:
    plugin: nil
    stage-packages:
      - dmidecode
    prime:
      - -usr/share
    organize:
      usr/sbin: usr/bin

slots:
  resources:
    interface: dbus
    bus: session
    name: net.nokyan.Resources


plugs:
  usr-share:
    interface: system-files
    read:
      - /var/lib/snapd/hostfs/usr/share/applications
      - /var/lib/snapd/hostfs/usr/share/icons
  var-lib-snapd-desktop:
    interface: system-files
    read:
      - /var/lib/snapd/desktop/applications
      - /var/lib/snapd/desktop/icons

apps:
  resources:
    command: usr/bin/resources
    desktop: usr/share/applications/net.nokyan.Resources.desktop
    common-id: net.nokyan.Resources
    extensions: [gnome]
    environment:
      XDG_DATA_DIRS: /var/lib/snapd/hostfs/usr/share:$XDG_DATA_DIRS
    plugs:
      - mount-observe
      - system-observe
      - hardware-observe

Also, the code is too much flatpak specific. We can make it work with strict confinement. You just need to adopt to the changes of how snaps work.

Thanks for the snapcraft.yaml.

Assuming we can fix the applications there are still two more issues that need solving:

  1. Starting/stopping/etc of services
  2. Retrieving service logs (aka reading /var/log/journal) tha doesn’t seem to work no matter with libsystemd out of the box

Also, the code is too much flatpak specific. We can make it work with strict confinement. You just need to adopt to the changes of how snaps work.

There is nothing about the code that’s Flatpak specific, other then where the missioncenter-gatherer executable is located. I develop and test using a native build on Ubuntu 24.04. The app also ships an AppImage that works fine.

1 Like

Here you go, found the needed plug, log-observe

How does that work? I mean how do you kill the apps? I am not a super knowledgeable guy on rust. Kindly forgive me for that, but can you please explain a bit about it?

How does that work? I mean how do you kill the apps? I am not a super knowledgeable guy on rust. Kindly forgive me for that, but can you please explain a bit about it?

I mean to say that the app supports managing SystemD services running on the system. This is done via the official DBUs API

Uhh okay, there is an interface named docker-support but, as the name suggests, it’s probably only for docker. You can give it a try and see if it’s working. If it works then I’ll try to implement the same in a different interface.

Cool, thanks.

I’ll give it a go.

docker-support fixed the service management :tada:

Logs still don’t work, but that’s not that big of a deal

Only thing remaining is the list of applications, I’ll keep at it in the hopes I can come up with something.

Thanks again for the help, wouldn’t have gotten this far without it.

One other thing that scares me is the list or plugs :worried::

      - desktop                                                            
      - desktop-legacy                                      
      - wayland
      - x11                                                                
      - opengl                                                     
      - network-manager                                                    
      - network-observe       
      - system-observe                                            
      - process-control                                           
      - hardware-observe                                            
      - block-devices                                                   
      - log-observe                                                   
      - docker-support

I think that docker-supoort connection is here as a workaround. We need support from architecture team here to work on this issue, since docker-support interface is super-privileged.