Giter Site home page Giter Site logo

u-root / cpu Goto Github PK

View Code? Open in Web Editor NEW
227.0 48.0 28.0 3.59 MB

cpu command in Go, inspired by the Plan 9 cpu command

License: BSD 3-Clause "New" or "Revised" License

Shell 1.10% Go 58.86% Makefile 0.40% Rust 39.41% Dockerfile 0.22%
cpu plan9 golang

cpu's Introduction

u-root

Build Status codecov Go Report Card CodeQL GoDoc Slack License OpenSSF Best Practices

Description

u-root embodies four different projects.

  • Go versions of many standard Linux tools, such as ls, cp, or shutdown. See cmds/core for most of these.

  • A way to compile many Go programs into a single binary with busybox mode.

  • A way to create initramfs (an archive of files) to use with Linux kernels, embeddable into firmware.

  • Go bootloaders that use kexec to boot Linux or multiboot kernels such as ESXi, Xen, or tboot. They are meant to be used with LinuxBoot.

Usage

Make sure your Go version is >= 1.21.

Download and install u-root either via git:

git clone https://github.com/u-root/u-root
cd u-root
go install

Or install directly with go:

go install github.com/u-root/u-root@latest

Note

The u-root command will end up in $GOPATH/bin/u-root, so you may need to add $GOPATH/bin to your $PATH.

Examples

Here are some examples of using the u-root command to build an initramfs.

git clone https://github.com/u-root/u-root
cd u-root

# Build an initramfs of all the Go cmds in ./cmds/core/... (default)
u-root

# Generate an archive with bootloaders
#
# core and boot are templates that expand to sets of commands
u-root core boot

# Generate an archive with only these given commands
u-root ./cmds/core/{init,ls,ip,dhclient,wget,cat,gosh}

# Generate an archive with all of the core tools with some exceptions
u-root core -cmds/core/{ls,losetup}

Important

u-root works exactly when go build and go list work as well.

Note

The u-root tool is the same as the mkuimage tool with some defaults applied.

In the near future, uimage will replace u-root.

Tip

To just build Go busybox binaries, try out gobusybox's makebb tool.

Multi-module workspace builds

There are several ways to build multi-module command images using standard Go tooling.

$ mkdir workspace
$ cd workspace
$ git clone https://github.com/u-root/u-root
$ git clone https://github.com/u-root/cpu

$ go work init ./u-root
$ go work use ./cpu

$ u-root ./u-root/cmds/core/{init,gosh} ./cpu/cmds/cpud

$ cpio -ivt < /tmp/initramfs.linux_amd64.cpio
...
-rwxr-x---   0 root     root      6365184 Jan  1  1970 bbin/bb
lrwxrwxrwx   0 root     root            2 Jan  1  1970 bbin/cpud -> bb
lrwxrwxrwx   0 root     root            2 Jan  1  1970 bbin/gosh -> bb
lrwxrwxrwx   0 root     root            2 Jan  1  1970 bbin/init -> bb
...

# Works for offline vendored builds as well.
$ go work vendor # Go 1.22 feature.

$ u-root ./u-root/cmds/core/{init,gosh} ./cpu/cmds/cpud

When creating a new Go workspace is too much work, the goanywhere tool can create one on the fly. This works only with local file system paths:

$ go install github.com/u-root/gobusybox/src/cmd/goanywhere@latest

$ goanywhere ./u-root/cmds/core/{init,gosh} ./cpu/cmds/cpud -- u-root

goanywhere creates a workspace in a temporary directory with the given modules, and then execs u-root in the workspace passing along the command names.

Tip

While workspaces are good for local compilation, they are not meant to be checked in to version control systems.

For a non-workspace way of building multi-module initramfs images, read more in the mkuimage README. (The u-root tool is mkuimage with more defaults applied.)

Extra Files

You may also include additional files in the initramfs using the -files flag.

If you add binaries with -files are listed, their ldd dependencies will be included as well.

$ u-root -files /bin/bash

$ cpio -ivt < /tmp/initramfs.linux_amd64.cpio
...
-rwxr-xr-x   0 root     root      1277936 Jan  1  1970 bin/bash
...
drwxr-xr-x   0 root     root            0 Jan  1  1970 lib/x86_64-linux-gnu
-rwxr-xr-x   0 root     root       210792 Jan  1  1970 lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-rwxr-xr-x   0 root     root      1926256 Jan  1  1970 lib/x86_64-linux-gnu/libc.so.6
lrwxrwxrwx   0 root     root           15 Jan  1  1970 lib/x86_64-linux-gnu/libtinfo.so.6 -> libtinfo.so.6.4
-rw-r--r--   0 root     root       216368 Jan  1  1970 lib/x86_64-linux-gnu/libtinfo.so.6.4
drwxr-xr-x   0 root     root            0 Jan  1  1970 lib64
lrwxrwxrwx   0 root     root           42 Jan  1  1970 lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
...

You can determine placement with colons:

$ u-root -files "/bin/bash:sbin/sh"

$ cpio -ivt < /tmp/initramfs.linux_amd64.cpio
...
-rwxr-xr-x   0 root     root      1277936 Jan  1  1970 sbin/sh
...

For example on Debian, if you want to add two kernel modules for testing, executing your currently booted kernel:

$ u-root -files "$HOME/hello.ko:etc/hello.ko" -files "$HOME/hello2.ko:etc/hello2.ko"
$ qemu-system-x86_64 -kernel /boot/vmlinuz-$(uname -r) -initrd /tmp/initramfs.linux_amd64.cpio

Init and Uinit

u-root has a very simple (exchangable) init system controlled by the -initcmd and -uinitcmd command-line flags.

  • -initcmd determines what /init is symlinked to. -initcmd may be a u-root command name or a symlink target.

  • -uinitcmd is run by the default u-root init after some basic file system setup. There is no default, users should optionally supply their own. -uinitcmd may be a u-root command name with arguments or a symlink target with arguments.

  • After running a uinit (if there is one), init will start a shell determined by the -defaultsh argument.

We expect most users to keep their -initcmd as init, but to supply their own uinit for additional initialization or to immediately load another operating system.

All three command-line args accept both a u-root command name or a target symlink path. Only -uinitcmd accepts command-line arguments, however. For example,

u-root -uinitcmd="echo Go Gopher" ./cmds/core/{init,echo,gosh}

cpio -ivt < /tmp/initramfs.linux_amd64.cpio
# ...
# lrwxrwxrwx   0 root     root           12 Dec 31  1969 bin/uinit -> ../bbin/echo
# lrwxrwxrwx   0 root     root            9 Dec 31  1969 init -> bbin/init

qemu-system-x86_64 -kernel $KERNEL -initrd /tmp/initramfs.linux_amd64.cpio -nographic -append "console=ttyS0"
# ...
# [    0.848021] Freeing unused kernel memory: 896K
# 2020/05/01 04:04:39 Welcome to u-root!
#                              _
#   _   _      _ __ ___   ___ | |_
#  | | | |____| '__/ _ \ / _ \| __|
#  | |_| |____| | | (_) | (_) | |_
#   \__,_|    |_|  \___/ \___/ \__|
#
# Go Gopher
# ~/>

Passing command line arguments like above is equivalent to passing the arguments to uinit via a flags file in /etc/uinit.flags, see Extra Files.

Additionally, you can pass arguments to uinit via the uroot.uinitargs kernel parameters, for example:

u-root -uinitcmd="echo Gopher" ./cmds/core/{init,echo,gosh}

cpio -ivt < /tmp/initramfs.linux_amd64.cpio
# ...
# lrwxrwxrwx   0 root     root           12 Dec 31  1969 bin/uinit -> ../bbin/echo
# lrwxrwxrwx   0 root     root            9 Dec 31  1969 init -> bbin/init

qemu-system-x86_64 -kernel $KERNEL -initrd /tmp/initramfs.linux_amd64.cpio -nographic -append "console=ttyS0 uroot.uinitargs=Go"
# ...
# [    0.848021] Freeing unused kernel memory: 896K
# 2020/05/01 04:04:39 Welcome to u-root!
#                              _
#   _   _      _ __ ___   ___ | |_
#  | | | |____| '__/ _ \ / _ \| __|
#  | |_| |____| | | (_) | (_) | |_
#   \__,_|    |_|  \___/ \___/ \__|
#
# Go Gopher
# ~/>

Note the order of the passed arguments in the above example.

The command you name must be present in the command set. The following will not work:

u-root -uinitcmd="echo Go Gopher" ./cmds/core/{init,gosh}
# 21:05:57 could not create symlink from "bin/uinit" to "echo": command or path "echo" not included in u-root build: specify -uinitcmd="" to ignore this error and build without a uinit

You can also refer to non-u-root-commands; they will be added as symlinks. We don't presume to know whether your symlink target is correct or not.

This will build, but not work unless you add a /bin/foobar to the initramfs.

u-root -uinitcmd="/bin/foobar Go Gopher" ./cmds/core/{init,gosh}

This will boot the same as the above.

u-root -uinitcmd="/bin/foobar Go Gopher" -files /bin/echo:bin/foobar -files your-hosts-file:/etc/hosts ./cmds/core/{init,gosh}

The effect of the above command:

  • Sets up the uinit command to be /bin/foobar, with 2 arguments: Go Gopher
  • Adds /bin/echo as bin/foobar
  • Adds your-hosts-file as etc/hosts
  • builds in the cmds/core/init, and cmds/core/gosh commands.

This will bypass the regular u-root init and just launch a shell:

u-root -initcmd=gosh ./cmds/core/{gosh,ls}

cpio -ivt < /tmp/initramfs.linux_amd64.cpio
# ...
# lrwxrwxrwx   0 root     root            9 Dec 31  1969 init -> bbin/gosh

qemu-system-x86_64 -kernel $KERNEL -initrd /tmp/initramfs.linux_amd64.cpio -nographic -append "console=ttyS0"
# ...
# [    0.848021] Freeing unused kernel memory: 896K
# failed to put myself in foreground: ioctl: inappropriate ioctl for device
# ~/>

(It fails to do that because some initialization is missing when the shell is started without a proper init.)

Cross Compilation (targeting different architectures and OSes)

Cross-OS and -architecture compilation comes for free with Go. In fact, every PR to the u-root repo is built against the following architectures: amd64, x86 (i.e. 32bit), mipsle, armv7, arm64, and ppc64le.

Further, we run integration tests on linux/amd64, and linux/arm64, using several CI systems. If you need to add another CI system, processor or OS, please let us know.

To cross compile for an ARM, on Linux:

GOARCH=arm u-root

If you are on OSX, and wish to build for Linux on AMD64:

GOOS=linux GOARCH=amd64 u-root

Testing in QEMU

A good way to test the initramfs generated by u-root is with qemu:

qemu-system-x86_64 -nographic -kernel path/to/kernel -initrd /tmp/initramfs.linux_amd64.cpio

Note that you do not have to build a special kernel on your own, it is sufficient to use an existing one. Usually you can find one in /boot.

If you don't have a kernel handy, you can also get the one we use for VM testing:

go install github.com/hugelgupf/vmtest/tools/runvmtest@latest

runvmtest -- bash -c "cp \$VMTEST_KERNEL ./kernel"

It may not have all features you require, however.

Framebuffer

For framebuffer support, append a VESA mode via the vga kernel parameter:

qemu-system-x86_64 \
  -kernel path/to/kernel \
  -initrd /tmp/initramfs.linux_amd64.cpio \
  -append "vga=786"

For a list of modes, refer to the Linux kernel documentation.

Entropy / Random Number Generator

Some utilities, e.g., dhclient, require entropy to be present. For a speedy virtualized random number generator, the kernel should have the following:

CONFIG_VIRTIO_PCI=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_CRYPTO_DEV_VIRTIO=y

Then you can run your kernel in QEMU with a virtio-rng-pci device:

qemu-system-x86_64 \
    -device virtio-rng-pci \
    -kernel vmlinuz \
    -initrd /tmp/initramfs.linux_amd64.cpio

In addition, you can pass your host's RNG:

qemu-system-x86_64 \
    -object rng-random,filename=/dev/urandom,id=rng0 \
    -device virtio-rng-pci,rng=rng0 \
    -kernel vmlinuz \
    -initrd /tmp/initramfs.linux_amd64.cpio

SystemBoot

SystemBoot is a set of bootloaders written in Go. It is meant to be a distribution for LinuxBoot to create a system firmware + bootloader. All of these use kexec to boot. The commands are in cmds/boot. Parsers are available for GRUB, syslinux, and other config files to make the transition to LinuxBoot easier.

  • pxeboot: a network boot client that uses DHCP and HTTP or TFTP to get a boot configuration which can be parsed as PXELinux or iPXE configuration files to get a boot program.

  • boot: finds all bootable kernels on local disk, shows a menu, and boots them. Supports (basic) GRUB, (basic) syslinux, (non-EFI) BootLoaderSpec, and ESXi configurations.

More detailed information about the build process for a full LinuxBoot firmware image using u-root/systemboot and coreboot can be found in the LinuxBoot book chapter about LinuxBoot using coreboot, u-root and systemboot.

This project started as a loose collection of programs in u-root by various LinuxBoot contributors, as well as a personal experiment by Andrea Barberio that has since been merged in. It is now an effort of a broader community and graduated to a real project for system firmwares.

Compression

You can compress the initramfs. However, for xz compression, the kernel has some restrictions on the compression options and it is suggested to align the file to 512 byte boundaries:

xz --check=crc32 -9 --lzma2=dict=1MiB \
   --stdout /tmp/initramfs.linux_amd64.cpio \
   | dd conv=sync bs=512 \
   of=/tmp/initramfs.linux_amd64.cpio.xz

Getting Packages of TinyCore

Using the tcz command included in u-root, you can install tinycore linux packages for things you want.

You can use QEMU NAT to allow you to fetch packages. Let's suppose, for example, you want bash. Once u-root is running, you can do this:

% tcz bash

The tcz command computes and fetches all dependencies. If you can't get to tinycorelinux.net, or you want package fetching to be faster, you can run your own server for tinycore packages.

You can do this to get a local server using the u-root srvfiles command:

% srvfiles -p 80 -d path-to-local-tinycore-packages

Of course you have to fetch all those packages first somehow :-)

Build an Embeddable u-root

You can build the cpio image created by u-root into a Linux kernel via the CONFIG_INITRAMFS_SOURCE config variable or coreboot config variable, and further embed the kernel image into firmware as a coreboot payload.

In the kernel and coreboot case, you may need to configure ethernet. We have a dhclient command that works for both ipv4 and ipv6. Since v6 does not yet work that well for most people, a typical invocation looks like this:

% dhclient -ipv4 -ipv6=false

Or, on newer linux kernels (> 4.x) boot with ip=dhcp in the command line, assuming your kernel is configured to work that way.

Build Modes

u-root can create an initramfs in two different modes, specified by -build:

  • gbb mode: One busybox-like binary comprising all the Go tools you ask to include. See the gobusybox README for how it works. In this mode, u-root copies and rewrites the source of the tools you asked to include to be able to compile everything into one busybox-like binary.

  • binary mode: each specified binary is compiled separately and all binaries are added to the initramfs.

Updating Dependencies

go get -u
go mod tidy
go mod vendor

Building without network access

The u-root command supports building with workspace vendoring and module vendoring. In both of those cases, if all dependencies are found in the vendored directories, the build happens completely offline.

Read more in the mkuimage README.

u-root also still supports GO111MODULE=off builds.

Hardware

If you want to see u-root on real hardware, this board is a good start.

Contributions

For information about contributing, including how we sign off commits, please see CONTRIBUTING.md.

Improving existing commands (e.g., additional currently unsupported flags) is very welcome. In this case it is not even required to build an initramfs, just enter the cmds/ directory and start coding. A list of commands that are on the roadmap can be found here.

cpu's People

Contributors

binjip978 avatar chrimarme avatar da4089 avatar dependabot[bot] avatar ericvh avatar fhs avatar hugelgupf avatar lencerf avatar orangecms avatar rjkroege avatar rminnich avatar rminnichcodeu avatar v-thakkar avatar walterchris avatar whentze avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cpu's Issues

Add documentation?

Itโ€™s not entirely clear how to use this tool: what are the requirements in terms of permissions and environment on the local and remote machine? Could a few example invocations be described?

Thanks,

\r \n line insertions on Darwin to Linux in terminal

I have discovered something that seems odd. Maybe it's working as intended but it results in a lot of spurious diff mismatches for me.

When I run cpu without a Pty (i.e. by middle clicking in Acme / Edwood), command results do not contain \r characters. I.e.:

cpu -namespace $_h helios4 echo hello | od -c
0000000    h   e   l   l   o  \n                                        
0000006

But when I run cpu with a Pty (i.e. by typing in a conventional terminal, it does contain \r as part of the line endings. I.e.:

; cpu -namespace $_h helios4 echo hello | od -c
0000000    h   e   l   l   o  \r  \n
0000007

cpud did not connect for more than 100ms

if you set cpu -namespace "" (empty string), instead of none or ":", cpu will complain.

notably debug lines (target machine is 7 hours ahead, which helps with debugging!):

2022/04/11 16:42:32 CPUD:namespace is ""
2022/04/11 09:42:32 cpud did not connect for more than 100ms

looks like cpu started the 9p server, but cpud never dialed back. there's a mismatch in what it means to have no CPU_NAMESPACE (empty vs non-existent). cpu will start the 9p server since namespace is not "none". cpud won't dial back since len(bindover) == 0.

possibly related: should CPU_NAMESPACE work for cpu?

if i try this:

CPU_NAMESPACE="" ./cpu

i get:

2022/04/11 16:53:48 CPUD:namespace is "/lib:/lib64:/usr:/bin:/etc:/home"

not sure if CPU_NAMESPACE is used in cpu anymore. its value gets discarded in one of the spots i see in cmds/cpu/cpu.go:

_, wantNameSpace := os.LookupEnv("CPU_NAMESPACE")

Netconfig: Check netconfig before running dhcp

At the moment dhcp runs no matter what.

I'm for "seperation of concern" here.
Netconfig should have happend before cpu is started, otherwise error out with "no net config found"

Edit1: Or at least check for a netconfig before running dhcp.

RFE: doc is cpu able to use password protected keys ?

Hi,

I am trying to use cpu with an ssh host with a password protected key and fails... (here is just an alias for localhost)

[tru@elitebook840g3 cpu]$ ./cpu_linux_amd64 -d -bin `pwd`/cpud_linux_amd64 here  cat -r /tmp/toto
2022/02/15 17:15:40 
Running as client, to host "here", args "cat -r /tmp/toto"
2022/02/15 17:15:40 getKeyFile for ""
2022/02/15 17:15:40 key file from config is "~/.ssh/keys/5CG6481CF1/id_ed25519"
2022/02/15 17:15:40 getKeyFile returns "/home/tru/.ssh/keys/5CG6481CF1/id_ed25519"
2022/02/15 17:15:40 getPort("here", "")
2022/02/15 17:15:40 config.Get("here",""): "22"
2022/02/15 17:15:40 getPort: return default "23"
2022/02/15 17:15:40 returns "23"
2022/02/15 17:15:40 SSH error ParsePrivateKey /home/tru/.ssh/keys/5CG6481CF1/id_ed25519: ssh: this private key is passphrase protected

ssh-agent is running and the key is added:

[tru@elitebook840g3 cpu]$ ssh-add -l
...
256 SHA256:VIYMqpyDakJNiscj3srwC4VivwK1HYPIr9xh2UF/Occ 5CG6481CF1 (ED25519)
...
[tru@elitebook840g3 cpu]$ ssh here cat /tmp/toto
X11 forwarding request failed on channel 1
toto

running dbench fails on cpu due to unimplemented functions

root@(none):~/src/v9fs/notebook/dbench# !dbench
dbench -c /usr/share/dbench/client.txt -t 30 8
dbench version 4.00 - Copyright Andrew Tridgell 1999-2004

Running for 30 seconds with load '/usr/share/dbench/client.txt' and minimum warmup 6 secs
0 of 8 processes prepared for launch 0 sec
8 of 8 processes prepared for launch 0 sec
releasing clients
8 67 23.59 MB/sec warmup 1 sec latency 20.699 ms
8 134 23.77 MB/sec warmup 2 sec latency 29.527 ms
8 213 22.11 MB/sec warmup 3 sec latency 33.198 ms
8 286 21.39 MB/sec warmup 4 sec latency 35.614 ms
8 360 20.44 MB/sec warmup 5 sec latency 32.911 ms
8 512 18.98 MB/sec execute 1 sec latency 32.316 ms
8 597 21.84 MB/sec execute 2 sec latency 46.772 ms
[652] unlink ./clients/client7/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 7 failed at line 652
[652] unlink ./clients/client6/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 6 failed at line 652
[652] unlink ./clients/client3/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 3 failed at line 652
[652] unlink ./clients/client0/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 0 failed at line 652
[652] unlink ./clients/client5/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 5 failed at line 652
[652] unlink ./clients/client4/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 4 failed at line 652
[652] unlink ./clients/client2/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 2 failed at line 652
[652] unlink ./clients/client1/~dmtmp/PWRPNT/NEWPCB.PPT failed (Function not implemented) - expected NT_STATUS_OK
ERROR: child 1 failed at line 652
Child failed with status 1

`cpud` command hang when `dsEnabled` is false

In ae73b13,
If dsEnabled is false, function DsRegister will never be called, thus no thread will receive from tenChan. On the other hand, in handler(), there is tenChan <- 1 at the beginning and end of the function. Since tenChan has capacity 1, the second tenChan <- 1 will block the function forever.

forward p9p services into remote

I noted that my Darwin client's entire disk was available on the Linux remote in /tmp/cpu.

So I (naรฏve maybe) tried:

# ...cpu to remote...
; NAMESPACE=/tmp/cpu/tmp/ns.rjkroege.:0
; ls $NAMESPACE
acme  acme.log  plumb
; 9p ls acme
9p: mount: dial unix!/tmp/cpu/tmp/ns.rjkroege.:0/acme: connect /tmp/cpu/tmp/ns.rjkroege.:0/acme: Connection refused

So: it would be nice to have the client's P9P namespace brought into the remote (semi)automatically. Or maybe I'm just doing it wrong?

Update README

CPU_NAMESPACE no longer works, convert to -namespace in the readme

Created an Arch Linux PKGBUILD

Hi, I uploaded a PKGBUILD for cpu-git on the Arch User Repository, you can find it here. When you'll release tagged version, I'll upload a versioned cpu PKGBUILD.

crash on IO copy

What?

In a QEMU RISC-V, cpud may get a runtime error when processing commands:

runtime: lfstack.push invalid packing: node=0xffffff92442960 cnt=0x1 packed=0xffff9244296000
fatal error: lfstack.push

which is defined in https://go.dev/src/runtime/lfstack.go

The part in the cpu server triggering it appears to be the go func doing io.Copy(f, s).

How?

I cannot exactly tell. This appears to happen on file transfer. However, it is okay with small files (say some lines of a shell script).
When I attempt a kexec, or even just copy over a file cpu qemu /bbin/cp ./10-meg-file /tmp/, the crash occurs.

see also https://go-review.googlesource.com/c/go/+/409055
(thanks @dramforever for finding this)

Stacktrace

runtime: lfstack.push invalid packing: node=0xffffff92442960 cnt=0x1 packed=0xffff9244296000
fatal error: lfstack.push

runtime stack:
runtime.throw({0x6f1d79?, 0x683b0?})
        runtime/panic.go:1047 +0x44 fp=0xffffffcecf1cf0 sp=0xffffffcecf1cc8 pc=0x46f6c
runtime.(*lfstack).push(0xcf3e60, 0xffffff92442960)
        runtime/lfstack.go:30 +0x120 fp=0xffffffcecf1d20 sp=0xffffffcecf1cf0 pc=0x19dd8
runtime.(*spanSetBlockAlloc).free(0x746bc?, 0x5c99d2c58?)
        runtime/mspanset.go:292 +0x44 fp=0xffffffcecf1d38 sp=0xffffffcecf1d20 pc=0x41604
runtime.(*spanSet).reset(0xced438)
        runtime/mspanset.go:265 +0xa4 fp=0xffffffcecf1d68 sp=0xffffffcecf1d38 pc=0x414ac
runtime.finishsweep_m()
        runtime/mgcsweep.go:260 +0xa4 fp=0xffffffcecf1d98 sp=0xffffffcecf1d68 pc=0x34924
runtime.gcStart.func1()
        runtime/mgc.go:668 +0x20 fp=0xffffffcecf1da0 sp=0xffffffcecf1d98 pc=0x29960
runtime.systemstack()
        runtime/asm_riscv64.s:133 +0x54 fp=0xffffffcecf1da8 sp=0xffffffcecf1da0 pc=0x746bc

goroutine 26 [running]:
runtime.systemstack_switch()
        runtime/asm_riscv64.s:96 +0x8 fp=0xc00007bd90 sp=0xc00007bd88 pc=0x74650
runtime.gcStart({0xffffffb98b3108?, 0x105b?, 0x1020?})
        runtime/mgc.go:667 +0x250 fp=0xc00007be18 sp=0xc00007bd90 pc=0x29bd0
runtime.mallocgc(0x1009, 0x0, 0x0)
        runtime/malloc.go:1138 +0x680 fp=0xc00007be90 sp=0xc00007be18 pc=0x1bdb0
golang.org/x/crypto/ssh.(*connectionState).readPacket(0xc000120a20, 0x0?)
        golang.org/x/[email protected]/ssh/transport.go:162 +0x1d4 fp=4
golang.org/x/crypto/ssh.(*transport).readPacket(0xc000120a20)
        golang.org/x/[email protected]/ssh/transport.go:114 +0x38 fp=08
golang.org/x/crypto/ssh.(*handshakeTransport).readOnePacket(0xc0000f82c0, 0x0)
        golang.org/x/[email protected]/ssh/handshake.go:374 +0x50 fp=08
golang.org/x/crypto/ssh.(*handshakeTransport).readLoop(0xc0000f82c0)
        golang.org/x/[email protected]/ssh/handshake.go:197 +0x4c fp=0c
golang.org/x/crypto/ssh.newServerTransport.func1()
        golang.org/x/[email protected]/ssh/handshake.go:142 +0x2c fp=0c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00007bfd8 sp=0xc00007bfd8 pc=0x7688c
created by golang.org/x/crypto/ssh.newServerTransport
        golang.org/x/[email protected]/ssh/handshake.go:142 +0x12c

goroutine 1 [IO wait]:
runtime.gopark(0x7e4148, 0xffffff92432700, 0x2, 0x1b, 0x5)
        runtime/proc.go:363 +0x108 fp=0xc00044fa18 sp=0xc00044f9f0 pc=0x49878
runtime.netpollblock(0xffffff924326e8, 0x72, 0x0)
        runtime/netpoll.go:526 +0xe4 fp=0xc00044fa48 sp=0xc00044fa18 pc=0x425ac
internal/poll.runtime_pollWait(0x0?, 0x72)
        runtime/netpoll.go:305 +0x58 fp=0xc00044fa68 sp=0xc00044fa48 pc=0x71c98
internal/poll.(*pollDesc).wait(0xd6b94?, 0xc00008e880?, 0xe0?)
        internal/poll/fd_poll_runtime.go:84 +0x60 fp=0xc00044fa88 sp=0xc00044fa68 pc=0xd2c30
internal/poll.(*pollDesc).waitRead(0xc00008e880?, 0xa?)
        internal/poll/fd_poll_runtime.go:89 +0x38 fp=0xc00044faa8 sp=0xc00044fa88 pc=0xd2c80
internal/poll.(*FD).Accept(0xc00008e880)
        internal/poll/fd_unix.go:614 +0x1b8 fp=0xc00044fb40 sp=0xc00044faa8 pc=0xd6cf8
net.(*netFD).accept(0xc00008e880)
        net/fd_unix.go:172 +0x30 fp=0xc00044fbb0 sp=0xc00044fb40 pc=0x12b068
net.(*TCPListener).accept(0xc00000a7e0)
        net/tcpsock_posix.go:142 +0x34 fp=0xc00044fbd8 sp=0xc00044fbb0 pc=0x13fa84
net.(*TCPListener).Accept(0xc00000a7e0)
        net/tcpsock.go:288 +0x3c fp=0xc00044fc08 sp=0xc00044fbd8 pc=0x13ecac
github.com/gliderlabs/ssh.(*Server).Serve(0xc000121320, {0x81f898?, 0xc00000a7e0})
        github.com/gliderlabs/[email protected]/server.go:237 +0x178 fp=0xc00044fcd0 sp=0xc00044fc08 8
github.com/u-root/cpu/cmds/cpud.serve()
        github.com/u-root/[email protected]/cmds/cpud/serve.go:80 +0x8ac fp=0xc00044fe28 sp=0xc00044fc
github.com/u-root/cpu/cmds/cpud.registeredMain()
        github.com/u-root/[email protected]/cmds/cpud/main.go:48 +0x38c fp=0xc00044feb8 sp=0xc00044fe4
bb.u-root.com/bb/pkg/bbmain.Run({0xc0000336b6?, 0x8?})
        bb.u-root.com/bb/pkg/bbmain/register.go:134 +0x9c fp=0xc00044fef8 sp=0xc00044feb8 pc=04
main.run()
        bb.u-root.com/bb/main.go:177 +0x4c fp=0xc00044ff68 sp=0xc00044fef8 pc=0x56d394
main.main()
        bb.u-root.com/bb/main.go:185 +0x7c fp=0xc00044ff80 sp=0xc00044ff68 pc=0x56d4ac
runtime.main()
        runtime/proc.go:250 +0x1e4 fp=0xc00044ffd8 sp=0xc00044ff80 pc=0x49454
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00044ffd8 sp=0xc00044ffd8 pc=0x7688c

goroutine 2 [force gc (idle)]:
runtime.gopark(0x7e4170, 0xcc44a0, 0x11, 0x14, 0x1)
        runtime/proc.go:363 +0x108 fp=0xc000048f90 sp=0xc000048f68 pc=0x49878
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
        runtime/proc.go:369 +0x58 fp=0xc000048fb8 sp=0xc000048f90 pc=0x498f0
runtime.forcegchelper()
        runtime/proc.go:302 +0xb0 fp=0xc000048fd8 sp=0xc000048fb8 pc=0x496e0
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000048fd8 sp=0xc000048fd8 pc=0x7688c
created by runtime.init.5
        runtime/proc.go:290 +0x28

goroutine 3 [GC sweep wait]:
runtime.gopark(0x7e4170, 0xcc4c40, 0xc, 0x14, 0x1)
        runtime/proc.go:363 +0x108 fp=0xc000049778 sp=0xc000049750 pc=0x49878
runtime.goparkunlock(0x1?, 0x0?, 0x0?, 0x0?)
        runtime/proc.go:369 +0x58 fp=0xc0000497a0 sp=0xc000049778 pc=0x498f0
runtime.bgsweep(0x0?)
        runtime/mgcsweep.go:297 +0xe4 fp=0xc0000497c8 sp=0xc0000497a0 pc=0x34a6c
runtime.gcenable.func1()
        runtime/mgc.go:178 +0x2c fp=0xc0000497d8 sp=0xc0000497c8 pc=0x2942c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc0000497d8 sp=0xc0000497d8 pc=0x7688c
created by runtime.gcenable
        runtime/mgc.go:178 +0x70

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x7e4170, 0xcc5900, 0xd, 0x14, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc000049f60 sp=0xc000049f38 pc=0x49878
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x412e848000000000?)
        runtime/proc.go:369 +0x58 fp=0xc000049f88 sp=0xc000049f60 pc=0x498f0
runtime.(*scavengerState).park(0xcc5900)
        runtime/mgcscavenge.go:389 +0x58 fp=0xc000049fa8 sp=0xc000049f88 pc=0x32848
runtime.bgscavenge(0x0?)
        runtime/mgcscavenge.go:622 +0x6c fp=0xc000049fc8 sp=0xc000049fa8 pc=0x32d8c
runtime.gcenable.func2()
        runtime/mgc.go:179 +0x2c fp=0xc000049fd8 sp=0xc000049fc8 pc=0x293cc
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000049fd8 sp=0xc000049fd8 pc=0x7688c
created by runtime.gcenable
        runtime/mgc.go:179 +0xb0

goroutine 5 [finalizer wait]:
runtime.gopark(0x7e4170, 0xcf3d98, 0x10, 0x14, 0x1)
        runtime/proc.go:363 +0x108 fp=0xc000048580 sp=0xc000048558 pc=0x49878
runtime.goparkunlock(0x0?, 0x48?, 0x3d?, 0xc0000ae120?)
        runtime/proc.go:369 +0x58 fp=0xc0000485a8 sp=0xc000048580 pc=0x498f0
runtime.runfinq()
        runtime/mfinal.go:180 +0xec fp=0xc0000487d8 sp=0xc0000485a8 pc=0x285e4
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc0000487d8 sp=0xc0000487d8 pc=0x7688c
created by runtime.createfing
        runtime/mfinal.go:157 +0x64

goroutine 6 [chan receive]:
runtime.gopark(0x7e3f98, 0xc0000766b8, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc00004a6f8 sp=0xc00004a6d0 pc=0x49878
runtime.chanrecv(0xc000076660, 0xc00004a7c8, 0x0?)
        runtime/chan.go:583 +0x2e8 fp=0xc00004a788 sp=0xc00004a6f8 pc=0x159c8
runtime.chanrecv2(0x0?, 0x0?)
        runtime/chan.go:447 +0x14 fp=0xc00004a7a8 sp=0xc00004a788 pc=0x156cc
src.elv.sh/pkg/eval.getBlackholeChan.func1()
        [email protected]/pkg/eval/port.go:96 +0x44 fp=0xc04
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00004a7d8 sp=0xc00004a7d8 pc=0x7688c
created by src.elv.sh/pkg/eval.getBlackholeChan
        [email protected]/pkg/eval/port.go:95 +0x70

goroutine 7 [syscall]:
syscall.Syscall6(0xc00006c050?, 0xc00007cd88?, 0x25c018?, 0xc00006c050?, 0x27?, 0xc0000b0e10?,)
        syscall/syscall_linux.go:90 +0x2c fp=0xc00007cd88 sp=0xc00007cd08 pc=0xbd79c
syscall.wait4(0xc00015a150?, 0x7076ba?, 0x10?, 0x6e8cd4?)
        syscall/zsyscall_linux_riscv64.go:178 +0x6c fp=0xc00007cde0 sp=0xc00007cd88 pc=0xbb84c
syscall.Wait4(0x7076ba?, 0xc00007ce44, 0xc00015a150?, 0x1?)
        syscall/syscall_linux.go:463 +0x4c fp=0xc00007ce10 sp=0xc00007cde0 pc=0xb8744
github.com/u-root/cpu/cmds/cpud.cpuSetup.func1()
        github.com/u-root/[email protected]/cmds/cpud/init.go:61 +0x50 fp=0xc00007cfd8 sp=0xc00007ce18
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00007cfd8 sp=0xc00007cfd8 pc=0x7688c
created by github.com/u-root/cpu/cmds/cpud.cpuSetup
        github.com/u-root/[email protected]/cmds/cpud/init.go:54 +0x54

goroutine 8 [GC worker (idle)]:
runtime.gopark(0x7e4000, 0xc0000aea80, 0x18, 0x14, 0x0)
        runtime/proc.go:363 +0x108 fp=0xc00004af40 sp=0xc00004af18 pc=0x49878
runtime.gcBgMarkWorker()
        runtime/mgc.go:1235 +0xec fp=0xc00004afd8 sp=0xc00004af40 pc=0x2b10c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00004afd8 sp=0xc00004afd8 pc=0x7688c
created by runtime.gcBgMarkStartWorkers
        runtime/mgc.go:1159 +0x2c

goroutine 25 [chan receive]:
runtime.gopark(0x7e3f98, 0xc000063498, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc00045de30 sp=0xc00045de08 pc=0x49878
runtime.chanrecv(0xc000063440, 0xc00045df70, 0xf8?)
        runtime/chan.go:583 +0x2e8 fp=0xc00045dec0 sp=0xc00045de30 pc=0x159c8
runtime.chanrecv2(0x6078a0?, 0xc000109b60?)
        runtime/chan.go:447 +0x14 fp=0xc00045dee0 sp=0xc00045dec0 pc=0x156cc
github.com/gliderlabs/ssh.(*Server).HandleConn(0xc000121320, {0x8230b8, 0xc00000c170})
        github.com/gliderlabs/[email protected]/server.go:296 +0x34c fp=0xc00045dfb8 sp=0xc00045dee0 4
github.com/gliderlabs/ssh.(*Server).Serve.func3()
        github.com/gliderlabs/[email protected]/server.go:258 +0x34 fp=0xc00045dfd8 sp=0xc00045dfb8 pc
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00045dfd8 sp=0xc00045dfd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*Server).Serve
        github.com/gliderlabs/[email protected]/server.go:258 +0x204

goroutine 28 [runnable]:
runtime.gopark(0x7e3f98, 0xc0000631f8, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc00007ae60 sp=0xc00007ae38 pc=0x49878
runtime.chanrecv(0xc0000631a0, 0xc00007af28, 0x4?)
        runtime/chan.go:583 +0x2e8 fp=0xc00007aef0 sp=0xc00007ae60 pc=0x159c8
runtime.chanrecv2(0x97c0e?, 0xc000133800?)
        runtime/chan.go:447 +0x14 fp=0xc00007af10 sp=0xc00007aef0 pc=0x156cc
golang.org/x/crypto/ssh.(*handshakeTransport).readPacket(0xc0000f82c0)
        golang.org/x/[email protected]/ssh/handshake.go:187 +0x44 fp=0c
golang.org/x/crypto/ssh.(*mux).onePacket(0xc000124930)
        golang.org/x/[email protected]/ssh/mux.go:215 +0x3c fp=0xc00004
golang.org/x/crypto/ssh.(*mux).loop(0xc000124930)
        golang.org/x/[email protected]/ssh/mux.go:190 +0x38 fp=0xc00008
golang.org/x/crypto/ssh.newMux.func1()
        golang.org/x/[email protected]/ssh/mux.go:128 +0x2c fp=0xc0000c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00007afd8 sp=0xc00007afd8 pc=0x7688c
created by golang.org/x/crypto/ssh.newMux
        golang.org/x/[email protected]/ssh/mux.go:128 +0x148

goroutine 33 [syscall]:
syscall.Syscall(0x42334?, 0x26708?, 0x71be0?, 0x0?)
        syscall/syscall_linux.go:68 +0x20 fp=0xc000015c88 sp=0xc000015c20 pc=0xbd728
syscall.read(0xd285c?, {0xc000180000?, 0xd2b78?, 0x0?})
        syscall/zsyscall_linux_riscv64.go:696 +0x68 fp=0xc000015cc0 sp=0xc000015c88 pc=0xbc0f0
syscall.Read(0x100000000000002?, {0xc000180000?, 0xd3aa0?, 0xc000063740?})
        syscall/syscall_unix.go:183 +0x44 fp=0xc000015ce8 sp=0xc000015cc0 pc=0xb9ffc
internal/poll.ignoringEINTRIO(0x7e4c70, 0xcf4a20?, {0xc000180000, 0x8000, 0x8000})
        internal/poll/fd_unix.go:794 +0x8c fp=0xc000015d18 sp=0xc000015ce8 pc=0xd8014
internal/poll.(*FD).Read(0xc000063740, {0xc000180000, 0x8000, 0x8000})
        internal/poll/fd_unix.go:163 +0x194 fp=0xc000015da8 sp=0xc000015d18 pc=0xd3bcc
os.(*File).read(0xc00000c1e8, {0xc000180000?, 0xb19d0?, 0x8000?})
        os/file_posix.go:31 +0x58 fp=0xc000015dd0 sp=0xc000015da8 pc=0xdef00
os.(*File).Read(0x0?, {0xc000180000, 0x8000, 0x8000})
        os/file.go:118 +0x8c fp=0xc000015e10 sp=0xc000015dd0 pc=0xdd7ac
io.copyBuffer({0xffffff923c5658, 0xc0000fd2b0}, {0x818d20, 0xc00000c1e8}, {0x0, 0x0, 0x0})
        io/io.go:427 +0x19c fp=0xc000015e90 sp=0xc000015e10 pc=0xb1a5c
io.Copy({0xffffff923c5658?, 0xc0000fd2b0?}, {0x818d20?, 0xc00000c1e8?})
        io/io.go:386 +0x5c fp=0xc000015ed0 sp=0xc000015e90 pc=0xb18a4
github.com/u-root/cpu/server.handler({0x824040, 0xc0000fd2b0})
        github.com/u-root/[email protected]/server/server.go:75 +0x498 fp=0xc000015fb8 sp=0xc000015ed0
github.com/gliderlabs/ssh.(*session).handleRequests.func1()
        github.com/gliderlabs/[email protected]/session.go:262 +0x38 fp=0xc000015fd8 sp=0xc000015fb8 0
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000015fd8 sp=0xc000015fd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*session).handleRequests
        github.com/gliderlabs/[email protected]/session.go:261 +0x4b8

goroutine 30 [chan receive]:
runtime.gopark(0x7e3f98, 0xc000076b38, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc0000456c8 sp=0xc0000456a0 pc=0x49878
runtime.chanrecv(0xc000076ae0, 0x0, 0x48?)
        runtime/chan.go:583 +0x2e8 fp=0xc000045758 sp=0xc0000456c8 pc=0x159c8
runtime.chanrecv1(0xc00013c470?, 0xd?)
        runtime/chan.go:442 +0x14 fp=0xc000045778 sp=0xc000045758 pc=0x1569c
github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func1()
        github.com/gliderlabs/[email protected]/tcpip.go:126 +0x4c fp=0xc0000457d8 sp=0xc000045778 pc4
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc0000457d8 sp=0xc0000457d8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest
        github.com/gliderlabs/[email protected]/tcpip.go:125 +0x434

goroutine 29 [chan receive]:
runtime.gopark(0x7e3f98, 0xc000063558, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc00007deb8 sp=0xc00007de90 pc=0x49878
runtime.chanrecv(0xc000063500, 0xc00007dfa8, 0xc0?)
        runtime/chan.go:583 +0x2e8 fp=0xc00007df48 sp=0xc00007deb8 pc=0x159c8
runtime.chanrecv2(0x823d48?, 0xc00000ae28?)
        runtime/chan.go:447 +0x14 fp=0xc00007df68 sp=0xc00007df48 pc=0x156cc
github.com/gliderlabs/ssh.(*Server).handleRequests(0xc000121320, {0x823d48, 0xc00000ae28}, 0xc)
        github.com/gliderlabs/[email protected]/server.go:310 +0x64 fp=0xc00007dfb0 sp=0xc00007df68 pc
github.com/gliderlabs/ssh.(*Server).HandleConn.func3()
        github.com/gliderlabs/[email protected]/server.go:295 +0x38 fp=0xc00007dfd8 sp=0xc00007dfb0 p8
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00007dfd8 sp=0xc00007dfd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*Server).HandleConn
        github.com/gliderlabs/[email protected]/server.go:295 +0x2d4

goroutine 31 [IO wait]:
runtime.gopark(0x7e4148, 0xffffff92432610, 0x2, 0x1b, 0x5)
        runtime/proc.go:363 +0x108 fp=0xc000013d38 sp=0xc000013d10 pc=0x49878
runtime.netpollblock(0xffffff924325f8, 0x72, 0x0)
        runtime/netpoll.go:526 +0xe4 fp=0xc000013d68 sp=0xc000013d38 pc=0x425ac
internal/poll.runtime_pollWait(0x0?, 0x72)
        runtime/netpoll.go:305 +0x58 fp=0xc000013d88 sp=0xc000013d68 pc=0x71c98
internal/poll.(*pollDesc).wait(0xd6b94?, 0xc00008f580?, 0x9?)
        internal/poll/fd_poll_runtime.go:84 +0x60 fp=0xc000013da8 sp=0xc000013d88 pc=0xd2c30
internal/poll.(*pollDesc).waitRead(0xc00008f580?, 0x46?)
        internal/poll/fd_poll_runtime.go:89 +0x38 fp=0xc000013dc8 sp=0xc000013da8 pc=0xd2c80
internal/poll.(*FD).Accept(0xc00008f580)
        internal/poll/fd_unix.go:614 +0x1b8 fp=0xc000013e60 sp=0xc000013dc8 pc=0xd6cf8
net.(*netFD).accept(0xc00008f580)
        net/fd_unix.go:172 +0x30 fp=0xc000013ed0 sp=0xc000013e60 pc=0x12b068
net.(*TCPListener).accept(0xc00000b068)
        net/tcpsock_posix.go:142 +0x34 fp=0xc000013ef8 sp=0xc000013ed0 pc=0x13fa84
net.(*TCPListener).Accept(0xc00000b068)
        net/tcpsock.go:288 +0x3c fp=0xc000013f28 sp=0xc000013ef8 pc=0x13ecac
github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2()
        github.com/gliderlabs/[email protected]/tcpip.go:136 +0x78 fp=0xc000013fd8 sp=0xc000013f28 pc0
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000013fd8 sp=0xc000013fd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest
        github.com/gliderlabs/[email protected]/tcpip.go:134 +0x4fc

goroutine 32 [chan receive]:
runtime.gopark(0x7e3f98, 0xc0000635b8, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc000079db0 sp=0xc000079d88 pc=0x49878
runtime.chanrecv(0xc000063560, 0xc000079f00, 0x50?)
        runtime/chan.go:583 +0x2e8 fp=0xc000079e40 sp=0xc000079db0 pc=0x159c8
runtime.chanrecv2(0xc000097c0e?, 0x32?)
        runtime/chan.go:447 +0x14 fp=0xc000079e60 sp=0xc000079e40 pc=0x156cc
github.com/gliderlabs/ssh.(*session).handleRequests(0xc0000fd2b0, 0xc000062598?)
        github.com/gliderlabs/[email protected]/session.go:238 +0x50 fp=0xc000079f60 sp=0xc000079e60 8
github.com/gliderlabs/ssh.DefaultSessionHandler(0xc000121320, 0xc00000b020, {0x820d90?, 0xc000)
        github.com/gliderlabs/[email protected]/session.go:107 +0x188 fp=0xc000079fa0 sp=0xc000079f608
github.com/gliderlabs/ssh.(*Server).HandleConn.func4()
        github.com/gliderlabs/[email protected]/server.go:305 +0x48 fp=0xc000079fd8 sp=0xc000079fa0 p8
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000079fd8 sp=0xc000079fd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*Server).HandleConn
        github.com/gliderlabs/[email protected]/server.go:305 +0x4b0

goroutine 37 [chan receive]:
runtime.gopark(0x7e3f98, 0xc000063858, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc0000466d8 sp=0xc0000466b0 pc=0x49878
runtime.chanrecv(0xc000063800, 0xc0000467c0, 0x70?)
        runtime/chan.go:583 +0x2e8 fp=0xc000046768 sp=0xc0000466d8 pc=0x159c8
runtime.chanrecv2(0xc000046788?, 0x7688c?)
        runtime/chan.go:447 +0x14 fp=0xc000046788 sp=0xc000046768 pc=0x156cc
golang.org/x/crypto/ssh.DiscardRequests(0xc00000c138?)
        golang.org/x/[email protected]/ssh/connection.go:80 +0x3c fp=0c
github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2.1.3()
        github.com/gliderlabs/[email protected]/tcpip.go:157 +0x2c fp=0xc0000467d8 sp=0xc0000467c8 pc4
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc0000467d8 sp=0xc0000467d8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2.1
        github.com/gliderlabs/[email protected]/tcpip.go:157 +0xec

goroutine 38 [IO wait]:
runtime.gopark(0x7e4148, 0xffffff92432250, 0x2, 0x1b, 0x5)
        runtime/proc.go:363 +0x108 fp=0xc000011cf8 sp=0xc000011cd0 pc=0x49878
runtime.netpollblock(0xffffff92432238, 0x72, 0x0)
        runtime/netpoll.go:526 +0xe4 fp=0xc000011d28 sp=0xc000011cf8 pc=0x425ac
internal/poll.runtime_pollWait(0x0?, 0x72)
        runtime/netpoll.go:305 +0x58 fp=0xc000011d48 sp=0xc000011d28 pc=0x71c98
internal/poll.(*pollDesc).wait(0xd3aa0?, 0xc00008f780?, 0xd?)
        internal/poll/fd_poll_runtime.go:84 +0x60 fp=0xc000011d68 sp=0xc000011d48 pc=0xd2c30
internal/poll.(*pollDesc).waitRead(0x7e4c70?, 0x0?)
        internal/poll/fd_poll_runtime.go:89 +0x38 fp=0xc000011d88 sp=0xc000011d68 pc=0xd2c80
internal/poll.(*FD).Read(0xc00008f780, {0xc000198000, 0x8000, 0x8000})
        internal/poll/fd_unix.go:167 +0x21c fp=0xc000011e18 sp=0xc000011d88 pc=0xd3c54
net.(*netFD).Read(0xc00008f780, {0xc000198000?, 0xc000133800?, 0xc000198000?})
        net/fd_posix.go:55 +0x4c fp=0xc000011e48 sp=0xc000011e18 pc=0x129c4c
net.(*conn).Read(0xc00000c1f8, {0xc000198000, 0x8000, 0x8000})
        net/net.go:183 +0x70 fp=0xc000011e88 sp=0xc000011e48 pc=0x1375a8
io.copyBuffer({0xffffff923c6f78, 0xc000133800}, {0x818a80, 0xc00000c1f8}, {0x0, 0x0, 0x0})
        io/io.go:427 +0x19c fp=0xc000011f08 sp=0xc000011e88 pc=0xb1a5c
io.Copy({0xffffff923c6f78?, 0xc000133800?}, {0x818a80?, 0xc00000c1f8?})
        io/io.go:386 +0x5c fp=0xc000011f48 sp=0xc000011f08 pc=0xb18a4
github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2.1.1()
        github.com/gliderlabs/[email protected]/tcpip.go:161 +0xe4 fp=0xc000011fd8 sp=0xc000011f48 pc4
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000011fd8 sp=0xc000011fd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2.1
        github.com/gliderlabs/[email protected]/tcpip.go:158 +0x174

goroutine 34 [chan receive]:
runtime.gopark(0x7e3f98, 0xc00005e368, 0xe, 0x17, 0x2)
        runtime/proc.go:363 +0x108 fp=0xc000046ee8 sp=0xc000046ec0 pc=0x49878
runtime.chanrecv(0xc00005e310, 0xc000046fb8, 0x88?)
        runtime/chan.go:583 +0x2e8 fp=0xc000046f78 sp=0xc000046ee8 pc=0x159c8
runtime.chanrecv2(0xc00016e190?, 0xc000121320?)
        runtime/chan.go:447 +0x14 fp=0xc000046f98 sp=0xc000046f78 pc=0x156cc
github.com/u-root/cpu/server.handler.func1()
        github.com/u-root/[email protected]/server/server.go:68 +0x54 fp=0xc000046fd8 sp=0xc000046f98c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000046fd8 sp=0xc000046fd8 pc=0x7688c
created by github.com/u-root/cpu/server.handler
        github.com/u-root/[email protected]/server/server.go:67 +0x404

goroutine 39 [sync.Cond.Wait]:
runtime.gopark(0x7e4170, 0xc00016af18, 0x14, 0x1a, 0x3)
        runtime/proc.go:363 +0x108 fp=0xc000014ba0 sp=0xc000014b78 pc=0x49878
runtime.goparkunlock(0x0?, 0x80?, 0x53?, 0x8ddb8?)
        runtime/proc.go:369 +0x58 fp=0xc000014bc8 sp=0xc000014ba0 pc=0x498f0
sync.runtime_notifyListWait(0xc00016af10, 0x1dd)
        runtime/sema.go:517 +0x174 fp=0xc000014c00 sp=0xc000014bc8 pc=0x733fc
sync.(*Cond).Wait(0xc00016af00)
        sync/cond.go:70 +0x70 fp=0xc000014c28 sp=0xc000014c00 pc=0x8ddf0
golang.org/x/crypto/ssh.(*buffer).Read(0xc000060760, {0xc000190000, 0x8000, 0x8000})
        golang.org/x/[email protected]/ssh/buffer.go:94 +0x20c fp=0xc0c
golang.org/x/crypto/ssh.(*channel).ReadExtended(0xc000133800, {0xc000190000?, 0xc000190000?, 0)
        golang.org/x/[email protected]/ssh/channel.go:351 +0xd0 fp=0xc8
golang.org/x/crypto/ssh.(*channel).Read(0x1baa8?, {0xc000190000?, 0xc00016e220?, 0xc00016e220?)
        golang.org/x/[email protected]/ssh/channel.go:528 +0x50 fp=0xc8
io.copyBuffer({0x81a420, 0xc00016e220}, {0xffffff923c6ef8, 0xc000133800}, {0x0, 0x0, 0x0})
        io/io.go:427 +0x19c fp=0xc000014db0 sp=0xc000014d30 pc=0xb1a5c
io.Copy({0x81a420?, 0xc00016e220?}, {0xffffff923c6ef8?, 0xc000133800?})
        io/io.go:386 +0x5c fp=0xc000014df0 sp=0xc000014db0 pc=0xb18a4
net.genericReadFrom({0x818aa0?, 0xc00000c1f8?}, {0xffffff923c6ef8, 0xc000133800})
        net/net.go:675 +0x84 fp=0xc000014e28 sp=0xc000014df0 pc=0x138d1c
net.(*TCPConn).readFrom(0xc00000c1f8, {0xffffff923c6ef8, 0xc000133800})
        net/tcpsock_posix.go:54 +0x94 fp=0xc000014e50 sp=0xc000014e28 pc=0x13f5bc
net.(*TCPConn).ReadFrom(0xc00000c1f8, {0xffffff923c6ef8, 0xc000133800})
        net/tcpsock.go:130 +0x60 fp=0xc000014e88 sp=0xc000014e50 pc=0x13da90
io.copyBuffer({0x818aa0, 0xc00000c1f8}, {0xffffff923c6ef8, 0xc000133800}, {0x0, 0x0, 0x0})
        io/io.go:413 +0x140 fp=0xc000014f08 sp=0xc000014e88 pc=0xb1a00
io.Copy({0x818aa0?, 0xc00000c1f8?}, {0xffffff923c6ef8?, 0xc000133800?})
        io/io.go:386 +0x5c fp=0xc000014f48 sp=0xc000014f08 pc=0xb18a4
github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2.1.2()
        github.com/gliderlabs/[email protected]/tcpip.go:166 +0xe4 fp=0xc000014fd8 sp=0xc000014f48 pcc
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000014fd8 sp=0xc000014fd8 pc=0x7688c
created by github.com/gliderlabs/ssh.(*ForwardedTCPHandler).HandleSSHRequest.func2.1
        github.com/gliderlabs/[email protected]/tcpip.go:163 +0x1e8

goroutine 35 [sync.Cond.Wait]:
runtime.gopark(0x7e4170, 0xc00047b098, 0x14, 0x1a, 0x3)
        runtime/proc.go:363 +0x108 fp=0xc000012bf0 sp=0xc000012bc8 pc=0x49878
runtime.goparkunlock(0x4?, 0x1?, 0x0?, 0x8ddb8?)
        runtime/proc.go:369 +0x58 fp=0xc000012c18 sp=0xc000012bf0 pc=0x498f0
sync.runtime_notifyListWait(0xc00047b090, 0x0)
        runtime/sema.go:517 +0x174 fp=0xc000012c50 sp=0xc000012c18 pc=0x733fc
sync.(*Cond).Wait(0xc00047b080)
        sync/cond.go:70 +0x70 fp=0xc000012c78 sp=0xc000012c50 pc=0x8ddf0
golang.org/x/crypto/ssh.(*buffer).Read(0xc00011fac0, {0xc000188000, 0x8000, 0x8000})
        golang.org/x/[email protected]/ssh/buffer.go:94 +0x20c fp=0xc0c
golang.org/x/crypto/ssh.(*channel).ReadExtended(0xc000132d80, {0xc000188000?, 0xc000188000?, 0)
        golang.org/x/[email protected]/ssh/channel.go:351 +0xd0 fp=0xc8
golang.org/x/crypto/ssh.(*channel).Read(0x8000?, {0xc000188000?, 0x5d0701?, 0xc00016e1c0?})
        golang.org/x/[email protected]/ssh/channel.go:528 +0x50 fp=0xc8
github.com/gliderlabs/ssh.(*session).Read(0x1baa8?, {0xc000188000?, 0xc00016e1c0?, 0xc00016e1c)
        <autogenerated>:1 +0x58 fp=0xc000012da8 sp=0xc000012d80 pc=0x259af8
io.copyBuffer({0x81a780, 0xc00016e1c0}, {0xffffff923c5698, 0xc0000fd2b0}, {0x0, 0x0, 0x0})
        io/io.go:427 +0x19c fp=0xc000012e28 sp=0xc000012da8 pc=0xb1a5c
io.Copy({0x81a780?, 0xc00016e1c0?}, {0xffffff923c5698?, 0xc0000fd2b0?})
        io/io.go:386 +0x5c fp=0xc000012e68 sp=0xc000012e28 pc=0xb18a4
os.genericReadFrom(0x0?, {0xffffff923c5698, 0xc0000fd2b0})
        os/file.go:161 +0x7c fp=0xc000012ea0 sp=0xc000012e68 pc=0xddbbc
os.(*File).ReadFrom(0x6ec85b?, {0xffffff923c5698, 0xc0000fd2b0})
        os/file.go:155 +0xb4 fp=0xc000012ee0 sp=0xc000012ea0 pc=0xddafc
io.copyBuffer({0x818d60, 0xc00000c1e8}, {0xffffff923c5698, 0xc0000fd2b0}, {0x0, 0x0, 0x0})
        io/io.go:413 +0x140 fp=0xc000012f60 sp=0xc000012ee0 pc=0xb1a00
io.Copy({0x818d60?, 0xc00000c1e8?}, {0xffffff923c5698?, 0xc0000fd2b0?})
        io/io.go:386 +0x5c fp=0xc000012fa0 sp=0xc000012f60 pc=0xb18a4
github.com/u-root/cpu/server.handler.func2()
        github.com/u-root/[email protected]/server/server.go:73 +0x54 fp=0xc000012fd8 sp=0xc000012fa0c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc000012fd8 sp=0xc000012fd8 pc=0x7688c
created by github.com/u-root/cpu/server.handler
        github.com/u-root/[email protected]/server/server.go:72 +0x474

goroutine 27 [select]:
runtime.gopark(0x7e41d0, 0x0, 0x9, 0x18, 0x1)
        runtime/proc.go:363 +0x108 fp=0xc00045fda0 sp=0xc00045fd78 pc=0x49878
runtime.selectgo(0xc00045ffa8, 0xc00045ff50, 0x370?, 0x0, 0xc000132c00?, 0x1)
        runtime/select.go:328 +0x698 fp=0xc00045ff00 sp=0xc00045fda0 pc=0x59460
golang.org/x/crypto/ssh.(*handshakeTransport).kexLoop(0xc0000f82c0)
        golang.org/x/[email protected]/ssh/handshake.go:268 +0x224 fp=4
golang.org/x/crypto/ssh.newServerTransport.func2()
        golang.org/x/[email protected]/ssh/handshake.go:143 +0x2c fp=0c
runtime.goexit()
        runtime/asm_riscv64.s:509 +0x4 fp=0xc00045ffd8 sp=0xc00045ffd8 pc=0x7688c
created by golang.org/x/crypto/ssh.newServerTransport
        golang.org/x/[email protected]/ssh/handshake.go:143 +0x16c
[    1.351910] u-root init [optional]: warning creating mount -t "cgroup" -o perf_event "cgrout
[   25.183899] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000200
[   25.184609] CPU: 0 PID: 65 Comm: init Not tainted 5.19.0 #4
[   25.184843] Hardware name: riscv-virtio,qemu (DT)
[   25.185052] Call Trace:
[   25.185255] [<ffffffff80003c5a>] dump_backtrace+0x1c/0x24
[   25.186117] [<ffffffff8041e4cc>] show_stack+0x2c/0x38
[   25.186256] [<ffffffff804259e4>] dump_stack_lvl+0x3c/0x54
[   25.186415] [<ffffffff80425a10>] dump_stack+0x14/0x1c
[   25.186566] [<ffffffff8041e828>] panic+0x102/0x2bc
[   25.186712] [<ffffffff800100b4>] do_exit+0x786/0x78c
[   25.186854] [<ffffffff800101da>] do_group_exit+0x24/0x7c
[   25.187007] [<ffffffff8001a514>] get_signal+0x64a/0x698
[   25.187148] [<ffffffff80002fb0>] do_notify_resume+0x6c/0x424
[   25.187304] [<ffffffff80001ebc>] ret_from_exception+0x0/0xc
[   25.187862] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000020---]

cmd/cpud doesn't build on osx

Lack of unix.MS_* on OSX is causing a build failure of cpud on OSX

While I originally figured this was just expected behavior, when I was fussing about, I noticed that the server package actually tries (and fails) to compile on OSX by using server_other.go -- which makes me think we can try and do something similar with mount_other?

elaborate on CPUD(as remote):9p mount no such device

On the remote, in a chroot, I am running:

cpud -d -remote -init

On my host machine, I then invoke:

export PATH="$(pwd)/bin:$PATH"
cpu -timeout9p 1000ms -d victure hello

Here is what I get:

On the remote (env vars stripped):

1970/01/01 00:02:43 CPUD:attempt to bind 127.0.0.1 0 granted
1970/01/01 00:02:44
CPUD:the handler is here, cmd is [cpud -remote -bin cpud -port9p 38098 hello]
1970/01/01 00:02:44
CPUD:the command is {/bbin/cpud [cpud -remote -bin cpud -port9p 38098 hello] [SHELL=/usr/bin/fish ... _=./cpu CPUNONCE=c57c260c0e9896b99dc53a35e5b198fa]  <nil> <nil> <nil> [] 0xc6f800 <nil> <nil> <nil> <nil> false [] [] [] [] <nil> <nil>}
1970/01/01 00:02:44
CPUD:command started with pty
1970/01/01 00:02:44
CPUD:wait for /bbin/cpud -remote -bin cpud -port9p 38098 hello
1970/01/01 00:02:44
CPUD:cmd returns with exit status 1
1970/01/01 00:02:44
CPUD:CPUD:child exited with  exit status 1
1970/01/01 00:02:44
CPUD:handler exits

On my host:

2021/04/06 20:41:47 
Running as client
2021/04/06 20:41:47 listener *ssh.tcpListener &{0xc0000661b0 0xc0000640a0 0xc0000122a0} addr 127.0.0.1:38098 port 0xc000098800
2021/04/06 20:41:47 command is "cpud -remote -bin cpud -port9p 38098 \"hello\""
2021/04/06 20:41:47 srv: try to accept
2021/04/06 20:41:48 Start remote with command "cpud -remote -bin cpud -port9p 38098 \"hello\""
1970/01/01 00:02:44 mkdir /home: read-only file system
2021/04/06 20:41:48 srv got &{0xc000232000 0xc0000661b0 0xc00021abd0}
2021/04/06 20:41:48 srv: read the nonce back got c57c260c0e9896b99dc53a35e5b198fa
1970/01/01 00:02:44 CPUD(as remote):9p mount no such device
2021/04/06 20:41:48 SSH error Process exited with status 1

I am not exactly sure where I get with that.

private key inline

how does every security scanner on the planet not barf on cpu/server/key.go? I get the need for sensible key pair for test, but shouldn't we autogenerate this?

Can't parse ~/ssh/.config properly

Hi -

In my .ssh/config:

Host qemu
    Hostname 127.0.0.1
    User root
    Port 5555
    IdentitiesOnly yes
    IdentityFile ~/.ssh/db_rsa

I've tried HostName vs Hostname, removing IdentitiesOnly, etc. I can tell the file is being read (strace). I've also removed everything else from my .ssh/config other than that block.

I get:

$ ./cpu qemu bash
...
2022/03/02 17:17:23 getKeyFile returns "/usr/local/google/home/brho/.ssh/cpu_rsa"

and it looks like kf = config.Get(host, "IdentityFile") is failing.

Thanks.

invalid use of WriteAt on file opened with O_APPEND

After running a command with bash or sh and hitting ctl-d or type 'exit', I get that error. If i hit ctl-d immediately, i do not. if the command is 'exit', i also get it.

seems like any time i issue any command, even 'exit', i'll get the error. but not if if i hit ctl-d first. (and not if i get some other error, as in the other bug, where ctl-c followed by ctl-d gave a different error).

e.g.

$ ./cpu TARGET sh
sh-5.1# ls
cpu	  cpu_darwin.go  cpu_linux.go  getattr_darwin.go  srv.go
cpu9p.go  cpu.go	 doc.go        getattr_linux.go
sh-5.1# exit
exit
2022/03/04 16:27:08 unknown error: os: invalid use of WriteAt on file opened with O_APPEND
                                                                                          $ 

$ ./cpu TARGET sh
sh-5.1# exit
exit
2022/03/04 16:27:32 unknown error: os: invalid use of WriteAt on file opened with O_APPEND
                                                                                           $ 

(i hit ctl-d on this one)
$ ./cpu TARGET sh
sh-5.1# 
exit

premature column wrapping

when in a large terminal, if i run bash or sh with cpu, my terminal will be "prematurely wrapped". meaning that instead of using the full window size of my host, it'll wrap to 70 characters.

e.g.

$ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ ./cpu TARGET bash --norc --noprofile
bash-5.1# fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffff
bash-5.1# resize
COLUMNS=164;
LINES=46;
export COLUMNS LINES;
bash-5.1# stty -a
speed 38400 baud; rows 46; columns 164; line = 0;

both on the target machine (natively), on my host, and in cpu, bash thinks there are 164 columns (which is correct). stty -a agrees.

What are the other options if I have systemd

Running cpud -d -remote I get:

2022/02/07 18:25:05 CPUD:Warning: unshare failed (operation not permitted). There will be no private 9p mount if systemd is there
2022/02/07 18:25:05 CPUD:Warning: tmpfs mount on /tmp (operation not permitted) failed. There will be no 9p mount
2022/02/07 18:25:05 
CPUD:Args [cpud -d -remote] pid 9903 *runasinit false *remote true
2022/02/07 18:25:05 
CPUD:Running as remote
2022/02/07 18:25:05 CPUD:namespace is "/lib:/lib64:/usr:/bin:/etc:/home"
2022/02/07 18:25:05 CPUD:Dial 127.0.0.1:
2022/02/07 18:25:05 CPUD:Dial 9p port: dial tcp4 127.0.0.1:0: connect: connection refused

First things first: since on my system (Arch Linux) I run systemd, what other options are there? Do I need to set up a virtual machine?

Missing much of /etc in Docker cpud?

I have setup a Docker container using cpud. It looks like so:

FROM debian:12.1-slim

COPY cpud /bin
COPY rjk_rsa.pub /

EXPOSE 17010
CMD [ "/bin/cpud",  "-pk" , "/rjk_rsa.pub",  "-d"]

I build it in the usual fashion. cpud is from tip of tree. Running it for inspection:

; docker run --rm -it --name cpud_test --privileged=true -p 17011:17010 cpud /bin/sh
# ls /etc
adduser.conf		debconf.conf	fstab	   hosts	ld.so.conf.d   mtab	      passwd-	 rc4.d	      selinux  terminfo
alternatives		debian_version	gai.conf   init.d	libaudit.conf  nsswitch.conf  profile	 rc5.d	      shadow   timezone
apt			default		group	   issue	localtime      opt	      profile.d  rc6.d	      shells   update-motd.d
bash.bashrc		deluser.conf	group-	   issue.net	login.defs     os-release     rc0.d	 rcS.d	      skel     xattr.conf
bindresvport.blacklist	dpkg		gshadow    kernel	logrotate.d    pam.conf       rc1.d	 resolv.conf  subgid
cron.d			e2scrub.conf	host.conf  ld.so.cache	mke2fs.conf    pam.d	      rc2.d	 rmt	      subuid
cron.daily		environment	hostname   ld.so.conf	motd	       passwd	      rc3.d	 security     systemd

Looks very reasonable.

I run it in the intended way on a GCP node called ween:

docker run --rm --name cpud_test --privileged=true -p 17011:17010 cpud

and then:

; TMPDIR=() PWD=/ cpu -namespace '' -sp 17011 ween ls /etc
adduser.conf  alternatives

Where's the rest of /etc? Is this operating as intended?

Newbie questions and feature requests

I'll simply list what surprised me, a cpu noob ๐Ÿ˜‰. Could you comment on each of the points?

  1. Running cpud on a Linux machine requires PID 1 - why? Shouldn't root privileges be enough? This makes it impossible to run on pretty much any ordinary Linux distribution (which I'd say defeats the major use case "to seamlessly perform work on running remote machines").
  2. Running cpud -remote on a Linux machine does run the daemon but in addition to that it executes an interactive shell ๐Ÿ˜ฎ - why the shell?
  3. cpu doesn't seem to support any way to specify the user to be used to execute the given command at the remote host if the host supports it (yes, this might be a "too high level" request for cpu/cpud but I stand at it as otherwise this again defeats the purpose of using cpu with ordinary running remote machines like Linux/BSD).
  4. On a Linux machine running cpud -remote (I've tried both as root and as a non-root user) and then in another terminal cpu localhost /bin/bash only returns the error 2022/05/04 10:56:43 SSH error Failed to dial: dial tcp [::1]:23: connect: connection refused instead of connecting to the running daemon (and no, there is no firewall on port 23 nor any running SSH daemon nor anything else). Why doesn't this simple case work?

Thanks for explanations, suggestions, etc.!

cpu command does not work in non-interactive environment

#include <unistd.h>
#include <stdio.h>

#define CPU_BIN "/path/to/cpu"
#define CPU_RSA "/path/to/.ssh/cpud_rsa"

const char *sub_argv[64] = {CPU_BIN, "-dbg9p", "-key", CPU_RSA, "-net", "vsock", "3", "/bin/bash", "--version" , NULL};

int main() {
    if (fork() == 0) {
            if (-1 == execve(sub_argv[0], (char **)sub_argv , NULL)) {
                    perror("child process execve failed [%m]");
                    return -1;
            }
    }
    return 0;
}

The C program above runs the cpu command as a subprocess. The cpu command would fail at

cpu/client/client.go

Lines 437 to 439 in f72e9ff

if err := c.SetupInteractive(); err != nil {
return err
}

since it's not executed in an interactive shell.

opportunities to improve cpu performance?

I had the (I thought inspired) but (obvious given the context here) idea of using cpu to mount a selection of pre-built binary tools into a GCP node rather than installing them or building an archive or such not. But performance is insufficient for this use case.

While Internet bandwidth is definitely a very significant part of this, I did some benchmarking and believe that cpu itself could be more performant.

# local to remote
; time rsync -av $_h/wrks/archive/bins/linux/amd64/rclone ween:
building file list ... done
rclone

sent 71019517 bytes  received 42 bytes  2407442.68 bytes/sec
total size is 71010723  speedup is 1.00
       29.16 real         0.26 user         0.32 sys
;
; time cpu ween cp /usr/local/rjkroege/wrks/archive/bins/linux/amd64/rclone /home/rjkroege/rclone2
      127.54 real         0.78 user         1.85 sys

Missing move, check on lock

In the README, we describe a cool hack - using a Docker image as a rootfs, enabling the cpu namespace to provide a whole distro:
https://github.com/u-root/cpu#cpu-and-docker

One essential feature of a distro is to install the software it offers.
That can be handled via commands when creating a Docker image.
However, in the cross architecture case, the host providing the environment would typically not be able to run the package manager made for the foreign architecture.
A solution would be to install a specific package using the machine to cpu into. That could be accepted to happen at container runtime, even though it'd be ephemeral. Now that raises another problem: package managers typically extract to some temporary directory, lock their database, move the files from the temporary directory and then commit to the darabase to finally unlock it. The 9p protocol used here, though, does not offer moving files, and locking needs some investigation.
hugelgupf/p9#52 should have fixed the lock

Note: I may have been using a somewhat older cpu binary.
I need to recheck again with a current build of the cpu command.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.