Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Freebsdcpud #289

Merged
merged 4 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
*=
*tar
*uck
*.pub
81 changes: 81 additions & 0 deletions cmds/cpud/init_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2018-2022 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This is init code for the case that cpu finds itself as pid 1.
// This is duplicative of the real init, but we're implementing it
// as a duplicate so we can get some idea of:
// what an init package should have
// what an init interface should have
// So we take a bit of duplication now to better understand these
// things. We also assume for now this is a busybox environment.
// It is unusual (I guess?) for cpu to be an init in anything else.
// So far, the case for an init pkg is not as strong as I thought
// it might be.
package main

import (
"log"
"runtime"
"syscall"
"time"

"github.com/u-root/u-root/pkg/libinit"
)

func cpuSetup() error {
// The process reaper runs from here, and needs to run
// as PID 1.
runtime.LockOSThread()
log.Printf(`

#### ##### # # ##
# # # # # # ##
# # # # # ##
# ##### # # ##
# # # # #
#### # #### ##
`)
// libinit.SetEnv()
// libinit.CreateRootfs()
libinit.NetInit()
// Wait for orphans, forever.
// Since there is no way of knowning when we are
// done for good, our work here is never done.
// A complication is that for long periods of time, there
// may be no orphans.In that case, sleep for one second,
// and try again. This background load is hardly enough
// to matter. And, in general, it will happen by definition
// when there is nothing to wait for, i.e. there is nothing
// on the node to be upset about.
// Were this ever to be a concern, an option is to kick off
// a process that will never exit, such that wait4 will always
// block and always return when any child process exits.
go func() {
var numReaped int
for {
var (
s syscall.WaitStatus
r syscall.Rusage
)
p, err := syscall.Wait4(-1, &s, 0, &r)
// Once per second, Wait 4 returns if there's nothing
// else to do.
if err != nil && err.Error() == "no child processes" {
continue
}
verbose("orphan reaper: returns with %v", p)
if p == -1 {
verbose("Nothing to wait for, %d wait for so far", numReaped)
time.Sleep(time.Second)
}
if err != nil {
log.Printf("CPUD: a process exited with %v, status %v, rusage %v, err %v", p, s, r, err)
}
numReaped++
}
}()

runtime.UnlockOSThread()
return nil
rminnich marked this conversation as resolved.
Show resolved Hide resolved
}
131 changes: 131 additions & 0 deletions cmds/cpud/main_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2018-2019 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"flag"
"log"
"os"
"time"

// We use this ssh because it implements port redirection.
// It can not, however, unpack password-protected keys yet.

"github.com/u-root/cpu/session"
)

var (
// For the ssh server part
hostKeyFile = flag.String("hk", "" /*"/etc/ssh/ssh_host_rsa_key"*/, "file for host key")
pubKeyFile = flag.String("pk", "key.pub", "file for public key")
port = flag.String("sp", "17010", "cpu default port")

debug = flag.Bool("d", false, "enable debug prints")
runAsInit = flag.Bool("init", false, "run as init (Debug only; normal test is if we are pid 1")
// v allows debug printing.
// Do not call it directly, call verbose instead.
v = func(string, ...interface{}) {}
remote = flag.Bool("remote", false, "indicates we are the remote side of the cpu session")
network = flag.String("net", "tcp", "network to use")
port9p = flag.String("port9p", "", "port9p # on remote machine for 9p mount")
klog = flag.Bool("klog", false, "Log cpud messages in kernel log, not stdout")

// Some networks are not well behaved, and for them we implement registration.
registerAddr = flag.String("register", "", "address and port to register with after listen on cpu server port")
registerTO = flag.Duration("registerTO", time.Duration(5*time.Second), "time.Duration for Dial address for registering")

// if we start up too quickly, mDNS won't work correctly.
// This sleep may be useful for other cases, so it is here,
// not specifically for mDNS uses.
sleepBeforeServing = flag.Duration("sleepBeforeServing", 0, "add a sleep before serving -- usually only needed if cpud runs as init with mDNS")

pid1 bool
)

func verbose(f string, a ...interface{}) {
if *remote {
v("CPUD(remote):"+f+"\r\n", a...)
} else {
v("CPUD:"+f, a...)
}
}

// There are three distinct cases to cover.
// 1. running as init (indicated by pid == 1 OR -init=true switch
// 2. running as server. pid != 1 AND -remote=true AND -init=false
// 3. running as 'remote', i.e. the thing that starts a command for
// a client. Indicated by remote=true.
//
// case (3) overrides case 2 and 1.
// This has evolved over the years, and, likely, the init and remote
// switches ought to be renamed to 'role'. But so it goes.
// The rules on arguments are very strict now. In the remote case,
// os.Args[1] MUST be remote; no other invocation is accepted, because
// the args to remote and the args to server are different.
// This invocation requirement is known to the server package.
func main() {
if len(os.Args) > 1 && (os.Args[1] == "-remote" || os.Args[1] == "-remote=true") {
*remote = true
}

if *remote {
// remote has far fewer args. Since they are specified by the client,
// we want to limit the set of args it can set.
flag.CommandLine = flag.NewFlagSet("cpud-remote", flag.ExitOnError)
debug = flag.Bool("d", false, "enable debug prints")
remote = flag.Bool("remote", false, "indicates we are the remote side of the cpu session")
port9p = flag.String("port9p", "", "port9p # on remote machine for 9p mount")

flag.Parse()
if *debug {
v = log.Printf
session.SetVerbose(verbose)
}
// If we are here, no matter what they may set, *remote must be true.
// sadly, cpud -d -remote=true -remote=false ... works.
*remote = true
rminnich marked this conversation as resolved.
Show resolved Hide resolved
} else {
flag.Parse()
// If we are here, no matter what they may set, *remote must be false.
*remote = false
if err := commonsetup(); err != nil {
log.Fatal(err)
}
}
pid := os.Getpid()
pid1 = pid == 1
*runAsInit = *runAsInit || pid1
verbose("Args %v pid %d *runasinit %v *remote %v env %v", os.Args, pid, *runAsInit, *remote, os.Environ())
args := flag.Args()
if *remote {
verbose("args %q, port9p %v", args, *port9p)

// This can happen if the user gets clever and
// invokes cpu with, e.g., nothing but switches.
if len(args) == 0 {
shell, ok := os.LookupEnv("SHELL")
if !ok {
log.Fatal("No arguments and $SHELL is not set")
}
args = []string{shell}
}
s := session.New(*port9p, args[0], args[1:]...)
if err := s.Run(); err != nil {
log.Fatalf("CPUD(remote): %v", err)
}
} else {
log.Printf("CPUD:PID(%d):running as a server (a.k.a. starter of cpud's for sessions)", pid)
if *runAsInit {
log.Printf("CPUD:also running as init")
if err := initsetup(); err != nil {
log.Fatal(err)
}
}
time.Sleep(*sleepBeforeServing)
if err := serve(os.Args[0]); err != nil {
log.Fatal(err)
}
}
}
16 changes: 9 additions & 7 deletions cmds/cpud/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"github.com/gliderlabs/ssh"
"github.com/mdlayher/vsock"
"github.com/u-root/cpu/server"
"github.com/u-root/u-root/pkg/ulog"
"golang.org/x/sys/unix"
)

const any = math.MaxUint32
Expand Down Expand Up @@ -65,17 +63,21 @@ func commonsetup() error {
server.SetVerbose(verbose)
v = log.Printf
if *klog {
ulog.KernelLog.Reinit()
v = ulog.KernelLog.Printf
//ulog.KernelLog.Reinit()
log.Panicf("klog: not yet")
//v = ulog.KernelLog.Printf
}
}
return nil
}

func initsetup() error {
if err := unix.Mount("cpu", "/tmp", "tmpfs", 0, ""); err != nil {
log.Printf("CPUD:Warning: tmpfs mount on /tmp (%v) failed. There will be no 9p mount", err)
}
// no tmpfs in freebsd?
/*
if err := unix.Mount("cpu", "/tmp", "tmpfs", 0, ""); err != nil {
log.Printf("CPUD:Warning: tmpfs mount on /tmp (%v) failed. There will be no 9p mount", err)
}
*/
if err := cpuSetup(); err != nil {
log.Printf("CPUD:CPU setup error with cpu running as init: %v", err)
}
Expand Down
4 changes: 0 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ require (
github.com/creack/pty v1.1.18
github.com/go-git/go-billy/v5 v5.5.1-0.20240514075308-8f1b719cb6a2
github.com/google/uuid v1.6.0
github.com/hashicorp/go-multierror v1.1.1
github.com/jacobsa/fuse v0.0.0-20240909130001-a1c7c8268f12
github.com/jacobsa/syncutil v0.0.0-20180201203307-228ac8e5a6c3
github.com/mdlayher/vsock v1.2.1
github.com/moby/sys/mountinfo v0.7.1
github.com/shirou/gopsutil v3.21.11+incompatible
Expand All @@ -32,7 +29,6 @@ require (
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
Expand Down
13 changes: 1 addition & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,13 @@ github.com/google/goexpect v0.0.0-20191001010744-5b6988669ffa h1:PMkmJA8ju9DjqAJ
github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 h1:CVuJwN34x4xM2aT4sIKhmeib40NeBPhRihNjQmpJsA4=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hugelgupf/p9 v0.2.1-0.20230814004337-e6037077d6dc h1:rYjeymvczXx9XLtaZRRSp/DMYKVXV1QZiCbaimPxAmY=
github.com/hugelgupf/p9 v0.2.1-0.20230814004337-e6037077d6dc/go.mod h1:QFmcCPNn66imQcu1wUqJ8sHKxYjs00Gq60QLjt9E+VI=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
github.com/jacobsa/fuse v0.0.0-20240909130001-a1c7c8268f12 h1:PIkShcSGp+IJB3h3Du/hNtrvug0b0o88p9pW8GF9xcg=
github.com/jacobsa/fuse v0.0.0-20240909130001-a1c7c8268f12/go.mod h1:JYi9iIxdYNgxmMgLwtSHO/hmVnP2kfX1oc+mtx+XWLA=
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA=
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff h1:2xRHTvkpJ5zJmglXLRqHiZQNjUoOkhUyhTAhEQvPAWw=
github.com/jacobsa/ogletest v0.0.0-20170503003838-80d50a735a11 h1:BMb8s3ENQLt5ulwVIHVDWFHp8eIXmbfSExkvdn9qMXI=
github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb h1:uSWBjJdMf47kQlXMwWEfmc864bA1wAC+Kl3ApryuG9Y=
github.com/jacobsa/syncutil v0.0.0-20180201203307-228ac8e5a6c3 h1:+gHfvQxomE6fI4zg7QYyaGDCnuw2wylD4i6yzrQvAmY=
github.com/jacobsa/syncutil v0.0.0-20180201203307-228ac8e5a6c3/go.mod h1:mPvulh9VKXvo+yOlrD4VYOOYuLdZJ36wa/5QIrtXvWs=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
Expand All @@ -48,7 +37,6 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
Expand All @@ -64,6 +52,7 @@ github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFu
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 h1:UVArwN/wkKjMVhh2EQGC0tEc1+FqiLlvYXY5mQ2f8Wg=
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93/go.mod h1:Nfe4efndBz4TibWycNE+lqyJZiMX4ycx+QKV8Ta0f/o=
github.com/rekby/gpt v0.0.0-20200219180433-a930afbc6edc h1:goZGTwEEn8mWLcY012VouWZWkJ8GrXm9tS3VORMxT90=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
Expand Down
38 changes: 33 additions & 5 deletions mount/mount_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import (
"bufio"
"errors"
"fmt"
"io"
"io/ioutil"
"os/exec"
"path/filepath"
"strings"
"syscall"
"unsafe"

"github.com/u-root/u-root/pkg/mount"
"golang.org/x/sys/unix"
)

Expand Down Expand Up @@ -66,6 +72,16 @@ func init() {
}
}

// iov returns an iovec for a string.
// there is no official package, and it is simple
// enough, that we just create it here.
func iovstring(val string) syscall.Iovec {
s := val + "\x00"
vec := syscall.Iovec{Base: (*byte)(unsafe.Pointer(&[]byte(s)[0]))}
vec.SetLen(len(s))
return vec
}

// Mount takes a full fstab as a string and does whatever mounts are needed.
// It ignores comment lines, and lines with less than 6 fields. In principal,
// Mount should be able to do a full remount with the contents of /proc/mounts.
Expand All @@ -74,14 +90,26 @@ func init() {
// a returned error, but be left in a situation in which further
// diagnostics are possible. i.e., follow the "Boots not Bricks"
// principle.
// Freebsd has very different ways of working than linux, so
// we shell out to mount for now.
func Mount(fstab string) error {
return fmt.Errorf("??")
}
f, err := ioutil.TempFile("", "cpu")
if err != nil {
return err
}
defer f.Close()

if _, err := io.WriteString(f, fstab); err != nil {
return err
}

if o, err := exec.Command("mount", "-a", "-F", f.Name()).CombinedOutput(); err != nil {
return fmt.Errorf("mount -F %q:%s:%w", f.Name(), string(o), err)
}

func mount(m mounter, fstab string) error {
return nil
var lineno int
s := bufio.NewScanner(strings.NewReader(fstab))
var err error
for s.Scan() {
lineno++
l := s.Text()
Expand Down Expand Up @@ -118,7 +146,7 @@ func mount(m mounter, fstab string) error {
// The man page implies that the Linux kernel handles flags of "defaults"
// we do no further manipulation of opts.
flags, data := parse(opts)
if e := m(dev, where, fstype, flags, data); e != nil {
if _, e := mount.Mount(dev, where, fstype, data, flags); e != nil {
err = errors.Join(err, fmt.Errorf("Mount(%q, %q, %q, %q=>(%#x, %q)): %w", dev, where, fstype, opts, flags, data, e))
}
}
Expand Down
Loading
Loading