Skip to content

Commit 33c3e7c

Browse files
committed
Print hints if kernel.apparmor_restrict_unprivileged_userns is set
For containerd/nerdctl issue 2847, moby/moby issue 47480 Signed-off-by: Akihiro Suda <[email protected]>
1 parent efee459 commit 33c3e7c

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

pkg/parent/parent.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ func Parent(opt Opt) error {
190190
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", opt.ParentEGIDEnvKey, os.Getegid()))
191191
}
192192
if err := cmd.Start(); err != nil {
193+
warnOnChildStartFailure(err)
193194
return fmt.Errorf("failed to start the child: %w", err)
194195
}
195196

pkg/parent/warn.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package parent
22

33
import (
4+
"errors"
45
"os"
56
"strconv"
67
"strings"
78

89
"github.com/moby/sys/mountinfo"
910
"github.com/sirupsen/logrus"
11+
"golang.org/x/sys/unix"
1012
)
1113

1214
func warnPropagation(propagation string) {
@@ -57,3 +59,46 @@ func warnSysctl() {
5759
}
5860
}
5961
}
62+
63+
func warnOnChildStartFailure(childStartErr error) {
64+
if errors.Is(childStartErr, unix.EACCES) {
65+
// apparmor_restrict_unprivileged_userns is available since Ubuntu 23.10.
66+
// Enabled by default since Ubuntu 24.04.
67+
// https://github.com/containerd/nerdctl/issues/2847
68+
b, err := os.ReadFile("/proc/sys/kernel/apparmor_restrict_unprivileged_userns")
69+
if err == nil {
70+
s := strings.TrimSpace(string(b))
71+
i, err := strconv.ParseInt(s, 10, 64)
72+
if err != nil {
73+
logrus.WithError(err).Warnf("Failed to parse /proc/sys/kernel/apparmor_restrict_unprivileged_userns (%q)", s)
74+
} else if i == 1 {
75+
logrus.WithError(childStartErr).Warnf("This error might have happened because /proc/sys/kernel/apparmor_restrict_unprivileged_userns is set to 1")
76+
selfExe, err := os.Executable()
77+
if err != nil {
78+
selfExe = "/usr/local/bin/rootlesskit"
79+
logrus.WithError(err).Warnf("Failed to detect the path of the rootlesskit binary, assuming it to be %q", selfExe)
80+
}
81+
profileName := strings.ReplaceAll(strings.TrimPrefix(selfExe, "/"), "/", ".")
82+
const tmpl = `
83+
84+
########## BEGIN ##########
85+
cat <<EOT | sudo tee "/etc/apparmor.d/%s"
86+
# ref: https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces
87+
abi <abi/4.0>,
88+
include <tunables/global>
89+
90+
%s flags=(unconfined) {
91+
userns,
92+
93+
# Site-specific additions and overrides. See local/README for details.
94+
include if exists <local/%s>
95+
}
96+
EOT
97+
sudo systemctl restart apparmor.service
98+
########## END ##########
99+
`
100+
logrus.Warnf("Hint: try running the following commands:\n"+tmpl+"\n", profileName, selfExe, profileName)
101+
}
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)