Skip to content

amazon-ebs: nil pointer dereference (SIGSEGV) when capacity_reservation_id is set without capacity_reservation_preference #684

Description

@vincer

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):

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:

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.:

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions