已开启
Fix CVE-2023-30549;CVE-2025-65105 #28
byj0创建于 5月27日
Fix CVE-2023-30549;CVE-2025-65105 #28
已开启
共 3 个文件变更+365-1
| @@ -42,7 +42,7 @@ | |||
| 42 | Summary: Application and environment virtualization formerly known as Singularity | 42 | Summary: Application and environment virtualization formerly known as Singularity |
| 43 | Name: apptainer | 43 | Name: apptainer |
| 44 | Version: 1.1.6 | 44 | Version: 1.1.6 |
| 45 | -Release: 3 | 45 | +Release: 4 |
| 46 | # See LICENSE.md for first party code (BSD-3-Clause and LBNL BSD) | 46 | # See LICENSE.md for first party code (BSD-3-Clause and LBNL BSD) |
| 47 | # See LICENSE_THIRD_PARTY.md for incorporated code (ASL 2.0) | 47 | # See LICENSE_THIRD_PARTY.md for incorporated code (ASL 2.0) |
| 48 | # See LICENSE_DEPENDENCIES.md for dependencies | 48 | # See LICENSE_DEPENDENCIES.md for dependencies |
| @@ -59,6 +59,8 @@ Patch12: 81.patch | |||
| 59 | %endif | 59 | %endif |
| 60 | Patch13: add-loong64-support-for-bbolt.patch | 60 | Patch13: add-loong64-support-for-bbolt.patch |
| 61 | Patch14: openEuler-golang-1.21.4.patch | 61 | Patch14: openEuler-golang-1.21.4.patch |
| 62 | +Patch15: backport-CVE-2023-30549.patch | ||
| 63 | +Patch16: backport-CVE-2025-65105.patch | ||
| 62 | 64 | ||
| 63 | # This Conflicts is in case someone tries to install the main apptainer | 65 | # This Conflicts is in case someone tries to install the main apptainer |
| 64 | # package when an old singularity package is installed. An Obsoletes is on | 66 | # package when an old singularity package is installed. An Obsoletes is on |
| @@ -290,6 +292,8 @@ Provides the optional setuid-root portion of Apptainer. | |||
| 290 | %patch -P 12 -p1 | 292 | %patch -P 12 -p1 |
| 291 | %setup -n %{name}-%{package_version} | 293 | %setup -n %{name}-%{package_version} |
| 292 | %patch -P 13 -p1 | 294 | %patch -P 13 -p1 |
| 295 | +%patch -P 15 -p1 | ||
| 296 | +%patch -P 16 -p1 | ||
| 293 | %else | 297 | %else |
| 294 | %autosetup -n %{name}-%{package_version} | 298 | %autosetup -n %{name}-%{package_version} |
| 295 | %endif | 299 | %endif |
| @@ -435,6 +439,10 @@ fi | |||
| 435 | %attr(4755, root, root) %{_libexecdir}/%{name}/bin/starter-suid | 439 | %attr(4755, root, root) %{_libexecdir}/%{name}/bin/starter-suid |
| 436 | 440 | ||
| 437 | %changelog | 441 | %changelog |
| 442 | +* Wed May 27 2026 baiyanjie <baiyanjie@kylinsec.com.cn> - 1.1.6-4 | ||
| 443 | +- Backport patch to fix CVE-2025-65105 | ||
| 444 | +- Backport patch to fix CVE-2023-30549 | ||
| 445 | + | ||
| 438 | * Mon Dec 09 2024 zhengting <zhengting13@huawei.com> - 1.1.6-3 | 446 | * Mon Dec 09 2024 zhengting <zhengting13@huawei.com> - 1.1.6-3 |
| 439 | - Patch golang verison fro openEuler 24.03 | 447 | - Patch golang verison fro openEuler 24.03 |
| 440 | 448 | ||
| @@ -0,0 +1,299 @@ | |||
| 1 | +diff -Naur a/internal/pkg/runtime/engine/apptainer/prepare_linux.go b/internal/pkg/runtime/engine/apptainer/prepare_linux.go | ||
| 2 | +--- a/internal/pkg/runtime/engine/apptainer/prepare_linux.go | ||
| 3 | ++++ b/internal/pkg/runtime/engine/apptainer/prepare_linux.go | ||
| 4 | +@@ -150,7 +150,7 @@ | ||
| 5 | + if err := e.prepareContainerConfig(starterConfig); err != nil { | ||
| 6 | + return err | ||
| 7 | + } | ||
| 8 | +- if err := e.loadImages(starterConfig); err != nil { | ||
| 9 | ++ if err := e.loadImages(starterConfig, userNS); err != nil { | ||
| 10 | + return err | ||
| 11 | + } | ||
| 12 | + } | ||
| 13 | +@@ -1131,12 +1131,12 @@ | ||
| 14 | + return nil | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | +-func (e *EngineOperations) loadImages(starterConfig *starter.Config) error { | ||
| 18 | ++func (e *EngineOperations) loadImages(starterConfig *starter.Config, userNS bool) error { | ||
| 19 | + images := make([]image.Image, 0) | ||
| 20 | + | ||
| 21 | + // load rootfs image | ||
| 22 | + writable := e.EngineConfig.GetWritableImage() | ||
| 23 | +- img, err := e.loadImage(e.EngineConfig.GetImage(), writable) | ||
| 24 | ++ img, err := e.loadImage(e.EngineConfig.GetImage(), writable, userNS) | ||
| 25 | + if err != nil { | ||
| 26 | + return err | ||
| 27 | + } | ||
| 28 | +@@ -1236,7 +1236,13 @@ | ||
| 29 | + return fmt.Errorf("while getting overlay partitions in %s: %s", img.Path, err) | ||
| 30 | + } | ||
| 31 | + for _, p := range overlays { | ||
| 32 | +- if img.Writable && p.Type == image.EXT3 { | ||
| 33 | ++ if p.Type != image.EXT3 { | ||
| 34 | ++ continue | ||
| 35 | ++ } | ||
| 36 | ++ if !userNS && !e.EngineConfig.File.AllowSetuidMountExtfs { | ||
| 37 | ++ return fmt.Errorf("configuration disallows users from mounting SIF extfs partition in setuid mode, try --userns") | ||
| 38 | ++ } | ||
| 39 | ++ if img.Writable { | ||
| 40 | + writableOverlayPath = img.Path | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | +@@ -1252,7 +1258,7 @@ | ||
| 44 | + | ||
| 45 | + switch e.EngineConfig.GetSessionLayer() { | ||
| 46 | + case apptainerConfig.OverlayLayer: | ||
| 47 | +- overlayImages, err := e.loadOverlayImages(starterConfig, writableOverlayPath) | ||
| 48 | ++ overlayImages, err := e.loadOverlayImages(starterConfig, writableOverlayPath, userNS) | ||
| 49 | + if err != nil { | ||
| 50 | + return fmt.Errorf("while loading overlay images: %s", err) | ||
| 51 | + } | ||
| 52 | +@@ -1264,7 +1270,7 @@ | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | +- bindImages, err := e.loadBindImages(starterConfig) | ||
| 57 | ++ bindImages, err := e.loadBindImages(starterConfig, userNS) | ||
| 58 | + if err != nil { | ||
| 59 | + return fmt.Errorf("while loading data bind images: %s", err) | ||
| 60 | + } | ||
| 61 | +@@ -1276,7 +1282,7 @@ | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + // loadOverlayImages loads overlay images. | ||
| 65 | +-func (e *EngineOperations) loadOverlayImages(starterConfig *starter.Config, writableOverlayPath string) ([]image.Image, error) { | ||
| 66 | ++func (e *EngineOperations) loadOverlayImages(starterConfig *starter.Config, writableOverlayPath string, userNS bool) ([]image.Image, error) { | ||
| 67 | + images := make([]image.Image, 0) | ||
| 68 | + | ||
| 69 | + for _, overlayImg := range e.EngineConfig.GetOverlayImage() { | ||
| 70 | +@@ -1289,7 +1295,7 @@ | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | +- img, err := e.loadImage(splitted[0], writableOverlay) | ||
| 75 | ++ img, err := e.loadImage(splitted[0], writableOverlay, userNS) | ||
| 76 | + if err != nil { | ||
| 77 | + if !image.IsReadOnlyFilesytem(err) { | ||
| 78 | + return nil, fmt.Errorf("failed to open overlay image %s: %s", splitted[0], err) | ||
| 79 | +@@ -1325,7 +1331,7 @@ | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + // loadBindImages load data bind images. | ||
| 83 | +-func (e *EngineOperations) loadBindImages(starterConfig *starter.Config) ([]image.Image, error) { | ||
| 84 | ++func (e *EngineOperations) loadBindImages(starterConfig *starter.Config, userNS bool) ([]image.Image, error) { | ||
| 85 | + images := make([]image.Image, 0) | ||
| 86 | + | ||
| 87 | + binds := e.EngineConfig.GetBindPath() | ||
| 88 | +@@ -1339,7 +1345,7 @@ | ||
| 89 | + | ||
| 90 | + sylog.Debugf("Loading data image %s", imagePath) | ||
| 91 | + | ||
| 92 | +- img, err := e.loadImage(imagePath, !binds[i].Readonly()) | ||
| 93 | ++ img, err := e.loadImage(imagePath, !binds[i].Readonly(), userNS) | ||
| 94 | + if err != nil && !image.IsReadOnlyFilesytem(err) { | ||
| 95 | + return nil, fmt.Errorf("failed to load data image %s: %s", imagePath, err) | ||
| 96 | + } | ||
| 97 | +@@ -1355,7 +1361,7 @@ | ||
| 98 | + return images, nil | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | +-func (e *EngineOperations) loadImage(path string, writable bool) (*image.Image, error) { | ||
| 102 | ++func (e *EngineOperations) loadImage(path string, writable bool, userNS bool) (*image.Image, error) { | ||
| 103 | + const delSuffix = " (deleted)" | ||
| 104 | + | ||
| 105 | + imgObject, imgErr := image.Init(path, writable) | ||
| 106 | +@@ -1413,11 +1419,17 @@ | ||
| 107 | + if !e.EngineConfig.File.AllowContainerSquashfs { | ||
| 108 | + return nil, fmt.Errorf("configuration disallows users from running squashFS containers") | ||
| 109 | + } | ||
| 110 | ++ if !userNS && !e.EngineConfig.File.AllowSetuidMountSquashfs { | ||
| 111 | ++ return nil, fmt.Errorf("configuration disallows users from mounting squashFS in setuid mode, try --userns") | ||
| 112 | ++ } | ||
| 113 | + // Bare EXT3 | ||
| 114 | + case image.EXT3: | ||
| 115 | + if !e.EngineConfig.File.AllowContainerExtfs { | ||
| 116 | + return nil, fmt.Errorf("configuration disallows users from running extFS containers") | ||
| 117 | + } | ||
| 118 | ++ if !userNS && !e.EngineConfig.File.AllowSetuidMountExtfs { | ||
| 119 | ++ return nil, fmt.Errorf("configuration disallows users from mounting extfs in setuid mode, try --userns") | ||
| 120 | ++ } | ||
| 121 | + // Bare sandbox directory | ||
| 122 | + case image.SANDBOX: | ||
| 123 | + if !e.EngineConfig.File.AllowContainerDir { | ||
| 124 | +@@ -1425,6 +1437,9 @@ | ||
| 125 | + } | ||
| 126 | + // SIF | ||
| 127 | + case image.SIF: | ||
| 128 | ++ if !userNS && !e.EngineConfig.File.AllowSetuidMountSquashfs { | ||
| 129 | ++ return nil, fmt.Errorf("configuration disallows users from mounting SIF squashFS partition in setuid mode, try --userns") | ||
| 130 | ++ } | ||
| 131 | + // Check if SIF contains an encrypted rootfs partition. | ||
| 132 | + // We don't support encryption for other partitions at present. | ||
| 133 | + encrypted, err := imgObject.HasEncryptedRootFs() | ||
| 134 | +@@ -1435,6 +1450,9 @@ | ||
| 135 | + if encrypted && !e.EngineConfig.File.AllowContainerEncrypted { | ||
| 136 | + return nil, fmt.Errorf("configuration disallows users from running encrypted SIF containers") | ||
| 137 | + } | ||
| 138 | ++ if encrypted && !userNS && !e.EngineConfig.File.AllowSetuidMountEncrypted { | ||
| 139 | ++ return nil, fmt.Errorf("configuration disallows users from mounting encrypted files in setuid mode") | ||
| 140 | ++ } | ||
| 141 | + // SIF without encryption - regardless of rootfs filesystem type | ||
| 142 | + if !encrypted && !e.EngineConfig.File.AllowContainerSIF { | ||
| 143 | + return nil, fmt.Errorf("configuration disallows users from running unencrypted SIF containers") | ||
| 144 | +diff -Naur a/pkg/util/apptainerconf/config.go b/pkg/util/apptainerconf/config.go | ||
| 145 | +--- a/pkg/util/apptainerconf/config.go | ||
| 146 | ++++ b/pkg/util/apptainerconf/config.go | ||
| 147 | +@@ -76,46 +76,49 @@ | ||
| 148 | + | ||
| 149 | + // File describes the apptainer.conf file options | ||
| 150 | + type File struct { | ||
| 151 | +- AllowSetuid bool `default:"yes" authorized:"yes,no" directive:"allow setuid"` | ||
| 152 | +- AllowPidNs bool `default:"yes" authorized:"yes,no" directive:"allow pid ns"` | ||
| 153 | +- ConfigPasswd bool `default:"yes" authorized:"yes,no" directive:"config passwd"` | ||
| 154 | +- ConfigGroup bool `default:"yes" authorized:"yes,no" directive:"config group"` | ||
| 155 | +- ConfigResolvConf bool `default:"yes" authorized:"yes,no" directive:"config resolv_conf"` | ||
| 156 | +- MountProc bool `default:"yes" authorized:"yes,no" directive:"mount proc"` | ||
| 157 | +- MountSys bool `default:"yes" authorized:"yes,no" directive:"mount sys"` | ||
| 158 | +- MountDevPts bool `default:"yes" authorized:"yes,no" directive:"mount devpts"` | ||
| 159 | +- MountHome bool `default:"yes" authorized:"yes,no" directive:"mount home"` | ||
| 160 | +- MountTmp bool `default:"yes" authorized:"yes,no" directive:"mount tmp"` | ||
| 161 | +- MountHostfs bool `default:"no" authorized:"yes,no" directive:"mount hostfs"` | ||
| 162 | +- UserBindControl bool `default:"yes" authorized:"yes,no" directive:"user bind control"` | ||
| 163 | +- EnableFusemount bool `default:"yes" authorized:"yes,no" directive:"enable fusemount"` | ||
| 164 | +- EnableUnderlay bool `default:"yes" authorized:"yes,no" directive:"enable underlay"` | ||
| 165 | +- MountSlave bool `default:"yes" authorized:"yes,no" directive:"mount slave"` | ||
| 166 | +- AllowContainerSIF bool `default:"yes" authorized:"yes,no" directive:"allow container sif"` | ||
| 167 | +- AllowContainerEncrypted bool `default:"yes" authorized:"yes,no" directive:"allow container encrypted"` | ||
| 168 | +- AllowContainerSquashfs bool `default:"yes" authorized:"yes,no" directive:"allow container squashfs"` | ||
| 169 | +- AllowContainerExtfs bool `default:"yes" authorized:"yes,no" directive:"allow container extfs"` | ||
| 170 | +- AllowContainerDir bool `default:"yes" authorized:"yes,no" directive:"allow container dir"` | ||
| 171 | +- AlwaysUseNv bool `default:"no" authorized:"yes,no" directive:"always use nv"` | ||
| 172 | +- UseNvCCLI bool `default:"no" authorized:"yes,no" directive:"use nvidia-container-cli"` | ||
| 173 | +- AlwaysUseRocm bool `default:"no" authorized:"yes,no" directive:"always use rocm"` | ||
| 174 | +- SharedLoopDevices bool `default:"no" authorized:"yes,no" directive:"shared loop devices"` | ||
| 175 | +- MaxLoopDevices uint `default:"256" directive:"max loop devices"` | ||
| 176 | +- SessiondirMaxSize uint `default:"16" directive:"sessiondir max size"` | ||
| 177 | +- MountDev string `default:"yes" authorized:"yes,no,minimal" directive:"mount dev"` | ||
| 178 | +- EnableOverlay string `default:"try" authorized:"yes,no,try,driver" directive:"enable overlay"` | ||
| 179 | +- BindPath []string `default:"/etc/localtime,/etc/hosts" directive:"bind path"` | ||
| 180 | +- LimitContainerOwners []string `directive:"limit container owners"` | ||
| 181 | +- LimitContainerGroups []string `directive:"limit container groups"` | ||
| 182 | +- LimitContainerPaths []string `directive:"limit container paths"` | ||
| 183 | +- AllowNetUsers []string `directive:"allow net users"` | ||
| 184 | +- AllowNetGroups []string `directive:"allow net groups"` | ||
| 185 | +- AllowNetNetworks []string `directive:"allow net networks"` | ||
| 186 | +- RootDefaultCapabilities string `default:"full" authorized:"full,file,no" directive:"root default capabilities"` | ||
| 187 | +- MemoryFSType string `default:"tmpfs" authorized:"tmpfs,ramfs" directive:"memory fs type"` | ||
| 188 | +- CniConfPath string `directive:"cni configuration path"` | ||
| 189 | +- CniPluginPath string `directive:"cni plugin path"` | ||
| 190 | +- BinaryPath string `default:"$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" directive:"binary path"` | ||
| 191 | ++ AllowSetuid bool `default:"yes" authorized:"yes,no" directive:"allow setuid"` | ||
| 192 | ++ AllowPidNs bool `default:"yes" authorized:"yes,no" directive:"allow pid ns"` | ||
| 193 | ++ ConfigPasswd bool `default:"yes" authorized:"yes,no" directive:"config passwd"` | ||
| 194 | ++ ConfigGroup bool `default:"yes" authorized:"yes,no" directive:"config group"` | ||
| 195 | ++ ConfigResolvConf bool `default:"yes" authorized:"yes,no" directive:"config resolv_conf"` | ||
| 196 | ++ MountProc bool `default:"yes" authorized:"yes,no" directive:"mount proc"` | ||
| 197 | ++ MountSys bool `default:"yes" authorized:"yes,no" directive:"mount sys"` | ||
| 198 | ++ MountDevPts bool `default:"yes" authorized:"yes,no" directive:"mount devpts"` | ||
| 199 | ++ MountHome bool `default:"yes" authorized:"yes,no" directive:"mount home"` | ||
| 200 | ++ MountTmp bool `default:"yes" authorized:"yes,no" directive:"mount tmp"` | ||
| 201 | ++ MountHostfs bool `default:"no" authorized:"yes,no" directive:"mount hostfs"` | ||
| 202 | ++ UserBindControl bool `default:"yes" authorized:"yes,no" directive:"user bind control"` | ||
| 203 | ++ EnableFusemount bool `default:"yes" authorized:"yes,no" directive:"enable fusemount"` | ||
| 204 | ++ EnableUnderlay bool `default:"yes" authorized:"yes,no" directive:"enable underlay"` | ||
| 205 | ++ MountSlave bool `default:"yes" authorized:"yes,no" directive:"mount slave"` | ||
| 206 | ++ AllowContainerSIF bool `default:"yes" authorized:"yes,no" directive:"allow container sif"` | ||
| 207 | ++ AllowContainerEncrypted bool `default:"yes" authorized:"yes,no" directive:"allow container encrypted"` | ||
| 208 | ++ AllowContainerSquashfs bool `default:"yes" authorized:"yes,no" directive:"allow container squashfs"` | ||
| 209 | ++ AllowContainerExtfs bool `default:"yes" authorized:"yes,no" directive:"allow container extfs"` | ||
| 210 | ++ AllowContainerDir bool `default:"yes" authorized:"yes,no" directive:"allow container dir"` | ||
| 211 | ++ AllowSetuidMountEncrypted bool `default:"yes" authorized:"yes,no" directive:"allow setuid-mount encrypted"` | ||
| 212 | ++ AllowSetuidMountSquashfs bool `default:"yes" authorized:"yes,no" directive:"allow setuid-mount squashfs"` | ||
| 213 | ++ AllowSetuidMountExtfs bool `default:"no" authorized:"yes,no" directive:"allow setuid-mount extfs"` | ||
| 214 | ++ AlwaysUseNv bool `default:"no" authorized:"yes,no" directive:"always use nv"` | ||
| 215 | ++ UseNvCCLI bool `default:"no" authorized:"yes,no" directive:"use nvidia-container-cli"` | ||
| 216 | ++ AlwaysUseRocm bool `default:"no" authorized:"yes,no" directive:"always use rocm"` | ||
| 217 | ++ SharedLoopDevices bool `default:"no" authorized:"yes,no" directive:"shared loop devices"` | ||
| 218 | ++ MaxLoopDevices uint `default:"256" directive:"max loop devices"` | ||
| 219 | ++ SessiondirMaxSize uint `default:"16" directive:"sessiondir max size"` | ||
| 220 | ++ MountDev string `default:"yes" authorized:"yes,no,minimal" directive:"mount dev"` | ||
| 221 | ++ EnableOverlay string `default:"try" authorized:"yes,no,try,driver" directive:"enable overlay"` | ||
| 222 | ++ BindPath []string `default:"/etc/localtime,/etc/hosts" directive:"bind path"` | ||
| 223 | ++ LimitContainerOwners []string `directive:"limit container owners"` | ||
| 224 | ++ LimitContainerGroups []string `directive:"limit container groups"` | ||
| 225 | ++ LimitContainerPaths []string `directive:"limit container paths"` | ||
| 226 | ++ AllowNetUsers []string `directive:"allow net users"` | ||
| 227 | ++ AllowNetGroups []string `directive:"allow net groups"` | ||
| 228 | ++ AllowNetNetworks []string `directive:"allow net networks"` | ||
| 229 | ++ RootDefaultCapabilities string `default:"full" authorized:"full,file,no" directive:"root default capabilities"` | ||
| 230 | ++ MemoryFSType string `default:"tmpfs" authorized:"tmpfs,ramfs" directive:"memory fs type"` | ||
| 231 | ++ CniConfPath string `directive:"cni configuration path"` | ||
| 232 | ++ CniPluginPath string `directive:"cni plugin path"` | ||
| 233 | ++ BinaryPath string `default:"$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" directive:"binary path"` | ||
| 234 | + // SuidBinaryPath is hidden; it is not referenced below, and overwritten | ||
| 235 | + SuidBinaryPath string `directive:"suidbinary path"` | ||
| 236 | + MksquashfsProcs uint `default:"0" directive:"mksquashfs procs"` | ||
| 237 | +@@ -127,6 +130,18 @@ | ||
| 238 | + SystemdCgroups bool `default:"yes" authorized:"yes,no" directive:"systemd cgroups"` | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | ++// NOTE: if you think that we may want to change the default for any | ||
| 242 | ++// configuration parameter in the future, it is a good idea to conditionally | ||
| 243 | ++// insert a comment before the default setting when the setting is equal | ||
| 244 | ++// to the current default. That enables the defaults to get updated in | ||
| 245 | ++// a new release even if an administrator has changed one of the *other* | ||
| 246 | ++// settings. This gets around the problem of packagers such as rpm | ||
| 247 | ++// refusing to overwrite a configuration file if any change has been made. | ||
| 248 | ++// This technique is used for example in the "allow setuid-mount" options | ||
| 249 | ++// below. If a default is changed in a future release, both the default | ||
| 250 | ++// setting above and the expression for the conditional comment below need | ||
| 251 | ++// to change at the same time. | ||
| 252 | ++ | ||
| 253 | + const TemplateAsset = `# APPTAINER.CONF | ||
| 254 | + # This is the global configuration file for Apptainer. This file controls | ||
| 255 | + # what the container is allowed to do on a particular host, and as a result | ||
| 256 | +@@ -321,7 +336,9 @@ | ||
| 257 | + # ALLOW CONTAINER ${TYPE}: [BOOL] | ||
| 258 | + # DEFAULT: yes | ||
| 259 | + # This feature limits what kind of containers that Apptainer will allow | ||
| 260 | +-# users to use (note this does not apply for root). | ||
| 261 | ++# users to use (note this does not apply for root). Note that some of the | ||
| 262 | ++# same operations can be limited in setuid mode by the ALLOW SETUID-MOUNT | ||
| 263 | ++# feature below; both types need to be "yes" to be allowed. | ||
| 264 | + # | ||
| 265 | + # Allow use of unencrypted SIF containers | ||
| 266 | + allow container sif = {{ if eq .AllowContainerSIF true}}yes{{ else }}no{{ end }} | ||
| 267 | +@@ -334,6 +351,32 @@ | ||
| 268 | + allow container extfs = {{ if eq .AllowContainerExtfs true }}yes{{ else }}no{{ end }} | ||
| 269 | + allow container dir = {{ if eq .AllowContainerDir true }}yes{{ else }}no{{ end }} | ||
| 270 | + | ||
| 271 | ++# ALLOW SETUID-MOUNT ${TYPE}: [BOOL] | ||
| 272 | ++# DEFAULT: yes, except no for extfs | ||
| 273 | ++# This feature limits what types of mounts that Apptainer will allow | ||
| 274 | ++# unprivileged users to use in setuid mode. Normally these operations | ||
| 275 | ++# require the elevated privileges of setuid mode, although Apptainer | ||
| 276 | ++# has unprivileged alternatives for squashfs and extfs. Note that some of | ||
| 277 | ++# the same operations can also be limited by the ALLOW CONTAINER feature | ||
| 278 | ++# above; both types need to be "yes" to be allowed. | ||
| 279 | ++# | ||
| 280 | ++# Allow mounting of SIF encryption (using the kernel device-mapper) in | ||
| 281 | ++# setuid mode | ||
| 282 | ++{{ if eq .AllowSetuidMountEncrypted true}}# {{ end }}allow setuid-mount encrypted = {{ if eq .AllowSetuidMountEncrypted true}}yes{{ else }}no{{ end }} | ||
| 283 | ++# | ||
| 284 | ++# Allow mounting of squashfs filesystem types in setuid mode, both inside and | ||
| 285 | ++# outside of SIF files | ||
| 286 | ++{{ if eq .AllowSetuidMountSquashfs true}}# {{ end }}allow setuid-mount squashfs = {{ if eq .AllowSetuidMountSquashfs true}}yes{{ else }}no{{ end }} | ||
| 287 | ++# | ||
| 288 | ++# Allow mounting of extfs filesystem types in setuid mode, both inside and | ||
| 289 | ++# outside of SIF files. WARNING: this filesystem type frequently has relevant | ||
| 290 | ++# CVEs that that take a very long time for vendors to patch because they are | ||
| 291 | ++# not considered to be High severity since normally unprivileged users do | ||
| 292 | ++# not have write access to the raw filesystem data. This is why this option | ||
| 293 | ++# defaults to "no". Change it at your own risk and consider using the | ||
| 294 | ++# LIMIT CONTAINER features above if you do. | ||
| 295 | ++{{ if eq .AllowSetuidMountExtfs false}}# {{ end }}allow setuid-mount extfs = {{ if eq .AllowSetuidMountExtfs true}}yes{{ else }}no{{ end }} | ||
| 296 | ++ | ||
| 297 | + # ALLOW NET USERS: [STRING] | ||
| 298 | + # DEFAULT: NULL | ||
| 299 | + # Allow specified root administered CNI network configurations to be used by the | ||
| @@ -0,0 +1,57 @@ | |||
| 1 | +--- a/internal/pkg/security/security.go 2023-02-15 05:46:54.000000000 +0800 | ||
| 2 | ++++ b/internal/pkg/security/security.go 2026-05-27 13:50:26.856910026 +0800 | ||
| 3 | +@@ -32,7 +32,7 @@ | ||
| 4 | + return err | ||
| 5 | + } | ||
| 6 | + } else { | ||
| 7 | +- sylog.Warningf("selinux is not enabled or supported on this system") | ||
| 8 | ++ return fmt.Errorf("selinux requested, but is not enabled or supported on this system") | ||
| 9 | + } | ||
| 10 | + } else if config.Process.ApparmorProfile != "" { | ||
| 11 | + if apparmor.Enabled() { | ||
| 12 | +@@ -40,7 +40,7 @@ | ||
| 13 | + return err | ||
| 14 | + } | ||
| 15 | + } else { | ||
| 16 | +- sylog.Warningf("apparmor is not enabled or supported on this system") | ||
| 17 | ++ return fmt.Errorf("apparmor requested, but is not enabled or supported on this system") | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | +@@ -50,7 +50,7 @@ | ||
| 22 | + return err | ||
| 23 | + } | ||
| 24 | + } else { | ||
| 25 | +- sylog.Warningf("seccomp requested but not enabled, seccomp library is missing or too old") | ||
| 26 | ++ return fmt.Errorf("seccomp requested but not enabled, seccomp library is missing or too old") | ||
| 27 | + } | ||
| 28 | + } | ||
| 29 | + return nil | ||
| 30 | +--- a/internal/pkg/security/apparmor/apparmor_supported.go 2023-02-15 05:46:54.000000000 +0800 | ||
| 31 | ++++ b/internal/pkg/security/apparmor/apparmor_supported.go 2026-05-27 13:51:27.319543034 +0800 | ||
| 32 | +@@ -15,6 +15,8 @@ | ||
| 33 | + "fmt" | ||
| 34 | + "io/ioutil" | ||
| 35 | + "os" | ||
| 36 | ++ | ||
| 37 | ++ "golang.org/x/sys/unix" | ||
| 38 | + ) | ||
| 39 | + | ||
| 40 | + // Enabled returns whether AppArmor is enabled. | ||
| 41 | +@@ -28,6 +30,16 @@ | ||
| 42 | + | ||
| 43 | + // LoadProfile loads the specified AppArmor profile. | ||
| 44 | + func LoadProfile(profile string) error { | ||
| 45 | ++ // Verify that /proc/self/attr/exec is on the real proc filesystem | ||
| 46 | ++ // to prevent containers from bypassing AppArmor by masking /proc. | ||
| 47 | ++ var st unix.Statfs_t | ||
| 48 | ++ if err := unix.Statfs("/proc/self/attr/exec", &st); err != nil { | ||
| 49 | ++ return fmt.Errorf("failed to verify proc filesystem: %w", err) | ||
| 50 | ++ } | ||
| 51 | ++ if st.Type != unix.PROC_SUPER_MAGIC { | ||
| 52 | ++ return fmt.Errorf("cannot set apparmor profile: /proc/self/attr/exec is not on procfs") | ||
| 53 | ++ } | ||
| 54 | ++ | ||
| 55 | + f, err := os.OpenFile("/proc/self/attr/exec", os.O_WRONLY, 0) | ||
| 56 | + if err != nil { | ||
| 57 | + return err | ||