ssh kitten: avoid in-place mutation of cmd by slices.Insert

slices.Insert(cmd, 1, "-O", "check") writes into cmd's backing array
when there is spare capacity (cap(cmd) >= len(cmd)+2). check_cmd points
at the shifted array, but cmd's slice header is unchanged: reading
cmd[:insertion_point] later returns "-O", "check", ... where the
original prefix used to be. run_control_master, forward_remote_control,
and the final ssh exec all build their argvs from this corrupted prefix.

Repro: share_connections=yes, forward_remote_control=yes, and enough
ssh_args to push cmd past Go's slice-growth threshold (kitten ssh -v
host does it). With the ControlMaster already up you'll see
"Multiplexing command already specified"; otherwise it fails with
"Failed to start SSH ControlMaster" and a stray -O check left in the
cmdline.
This commit is contained in:
Connor Welsh 2026-05-18 22:34:55 -04:00
parent 656af81cfb
commit d50d1bba65
No known key found for this signature in database

View file

@ -692,7 +692,8 @@ func run_ssh(ssh_args, server_args, found_extra_args []string, ssh_config_channe
return master_is_alive
}
master_checked = true
check_cmd := slices.Insert(cmd, 1, "-O", "check")
// slices.Insert can mutate cmd's backing array in place; clone so cmd stays intact
check_cmd := slices.Insert(slices.Clone(cmd), 1, "-O", "check")
master_is_alive = exec.Command(check_cmd[0], check_cmd[1:]...).Run() == nil
return master_is_alive
}