Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
95b6917
Drop obsolete libraries
aleasto May 16, 2026
e0bad1f
Drop unused CRAFT_EXT_CORE_LEVEL variable
aleasto May 15, 2026
44ad564
Re-use snap name from the CRAFT_PROJECT_NAME variable
aleasto May 15, 2026
93adca8
Bump base to core26 and rename snap
aleasto May 15, 2026
9756056
debs: Update to python 3.14
aleasto May 29, 2026
0cec283
buildenv: Set PYTHONPATH to include modules build from source
aleasto May 29, 2026
3695a0b
Fix automake by adding unversioned symlinks
aleasto May 15, 2026
75ff2f0
meson: Don't install in /usr
aleasto May 29, 2026
fde1bf2
meson: Explain why we also need a meson build-package
aleasto May 29, 2026
165ce74
fontconfig: Switch build to meson
aleasto May 15, 2026
6f1d5b5
librsvg: Drop unnecessary meson build package
aleasto May 16, 2026
252c1e7
librsvg: Switch to latest cargo from core26
aleasto May 16, 2026
decea11
libsecret: Disable manpage generation
aleasto May 16, 2026
9c5c42c
libnotify: Order explicitly after meson-deps
aleasto May 16, 2026
36fbdeb
libayatana-appindicator: Drop unused dependency on pcre3
aleasto May 16, 2026
2771a3c
libayatana-appindicator: Do not stage debs from this part
aleasto May 29, 2026
1438d74
Drop clear-execstack cleanup step
aleasto May 16, 2026
9b8de1a
bindtextdomain: Move to merged-usr
aleasto May 16, 2026
380c15c
debs: Follow package renames for core26
aleasto May 16, 2026
8dacf53
Update GLib stack
aleasto May 16, 2026
4e35a9c
Update parts to last versions
sergio-costas May 26, 2026
93e72aa
Add full fontconfig, and make cairo depend on it
sergio-costas May 26, 2026
78b1b95
Fix clash between .deb and fontconfig
sergio-costas May 26, 2026
45d63f0
libffi: Fix build from source
aleasto May 29, 2026
d69956b
Add glycin and update gdk-pixbuf to use glycin
aleasto May 29, 2026
1132a87
tools: Add script for checking why a deb package ends up in the SDK
aleasto May 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions patches/fontconfig-delay.patch
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index a99adba9..e9956fe7 100644
index e225bdc4..29972741 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -442,16 +442,6 @@ main (int argc, char **argv)
@@ -414,16 +414,6 @@ main (int argc, char **argv)

FcConfigDestroy (config);
FcFini ();
- /*
FcFini();
- /*
- * Now we need to sleep a second (or two, to be extra sure), to make
- * sure that timestamps for changes after this run of fc-cache are later
- * then any timestamps we wrote. We don't use gettimeofday() because
Expand Down
234 changes: 234 additions & 0 deletions patches/glycin-snap-no-sandbox.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
diff --git a/glycin/src/api_common.rs b/glycin/src/api_common.rs
index 77285117..4a35f6d6 100644
--- a/glycin/src/api_common.rs
+++ b/glycin/src/api_common.rs
@@ -22,6 +22,7 @@ pub enum SandboxMechanism {
impl SandboxMechanism {
pub async fn detect() -> Self {
match RunEnvironment::cached().await {
+ RunEnvironment::Snap => Self::NotSandboxed,
RunEnvironment::FlatpakDevel => Self::NotSandboxed,
RunEnvironment::Flatpak => Self::FlatpakSpawn,
RunEnvironment::Host => Self::Bwrap,
diff --git a/glycin/src/sandbox.rs b/glycin/src/sandbox.rs
index 2e6d5a15..b2105395 100644
--- a/glycin/src/sandbox.rs
+++ b/glycin/src/sandbox.rs
@@ -18,7 +18,7 @@ use nix::libc::siginfo_t;
use nix::sys::resource;

use crate::config::{ConfigEntry, ImageLoaderConfig};
-use crate::util::{self, AsyncMutex, new_async_mutex, spawn_blocking};
+use crate::util::{self, AsyncMutex, RunEnvironment, new_async_mutex, spawn_blocking};
use crate::{Error, SandboxMechanism};

type SystemSetupStore = Arc<Result<SystemSetup, Arc<io::Error>>>;
@@ -171,6 +171,39 @@ const ALLOWED_SYSCALLS_FONTCONFIG: &[&str] = &[
];

const INHERITED_ENVIRONMENT_VARIABLES: &[&str] = &["RUST_BACKTRACE", "RUST_LOG", "XDG_RUNTIME_DIR"];
+const SNAP_INHERITED_ENVIRONMENT_VARIABLES: &[&str] = &[
+ "RUST_BACKTRACE",
+ "RUST_LOG",
+ "XDG_RUNTIME_DIR",
+ "LD_LIBRARY_PATH",
+ "PATH",
+ "SNAP",
+ "SNAP_ARCH",
+ "SNAP_COMMON",
+ "SNAP_DATA",
+ "SNAP_INSTANCE_KEY",
+ "SNAP_INSTANCE_NAME",
+ "SNAP_LIBRARY_PATH",
+ "SNAP_NAME",
+ "SNAP_REAL_HOME",
+ "SNAP_REVISION",
+ "SNAP_USER_COMMON",
+ "SNAP_USER_DATA",
+ "GIO_EXTRA_MODULES",
+ "GI_TYPELIB_PATH",
+ "GDK_PIXBUF_MODULEDIR",
+ "GDK_PIXBUF_MODULE_FILE",
+ "GST_PLUGIN_PATH",
+ "GST_PLUGIN_SCANNER",
+ "GST_PLUGIN_SYSTEM_PATH",
+ "LIBGL_DRIVERS_PATH",
+ "FONTCONFIG_FILE",
+ "FONTCONFIG_PATH",
+ "FONTCONFIG_SYSROOT",
+ "XDG_CACHE_HOME",
+ "XDG_CONFIG_DIRS",
+ "XDG_DATA_DIRS",
+];

pub struct Sandbox {
sandbox_mechanism: SandboxMechanism,
@@ -216,10 +249,11 @@ impl Sandbox {
let dbus_fd = self.dbus_socket.as_raw_fd();

let mut shared_fds = Vec::new();
+ let run_environment = RunEnvironment::cached().await;

let (mut command, seccomp_fd) = match self.sandbox_mechanism {
SandboxMechanism::Bwrap => {
- let seccomp_memfd = Self::seccomp_export_bpf(&self.seccomp_filter()?)?;
+ let seccomp_memfd = Self::seccomp_export_bpf(&Self::seccomp_filter(&self.config_entry)?)?;
let command = self.bwrap_command(&seccomp_memfd).await?;

shared_fds.push(seccomp_memfd.as_raw_fd());
@@ -232,8 +266,16 @@ impl Sandbox {
(command, None)
}
SandboxMechanism::NotSandboxed => {
- eprintln!("WARNING: Glycin running without sandbox.");
- let command = self.no_sandbox_command();
+ let snap_confined = matches!(run_environment, RunEnvironment::Snap);
+ let command = if snap_confined {
+ eprintln!(
+ "WARNING: Glycin running without additional sandbox inside snap confinement.",
+ );
+ self.snap_command()?
+ } else {
+ eprintln!("WARNING: Glycin running without sandbox.");
+ self.no_sandbox_command()
+ };

(command, None)
}
@@ -560,6 +602,39 @@ impl Sandbox {
command
}

+ fn snap_command(&self) -> Result<Command, Error> {
+ let mut command = Command::new(self.exec());
+
+ command.env_clear();
+ for key in SNAP_INHERITED_ENVIRONMENT_VARIABLES {
+ if let Some(val) = std::env::var_os(key) {
+ command.env(key, val);
+ }
+ }
+
+ let config_entry = self.config_entry.clone();
+
+ unsafe {
+ command.pre_exec(move || {
+ nix::sys::prctl::set_pdeathsig(nix::sys::signal::SIGKILL)
+ .map_err(std::io::Error::from)?;
+
+ let filter = Self::seccomp_filter(&config_entry).map_err(std::io::Error::other)?;
+ if let Err(err) = Self::load_seccomp_filter(&filter) {
+ libc_eprint(
+ "glycin sandbox: Failed to load direct seccomp filter in snap confinement, continuing without syscall filtering: ",
+ );
+ libc_eprint(&err.to_string());
+ libc_eprint("\n");
+ }
+
+ Ok(())
+ });
+ }
+
+ Ok(command)
+ }
+
/// Memory limit in bytes that should be applied to sandboxes
fn memory_limit() -> resource::rlim_t {
// Lookup free memory
@@ -635,7 +710,7 @@ impl Sandbox {
}
}

- fn seccomp_filter(&self) -> Result<ScmpFilterContext, SeccompError> {
+ fn seccomp_filter(config_entry: &ConfigEntry) -> Result<ScmpFilterContext, SeccompError> {
// Using `KillProcess` allows rejected syscalls to be logged by auditd. But it
// doesn't work with tools like valgrind. That's why it's not used by default.
let mut filter = if std::env::var("GLYCIN_SECCOMP_DEFAULT_ACTION")
@@ -649,7 +724,7 @@ impl Sandbox {
};

let mut syscalls = vec![ALLOWED_SYSCALLS];
- if self.config_entry.fontconfig() {
+ if config_entry.fontconfig() {
// Enable some write operations for fontconfig to update its cache
syscalls.push(ALLOWED_SYSCALLS_FONTCONFIG);
}
@@ -666,6 +741,14 @@ impl Sandbox {
Ok(filter)
}

+ fn load_seccomp_filter(filter: &ScmpFilterContext) -> io::Result<()> {
+ if unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) } != 0 {
+ return Err(io::Error::last_os_error());
+ }
+
+ filter.load().map_err(io::Error::other)
+ }
+
/// Make seccomp filters available under FD
///
/// Bubblewrap supports taking an fd to seccomp filters in the BPF format.
@@ -710,7 +793,7 @@ impl Sandbox {
let (dbus_socket, _) = UnixStream::pair()?;
let sandbox = Self::new(SandboxMechanism::Bwrap, config_entry, dbus_socket);

- let seccomp_memfd = Self::seccomp_export_bpf(&sandbox.seccomp_filter()?)?;
+ let seccomp_memfd = Self::seccomp_export_bpf(&Self::seccomp_filter(&sandbox.config_entry)?)?;
let mut command = sandbox.bwrap_command(&seccomp_memfd).await?;

unsafe {
diff --git a/glycin/src/util.rs b/glycin/src/util.rs
index 765a5953..df48aede 100644
--- a/glycin/src/util.rs
+++ b/glycin/src/util.rs
@@ -71,6 +71,8 @@ pub enum RunEnvironment {
Host,

HostBwrapSyscallsBlocked,
+ /// Inside Snap confinement
+ Snap,
/// Inside Flatpak
Flatpak,
/// Inside Flatpak and development environment
@@ -86,7 +88,9 @@ impl RunEnvironment {
if let Some(result) = *run_environment {
result
} else {
- let run_env = if let Some(devel) = flatpak_devel().await {
+ let run_env = if snap_confined().await {
+ Self::Snap
+ } else if let Some(devel) = flatpak_devel().await {
if devel {
Self::FlatpakDevel
} else {
@@ -104,6 +108,30 @@ impl RunEnvironment {
}
}

+async fn snap_confined() -> bool {
+ if let Ok(apparmor_label) = read("/proc/self/attr/current").await
+ && snap_apparmor_label(&apparmor_label)
+ {
+ return true;
+ }
+
+ std::env::var_os("SNAP").is_some() || std::env::var_os("SNAP_NAME").is_some()
+}
+
+fn snap_apparmor_label(label: &[u8]) -> bool {
+ let label = String::from_utf8_lossy(label);
+ let label = label.trim_matches(char::from(0)).trim();
+
+ if label == "unconfined" {
+ return false;
+ }
+
+ label
+ .split_ascii_whitespace()
+ .next()
+ .is_some_and(|profile| profile.starts_with("snap."))
+}
+
/// Returns None if not in Flatpak environment, otherwise true if development
async fn flatpak_devel() -> Option<bool> {
let data = read("/.flatpak-info").await.ok()?;
12 changes: 0 additions & 12 deletions patches/libgweather.diff

This file was deleted.

Loading
Loading