Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package apptainer for openSUSE:Factory 
checked in at 2023-04-28 16:23:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apptainer (Old)
 and      /work/SRC/openSUSE:Factory/.apptainer.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "apptainer"

Fri Apr 28 16:23:41 2023 rev:17 rq:1083268 version:1.1.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/apptainer/apptainer.changes      2023-03-29 
23:28:07.343752744 +0200
+++ /work/SRC/openSUSE:Factory/.apptainer.new.1533/apptainer.changes    
2023-04-28 16:24:39.822463887 +0200
@@ -1,0 +2,19 @@
+Thu Apr 27 12:59:22 UTC 2023 - Christian Goll <cg...@suse.com>
+
+- Included a fix for CVE-2023-30549 which is a vulnerability in setuid-root
+  installations of Apptainer iwhich was not active in the recent openSUSE
+  packages. Still this is included for completenss. The fix adds allow
+  setuid-mount configuration options encrypted, squashfs, and extfs, and makes
+  the default for extfs be "no". That disables the use of extfs mounts
+  including for overlays or binds while in the setuid-root mode, while leaving
+  it enabled for unprivileged user namespace mode. The default for encrypted
+  and squashfs is "yes".
+- Other bug fixes:
+  * Fix loop device 'no such device or address' spurious errors when using 
shared
+    loop devices.
+  * Add xino=on mount option for writable kernel overlay mount points to fix
+    inode numbers consistency after kernel cache flush (not applicable to
+    fuse-overlayfs).
+ 
+
+-------------------------------------------------------------------

Old:
----
  apptainer-1.1.7.tar.gz

New:
----
  apptainer-1.1.8.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ apptainer.spec ++++++
--- /var/tmp/diff_new_pack.sMCmqG/_old  2023-04-28 16:24:43.114483102 +0200
+++ /var/tmp/diff_new_pack.sMCmqG/_new  2023-04-28 16:24:43.118483125 +0200
@@ -25,7 +25,7 @@
 License:        BSD-3-Clause-LBNL
 Group:          Productivity/Clustering/Computing
 Name:           apptainer
-Version:        1.1.7
+Version:        1.1.8
 Release:        0
 # https://spdx.org/licenses/BSD-3-Clause-LBNL.html
 URL:            https://apptainer.org

++++++ apptainer-1.1.7.tar.gz -> apptainer-1.1.8.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/CHANGELOG.md 
new/apptainer-1.1.8/CHANGELOG.md
--- old/apptainer-1.1.7/CHANGELOG.md    2023-03-28 22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/CHANGELOG.md    2023-04-25 17:50:20.000000000 +0200
@@ -5,6 +5,31 @@
 and re-branded as Apptainer.
 For older changes see the [archived Singularity change 
log](https://github.com/apptainer/singularity/blob/release-3.8/CHANGELOG.md).
 
+## v1.1.8 - \[2023-04-25\]
+
+### Security fix
+
+- Included a fix for 
[CVE-2023-30549](https://github.com/sylabs/scs-library-client/security/advisories/GHSA-7p8m-22h4-9pj7)
+  which is a vulnerability in setuid-root installations of Apptainer
+  and Singularity that causes an elevation in severity of an existing
+  ext4 filesystem driver vulnerability that is unpatched in several
+  older but still actively supported operating systems including RHEL7,
+  Debian 10, Ubuntu 18.04 and Ubuntu 20.04.
+  The fix adds `allow setuid-mount` configuration options `encrypted`,
+  `squashfs`, and `extfs`, and makes the default for `extfs` be "no".
+  That disables the use of extfs mounts including for overlays or
+  binds while in the setuid-root mode, while leaving it enabled for
+  unprivileged user namespace mode.
+  The default for `encrypted` and `squashfs` is "yes".  
+
+### Other changes
+
+- Fix loop device 'no such device or address' spurious errors when using shared
+  loop devices.
+- Remove unwanted colors to STDERR.
+- Add `xino=on` mount option for writable kernel overlay mount points to fix
+  inode numbers consistency after kernel cache flush (not applicable to 
fuse-overlayfs).
+
 ## v1.1.7 - \[2023-03-28\]
 
 ### Changes since last release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/INSTALL.md 
new/apptainer-1.1.8/INSTALL.md
--- old/apptainer-1.1.7/INSTALL.md      2023-03-28 22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/INSTALL.md      2023-04-25 17:50:20.000000000 +0200
@@ -137,7 +137,7 @@
 for example:
 
 ```sh
-git checkout v1.1.7
+git checkout v1.1.8
 ```
 
 ## Compiling Apptainer
@@ -259,7 +259,7 @@
 <!-- markdownlint-disable MD013 -->
 
 ```sh
-VERSION=1.1.7  # this is the apptainer version, change as you need
+VERSION=1.1.8  # this is the apptainer version, change as you need
 # Fetch the source
 wget 
https://github.com/apptainer/apptainer/releases/download/v${VERSION}/apptainer-${VERSION}.tar.gz
 ```
@@ -308,7 +308,7 @@
 <!-- markdownlint-disable MD013 -->
 
 ```sh
-VERSION=1.1.7 # this is the latest apptainer version, change as you need
+VERSION=1.1.8 # this is the latest apptainer version, change as you need
 ./mconfig
 make -C builddir rpm
 sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/apptainer-$(echo $VERSION|tr - 
\~)*.x86_64.rpm 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/cmd/internal/cli/apptainer.go 
new/apptainer-1.1.8/cmd/internal/cli/apptainer.go
--- old/apptainer-1.1.7/cmd/internal/cli/apptainer.go   2023-03-28 
22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/cmd/internal/cli/apptainer.go   2023-04-25 
17:50:20.000000000 +0200
@@ -454,7 +454,6 @@
 }
 
 func persistentPreRun(cmd *cobra.Command, args []string) error {
-       setSylogMessageLevel()
        sylog.Debugf("Apptainer version: %s", buildcfg.PACKAGE_VERSION)
 
        if cmd.CalledAs() == "confgen" {
@@ -526,6 +525,8 @@
 
        // set persistent pre run function here to avoid initialization loop 
error
        apptainerCmd.PersistentPreRunE = func(cmd *cobra.Command, args 
[]string) error {
+               // call configuring message level method earlier to solve this 
issue https://github.com/apptainer/apptainer/issues/1259
+               setSylogMessageLevel()
                var err error
                foundKeys := make(map[string]string)
                for precedence := range env.ApptainerPrefixes {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/actions/actions.go 
new/apptainer-1.1.8/e2e/actions/actions.go
--- old/apptainer-1.1.7/e2e/actions/actions.go  2023-03-28 22:17:08.000000000 
+0200
+++ new/apptainer-1.1.8/e2e/actions/actions.go  2023-04-25 17:50:20.000000000 
+0200
@@ -790,6 +790,9 @@
                e2e.ExpectExit(0),
        )
 
+       e2e.SetDirective(t, c.env, "allow setuid-mount extfs", "yes")
+       defer e2e.ResetDirective(t, c.env, "allow setuid-mount extfs")
+
        tests := []struct {
                name    string
                argv    []string
@@ -1934,6 +1937,9 @@
                e2e.ExpectExit(0),
        )
 
+       e2e.SetDirective(t, c.env, "allow setuid-mount extfs", "yes")
+       defer e2e.ResetDirective(t, c.env, "allow setuid-mount extfs")
+
        tests := []struct {
                name    string
                profile e2e.Profile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/config/config.go 
new/apptainer-1.1.8/e2e/config/config.go
--- old/apptainer-1.1.7/e2e/config/config.go    2023-03-28 22:17:08.000000000 
+0200
+++ new/apptainer-1.1.8/e2e/config/config.go    2023-04-25 17:50:20.000000000 
+0200
@@ -25,14 +25,15 @@
 )
 
 type configTests struct {
-       env            e2e.TestEnv
-       sifImage       string
-       encryptedImage string
-       squashfsImage  string
-       ext3Image      string
-       sandboxImage   string
-       pemPublic      string
-       pemPrivate     string
+       env              e2e.TestEnv
+       sifImage         string
+       encryptedImage   string
+       squashfsImage    string
+       ext3Image        string
+       ext3OverlayImage string
+       sandboxImage     string
+       pemPublic        string
+       pemPrivate       string
 }
 
 // prepImages creates containers covering all image formats to test the
@@ -96,6 +97,20 @@
                }
        })
 
+       // An ext3 overlay embedded in a SIF
+       c.ext3OverlayImage = filepath.Join(tmpDir, "ext3Overlay.img")
+       if err := fs.CopyFile(c.sifImage, c.ext3OverlayImage, 0o755); err != 
nil {
+               t.Fatalf("Could not copy test image file: %v", err)
+       }
+       c.env.RunApptainer(
+               t,
+               e2e.AsSubtest("PrepareExt3Overlay"),
+               e2e.WithProfile(e2e.UserProfile),
+               e2e.WithCommand("overlay"),
+               e2e.WithArgs("create", c.ext3OverlayImage),
+               e2e.ExpectExit(0),
+       )
+
        return cleanup
 }
 
@@ -104,24 +119,8 @@
        cleanup := c.prepImages(t)
        defer cleanup(t)
 
-       setDirective := func(t *testing.T, directive, value string) {
-               c.env.RunApptainer(
-                       t,
-                       e2e.WithProfile(e2e.RootProfile),
-                       e2e.WithCommand("config global"),
-                       e2e.WithArgs("--set", directive, value),
-                       e2e.ExpectExit(0),
-               )
-       }
-       resetDirective := func(t *testing.T, directive string) {
-               c.env.RunApptainer(
-                       t,
-                       e2e.WithProfile(e2e.RootProfile),
-                       e2e.WithCommand("config global"),
-                       e2e.WithArgs("--reset", directive),
-                       e2e.ExpectExit(0),
-               )
-       }
+       e2e.SetDirective(t, c.env, "allow setuid-mount extfs", "yes")
+       defer e2e.ResetDirective(t, c.env, "allow setuid-mount extfs")
 
        u := e2e.UserProfile.HostUser(t)
        g, err := user.GetGrGID(u.GID)
@@ -504,6 +503,169 @@
                        directiveValue: "yes",
                        exit:           0,
                },
+               // NOTE: the "allow setuid-mount" tests have to stay after the
+               // "allow container" tests because they will be left in their
+               // default settings which can interfere with "allow container" 
tests.
+               {
+                       name:           "AllowSetuidMountEncryptedNo",
+                       argv:           []string{"--pem-path", c.pemPrivate, 
c.encryptedImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount encrypted",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountEncryptedYes",
+                       argv:           []string{"--pem-path", c.pemPrivate, 
c.encryptedImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount encrypted",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsNo",
+                       argv:           []string{c.squashfsImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsNoSif",
+                       argv:           []string{c.sifImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsNoBind",
+                       argv:           []string{"-B", c.squashfsImage + 
":/sqsh:image-src=/", c.sifImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsNoUserns",
+                       argv:           []string{c.squashfsImage, "true"},
+                       profile:        e2e.UserNamespaceProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "no",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsNoUsernsSif",
+                       argv:           []string{c.sifImage, "true"},
+                       profile:        e2e.UserNamespaceProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "no",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsNoUsernsBind",
+                       argv:           []string{"-B", c.squashfsImage + 
":/sqsh:image-src=/", c.sifImage, "true"},
+                       profile:        e2e.UserNamespaceProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "no",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsYes",
+                       argv:           []string{c.squashfsImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsYesSif",
+                       argv:           []string{c.sifImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountSquashfsYesBind",
+                       argv:           []string{"-B", c.squashfsImage + 
":/sqsh:image-src=/", c.sifImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount squashfs",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsNo",
+                       argv:           []string{c.ext3Image, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsNoSif",
+                       argv:           []string{c.ext3OverlayImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsNoBind",
+                       argv:           []string{"-B", c.ext3Image + 
":/ext3:image-src=/", c.sifImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "no",
+                       exit:           255,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsNoUserns",
+                       argv:           []string{c.ext3Image, "true"},
+                       profile:        e2e.UserNamespaceProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "no",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsNoUsernsSif",
+                       argv:           []string{c.ext3OverlayImage, "true"},
+                       profile:        e2e.UserNamespaceProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "no",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsNoUsernsBind",
+                       argv:           []string{"-B", c.ext3Image + 
":/ext3:image-src=/", c.sifImage, "true"},
+                       profile:        e2e.UserNamespaceProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "no",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsYes",
+                       argv:           []string{c.ext3Image, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsYesSif",
+                       argv:           []string{c.ext3OverlayImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
+               {
+                       name:           "AllowSetuidMountExtfsYesBind",
+                       argv:           []string{"-B", c.ext3Image + 
":/ext3:image-src=/", c.sifImage, "true"},
+                       profile:        e2e.UserProfile,
+                       directive:      "allow setuid-mount extfs",
+                       directiveValue: "yes",
+                       exit:           0,
+               },
                // FIXME
                // The e2e tests currently run inside a PID namespace.
                //   (see internal/init/init_linux.go)
@@ -537,10 +699,10 @@
                                if tt.addRequirementsFn != nil {
                                        tt.addRequirementsFn(t)
                                }
-                               setDirective(t, tt.directive, tt.directiveValue)
+                               e2e.SetDirective(t, c.env, tt.directive, 
tt.directiveValue)
                        }),
                        e2e.PostRun(func(t *testing.T) {
-                               resetDirective(t, tt.directive)
+                               e2e.ResetDirective(t, c.env, tt.directive)
                        }),
                        e2e.WithCommand("exec"),
                        e2e.WithArgs(tt.argv...),
@@ -553,26 +715,14 @@
 func (c configTests) configGlobalCombination(t *testing.T) {
        e2e.EnsureImage(t, c.env)
 
-       setDirective := func(t *testing.T, directives map[string]string) {
+       setDirectives := func(t *testing.T, directives map[string]string) {
                for k, v := range directives {
-                       c.env.RunApptainer(
-                               t,
-                               e2e.WithProfile(e2e.RootProfile),
-                               e2e.WithCommand("config global"),
-                               e2e.WithArgs("--set", k, v),
-                               e2e.ExpectExit(0),
-                       )
+                       e2e.SetDirective(t, c.env, k, v)
                }
        }
-       resetDirective := func(t *testing.T, directives map[string]string) {
+       resetDirectives := func(t *testing.T, directives map[string]string) {
                for k := range directives {
-                       c.env.RunApptainer(
-                               t,
-                               e2e.WithProfile(e2e.RootProfile),
-                               e2e.WithCommand("config global"),
-                               e2e.WithArgs("--reset", k),
-                               e2e.ExpectExit(0),
-                       )
+                       e2e.ResetDirective(t, c.env, k)
                }
        }
 
@@ -741,10 +891,10 @@
                                if tt.addRequirementsFn != nil {
                                        tt.addRequirementsFn(t)
                                }
-                               setDirective(t, tt.directives)
+                               setDirectives(t, tt.directives)
                        }),
                        e2e.PostRun(func(t *testing.T) {
-                               resetDirective(t, tt.directives)
+                               resetDirectives(t, tt.directives)
                        }),
                        e2e.WithCommand("exec"),
                        e2e.WithArgs(tt.argv...),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/internal/e2e/config.go 
new/apptainer-1.1.8/e2e/internal/e2e/config.go
--- old/apptainer-1.1.7/e2e/internal/e2e/config.go      2023-03-28 
22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/e2e/internal/e2e/config.go      2023-04-25 
17:50:20.000000000 +0200
@@ -43,3 +43,23 @@
                }
        })(t)
 }
+
+func SetDirective(t *testing.T, env TestEnv, directive, value string) {
+       env.RunApptainer(
+               t,
+               WithProfile(RootProfile),
+               WithCommand("config global"),
+               WithArgs("--set", directive, value),
+               ExpectExit(0),
+       )
+}
+
+func ResetDirective(t *testing.T, env TestEnv, directive string) {
+       env.RunApptainer(
+               t,
+               WithProfile(RootProfile),
+               WithCommand("config global"),
+               WithArgs("--reset", directive),
+               ExpectExit(0),
+       )
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/legacy/actions.go 
new/apptainer-1.1.8/e2e/legacy/actions.go
--- old/apptainer-1.1.7/e2e/legacy/actions.go   2023-03-28 22:17:08.000000000 
+0200
+++ new/apptainer-1.1.8/e2e/legacy/actions.go   2023-04-25 17:50:20.000000000 
+0200
@@ -266,9 +266,13 @@
                env: env,
        }
 
+       // legacy tests run sequentially due to loop device issue,
+       // see https://github.com/apptainer/apptainer/issues/1272
+       np := testhelper.NoParallel
+
        return testhelper.Tests{
-               "run legacy":   c.runLegacy,
-               "shell legacy": c.shellLegacy,
-               "exec legacy":  c.execLegacy,
+               "run legacy":   np(c.runLegacy),
+               "shell legacy": np(c.shellLegacy),
+               "exec legacy":  np(c.execLegacy),
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/overlay/overlay.go 
new/apptainer-1.1.8/e2e/overlay/overlay.go
--- old/apptainer-1.1.7/e2e/overlay/overlay.go  2023-03-28 22:17:08.000000000 
+0200
+++ new/apptainer-1.1.8/e2e/overlay/overlay.go  2023-04-25 17:50:20.000000000 
+0200
@@ -74,6 +74,9 @@
                e2e.ExpectExit(0),
        )
 
+       e2e.SetDirective(t, c.env, "allow setuid-mount extfs", "yes")
+       defer e2e.ResetDirective(t, c.env, "allow setuid-mount extfs")
+
        type test struct {
                name    string
                profile e2e.Profile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/run/run.go 
new/apptainer-1.1.8/e2e/run/run.go
--- old/apptainer-1.1.7/e2e/run/run.go  2023-03-28 22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/e2e/run/run.go  2023-04-25 17:50:20.000000000 +0200
@@ -286,6 +286,9 @@
                t.Fatalf(err.Error())
        }
 
+       e2e.SetDirective(t, c.env, "allow setuid-mount extfs", "yes")
+       defer e2e.ResetDirective(t, c.env, "allow setuid-mount extfs")
+
        c.env.RunApptainer(
                t,
                e2e.WithProfile(e2e.UserProfile),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/e2e/testdata/Singularity_legacy.def 
new/apptainer-1.1.8/e2e/testdata/Singularity_legacy.def
--- old/apptainer-1.1.7/e2e/testdata/Singularity_legacy.def     2023-03-28 
22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/e2e/testdata/Singularity_legacy.def     2023-04-25 
17:50:20.000000000 +0200
@@ -3,6 +3,6 @@
 
 %post
     cd /
-    apt-get update -y && apt-get install -y wget cryptsetup-bin squashfs-tools
+    apt-get update -y && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get 
install -y wget cryptsetup-bin squashfs-tools tzdata
     wget 
https://github.com/sylabs/singularity/releases/download/v3.9.2/singularity-ce_3.9.2-focal_amd64.deb
     dpkg -i singularity-ce_3.9.2-focal_amd64.deb && rm 
singularity-ce_3.9.2-focal_amd64.deb
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/apptainer-1.1.7/internal/pkg/runtime/engine/apptainer/container_linux.go 
new/apptainer-1.1.8/internal/pkg/runtime/engine/apptainer/container_linux.go
--- 
old/apptainer-1.1.7/internal/pkg/runtime/engine/apptainer/container_linux.go    
    2023-03-28 22:17:08.000000000 +0200
+++ 
new/apptainer-1.1.8/internal/pkg/runtime/engine/apptainer/container_linux.go    
    2023-04-25 17:50:20.000000000 +0200
@@ -722,6 +722,10 @@
                                sylog.Verbosef("Overlay mount failed with %s, 
mounting with index=off", err)
                                optsString = fmt.Sprintf("%s,index=off", 
optsString)
                                goto mount
+                       } else if mnt.Type == "overlay" && err == 
syscall.EINVAL {
+                               sylog.Verbosef("Overlay mount failed with %s, 
mounting without xino option", err)
+                               optsString = strings.Replace(optsString, 
",xino=on", "", -1)
+                               goto mount
                        } else if mnt.Type == "overlay" && tag == 
mount.LayerTag {
                                if imageDriver != nil && 
imageDriver.Features()&image.OverlayFeature != 0 {
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/apptainer-1.1.7/internal/pkg/runtime/engine/apptainer/prepare_linux.go 
new/apptainer-1.1.8/internal/pkg/runtime/engine/apptainer/prepare_linux.go
--- old/apptainer-1.1.7/internal/pkg/runtime/engine/apptainer/prepare_linux.go  
2023-03-28 22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/internal/pkg/runtime/engine/apptainer/prepare_linux.go  
2023-04-25 17:50:20.000000000 +0200
@@ -150,7 +150,7 @@
                if err := e.prepareContainerConfig(starterConfig); err != nil {
                        return err
                }
-               if err := e.loadImages(starterConfig); err != nil {
+               if err := e.loadImages(starterConfig, userNS); err != nil {
                        return err
                }
        }
@@ -1131,12 +1131,12 @@
        return nil
 }
 
-func (e *EngineOperations) loadImages(starterConfig *starter.Config) error {
+func (e *EngineOperations) loadImages(starterConfig *starter.Config, userNS 
bool) error {
        images := make([]image.Image, 0)
 
        // load rootfs image
        writable := e.EngineConfig.GetWritableImage()
-       img, err := e.loadImage(e.EngineConfig.GetImage(), writable)
+       img, err := e.loadImage(e.EngineConfig.GetImage(), writable, userNS)
        if err != nil {
                return err
        }
@@ -1236,7 +1236,13 @@
                                return fmt.Errorf("while getting overlay 
partitions in %s: %s", img.Path, err)
                        }
                        for _, p := range overlays {
-                               if img.Writable && p.Type == image.EXT3 {
+                               if p.Type != image.EXT3 {
+                                       continue
+                               }
+                               if !userNS && 
!e.EngineConfig.File.AllowSetuidMountExtfs {
+                                       return fmt.Errorf("configuration 
disallows users from mounting SIF extfs partition in setuid mode, try --userns")
+                               }
+                               if img.Writable {
                                        writableOverlayPath = img.Path
                                }
                        }
@@ -1252,7 +1258,7 @@
 
        switch e.EngineConfig.GetSessionLayer() {
        case apptainerConfig.OverlayLayer:
-               overlayImages, err := e.loadOverlayImages(starterConfig, 
writableOverlayPath)
+               overlayImages, err := e.loadOverlayImages(starterConfig, 
writableOverlayPath, userNS)
                if err != nil {
                        return fmt.Errorf("while loading overlay images: %s", 
err)
                }
@@ -1264,7 +1270,7 @@
                }
        }
 
-       bindImages, err := e.loadBindImages(starterConfig)
+       bindImages, err := e.loadBindImages(starterConfig, userNS)
        if err != nil {
                return fmt.Errorf("while loading data bind images: %s", err)
        }
@@ -1276,7 +1282,7 @@
 }
 
 // loadOverlayImages loads overlay images.
-func (e *EngineOperations) loadOverlayImages(starterConfig *starter.Config, 
writableOverlayPath string) ([]image.Image, error) {
+func (e *EngineOperations) loadOverlayImages(starterConfig *starter.Config, 
writableOverlayPath string, userNS bool) ([]image.Image, error) {
        images := make([]image.Image, 0)
 
        for _, overlayImg := range e.EngineConfig.GetOverlayImage() {
@@ -1289,7 +1295,7 @@
                        }
                }
 
-               img, err := e.loadImage(splitted[0], writableOverlay)
+               img, err := e.loadImage(splitted[0], writableOverlay, userNS)
                if err != nil {
                        if !image.IsReadOnlyFilesytem(err) {
                                return nil, fmt.Errorf("failed to open overlay 
image %s: %s", splitted[0], err)
@@ -1325,7 +1331,7 @@
 }
 
 // loadBindImages load data bind images.
-func (e *EngineOperations) loadBindImages(starterConfig *starter.Config) 
([]image.Image, error) {
+func (e *EngineOperations) loadBindImages(starterConfig *starter.Config, 
userNS bool) ([]image.Image, error) {
        images := make([]image.Image, 0)
 
        binds := e.EngineConfig.GetBindPath()
@@ -1339,7 +1345,7 @@
 
                sylog.Debugf("Loading data image %s", imagePath)
 
-               img, err := e.loadImage(imagePath, !binds[i].Readonly())
+               img, err := e.loadImage(imagePath, !binds[i].Readonly(), userNS)
                if err != nil && !image.IsReadOnlyFilesytem(err) {
                        return nil, fmt.Errorf("failed to load data image %s: 
%s", imagePath, err)
                }
@@ -1355,7 +1361,7 @@
        return images, nil
 }
 
-func (e *EngineOperations) loadImage(path string, writable bool) 
(*image.Image, error) {
+func (e *EngineOperations) loadImage(path string, writable bool, userNS bool) 
(*image.Image, error) {
        const delSuffix = " (deleted)"
 
        imgObject, imgErr := image.Init(path, writable)
@@ -1413,11 +1419,17 @@
                if !e.EngineConfig.File.AllowContainerSquashfs {
                        return nil, fmt.Errorf("configuration disallows users 
from running squashFS containers")
                }
+               if !userNS && !e.EngineConfig.File.AllowSetuidMountSquashfs {
+                       return nil, fmt.Errorf("configuration disallows users 
from mounting squashFS in setuid mode, try --userns")
+               }
        // Bare EXT3
        case image.EXT3:
                if !e.EngineConfig.File.AllowContainerExtfs {
                        return nil, fmt.Errorf("configuration disallows users 
from running extFS containers")
                }
+               if !userNS && !e.EngineConfig.File.AllowSetuidMountExtfs {
+                       return nil, fmt.Errorf("configuration disallows users 
from mounting extfs in setuid mode, try --userns")
+               }
        // Bare sandbox directory
        case image.SANDBOX:
                if !e.EngineConfig.File.AllowContainerDir {
@@ -1425,6 +1437,9 @@
                }
        // SIF
        case image.SIF:
+               if !userNS && !e.EngineConfig.File.AllowSetuidMountSquashfs {
+                       return nil, fmt.Errorf("configuration disallows users 
from mounting SIF squashFS partition in setuid mode, try --userns")
+               }
                // Check if SIF contains an encrypted rootfs partition.
                // We don't support encryption for other partitions at present.
                encrypted, err := imgObject.HasEncryptedRootFs()
@@ -1435,6 +1450,9 @@
                if encrypted && !e.EngineConfig.File.AllowContainerEncrypted {
                        return nil, fmt.Errorf("configuration disallows users 
from running encrypted SIF containers")
                }
+               if encrypted && !userNS && 
!e.EngineConfig.File.AllowSetuidMountEncrypted {
+                       return nil, fmt.Errorf("configuration disallows users 
from mounting encrypted files in setuid mode")
+               }
                // SIF without encryption - regardless of rootfs filesystem type
                if !encrypted && !e.EngineConfig.File.AllowContainerSIF {
                        return nil, fmt.Errorf("configuration disallows users 
from running unencrypted SIF containers")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/internal/pkg/util/crypt/crypt_dev.go 
new/apptainer-1.1.8/internal/pkg/util/crypt/crypt_dev.go
--- old/apptainer-1.1.7/internal/pkg/util/crypt/crypt_dev.go    2023-03-28 
22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/internal/pkg/util/crypt/crypt_dev.go    2023-04-25 
17:50:20.000000000 +0200
@@ -47,7 +47,6 @@
 func createLoop(path string, offset, size uint64) (string, error) {
        loopDev := &loop.Device{
                MaxLoopDevices: loop.GetMaxLoopDevices(),
-               Shared:         true,
                Info: &loop.Info64{
                        SizeLimit: size,
                        Offset:    offset,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/apptainer-1.1.7/internal/pkg/util/fs/mount/mount_linux.go 
new/apptainer-1.1.8/internal/pkg/util/fs/mount/mount_linux.go
--- old/apptainer-1.1.7/internal/pkg/util/fs/mount/mount_linux.go       
2023-03-28 22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/internal/pkg/util/fs/mount/mount_linux.go       
2023-04-25 17:50:20.000000000 +0200
@@ -701,7 +701,7 @@
                if !strings.HasPrefix(workdir, "/") {
                        return fmt.Errorf("workdir must be an absolute path")
                }
-               options = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", 
lowerdir, upperdir, workdir)
+               options = 
fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s,xino=on", lowerdir, upperdir, 
workdir)
        } else {
                options = fmt.Sprintf("lowerdir=%s", lowerdir)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/pkg/util/apptainerconf/config.go 
new/apptainer-1.1.8/pkg/util/apptainerconf/config.go
--- old/apptainer-1.1.7/pkg/util/apptainerconf/config.go        2023-03-28 
22:17:08.000000000 +0200
+++ new/apptainer-1.1.8/pkg/util/apptainerconf/config.go        2023-04-25 
17:50:20.000000000 +0200
@@ -76,46 +76,49 @@
 
 // File describes the apptainer.conf file options
 type File struct {
-       AllowSetuid             bool     `default:"yes" authorized:"yes,no" 
directive:"allow setuid"`
-       AllowPidNs              bool     `default:"yes" authorized:"yes,no" 
directive:"allow pid ns"`
-       ConfigPasswd            bool     `default:"yes" authorized:"yes,no" 
directive:"config passwd"`
-       ConfigGroup             bool     `default:"yes" authorized:"yes,no" 
directive:"config group"`
-       ConfigResolvConf        bool     `default:"yes" authorized:"yes,no" 
directive:"config resolv_conf"`
-       MountProc               bool     `default:"yes" authorized:"yes,no" 
directive:"mount proc"`
-       MountSys                bool     `default:"yes" authorized:"yes,no" 
directive:"mount sys"`
-       MountDevPts             bool     `default:"yes" authorized:"yes,no" 
directive:"mount devpts"`
-       MountHome               bool     `default:"yes" authorized:"yes,no" 
directive:"mount home"`
-       MountTmp                bool     `default:"yes" authorized:"yes,no" 
directive:"mount tmp"`
-       MountHostfs             bool     `default:"no" authorized:"yes,no" 
directive:"mount hostfs"`
-       UserBindControl         bool     `default:"yes" authorized:"yes,no" 
directive:"user bind control"`
-       EnableFusemount         bool     `default:"yes" authorized:"yes,no" 
directive:"enable fusemount"`
-       EnableUnderlay          bool     `default:"yes" authorized:"yes,no" 
directive:"enable underlay"`
-       MountSlave              bool     `default:"yes" authorized:"yes,no" 
directive:"mount slave"`
-       AllowContainerSIF       bool     `default:"yes" authorized:"yes,no" 
directive:"allow container sif"`
-       AllowContainerEncrypted bool     `default:"yes" authorized:"yes,no" 
directive:"allow container encrypted"`
-       AllowContainerSquashfs  bool     `default:"yes" authorized:"yes,no" 
directive:"allow container squashfs"`
-       AllowContainerExtfs     bool     `default:"yes" authorized:"yes,no" 
directive:"allow container extfs"`
-       AllowContainerDir       bool     `default:"yes" authorized:"yes,no" 
directive:"allow container dir"`
-       AlwaysUseNv             bool     `default:"no" authorized:"yes,no" 
directive:"always use nv"`
-       UseNvCCLI               bool     `default:"no" authorized:"yes,no" 
directive:"use nvidia-container-cli"`
-       AlwaysUseRocm           bool     `default:"no" authorized:"yes,no" 
directive:"always use rocm"`
-       SharedLoopDevices       bool     `default:"no" authorized:"yes,no" 
directive:"shared loop devices"`
-       MaxLoopDevices          uint     `default:"256" directive:"max loop 
devices"`
-       SessiondirMaxSize       uint     `default:"16" directive:"sessiondir 
max size"`
-       MountDev                string   `default:"yes" 
authorized:"yes,no,minimal" directive:"mount dev"`
-       EnableOverlay           string   `default:"try" 
authorized:"yes,no,try,driver" directive:"enable overlay"`
-       BindPath                []string `default:"/etc/localtime,/etc/hosts" 
directive:"bind path"`
-       LimitContainerOwners    []string `directive:"limit container owners"`
-       LimitContainerGroups    []string `directive:"limit container groups"`
-       LimitContainerPaths     []string `directive:"limit container paths"`
-       AllowNetUsers           []string `directive:"allow net users"`
-       AllowNetGroups          []string `directive:"allow net groups"`
-       AllowNetNetworks        []string `directive:"allow net networks"`
-       RootDefaultCapabilities string   `default:"full" 
authorized:"full,file,no" directive:"root default capabilities"`
-       MemoryFSType            string   `default:"tmpfs" 
authorized:"tmpfs,ramfs" directive:"memory fs type"`
-       CniConfPath             string   `directive:"cni configuration path"`
-       CniPluginPath           string   `directive:"cni plugin path"`
-       BinaryPath              string   
`default:"$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 
directive:"binary path"`
+       AllowSetuid               bool     `default:"yes" authorized:"yes,no" 
directive:"allow setuid"`
+       AllowPidNs                bool     `default:"yes" authorized:"yes,no" 
directive:"allow pid ns"`
+       ConfigPasswd              bool     `default:"yes" authorized:"yes,no" 
directive:"config passwd"`
+       ConfigGroup               bool     `default:"yes" authorized:"yes,no" 
directive:"config group"`
+       ConfigResolvConf          bool     `default:"yes" authorized:"yes,no" 
directive:"config resolv_conf"`
+       MountProc                 bool     `default:"yes" authorized:"yes,no" 
directive:"mount proc"`
+       MountSys                  bool     `default:"yes" authorized:"yes,no" 
directive:"mount sys"`
+       MountDevPts               bool     `default:"yes" authorized:"yes,no" 
directive:"mount devpts"`
+       MountHome                 bool     `default:"yes" authorized:"yes,no" 
directive:"mount home"`
+       MountTmp                  bool     `default:"yes" authorized:"yes,no" 
directive:"mount tmp"`
+       MountHostfs               bool     `default:"no" authorized:"yes,no" 
directive:"mount hostfs"`
+       UserBindControl           bool     `default:"yes" authorized:"yes,no" 
directive:"user bind control"`
+       EnableFusemount           bool     `default:"yes" authorized:"yes,no" 
directive:"enable fusemount"`
+       EnableUnderlay            bool     `default:"yes" authorized:"yes,no" 
directive:"enable underlay"`
+       MountSlave                bool     `default:"yes" authorized:"yes,no" 
directive:"mount slave"`
+       AllowContainerSIF         bool     `default:"yes" authorized:"yes,no" 
directive:"allow container sif"`
+       AllowContainerEncrypted   bool     `default:"yes" authorized:"yes,no" 
directive:"allow container encrypted"`
+       AllowContainerSquashfs    bool     `default:"yes" authorized:"yes,no" 
directive:"allow container squashfs"`
+       AllowContainerExtfs       bool     `default:"yes" authorized:"yes,no" 
directive:"allow container extfs"`
+       AllowContainerDir         bool     `default:"yes" authorized:"yes,no" 
directive:"allow container dir"`
+       AllowSetuidMountEncrypted bool     `default:"yes" authorized:"yes,no" 
directive:"allow setuid-mount encrypted"`
+       AllowSetuidMountSquashfs  bool     `default:"yes" authorized:"yes,no" 
directive:"allow setuid-mount squashfs"`
+       AllowSetuidMountExtfs     bool     `default:"no" authorized:"yes,no" 
directive:"allow setuid-mount extfs"`
+       AlwaysUseNv               bool     `default:"no" authorized:"yes,no" 
directive:"always use nv"`
+       UseNvCCLI                 bool     `default:"no" authorized:"yes,no" 
directive:"use nvidia-container-cli"`
+       AlwaysUseRocm             bool     `default:"no" authorized:"yes,no" 
directive:"always use rocm"`
+       SharedLoopDevices         bool     `default:"no" authorized:"yes,no" 
directive:"shared loop devices"`
+       MaxLoopDevices            uint     `default:"256" directive:"max loop 
devices"`
+       SessiondirMaxSize         uint     `default:"16" directive:"sessiondir 
max size"`
+       MountDev                  string   `default:"yes" 
authorized:"yes,no,minimal" directive:"mount dev"`
+       EnableOverlay             string   `default:"try" 
authorized:"yes,no,try,driver" directive:"enable overlay"`
+       BindPath                  []string `default:"/etc/localtime,/etc/hosts" 
directive:"bind path"`
+       LimitContainerOwners      []string `directive:"limit container owners"`
+       LimitContainerGroups      []string `directive:"limit container groups"`
+       LimitContainerPaths       []string `directive:"limit container paths"`
+       AllowNetUsers             []string `directive:"allow net users"`
+       AllowNetGroups            []string `directive:"allow net groups"`
+       AllowNetNetworks          []string `directive:"allow net networks"`
+       RootDefaultCapabilities   string   `default:"full" 
authorized:"full,file,no" directive:"root default capabilities"`
+       MemoryFSType              string   `default:"tmpfs" 
authorized:"tmpfs,ramfs" directive:"memory fs type"`
+       CniConfPath               string   `directive:"cni configuration path"`
+       CniPluginPath             string   `directive:"cni plugin path"`
+       BinaryPath                string   
`default:"$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 
directive:"binary path"`
        // SuidBinaryPath is hidden; it is not referenced below, and overwritten
        SuidBinaryPath      string `directive:"suidbinary path"`
        MksquashfsProcs     uint   `default:"0" directive:"mksquashfs procs"`
@@ -127,6 +130,18 @@
        SystemdCgroups      bool   `default:"yes" authorized:"yes,no" 
directive:"systemd cgroups"`
 }
 
+// NOTE: if you think that we may want to change the default for any
+// configuration parameter in the future, it is a good idea to conditionally
+// insert a comment before the default setting when the setting is equal
+// to the current default.  That enables the defaults to get updated in
+// a new release even if an administrator has changed one of the *other*
+// settings.  This gets around the problem of packagers such as rpm
+// refusing to overwrite a configuration file if any change has been made.
+// This technique is used for example in the "allow setuid-mount" options
+// below.  If a default is changed in a future release, both the default
+// setting above and the expression for the conditional comment below need
+// to change at the same time.
+
 const TemplateAsset = `# APPTAINER.CONF
 # This is the global configuration file for Apptainer. This file controls
 # what the container is allowed to do on a particular host, and as a result
@@ -321,7 +336,9 @@
 # ALLOW CONTAINER ${TYPE}: [BOOL]
 # DEFAULT: yes
 # This feature limits what kind of containers that Apptainer will allow
-# users to use (note this does not apply for root).
+# users to use (note this does not apply for root).  Note that some of the
+# same operations can be limited in setuid mode by the ALLOW SETUID-MOUNT
+# feature below; both types need to be "yes" to be allowed.
 #
 # Allow use of unencrypted SIF containers
 allow container sif = {{ if eq .AllowContainerSIF true}}yes{{ else }}no{{ end 
}}
@@ -334,6 +351,32 @@
 allow container extfs = {{ if eq .AllowContainerExtfs true }}yes{{ else }}no{{ 
end }}
 allow container dir = {{ if eq .AllowContainerDir true }}yes{{ else }}no{{ end 
}}
 
+# ALLOW SETUID-MOUNT ${TYPE}: [BOOL]
+# DEFAULT: yes, except no for extfs
+# This feature limits what types of mounts that Apptainer will allow
+# unprivileged users to use in setuid mode.  Normally these operations
+# require the elevated privileges of setuid mode, although Apptainer
+# has unprivileged alternatives for squashfs and extfs.  Note that some of
+# the same operations can also be limited by the ALLOW CONTAINER feature
+# above; both types need to be "yes" to be allowed.
+#
+# Allow mounting of SIF encryption (using the kernel device-mapper) in
+# setuid mode
+{{ if eq .AllowSetuidMountEncrypted true}}# {{ end }}allow setuid-mount 
encrypted = {{ if eq .AllowSetuidMountEncrypted true}}yes{{ else }}no{{ end }}
+#
+# Allow mounting of squashfs filesystem types in setuid mode, both inside and
+# outside of SIF files
+{{ if eq .AllowSetuidMountSquashfs true}}# {{ end }}allow setuid-mount 
squashfs = {{ if eq .AllowSetuidMountSquashfs true}}yes{{ else }}no{{ end }}
+#
+# Allow mounting of extfs filesystem types in setuid mode, both inside and
+# outside of SIF files.  WARNING: this filesystem type frequently has relevant
+# CVEs that that take a very long time for vendors to patch because they are
+# not considered to be High severity since normally unprivileged users do
+# not have write access to the raw filesystem data.  This is why this option
+# defaults to "no".  Change it at your own risk and consider using the
+# LIMIT CONTAINER features above if you do.
+{{ if eq .AllowSetuidMountExtfs false}}# {{ end }}allow setuid-mount extfs = 
{{ if eq .AllowSetuidMountExtfs true}}yes{{ else }}no{{ end }}
+
 # ALLOW NET USERS: [STRING]
 # DEFAULT: NULL
 # Allow specified root administered CNI network configurations to be used by 
the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/pkg/util/loop/loop.go 
new/apptainer-1.1.8/pkg/util/loop/loop.go
--- old/apptainer-1.1.7/pkg/util/loop/loop.go   2023-03-28 22:17:08.000000000 
+0200
+++ new/apptainer-1.1.8/pkg/util/loop/loop.go   2023-04-25 17:50:20.000000000 
+0200
@@ -150,8 +150,6 @@
        imageDev := uint64(imageInfo.Dev)
 
        for device := 0; device < loop.MaxLoopDevices; device++ {
-               *number = device
-
                // Try to open an existing loop device, but don't create a new 
one
                loopFd, releaseLock, err := openLoopDev(device, mode, true, nil)
                if err != nil {
@@ -172,6 +170,7 @@
                        // be sure that the loop device won't be released 
between this
                        // check and the mount of the filesystem
                        sylog.Debugf("Sharing loop device %d", device)
+                       *number = device
                        loop.fd = &loopFd
                        return true, nil
                }
@@ -186,22 +185,24 @@
 // When setting loop device status, some kernel may return EAGAIN, this 
function would sync
 // workaround this error.
 func (loop *Device) attachLoop(imageFd uintptr, imageInfo *syscall.Stat_t, 
mode int, number *int) error {
-       releaseDevice := func(fd int, clear bool) {
+       releaseDevice := func(fd int, clear bool, releaseLock func()) {
                if clear {
                        syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), 
CmdClrFd, 0)
                }
                syscall.Close(fd)
+               releaseLock()
        }
 
        createFn := getCreateDeviceFn()
        retryFn := getRetryStatusFn(imageFd, imageInfo)
 
        for device := 0; device < loop.MaxLoopDevices; device++ {
-               *number = device
-
                // Try to open the loop device, creating the device node if 
needed
                loopFd, releaseLock, err := openLoopDev(device, mode, 
loop.Shared, createFn)
                if err != nil {
+                       if os.IsNotExist(err) {
+                               continue
+                       }
                        sylog.Debugf("Couldn't open loop device %d: %v", 
device, err)
                        return err
                }
@@ -209,24 +210,22 @@
                // On error, we'll move on to try the next loop device
                _, _, esys := syscall.Syscall(syscall.SYS_IOCTL, 
uintptr(loopFd), CmdSetFd, imageFd)
                if esys != 0 {
-                       releaseDevice(loopFd, false)
-                       releaseLock()
+                       releaseDevice(loopFd, false, releaseLock)
                        continue
                }
 
                if _, _, esys := syscall.Syscall(syscall.SYS_FCNTL, 
uintptr(loopFd), syscall.F_SETFD, syscall.FD_CLOEXEC); esys != 0 {
-                       releaseDevice(loopFd, true)
-                       releaseLock()
+                       releaseDevice(loopFd, true, releaseLock)
                        return fmt.Errorf("failed to set close-on-exec on loop 
device %s: error message=%s", getLoopPath(device), esys.Error())
                }
 
                if err := setLoopStatus(loopFd, loop.Info, getLoopPath(device), 
retryFn); err != nil {
-                       releaseDevice(loopFd, true)
-                       releaseLock()
+                       releaseDevice(loopFd, true, releaseLock)
                        return fmt.Errorf("loop device status: %s", err)
                }
 
                releaseLock()
+               *number = device
                loop.fd = &loopFd
                return nil
        }
@@ -239,21 +238,29 @@
 // Returns the fd for the opened device, or -1 if it was not possible to 
openLoopDev it.
 func openLoopDev(device, mode int, sharedLoop bool, createFn createDeviceFn) 
(int, func(), error) {
        path := getLoopPath(device)
-       fi, err := os.Stat(path)
+
+       // loop device can exist but without any device attached to it in 
kernel,
+       // a stat call couldn't catch ENXIO error in this case, use open
+       loopFd, err := syscall.Open(path, mode, 0o600)
        if err != nil {
-               if !os.IsNotExist(err) {
-                       return -1, nil, fmt.Errorf("could not stat %s: %w", 
path, err)
+               if errno, ok := err.(syscall.Errno); ok && errno == unix.ENXIO {
+                       if createFn == nil {
+                               err = os.ErrNotExist
+                       }
+               } else if !os.IsNotExist(err) {
+                       return -1, nil, fmt.Errorf("could not open %s: %w", 
path, err)
                }
                // device doesn't exist but no create function passed ... done
                if createFn == nil {
                        return -1, nil, err
                }
                // create the device node if we need to
-               if err := createFn(device); err != nil {
+               err := createFn(device)
+               if err != nil {
                        return -1, nil, fmt.Errorf("could not create %s: %w", 
path, err)
                }
-       } else if fi.Mode()&os.ModeDevice == 0 {
-               return -1, nil, fmt.Errorf("%s is not a block device", path)
+       } else {
+               _ = syscall.Close(loopFd)
        }
 
        releaseLock := func() {}
@@ -272,8 +279,7 @@
                }
        }
 
-       // Now open the loop device
-       loopFd, err := syscall.Open(path, mode, 0o600)
+       loopFd, err = syscall.Open(path, mode, 0o600)
        if err != nil {
                releaseLock()
                return -1, nil, fmt.Errorf("could not open %s: %w", path, err)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apptainer-1.1.7/scripts/should-e2e-run 
new/apptainer-1.1.8/scripts/should-e2e-run
--- old/apptainer-1.1.7/scripts/should-e2e-run  2023-03-28 22:17:08.000000000 
+0200
+++ new/apptainer-1.1.8/scripts/should-e2e-run  2023-04-25 17:50:20.000000000 
+0200
@@ -83,6 +83,10 @@
                require_e2e=true
                ;;
 
+       null)
+               # Failed to read api, could be private repo.  Run tests.
+               require_e2e=true
+               ;;
        *)
                # The branch is not master or release, skip e2e
                require_e2e=false

Reply via email to