Repository: moby/moby (language: go)

Issue:
[rootless+pasta] `docker version`: `http: panic serving @: runtime error: invalid memory address or nil pointer dereference`
### Description

`docker version` panics in rootless + pasta mode.

`docke run`, etc. continues to work.

### Reproduce

Run the daemon in rootless mode, with pasta
```console
$ DOCKERD_ROOTLESS_ROOTLESSKIT_NET=pasta \
  DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=implicit \
  dockerd-rootless.sh
```

Run `docker version` against the rootless daemon
```console
$ DOCKER_HOST=unix://${XDG_RUNTIME_DIR}/docker.sock docker version
Client:
 Version:           25.0.0-rc.2-13-ga18dad383.m
 API version:       1.44
 Go version:        go1.21.6
 Git commit:        a18dad383
 Built:             Tue Jan 16 15:31:18 2024
 OS/Arch:           linux/amd64
 Context:           default
error during connect: Get "http://%2Frun%2Fuser%2F1001%2Fdocker.sock/v1.44/version": EOF
```

The server panics (and recovers)
```
2024/01/17 00:38:04 http: panic serving @: runtime error: invalid memory address or nil pointer dereference
goroutine 297 [running]:
net/http.(*conn).serve.func1()
        /usr/local/go/src/net/http/server.go:1868 +0xb9
panic({0x481d80?, 0x3999430?})
        /usr/local/go/src/runtime/panic.go:920 +0x270
go.opentelemetry.io/otel/sdk/trace.(*recordingSpan).End.func1()
        /go/src/github.com/docker/docker/vendor/go.opentelemetry.io/otel/sdk/trace/span.go:383 +0x25
go.opentelemetry.io/otel/sdk/trace.(*recordingSpan).End(0xc000ed7500, {0x0, 0x0, 0xc0011bc050?})
        /go/src/github.com/docker/docker/vendor/go.opentelemetry.io/otel/sdk/trace/span.go:421 +0x9fb
panic({0x481d80?, 0x3999430?})
        /usr/local/go/src/runtime/panic.go:914 +0x21f
github.com/docker/docker/daemon.(*Daemon).fillRootlessVersion(0xc91840?, {0xc91840, 0xc0013ccb70}, 0xc0009b2600)
        /go/src/github.com/docker/docker/daemon/info_unix.go:249 +0x1cb
github.com/docker/docker/daemon.(*Daemon).fillPlatformVersion(0x44cb00?, {0xc91840, 0xc0013ccb70}, 0xc?, 0x1?)
        /go/src/github.com/docker/docker/daemon/info_unix.go:184 +0x225
github.com/docker/docker/daemon.(*Daemon).SystemVersion(0xc0007e0000, {0xc91840, 0xc0013ccb70})
        /go/src/github.com/docker/docker/daemon/info.go:145 +0x6bd
github.com/docker/docker/api/server/router/system.(*systemRouter).getVersion(0xc0013cc870?, {0xc91840?, 0xc0013ccb70?}, {0xc885c0, 0xc000eeacc0}, 0x8c83d4?, 0xc0013cc870?)
        /go/src/github.com/docker/docker/api/server/router/system/system_routes.go:109 +0x66
github.com/docker/docker/api/server/middleware.(*ExperimentalMiddleware).WrapHandler.ExperimentalMiddleware.WrapHandler.func1({0xc91840, 0xc0013ccb70}, {0xc885c0?, 0xc000eeacc0?}, 0x373c40?, 0xc0011bc010?)
        /go/src/github.com/docker/docker/api/server/middleware/experimental.go:26 +0xb4
github.com/docker/docker/api/server/middleware.(*VersionMiddleware).WrapHandler.VersionMiddleware.WrapHandler.func1({0xc91840, 0xc0013ccb10}, {0xc885c0, 0xc000eeacc0}, 0x40?, 0x40?)
        /go/src/github.com/docker/docker/api/server/middleware/version.go:62 +0x2ae
github.com/docker/docker/pkg/authorization.(*Middleware).WrapHandler.func1({0xc91840, 0xc0013ccb10}, {0xc885c0?, 0xc000eeacc0?}, 0xc000d6dd00, 0xc000053f90?)
        /go/src/github.com/docker/docker/pkg/authorization/middleware.go:59 +0x683
github.com/docker/docker/api/server.(*Server).makeHTTPHandler.func1({0xc885c0, 0xc000eeacc0}, 0xc000d6dc00)
        /go/src/github.com/docker/docker/api/server/server.go:55 +0x1c3
net/http.HandlerFunc.ServeHTTP(0xc91840?, {0xc885c0?, 0xc000eeacc0?}, 0xc5e6e8?)
        /usr/local/go/src/net/http/server.go:2136 +0x29
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.(*middleware).serveHTTP(0xc001405080, {0xc804d0?, 0xc000937880}, 0xc000d6da00, {0xc673e0, 0xc001432828})
        /go/src/github.com/docker/docker/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go:217 +0x1202
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.NewMiddleware.func1.1({0xc804d0?, 0xc000937880?}, 0xc58201?)
        /go/src/github.com/docker/docker/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go:81 +0x35
net/http.HandlerFunc.ServeHTTP(0xc91840?, {0xc804d0?, 0xc000937880?}, 0xc58218?)
        /usr/local/go/src/net/http/server.go:2136 +0x29
net/http.HandlerFunc.ServeHTTP(0xc000d6d900?, {0xc804d0?, 0xc000937880?}, 0x7f60b627f5a0?)
        /usr/local/go/src/net/http/server.go:2136 +0x29
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0006c3380, {0xc804d0, 0xc000937880}, 0xc000d6d800)
        /go/src/github.com/docker/docker/vendor/github.com/gorilla/mux/mux.go:212 +0x1c5
net/http.serverHandler.ServeHTTP({0xc0013cc720?}, {0xc804d0?, 0xc000937880?}, 0x6?)
        /usr/local/go/src/net/http/server.go:2938 +0x8e
net/http.(*conn).serve(0xc000d36870, {0xc91840, 0xc0008bd890})
        /usr/local/go/src/net/http/server.go:2009 +0x5f4
created by net/http.(*Server).Serve in goroutine 262
        /usr/local/go/src/net/http/server.go:3086 +0x5cb
```

### Expected behavior

Shouldn't panic

### docker version

```bash
Client:
 Version:           25.0.0-rc.2-13-ga18dad383.m
 API version:       1.44
 Go version:        go1.21.6
 Git commit:        a18dad383
 Built:             Tue Jan 16 15:31:18 2024
 OS/Arch:           linux/amd64
 Context:           default

Server:
 Engine:
  Version:          dev
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.6
  Git commit:       5c4189e6b2a7d15b62cd8b055e1473fcf0531295
  Built:            Tue Jan 16 15:27:49 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.7.12
  GitCommit:        71909c1814c544ac47ab91d2e8b84718e517bb99
 runc:
  Version:          1.1.11
  GitCommit:        v1.1.11-0-g4bccb38
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
 rootlesskit:
  Version:          2.0.0
  ApiVersion:       1.1.1
  NetworkDriver:    slirp4netns
  PortDriver:       builtin
  StateDir:         /tmp/rootlesskit3519389972
 slirp4netns:
  Version:          1.2.1
  GitCommit:        09e31e92fa3d2a1d3ca261adaeb012c8d75a8194
```


### docker info

```bash
Client:
 Version:    25.0.0-rc.2-13-ga18dad383.m
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.12.0-rc2-77-gb1fdc54f
    Path:     /home/suda/.docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.22.0
    Path:     /home/suda/.docker/cli-plugins/docker-compose

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 5
 Server Version: dev
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: false
  userxattr: true
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 71909c1814c544ac47ab91d2e8b84718e517bb99
 runc version: v1.1.11-0-g4bccb38
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
  rootless
  cgroupns
 Kernel Version: 6.5.0-14-generic
 Operating System: Ubuntu 23.10
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 15.57GiB
 Name: suda-ws01
 ID: 8ae91aea-ab11-4a5c-89da-0d4232356877
 Docker Root Dir: /home/suda/.local/share/docker
 Debug Mode: false
 Username: akihirosuda
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
```


### Additional Info

_No response_


Discussion / hints:

Fix patch:
diff --git a/daemon/info_unix.go b/daemon/info_unix.go
index b12de6f601089..c5abc39709fa4 100644
--- a/daemon/info_unix.go
+++ b/daemon/info_unix.go
@@ -239,16 +239,27 @@ func (daemon *Daemon) fillRootlessVersion(ctx context.Context, v *types.Version)
 	if err != nil {
 		return errors.Wrap(err, "failed to retrieve RootlessKit version")
 	}
-	v.Components = append(v.Components, types.ComponentVersion{
+	rlV := types.ComponentVersion{
 		Name:    "rootlesskit",
 		Version: rlInfo.Version,
 		Details: map[string]string{
-			"ApiVersion":    rlInfo.APIVersion,
-			"StateDir":      rlInfo.StateDir,
-			"NetworkDriver": rlInfo.NetworkDriver.Driver,
-			"PortDriver":    rlInfo.PortDriver.Driver,
+			"ApiVersion": rlInfo.APIVersion,
+			"StateDir":   rlInfo.StateDir,
 		},
-	})
+	}
+	if netDriver := rlInfo.NetworkDriver; netDriver != nil {
+		// netDriver is nil for the "host" network driver
+		// (not used for Rootless Docker)
+		rlV.Details["NetworkDriver"] = netDriver.Driver
+	}
+	if portDriver := rlInfo.PortDriver; portDriver != nil {
+		// portDriver is nil for the "implicit" port driver
+		// (used with "pasta" network driver)
+		//
+		// Because the ports are not managed via RootlessKit API in this case.
+		rlV.Details["PortDriver"] = portDriver.Driver
+	}
+	v.Components = append(v.Components, rlV)
 
 	switch rlInfo.NetworkDriver.Driver {
 	case "slirp4netns":


Test patch: