Skip to content

Commit 9d214b1

Browse files
committed
updated defaulting logic, documentation, and added integration tests
1 parent 39ef522 commit 9d214b1

File tree

4 files changed

+50
-69
lines changed

4 files changed

+50
-69
lines changed

cmd/nerdctl/container/container_run_runtime_linux_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,31 @@ func TestRunSysctl(t *testing.T) {
2727
base := testutil.NewBase(t)
2828
base.Cmd("run", "--rm", "--sysctl", "net.ipv4.ip_forward=1", testutil.AlpineImage, "cat", "/proc/sys/net/ipv4/ip_forward").AssertOutExactly("1\n")
2929
}
30+
31+
func TestRunSysctl_DefaultUnprivilegedPortStart(t *testing.T) {
32+
t.Parallel()
33+
base := testutil.NewBase(t)
34+
35+
// No --sysctl flags, default network mode (non-host).
36+
// We expect net.ipv4.ip_unprivileged_port_start=0 inside the container,
37+
// because withDefaultUnprivilegedPortSysctl should apply the default.
38+
base.Cmd(
39+
"run", "--rm",
40+
testutil.AlpineImage,
41+
"cat", "/proc/sys/net/ipv4/ip_unprivileged_port_start",
42+
).AssertOutExactly("0\n")
43+
}
44+
45+
func TestRunSysctl_UnprivilegedPortStartOverride(t *testing.T) {
46+
t.Parallel()
47+
base := testutil.NewBase(t)
48+
49+
// User explicitly sets net.ipv4.ip_unprivileged_port_start=1000.
50+
// We must NOT override this; the container should see "1000".
51+
base.Cmd(
52+
"run", "--rm",
53+
"--sysctl", "net.ipv4.ip_unprivileged_port_start=1000",
54+
testutil.AlpineImage,
55+
"cat", "/proc/sys/net/ipv4/ip_unprivileged_port_start",
56+
).AssertOutExactly("1000\n")
57+
}

docs/faq.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,6 @@ Set sysctl value `net.ipv4.ip_unprivileged_port_start=0` .
322322
323323
See https://rootlesscontaine.rs/getting-started/common/sysctl/#optional-allowing-listening-on-tcp--udp-ports-below-1024
324324
325-
`nerdctl` now defaults `net.ipv4.ip_unprivileged_port_start=0` inside the container unless you override it with `--sysctl`. This does not change the host-side sysctl, which may still need to be configured for rootless port publishing.
326-
327325
### Can't ping
328326
329327
Set sysctl value `net.ipv4.ping_group_range=0 2147483647` .

pkg/cmd/container/create.go

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"runtime"
3030
"strconv"
3131
"strings"
32+
"slices"
3233

3334
dockercliopts "github.com/docker/cli/opts"
3435
"github.com/opencontainers/runtime-spec/specs-go"
@@ -331,7 +332,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa
331332
opts = append(opts, umaskOpts...)
332333

333334
if !isHostNetwork(netLabelOpts) {
334-
opts = append(opts, withDefaultUnprivilegedPortSysctl(options.Sysctl))
335+
opts = append(opts, withDefaultUnprivilegedPortSysctl())
335336
}
336337

337338
rtCOpts, err := generateRuntimeCOpts(options.GOptions.CgroupManager, options.Runtime)
@@ -568,37 +569,28 @@ func GenerateLogURI(dataStore string) (*url.URL, error) {
568569
}
569570

570571
func isHostNetwork(netOpts types.NetworkOptions) bool {
571-
for _, n := range netOpts.NetworkSlice {
572-
if n == "host" {
573-
return true
574-
}
575-
}
576-
return false
572+
return slices.Contains(netOpts.NetworkSlice, "host")
577573
}
578574

579-
func withDefaultUnprivilegedPortSysctl(sysctls []string) oci.SpecOpts {
580-
const key = "net.ipv4.ip_unprivileged_port_start"
581-
for _, kv := range sysctls {
582-
if strings.HasPrefix(kv, key) {
583-
return func(_ context.Context, _ oci.Client, _ *containers.Container, _ *oci.Spec) error {
584-
return nil
585-
}
586-
}
587-
}
588-
589-
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
590-
if s.Linux == nil {
591-
return nil
592-
}
593-
if s.Linux.Sysctl == nil {
594-
s.Linux.Sysctl = make(map[string]string)
595-
}
596-
597-
if _, exists := s.Linux.Sysctl[key]; !exists {
598-
s.Linux.Sysctl[key] = "0"
599-
}
600-
return nil
601-
}
575+
// NOTE: withDefaultUnprivilegedPortSysctl ensures that containers can bind to
576+
// privileged ports (<1024) without requiring CAP_NET_BIND_SERVICE inside
577+
// the container by defaulting net.ipv4.ip_unprivileged_port_start to 0
578+
// in the container's network namespace.
579+
func withDefaultUnprivilegedPortSysctl() oci.SpecOpts {
580+
const key = "net.ipv4.ip_unprivileged_port_start"
581+
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
582+
if s.Linux == nil {
583+
s.Linux = &specs.Linux{}
584+
}
585+
if s.Linux.Sysctl == nil {
586+
s.Linux.Sysctl = make(map[string]string)
587+
}
588+
589+
if _, exists := s.Linux.Sysctl[key]; !exists {
590+
s.Linux.Sysctl[key] = "0"
591+
}
592+
return nil
593+
}
602594
}
603595

604596
func withNerdctlOCIHook(cmd string, args []string) (oci.SpecOpts, error) {

pkg/cmd/container/create_unprivileged_sysctl_test.go

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)