Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package runc for openSUSE:Factory checked in 
at 2026-06-29 17:30:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/runc (Old)
 and      /work/SRC/openSUSE:Factory/.runc.new.11887 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "runc"

Mon Jun 29 17:30:03 2026 rev:80 rq:1362242 version:1.4.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/runc/runc.changes        2026-03-30 
18:31:04.270501350 +0200
+++ /work/SRC/openSUSE:Factory/.runc.new.11887/runc.changes     2026-06-29 
17:30:38.502611058 +0200
@@ -1,0 +2,7 @@
+Wed May 27 07:23:06 UTC 2026 - Madhankumar Chellamuthu 
<[email protected]>
+
+- Update to runc v1.4.2. Upstream changelog is available from
+  <https://github.com/opencontainers/runc/releases/tag/v1.4.2>.
+- runc.keyring has been updated to match the new version from upstream. 
+
+-------------------------------------------------------------------

Old:
----
  runc-1.4.1.tar.xz
  runc-1.4.1.tar.xz.asc

New:
----
  runc-1.4.2.tar.xz
  runc-1.4.2.tar.xz.asc

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

Other differences:
------------------
++++++ runc.spec ++++++
--- /var/tmp/diff_new_pack.obsUVb/_old  2026-06-29 17:30:39.078630916 +0200
+++ /var/tmp/diff_new_pack.obsUVb/_new  2026-06-29 17:30:39.086631193 +0200
@@ -27,7 +27,7 @@
 %define project github.com/opencontainers/runc
 
 Name:           runc
-Version:        1.4.1
+Version:        1.4.2
 %define upstream_version %{version}
 Release:        0
 Summary:        Tool for spawning and running OCI containers

++++++ runc-1.4.1.tar.xz -> runc-1.4.2.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/.github/workflows/validate.yml 
new/runc-1.4.2/.github/workflows/validate.yml
--- old/runc-1.4.1/.github/workflows/validate.yml       2026-03-12 
21:23:25.000000000 +0100
+++ new/runc-1.4.2/.github/workflows/validate.yml       2026-04-03 
00:52:45.000000000 +0200
@@ -263,6 +263,50 @@
         ./bootstrap-get-images.sh > get-images.sh
         git diff --exit-code
 
+  conmon:
+    runs-on: ubuntu-24.04
+    steps:
+    - name: checkout
+      uses: actions/checkout@v6
+
+    - name: install runc and conmon deps
+      # XXX maybe switch to conmon/hack/github-actions-setup if the burden
+      # to maintain the list of needed packages here is too much to handle.
+      run: |
+        sudo apt update
+        sudo apt -y install libseccomp-dev libglib2.0-dev libsystemd-dev socat
+
+    - name: install Go
+      uses: actions/setup-go@v6
+      with:
+        go-version: "${{ env.GO_VERSION }}"
+
+    - name: build runc
+      run: make
+
+    - name: setup bats
+      uses: bats-core/[email protected]
+      with:
+        bats-version: 1.13.0 # As required by conmon in 
hack/github-actions-setup.
+        support-install: false
+        assert-install: false
+        detik-install: false
+        file-install: false
+
+    - name: checkout conmon
+      uses: actions/checkout@v6
+      with:
+        repository: containers/conmon
+        path: conmon
+        ref: v2.2.1
+
+    - name: build conmon
+      run: cd conmon && make
+
+    - name: run conmon tests
+      run: |
+        RUNTIME_BINARY=$(pwd)/runc ./conmon/test/run-tests.sh -j $(nproc)
+
   all-done:
     needs:
       - check-go
@@ -270,6 +314,7 @@
       - codespell
       - commit
       - compile-buildtags
+      - conmon
       - deps
       - get-images
       - keyring
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/CHANGELOG.md new/runc-1.4.2/CHANGELOG.md
--- old/runc-1.4.1/CHANGELOG.md 2026-03-12 21:23:25.000000000 +0100
+++ new/runc-1.4.2/CHANGELOG.md 2026-04-03 00:52:45.000000000 +0200
@@ -6,6 +6,19 @@
 
 ## [Unreleased 1.4.z]
 
+## [1.4.2] - 2026-04-02
+
+> Я — Земля! Я своих провожаю питомцев.
+
+### Fixed ###
+- A regression in runc v1.3.0 which can result in a stuck `runc exec` or
+  `runc run` when the container process runs for a short time. (#5208,
+  #5210, #5216)
+- Mount sources that need to be open on the host are now closed earlier during
+  container start, reducing the total amount of used file descriptors and
+  helping to avoid hitting the open files limit when handling many such mounts.
+  (#5177, #5201)
+
 ## [1.4.1] - 2026-03-12
 
 > La guerre n'est pas une aventure. La guerre est une maladie. Comme le typhus.
@@ -90,6 +103,9 @@
 ### Changed
 - libct: switch to `(*CPUSet).Fill`. (#4927)
 - docs/spec-conformance.md: update for spec v1.3.0. (#4948)
+- Errors from `runc init` have historically been quite painful to understand
+  and debug, we have made several improvements to make them more comprehensive
+  and thus useful when debugging issues. (#5040, #4951, #4928)
 
 [CVE-2025-52881]: 
https://github.com/opencontainers/runc/security/advisories/GHSA-cgrx-mc8f-2prm
 
@@ -1463,7 +1479,8 @@
 [1.3.0-rc.1]: 
https://github.com/opencontainers/runc/compare/v1.2.0...v1.3.0-rc.1
 
 <!-- 1.4.z patch releases -->
-[Unreleased 1.4.z]: 
https://github.com/opencontainers/runc/compare/v1.4.1...release-1.4
+[Unreleased 1.4.z]: 
https://github.com/opencontainers/runc/compare/v1.4.2...release-1.4
+[1.4.2]: https://github.com/opencontainers/runc/compare/v1.4.1...v1.4.2
 [1.4.1]: https://github.com/opencontainers/runc/compare/v1.4.0...v1.4.1
 [1.4.0]: https://github.com/opencontainers/runc/compare/v1.4.0-rc.3...v1.4.0
 [1.4.0-rc.3]: 
https://github.com/opencontainers/runc/compare/v1.4.0-rc.2...v1.4.0-rc.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/VERSION new/runc-1.4.2/VERSION
--- old/runc-1.4.1/VERSION      2026-03-12 21:23:25.000000000 +0100
+++ new/runc-1.4.2/VERSION      2026-04-03 00:52:45.000000000 +0200
@@ -1 +1 @@
-1.4.1
+1.4.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/libcontainer/mount_linux.go 
new/runc-1.4.2/libcontainer/mount_linux.go
--- old/runc-1.4.1/libcontainer/mount_linux.go  2026-03-12 21:23:25.000000000 
+0100
+++ new/runc-1.4.2/libcontainer/mount_linux.go  2026-04-03 00:52:45.000000000 
+0200
@@ -110,7 +110,7 @@
 
        if e.source != "" {
                out += "src=" + e.source + ", "
-               if e.srcFile != nil {
+               if e.srcFile != nil && e.srcFile.file != nil {
                        out += "srcType=" + string(e.srcFile.Type) + ", "
                        out += "srcFd=" + 
strconv.Itoa(int(e.srcFile.file.Fd())) + ", "
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/libcontainer/rootfs_linux.go 
new/runc-1.4.2/libcontainer/rootfs_linux.go
--- old/runc-1.4.1/libcontainer/rootfs_linux.go 2026-03-12 21:23:25.000000000 
+0100
+++ new/runc-1.4.2/libcontainer/rootfs_linux.go 2026-04-03 00:52:45.000000000 
+0200
@@ -97,6 +97,60 @@
        return true
 }
 
+// setupAndMountToRootfs sets up the mount for a single mount point and mounts 
it to the rootfs.
+func setupAndMountToRootfs(pipe *syncSocket, config *configs.Config, 
mountConfig *mountConfig, m *configs.Mount) error {
+       entry := mountEntry{Mount: m}
+       // Figure out whether we need to request runc to give us an
+       // open_tree(2)-style mountfd. For idmapped mounts, this is always
+       // necessary. For bind-mounts, this is only necessary if we cannot
+       // resolve the parent mount (this is only hit if you are running in a
+       // userns -- but for rootless the host-side thread can't help).
+       wantSourceFile := m.IsIDMapped()
+       if m.IsBind() && !config.RootlessEUID {
+               if _, err := os.Stat(m.Source); err != nil {
+                       wantSourceFile = true
+               }
+       }
+       if wantSourceFile {
+               // Request a source file from the host.
+               if err := writeSyncArg(pipe, procMountPlease, m); err != nil {
+                       return fmt.Errorf("failed to request mountfd for %q: 
%w", m.Source, err)
+               }
+               sync, err := readSyncFull(pipe, procMountFd)
+               if err != nil {
+                       return fmt.Errorf("mountfd request for %q failed: %w", 
m.Source, err)
+               }
+               if sync.File == nil {
+                       return fmt.Errorf("mountfd request for %q: response 
missing attached fd", m.Source)
+               }
+               defer sync.File.Close()
+               // Sanity-check to make sure we didn't get the wrong fd back. 
Note
+               // that while m.Source might contain symlinks, the 
(*os.File).Name
+               // is based on the path provided to os.OpenFile, not what it
+               // resolves to. So this should never happen.
+               if sync.File.Name() != m.Source {
+                       return fmt.Errorf("returned mountfd for %q doesn't 
match requested mount configuration: mountfd path is %q", m.Source, 
sync.File.Name())
+               }
+               // Unmarshal the procMountFd argument (the file is sync.File).
+               var src *mountSource
+               if sync.Arg == nil {
+                       return fmt.Errorf("sync %q is missing an argument", 
sync.Type)
+               }
+               if err := json.Unmarshal(*sync.Arg, &src); err != nil {
+                       return fmt.Errorf("invalid mount fd response argument 
%q: %w", string(*sync.Arg), err)
+               }
+               if src == nil {
+                       return fmt.Errorf("mountfd request for %q: no mount 
source info received", m.Source)
+               }
+               src.file = sync.File
+               entry.srcFile = src
+       }
+       if err := mountToRootfs(mountConfig, entry); err != nil {
+               return fmt.Errorf("error mounting %q to rootfs at %q: %w", 
m.Source, m.Destination, err)
+       }
+       return nil
+}
+
 // prepareRootfs sets up the devices, mount points, and filesystems for use
 // inside a new mount namespace. It doesn't set anything as ro. You must call
 // finalizeRootfs after this function to finish setting up the rootfs.
@@ -114,54 +168,8 @@
                cgroupns:        config.Namespaces.Contains(configs.NEWCGROUP),
        }
        for _, m := range config.Mounts {
-               entry := mountEntry{Mount: m}
-               // Figure out whether we need to request runc to give us an
-               // open_tree(2)-style mountfd. For idmapped mounts, this is 
always
-               // necessary. For bind-mounts, this is only necessary if we 
cannot
-               // resolve the parent mount (this is only hit if you are 
running in a
-               // userns -- but for rootless the host-side thread can't help).
-               wantSourceFile := m.IsIDMapped()
-               if m.IsBind() && !config.RootlessEUID {
-                       if _, err := os.Stat(m.Source); err != nil {
-                               wantSourceFile = true
-                       }
-               }
-               if wantSourceFile {
-                       // Request a source file from the host.
-                       if err := writeSyncArg(pipe, procMountPlease, m); err 
!= nil {
-                               return fmt.Errorf("failed to request mountfd 
for %q: %w", m.Source, err)
-                       }
-                       sync, err := readSyncFull(pipe, procMountFd)
-                       if err != nil {
-                               return fmt.Errorf("mountfd request for %q 
failed: %w", m.Source, err)
-                       }
-                       if sync.File == nil {
-                               return fmt.Errorf("mountfd request for %q: 
response missing attached fd", m.Source)
-                       }
-                       defer sync.File.Close()
-                       // Sanity-check to make sure we didn't get the wrong fd 
back. Note
-                       // that while m.Source might contain symlinks, the 
(*os.File).Name
-                       // is based on the path provided to os.OpenFile, not 
what it
-                       // resolves to. So this should never happen.
-                       if sync.File.Name() != m.Source {
-                               return fmt.Errorf("returned mountfd for %q 
doesn't match requested mount configuration: mountfd path is %q", m.Source, 
sync.File.Name())
-                       }
-                       // Unmarshal the procMountFd argument (the file is 
sync.File).
-                       var src *mountSource
-                       if sync.Arg == nil {
-                               return fmt.Errorf("sync %q is missing an 
argument", sync.Type)
-                       }
-                       if err := json.Unmarshal(*sync.Arg, &src); err != nil {
-                               return fmt.Errorf("invalid mount fd response 
argument %q: %w", string(*sync.Arg), err)
-                       }
-                       if src == nil {
-                               return fmt.Errorf("mountfd request for %q: no 
mount source info received", m.Source)
-                       }
-                       src.file = sync.File
-                       entry.srcFile = src
-               }
-               if err := mountToRootfs(mountConfig, entry); err != nil {
-                       return fmt.Errorf("error mounting %q to rootfs at %q: 
%w", m.Source, m.Destination, err)
+               if err := setupAndMountToRootfs(pipe, config, mountConfig, m); 
err != nil {
+                       return err
                }
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/signals.go new/runc-1.4.2/signals.go
--- old/runc-1.4.1/signals.go   2026-03-12 21:23:25.000000000 +0100
+++ new/runc-1.4.2/signals.go   2026-04-03 00:52:45.000000000 +0200
@@ -26,14 +26,17 @@
                }
        }
        handler := make(chan *signalHandler)
+
+       // Ensure that we have a large buffer size so that we do not miss any
+       // signals in case we are not processing them fast enough.
+       s := make(chan os.Signal, signalBufferSize)
+
        // signal.Notify is actually quite expensive, as it has to configure the
        // signal mask and add signal handlers for all signals (all ~65 of 
them).
        // So, defer this to a background thread while doing the rest of the 
io/tty
-       // setup.
+       // setup, except for SIGCHLD which is very important (see #5208).
+       signal.Notify(s, unix.SIGCHLD)
        go func() {
-               // ensure that we have a large buffer size so that we do not 
miss any
-               // signals in case we are not processing them fast enough.
-               s := make(chan os.Signal, signalBufferSize)
                // handle all signals for the process.
                signal.Notify(s)
                handler <- &signalHandler{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/runc-1.4.1/tests/integration/idmap.bats 
new/runc-1.4.2/tests/integration/idmap.bats
--- old/runc-1.4.1/tests/integration/idmap.bats 2026-03-12 21:23:25.000000000 
+0100
+++ new/runc-1.4.2/tests/integration/idmap.bats 2026-04-03 00:52:45.000000000 
+0200
@@ -104,7 +104,27 @@
 
 function setup_idmap_basic_mount() {
        mountname="${1:-1}"
-       setup_idmap_single_mount 0:100000:65536 0:100000:65536 "$mountname"
+       destname="${2:-}"
+       setup_idmap_single_mount 0:100000:65536 0:100000:65536 "$mountname" 
"$destname"
+}
+
+@test "Check mount source fds are cleaned up with idmapped mounts [userns]" {
+       setup_idmap_userns
+       for i in {1..10}; do
+               setup_idmap_basic_mount 1 "1$i"
+               setup_idmap_basic_mount 2 "2$i"
+       done
+
+       update_config '.process.args = ["sh", "-c", "stat -c =%u=%g= 
/tmp/mount-11/foo.txt"]'
+       update_config '.process.rlimits = [{
+               "type": "RLIMIT_NOFILE",
+               "soft": 20,
+               "hard": 20
+       }]'
+
+       runc run test_debian
+       [ "$status" -eq 0 ]
+       [[ "$output" == *"=0=0="* ]]
 }
 
 @test "simple idmap mount [userns]" {

Reply via email to