hashicorp / hashicorp/packer-plugin-amazon
amazon-ebs: nil pointer dereference (SIGSEGV) when capacity_reservation_id is set without capacity_reservation_preference
- Dominant language
- Go
- Stars
- 91
- Forks
- 141
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 3
Description
### Overview
Setting `capacity_reservation_id` (or `capacity_reservation_group_arn`) **without** also
setting `capacity_reservation_preference` causes the `amazon-ebs` builder to panic with a nil
pointer dereference at instance launch. Because `run_config.go` validation treats
`capacity_reservation_id` and `capacity_reservation_preference` as **mutually exclusive**, there
is no configuration in which `capacity_reservation_id` can be used at all — every valid config
that sets it crashes.
### Reproduction
Minimal template (`crash.pkr.hcl`):
```hcl
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1"
}
}
}
source "amazon-ebs" "t" {
region = "us-west-2"
instance_type = "g4dn.8xlarge"
source_ami = "ami-xxxxxxxxxxxxxxxxx" # any AMI
subnet_id = "subnet-xxxxxxxxxxxxxxxxx"
communicator = "none"
skip_create_ami = true
ami_name = "crash-placeholder"
capacity_reservation_id = "cr-xxxxxxxxxxxxxxxxx" # a real, targeted ODCR in the subnet's AZ
}
build {
sources = ["source.amazon-ebs.t"]
}
```
```
packer init crash.pkr.hcl
packer build crash.pkr.hcl
```
Result — panic at the run-source-instance step:
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=... addr=0x0 ...]
... github.com/hashicorp/packer-plugin-amazon/builder/common.(*StepRunSourceInstance).Run
.../builder/common/step_run_source_instance.go:263
```
If you instead add `capacity_reservation_preference = "open"` to try to avoid the crash, the
build fails validation before launch:
```
capacity_reservation_id, capacity_reservation_group_arn and capacity_reservation_preference
are mutually exclusive, only one should be set
```
So the two fields can never be combined, and `capacity_reservation_id` on its own always panics.
### Root cause
In `builder/common/step_run_source_instance.go`, `CapacityReservationSpecification` is only
allocated inside the `CapacityReservationPreference != ""` branch:
```go
if s.CapacityReservationPreference != "" {
runOpts.CapacityReservationSpecification = &ec2.CapacityReservationSpecification{
CapacityReservationPreference: aws.String(s.CapacityReservationPreference),
}
}
if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" {
// runOpts.CapacityReservationSpecification is still nil here when only the
// id/group_arn was provided -> nil pointer dereference on the next line.
runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2.CapacityReservationTarget{}
if s.CapacityReservationId != "" {
runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId = aws.String(s.CapacityReservationId)
}
if s.CapacityReservationGroupArn != "" {
runOpts.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn = aws.String(s.CapacityReservationGroupArn)
}
}
```
When only `capacity_reservation_id`/`capacity_reservation_group_arn` is set,
`CapacityReservationSpecification` is `nil`, and assigning `.CapacityReservationTarget` on it
dereferences the nil pointer. The one config that would allocate the spec
(`CapacityReservationPreference`) is rejected by `run_config.go` as mutually exclusive with the
target fields, so `capacity_reservation_id` is unusable in every valid configuration.
### Suggested fix
Allocate the specification if it is nil before setting the target, e.g.:
```go
if s.CapacityReservationId != "" || s.CapacityReservationGroupArn != "" {
if runOpts.CapacityReservationSpecification == nil {
runOpts.CapacityReservationSpecification = &ec2.CapacityReservationSpecification{}
}
runOpts.CapacityReservationSpecification.CapacityReservationTarget = &ec2.CapacityReservationTarget{}
...
}
```
(The same construction appears in the spot-instance run step and should be checked there too.)
### Affected versions
- Reproduced on **packer-plugin-amazon v1.3.9** (with Packer 1.13.1) and **v1.8.1** (with Packer 1.15.4).
- The same code structure is present on `main`, so it is not fixed in any released version.
### Environment
- Packer: 1.13.1 and 1.15.4
- packer-plugin-amazon: 1.3.9 and 1.8.1
- Host OS: Linux (amd64)
Contributor guide
Assessment
This issue has not been assessed yet.