Version in base suite: 6.0.4-2 Version in overlay suite: 6.0.4-2+deb13u1 Base version: incus_6.0.4-2+deb13u1 Target version: incus_6.0.4-2+deb13u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/i/incus/incus_6.0.4-2+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/i/incus/incus_6.0.4-2+deb13u2.dsc changelog | 6 + patches/106a-GHSA-56mx-8g9f-5crf.patch | 111 +++++++++++++++++++++++++++++++++ patches/106b-GHSA-56mx-8g9f-5crf.patch | 69 ++++++++++++++++++++ patches/106c-GHSA-56mx-8g9f-5crf.patch | 34 ++++++++++ patches/series | 3 5 files changed, 223 insertions(+) diff -Nru incus-6.0.4/debian/changelog incus-6.0.4/debian/changelog --- incus-6.0.4/debian/changelog 2025-10-02 15:51:07.000000000 +0000 +++ incus-6.0.4/debian/changelog 2025-11-10 13:32:56.000000000 +0000 @@ -1,3 +1,9 @@ +incus (6.0.4-2+deb13u2) trixie-security; urgency=high + + * Backport upstream fix for GHSA-56mx-8g9f-5crf + + -- Mathias Gibbens Mon, 10 Nov 2025 13:32:56 +0000 + incus (6.0.4-2+deb13u1) trixie-security; urgency=high * Backport fixes for the following security issues: diff -Nru incus-6.0.4/debian/patches/106a-GHSA-56mx-8g9f-5crf.patch incus-6.0.4/debian/patches/106a-GHSA-56mx-8g9f-5crf.patch --- incus-6.0.4/debian/patches/106a-GHSA-56mx-8g9f-5crf.patch 1970-01-01 00:00:00.000000000 +0000 +++ incus-6.0.4/debian/patches/106a-GHSA-56mx-8g9f-5crf.patch 2025-11-10 04:40:22.000000000 +0000 @@ -0,0 +1,111 @@ +From c5359c809836c0f3b1e6022bf0528bb90ce06ad7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?St=C3=A9phane=20Graber?= +Date: Sun, 9 Nov 2025 18:41:24 -0500 +Subject: [PATCH] incusd/storage: Tighten storage pool volume permissions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Closes #2641 + +Signed-off-by: Stéphane Graber +--- + internal/server/storage/backend.go | 5 +++-- + internal/server/storage/drivers/driver_btrfs.go | 2 +- + .../server/storage/drivers/driver_zfs_utils.go | 4 ++-- + internal/server/storage/drivers/generic_vfs.go | 4 ++-- + internal/server/storage/drivers/volume.go | 17 +++++++++++------ + 5 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/internal/server/storage/backend.go b/internal/server/storage/backend.go +index 2b69c426fa0..43dcaa760a1 100644 +--- a/internal/server/storage/backend.go ++++ b/internal/server/storage/backend.go +@@ -6205,9 +6205,10 @@ func (b *backend) RestoreCustomVolume(projectName, volName string, snapshotName + + func (b *backend) createStorageStructure(path string) error { + for _, volType := range b.driver.Info().VolumeTypes { +- for _, name := range drivers.BaseDirectories[volType] { ++ for _, name := range drivers.BaseDirectories[volType].Paths { + path := filepath.Join(path, name) +- err := os.MkdirAll(path, 0o711) ++ ++ err := os.MkdirAll(path, drivers.BaseDirectories[volType].Mode) + if err != nil && !os.IsExist(err) { + return fmt.Errorf("Failed to create directory %q: %w", path, err) + } +diff --git a/internal/server/storage/drivers/driver_btrfs.go b/internal/server/storage/drivers/driver_btrfs.go +index 5e436aa4776..24cdaa308e1 100644 +--- a/internal/server/storage/drivers/driver_btrfs.go ++++ b/internal/server/storage/drivers/driver_btrfs.go +@@ -268,7 +268,7 @@ func (d *btrfs) Delete(op *operations.Operation) error { + + // Delete potential intermediate btrfs subvolumes. + for _, volType := range d.Info().VolumeTypes { +- for _, dir := range BaseDirectories[volType] { ++ for _, dir := range BaseDirectories[volType].Paths { + path := filepath.Join(GetPoolMountPath(d.name), dir) + if !util.PathExists(path) { + continue +diff --git a/internal/server/storage/drivers/driver_zfs_utils.go b/internal/server/storage/drivers/driver_zfs_utils.go +index ae2c80138a3..c2a71e17068 100644 +--- a/internal/server/storage/drivers/driver_zfs_utils.go ++++ b/internal/server/storage/drivers/driver_zfs_utils.go +@@ -301,8 +301,8 @@ func (d *zfs) initialDatasets() []string { + + // Iterate over the listed supported volume types. + for _, volType := range d.Info().VolumeTypes { +- entries = append(entries, BaseDirectories[volType][0]) +- entries = append(entries, filepath.Join("deleted", BaseDirectories[volType][0])) ++ entries = append(entries, BaseDirectories[volType].Paths[0]) ++ entries = append(entries, filepath.Join("deleted", BaseDirectories[volType].Paths[0])) + } + + return entries +diff --git a/internal/server/storage/drivers/generic_vfs.go b/internal/server/storage/drivers/generic_vfs.go +index 8727c003c3a..6489b6b0547 100644 +--- a/internal/server/storage/drivers/generic_vfs.go ++++ b/internal/server/storage/drivers/generic_vfs.go +@@ -1151,11 +1151,11 @@ func genericVFSListVolumes(d Driver) ([]Volume, error) { + poolMountPath := GetPoolMountPath(poolName) + + for _, volType := range d.Info().VolumeTypes { +- if len(BaseDirectories[volType]) < 1 { ++ if len(BaseDirectories[volType].Paths) < 1 { + return nil, fmt.Errorf("Cannot get base directory name for volume type %q", volType) + } + +- volTypePath := filepath.Join(poolMountPath, BaseDirectories[volType][0]) ++ volTypePath := filepath.Join(poolMountPath, BaseDirectories[volType].Paths[0]) + ents, err := os.ReadDir(volTypePath) + if err != nil { + return nil, fmt.Errorf("Failed to list directory %q for volume type %q: %w", volTypePath, volType, err) +diff --git a/internal/server/storage/drivers/volume.go b/internal/server/storage/drivers/volume.go +index cc503b2ead0..640c614ca25 100644 +--- a/internal/server/storage/drivers/volume.go ++++ b/internal/server/storage/drivers/volume.go +@@ -85,13 +85,18 @@ const ContentTypeISO = ContentType("iso") + // VolumePostHook function returned from a storage action that should be run later to complete the action. + type VolumePostHook func(vol Volume) error + ++type baseDirectory struct { ++ Paths []string ++ Mode os.FileMode ++} ++ + // BaseDirectories maps volume types to the expected directories. +-var BaseDirectories = map[VolumeType][]string{ +- VolumeTypeBucket: {"buckets"}, +- VolumeTypeContainer: {"containers", "containers-snapshots"}, +- VolumeTypeCustom: {"custom", "custom-snapshots"}, +- VolumeTypeImage: {"images"}, +- VolumeTypeVM: {"virtual-machines", "virtual-machines-snapshots"}, ++var BaseDirectories = map[VolumeType]baseDirectory{ ++ VolumeTypeBucket: {Paths: []string{"buckets"}, Mode: 0o711}, ++ VolumeTypeContainer: {Paths: []string{"containers", "containers-snapshots"}, Mode: 0o711}, ++ VolumeTypeCustom: {Paths: []string{"custom", "custom-snapshots"}, Mode: 0o700}, ++ VolumeTypeImage: {Paths: []string{"images"}, Mode: 0o700}, ++ VolumeTypeVM: {Paths: []string{"virtual-machines", "virtual-machines-snapshots"}, Mode: 0o700}, + } + + // Volume represents a storage volume, and provides functions to mount and unmount it. diff -Nru incus-6.0.4/debian/patches/106b-GHSA-56mx-8g9f-5crf.patch incus-6.0.4/debian/patches/106b-GHSA-56mx-8g9f-5crf.patch --- incus-6.0.4/debian/patches/106b-GHSA-56mx-8g9f-5crf.patch 1970-01-01 00:00:00.000000000 +0000 +++ incus-6.0.4/debian/patches/106b-GHSA-56mx-8g9f-5crf.patch 2025-11-10 13:32:31.000000000 +0000 @@ -0,0 +1,69 @@ +From 57096066959c843e1c413c4a97f64077b95cb397 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?St=C3=A9phane=20Graber?= +Date: Sun, 9 Nov 2025 18:41:39 -0500 +Subject: [PATCH] incusd/patches: Re-apply storage permissions on update +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Stéphane Graber +--- + cmd/incusd/patches.go | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/cmd/incusd/patches.go b/cmd/incusd/patches.go +index b808ffa2907..14d78f92720 100644 +--- a/cmd/incusd/patches.go ++++ b/cmd/incusd/patches.go +@@ -86,6 +86,7 @@ var patches = []patch{ + {name: "runtime_directory", stage: patchPostDaemonStorage, run: patchRuntimeDirectory}, + {name: "lvm_node_force_reuse", stage: patchPostDaemonStorage, run: patchLvmForceReuseKey}, + {name: "auth_openfga_viewer", stage: patchPostNetworks, run: patchGenericAuthorization}, ++ {name: "pool_fix_default_permissions", stage: patchPostDaemonStorage, run: patchDefaultStoragePermissions}, + } + + type patch struct { +@@ -1342,4 +1343,43 @@ UPDATE networks_load_balancers SET ports="null" WHERE ports=""; + return nil + } + ++// patchDefaultStoragePermissions re-applies the default modes to all storage pools. ++func patchDefaultStoragePermissions(_ string, d *Daemon) error { ++ s := d.State() ++ ++ var pools []string ++ ++ err := s.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error { ++ var err error ++ ++ // Get all storage pool names. ++ pools, err = tx.GetStoragePoolNames(ctx) ++ ++ return err ++ }) ++ if err != nil { ++ // Skip the rest of the patch if no storage pools were found. ++ if api.StatusErrorCheck(err, http.StatusNotFound) { ++ return nil ++ } ++ ++ return fmt.Errorf("Failed getting storage pool names: %w", err) ++ } ++ ++ for _, pool := range pools { ++ for _, volEntry := range storageDrivers.BaseDirectories { ++ for _, volDir := range volEntry.Paths { ++ path := filepath.Join(storagePools.GetStoragePoolMountPoint(pool), volDir) ++ ++ err := os.Chmod(path, volEntry.Mode) ++ if err != nil && !os.IsExist(err) { ++ return fmt.Errorf("Failed to set directory mode %q: %w", path, err) ++ } ++ } ++ } ++ } ++ ++ return nil ++} ++ + // Patches end here diff -Nru incus-6.0.4/debian/patches/106c-GHSA-56mx-8g9f-5crf.patch incus-6.0.4/debian/patches/106c-GHSA-56mx-8g9f-5crf.patch --- incus-6.0.4/debian/patches/106c-GHSA-56mx-8g9f-5crf.patch 1970-01-01 00:00:00.000000000 +0000 +++ incus-6.0.4/debian/patches/106c-GHSA-56mx-8g9f-5crf.patch 2025-11-10 13:32:38.000000000 +0000 @@ -0,0 +1,34 @@ +From 27232680a75f5c96bae1f39dc085b7e59b882815 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?St=C3=A9phane=20Graber?= +Date: Mon, 10 Nov 2025 05:42:13 -0500 +Subject: [PATCH] incusd/patches: Fix incorrect error check in permission patch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Stéphane Graber +--- + cmd/incusd/patches.go | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/cmd/incusd/patches.go b/cmd/incusd/patches.go +index e6bef88e7ab..c64c9bbf828 100644 +--- a/cmd/incusd/patches.go ++++ b/cmd/incusd/patches.go +@@ -4,6 +4,7 @@ import ( + "context" + "errors" + "fmt" ++ "io/fs" + "net/http" + "os" + "path/filepath" +@@ -1638,7 +1639,7 @@ func patchDefaultStoragePermissions(_ string, d *Daemon) error { + path := filepath.Join(storagePools.GetStoragePoolMountPoint(pool), volDir) + + err := os.Chmod(path, volEntry.Mode) +- if err != nil && !os.IsExist(err) { ++ if err != nil && !errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("Failed to set directory mode %q: %w", path, err) + } + } diff -Nru incus-6.0.4/debian/patches/series incus-6.0.4/debian/patches/series --- incus-6.0.4/debian/patches/series 2025-10-02 14:47:22.000000000 +0000 +++ incus-6.0.4/debian/patches/series 2025-11-10 13:32:50.000000000 +0000 @@ -11,3 +11,6 @@ 103-CVE-2025-54286.patch 104-CVE-2025-54290_CVE-2025-54291.patch 105-CVE-2025-54289.patch +106a-GHSA-56mx-8g9f-5crf.patch +106b-GHSA-56mx-8g9f-5crf.patch +106c-GHSA-56mx-8g9f-5crf.patch