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

Tweak #283

Merged
merged 9 commits into from
Oct 2, 2024
13 changes: 7 additions & 6 deletions cmds/cpu/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const defaultPort = "17010"

var (
defaultKeyFile = filepath.Join(os.Getenv("HOME"), ".ssh/cpu_rsa")
// For the ssh server part
// cpuns might not be in the limited search path of sshd. Allow users to set it.
cpuns = flag.String("cpuns", "cpuns", "command to run to build cpu namespace")
debug = flag.Bool("d", false, "enable debug prints")
dbg9p = flag.Bool("dbg9p", false, "show 9p io")
dump = flag.Bool("dump", false, "Dump copious output, including a 9p trace, to a temp file at exit")
Expand All @@ -49,7 +50,7 @@ var (
srvnfs = flag.Bool("nfs", false, "start nfs")
cpioRoot = flag.String("cpio", "", "cpio initrd")

ssh = flag.Bool("ssh", false, "ssh only, no internal 9p, nfs, or mounts")
ssh = flag.Bool("ssh", false, "ssh only, no internal 9p, nfs, or mounts")
sshd = flag.Bool("sshd", false, "server is sshd, not cpud")

// v allows debug printing.
Expand Down Expand Up @@ -153,7 +154,7 @@ func newCPU(host string, args ...string) (retErr error) {
if *sshd && *srvnfs {
env := append(os.Environ(), "CPU_PWD="+os.Getenv("PWD"))
envargs := "-env=" + strings.Join(env, "\n")
args = append([]string{"cpuns", envargs}, args...)
args = append([]string{*cpuns, envargs}, args...)
}
c := client.Command(host, args...)
defer func() {
Expand Down Expand Up @@ -215,9 +216,9 @@ func newCPU(host string, args ...string) (retErr error) {
log.Printf("nfs: %v", err)
// wg.Done()
}()
verbose("nfsmount %q fstab %q join %q", nfsmount, fstab, client.JoinFSTab(nfsmount, fstab))
fstab = client.JoinFSTab(nfsmount, fstab)
c.Env = append(c.Env, "CPU_FSTAB="+fstab, "LC_GLENDA_CPU_FSTAB="+fstab)
jfstab := client.JoinFSTab(nfsmount, fstab)
c.Env = append(c.Env, "CPU_FSTAB="+jfstab, "LC_GLENDA_CPU_FSTAB="+jfstab)
verbose("nfsmount %q fstab %q join %q env %q", nfsmount, fstab, jfstab, c.Env)
}

go func() {
Expand Down
50 changes: 27 additions & 23 deletions cmds/cpuns/main_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,34 +65,33 @@ func checkprivate() error {
// sudo will get us into a root process, with correct environment
// set up.
func sudo(env string, args ...string) {
log.Printf("sudo: os.Env %v\nenv %v\nargs %v", os.Environ(), env, args)
n, err := os.Executable()
if err != nil {
log.Fatal(err)
}

v("Executable: %q", n)
verbose("Executable: %q", n)
// sshd filters most environment variables save LC_*.
// sudo strips most LC_* variables.
// the cpu command sets LC_GLENDA_CPU_FSTAB to the fstab;
// we need to transform it here.

c := exec.Command("sudo", append([]string{"-E", n, "-env=" + env}, args...)...)
v("exec.Cmd args %q", c.Args)
c := exec.Command("sudo", append([]string{"--preserve-env=CPU_FSTAB", n, "-env=" + env}, args...)...)
verbose("exec.Cmd args %q", c.Args)

// Find the environment variable, and transform it.
// sudo seems to strip many LC_* variables.
fstab, ok := os.LookupEnv("LC_GLENDA_CPU_FSTAB")
v("fstab set? %v value %q", ok, fstab)
verbose("fstab set? %v value %q", ok, fstab)
if ok {
c.Env = append(c.Env, "CPU_FSTAB="+fstab)
v("extended c.Env: %v", c.Env)
verbose("extended c.Env: %v", c.Env)
}
if s := strings.Split(env, "\n"); len(s) > 0 {
c.Env = append(c.Env, s...)
}
c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr
v("Run %q", c)
verbose("Run %q", c)

// The return is carefully done here to avoid the caller
// making a mistake and fork-bomb.
Expand All @@ -107,7 +106,6 @@ func sudo(env string, args ...string) {
// Be very careful in modifying this; it is designed to be
// simple and avoid fork bombs.
func unshare(env string, args ...string) {
log.Printf("unshare: os.Env %v\nenv %v\n args %v", os.Environ(), env, args)
n, err := os.Executable()
if err != nil {
log.Fatal(err)
Expand All @@ -119,21 +117,24 @@ func unshare(env string, args ...string) {
// we need to transform it here.
// Since we can get here direct from sshd, not sudo,
// we have to this twice.
v("Executable: %q", n)
verbose("Executable: %q", n)
c := exec.Command(n, args...)
v("exec.Cmd args %q", c.Args)
verbose("exec.Cmd args %q", c.Args)

c.Env = os.Environ()
if s := strings.Split(env, "\n"); len(s) > 0 {
c.Env = append(c.Env, s...)
}

fstab, ok := os.LookupEnv("LC_GLENDA_CPU_FSTAB")
v("fstab set? %v value %q", ok, fstab)
verbose("fstab set? %v value %q", ok, fstab)
if ok {
c.Env = append(c.Env, "CPU_FSTAB="+fstab)
v("extended c.Env: %v", c.Env)
if s := strings.Split(env, "\n"); len(s) > 0 {
c.Env = append(c.Env, s...)
}
verbose("extended c.Env: %v", c.Env)
}

c.Stdin, c.Stdout, c.Stderr, c.Dir = os.Stdin, os.Stdout, os.Stderr, os.Getenv("PWD")
v("Run %q", c)
verbose("Run %q", c)

c.SysProcAttr = &syscall.SysProcAttr{Unshareflags: syscall.CLONE_NEWNS}
// The return is carefully done here to avoid the caller
Expand All @@ -154,21 +155,23 @@ func main() {
flag.Parse()
if *debug {
v = log.Printf
verbose("cpuns: os.Args %q", os.Args)
session.SetVerbose(v)
verbose("cpuns: os.Args %q env %q", os.Args, os.Environ())
}
args := flag.Args()
v("LC_GLENDA_CPU_FSTAB %s", os.Getenv("LC_GLENDA_CPU_FSTAB"))
v("CPU_FSTAB %s", os.Getenv("CPU_FSTAB"))
verbose("LC_GLENDA_CPU_FSTAB %s", os.Getenv("LC_GLENDA_CPU_FSTAB"))
verbose("CPU_FSTAB %s", os.Getenv("CPU_FSTAB"))
verbose("env\n\n%q\n\n", *env)
if os.Getuid() != 0 {
verbose("sudo %q %q", *env, args)
sudo(*env, args...)
}

if err := checkprivate(); err != nil {
verbose("unshare %q %q", *env, args)
unshare(*env, args...)
}

log.Printf("mount and run: os.Env %v\n*env %v\n args %v", os.Environ(), *env, args)
shell := "/bin/sh"
if len(args) == 0 {
sh, ok := os.LookupEnv("SHELL")
Expand All @@ -191,8 +194,8 @@ func main() {
}

// the default value of uid, gid is 0
uid := uint32(os.Getuid())
gid := uint32(os.Getgid())
uid := uint32(syscall.Getuid())
gid := uint32(syscall.Getgid())
if u, ok := os.LookupEnv("SUDO_UID"); ok {
i, err := strconv.ParseUint(u, 0, 32)
if err != nil {
Expand All @@ -209,10 +212,10 @@ func main() {
}

c := s.Command()
c.Env = os.Environ()
if s := strings.Split(*env, "\n"); len(s) > 0 {
c.Env = append(c.Env, s...)
}
verbose("cpuns: Command is %q, with args %q", c, args)
pwd := os.Getenv("CPU_PWD")
if _, err := os.Stat(pwd); err != nil {
log.Printf("%v:setting pwd to /", err)
Expand All @@ -221,6 +224,7 @@ func main() {
c.Stdin, c.Stdout, c.Stderr, c.Dir = s.Stdin, s.Stdout, s.Stderr, pwd
c.SysProcAttr = &syscall.SysProcAttr{}
c.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
verbose("Run %q %q %q", c, c.Args, c.Env)
if err := c.Run(); err != nil {
log.Fatalf("Run %v returns %v", c, err)
}
Expand Down
Loading