Skip to content

cleanup: check GetParameters() for nil in CSI requests - #6463

Draft
nixpanic wants to merge 7 commits into
ceph:develfrom
nixpanic:cleanup/GetParameters-nil
Draft

cleanup: check GetParameters() for nil in CSI requests#6463
nixpanic wants to merge 7 commits into
ceph:develfrom
nixpanic:cleanup/GetParameters-nil

Conversation

@nixpanic

@nixpanic nixpanic commented Aug 6, 2026

Copy link
Copy Markdown
Member

Copilot reported a potential panic when there are no parameters passed in CSI
requests. It is unlikely that a StorageClass or other sources of requests do
not contain parameters, but technically users could do this and cause Ceph-CSI
to crash.

See-also: #6458 (comment)

Add validation to check if req.GetParameters() returns nil before
accessing the parameters map. This prevents potential nil pointer
dereferences in the following functions:
- CreateSnapshot in controllerserver.go
- validation function in groupcontrollerserver.go
- NewVolumeOptions in store/volumeoptions.go
- NewVolumeGroupOptions in store/volumegroup.go

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Add validation to check if req.GetParameters() returns nil before
accessing the parameters map. This prevents potential nil pointer
dereferences in the following functions:
- CreateSnapshot in controllerserver.go
- genVolFromVolID in rbd_util.go

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Add validation to check if req.GetParameters() returns nil before
accessing the parameters map in the network fence implementation.
This prevents potential nil pointer dereferences.

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Add validation to check if req.GetParameters() returns nil before
accessing the parameters map in the network fence implementation.
This prevents potential nil pointer dereferences.

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Add validation to check if req.GetParameters() returns nil before
accessing the parameters map in the following RBD csi-addons functions:
- network_fence.go: FenceClusterNetwork and UnfenceClusterNetwork
- replication.go: EnableVolumeReplication
- volumegroup.go: CreateVolumeGroup

This prevents potential nil pointer dereferences.

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Add validation to check if req.GetParameters() returns nil before
accessing the parameters map in the CreateSnapshot function in
controller/controllerserver.go. This prevents potential nil pointer
dereferences.

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Add validation to check if req.GetParameters() returns nil before
accessing the parameters map in the CreateVolumeGroup function in
group_controllerserver.go. This prevents potential nil pointer
dereferences.

Assisted-by: AskBob <askbob@ibm.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
Copilot AI lite review requested due to automatic review settings August 6, 2026 15:59
@mergify mergify Bot added the cleanup label Aug 6, 2026
@nixpanic
nixpanic marked this pull request as ready for review August 6, 2026 16:02
@nixpanic
nixpanic requested review from a team as code owners August 6, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to prevent potential nil-map handling issues by explicitly checking GetParameters() results across several CSI and CSI-addons request handlers in Ceph-CSI (RBD, CephFS, NVMe-oF).

Changes:

  • Added early nil checks for req.GetParameters() in multiple controller and helper paths.
  • Returned InvalidArgument/errors when parameters are nil, before continuing request validation/processing.
  • Updated various call sites to pass locally-captured parameters into downstream helpers/managers.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
internal/rbd/group_controllerserver.go Adds parameters nil-check before creating the RBD manager for volume group snapshot ops.
internal/rbd/controllerserver.go Adds parameters nil-checks in create-volume and create-snapshot request validation.
internal/nvmeof/controller/controllerserver.go Adds parameters nil-checks in NVMe-oF create-volume validation and NVMe-oF resource creation.
internal/csi-addons/rbd/volumegroup.go Adds parameters nil-checks when creating volume groups and extracting flatten mode.
internal/csi-addons/rbd/replication.go Adds parameters nil-checks across replication RPCs before using request parameters.
internal/csi-addons/rbd/network_fence.go Adds parameters nil-checks for network fencing/unfencing operations.
internal/csi-addons/networkfence/fencing.go Adds parameters nil-check in GetFenceClients before reading clusterID.
internal/csi-addons/cephfs/network_fence.go Adds parameters nil-checks for CephFS network fencing/unfencing operations.
internal/cephfs/store/volumeoptions.go Adds parameters nil-check in volume options construction.
internal/cephfs/store/volumegroup.go Adds parameters nil-check in volume group options construction.
internal/cephfs/groupcontrollerserver.go Adds parameters nil-check during volume group snapshot request validation.
internal/cephfs/controllerserver.go Adds parameters nil-check before extracting cluster information during snapshot create.
Suppressed comments (5)

internal/csi-addons/rbd/replication.go:359

  • Nil maps are a valid zero value for protobuf map fields and are safe to index/iterate in Go. Returning an error for nil here changes behavior compared to an empty map (which would just use defaults). Consider normalizing nil to an empty map instead of rejecting the request.
	parameters := req.GetParameters()
	if parameters == nil {
		return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
	}

internal/csi-addons/rbd/replication.go:522

  • Nil protobuf maps are safe for reads and equivalent to empty maps for this code path. Rejecting nil here is an unnecessary behavior change; prefer normalizing nil to an empty map and letting subsequent logic apply defaults/required-key validation.
	parameters := req.GetParameters()
	if parameters == nil {
		return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
	}

internal/csi-addons/rbd/replication.go:644

  • A nil parameters map is a valid state for omitted protobuf map fields and is safe to read from. Returning an error here is stricter than necessary and makes nil behave differently from an empty map. Prefer normalizing nil to map[string]string{} and continue.
	parameters := req.GetParameters()
	if parameters == nil {
		return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
	}

internal/csi-addons/rbd/network_fence.go:104

  • Same as FenceClusterNetwork: nil protobuf maps are safe for reads and the existing validation already returns a specific error when clusterID is missing. Rejecting nil parameters is stricter and less informative. Prefer normalizing to an empty map and reuse parameters for the NewNetworkFence call.
	parameters := req.GetParameters()
	if parameters == nil {
		return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
	}

internal/csi-addons/cephfs/network_fence.go:109

  • Same as FenceClusterNetwork: nil protobuf maps are safe for reads and the existing validation already reports missing clusterID. Rejecting nil parameters is stricter and less informative. Prefer normalizing to an empty map and reuse parameters for the NewNetworkFence call.
	parameters := req.GetParameters()
	if parameters == nil {
		return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +78 to +81
parameters := req.GetParameters()
if parameters == nil {
return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
}
Comment on lines 82 to +85
options := req.GetParameters()
if options == nil {
return status.Error(codes.InvalidArgument, "parameters cannot be nil")
}
Comment on lines 1404 to +1407
options := req.GetParameters()
if options == nil {
return status.Error(codes.InvalidArgument, "parameters cannot be nil")
}
Comment on lines 468 to +471
params := req.GetParameters()
if params == nil {
return errors.New("parameters cannot be nil")
}
Comment on lines 803 to +806
params := req.GetParameters()
if params == nil {
return nil, errors.New("parameters cannot be nil")
}
Comment on lines +73 to +76
parameters := req.GetParameters()
if parameters == nil {
return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
}
Comment on lines +776 to +779
parameters := req.GetParameters()
if parameters == nil {
return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
}
Comment on lines 279 to +282
volOptions := req.GetParameters()
if volOptions == nil {
return nil, fmt.Errorf("parameters cannot be nil")
}
Comment on lines 47 to +50
volOptions := req.GetParameters()
if volOptions == nil {
return nil, fmt.Errorf("parameters cannot be nil")
}
Comment on lines 63 to +66
param := req.GetParameters()
if param == nil {
return status.Error(codes.InvalidArgument, "parameters cannot be nil")
}

@iPraveenParihar iPraveenParihar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be copilot is overthinking 😜, nil map reads don't panic in Go, so these are for better error messages rather than crash prevention.

}
}

interval, startTime := getSchedulingDetails(req.GetParameters())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need check here too?

}

// extract the flatten mode
flattenMode, err := getFlattenMode(ctx, req.GetParameters())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other replaces where we don't have nil check.

if parameters == nil {
return nil, status.Error(codes.InvalidArgument, "parameters cannot be nil")
}
mgr := rbd.NewManager(rs.driverInstance, parameters, req.GetSecrets())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nixpanic, How about moving the check into NewManager() ?

@nixpanic

nixpanic commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

May be copilot is overthinking 😜, nil map reads don't panic in Go, so these are for better error messages rather than crash prevention.

A, interesting! I was expecting this to panic, but it does not:

package main

import (
	"fmt"
)

func getMap() map[string]any {
	return nil
}

func main() {
	m := getMap()
	v := m["panic"]

	fmt.Printf("no panic happened, value: %v\n", v)
}

Result:

$ go run nil-map.go
no panic happened, value: <nil>

It seems that adding a new key/value to the map m above does cause a panic.

I'll have a think about how to progress with this. Better error reporting is helpful, but maybe #6458 is sufficient for that already.

@nixpanic
nixpanic marked this pull request as draft August 7, 2026 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants