Beispiel #1
0
// CreateNewNamespace creates a new namespace and binds it's fd to the specified path
func CreateNewNamespace(namespace libcontainer.Namespace, bindTo string) error {
	var (
		flag   = namespaceMap[namespace]
		name   = namespaceFileMap[namespace]
		nspath = filepath.Join("/proc/self/ns", name)
	)
	// TODO: perform validation on name and flag

	pid, err := fork()
	if err != nil {
		return err
	}

	if pid == 0 {
		if err := unshare(flag); err != nil {
			writeError("unshare %s", err)
		}
		if err := mount(nspath, bindTo, "none", syscall.MS_BIND, ""); err != nil {
			writeError("bind mount %s", err)
		}
		os.Exit(0)
	}
	exit, err := utils.WaitOnPid(pid)
	if err != nil {
		return err
	}
	if exit != 0 {
		return fmt.Errorf("exit status %d", exit)
	}
	return err
}
Beispiel #2
0
func execinAction(container *libcontainer.Container, cmd *libcontainer.Command, fds []uintptr) error {
	for _, fd := range fds {
		if fd > 0 {
			if err := JoinExistingNamespace(fd, ""); err != nil {
				for _, fd := range fds {
					syscall.Close(int(fd))
				}
				return err
			}
		}
		syscall.Close(int(fd))
	}

	if container.Namespaces.Contains(libcontainer.CLONE_NEWNS) &&
		container.Namespaces.Contains(libcontainer.CLONE_NEWPID) {
		// important:
		// we need to fork and unshare so that re can remount proc and sys within
		// the namespace so the CLONE_NEWPID namespace will take effect
		// if we don't fork we would end up unmounting proc and sys for the entire
		// namespace
		child, err := fork()
		if err != nil {
			return fmt.Errorf("fork child %s", err)
		}

		if child == 0 {
			if err := unshare(CLONE_NEWNS); err != nil {
				writeError("unshare newns %s", err)
			}
			if err := remountProc(); err != nil {
				writeError("remount proc %s", err)
			}
			if err := remountSys(); err != nil {
				writeError("remount sys %s", err)
			}
			if err := capabilities.DropCapabilities(container); err != nil {
				writeError("drop caps %s", err)
			}

			if err := exec(cmd.Args[0], cmd.Args[0:], cmd.Env); err != nil {
				writeError("exec %s", err)
			}
			// unreachable
		}
		exit, err := utils.WaitOnPid(child)
		if err != nil {
			writeError("wait on child %s", err)
		}
		os.Exit(exit)
	}
	return nil
}
Beispiel #3
0
func RunIn(containerName string, nsPid int, args []string, env []string) (int, error) {
	container, err := createContainer(containerName, nsPid, args, env)
	if err != nil {
		return -1, fmt.Errorf("error creating container %s", err)
	}

	pid, err := namespaces.ExecIn(container, container.Command)
	if err != nil {
		return -1, fmt.Errorf("error execin container %s", err)
	}
	exitcode, err := utils.WaitOnPid(pid)
	if err != nil {
		return -1, fmt.Errorf("error waiting on child %s", err)
	}
	return exitcode, nil
}
Beispiel #4
0
func JoinContainer(containerName string, nsPid int, args []string, env []string) error {
	container, err := CreateContainer(containerName, nsPid, args, env)
	if err != nil {
		return fmt.Errorf("error creating container %s", err)
	}

	pid, err := namespaces.ExecIn(container, container.Command)
	if err != nil {
		return fmt.Errorf("error exexin container %s", err)
	}
	exitcode, err := utils.WaitOnPid(pid)
	if err != nil {
		return fmt.Errorf("error waiting on child %s", err)
	}
	os.Exit(exitcode)
	return nil
}
Beispiel #5
0
func exec(container *libcontainer.Container, name string) error {
	f, err := os.Open("/root/nsroot/test")
	if err != nil {
		return err
	}
	container.NetNsFd = f.Fd()

	pid, err := namespaces.Exec(container)
	if err != nil {
		return fmt.Errorf("error exec container %s", err)
	}

	container.NsPid = pid
	if displayPid {
		fmt.Println(pid)
	}

	body, err := json.Marshal(container)
	if err != nil {
		return err
	}
	buf := bytes.NewBuffer(nil)
	if err := json.Indent(buf, body, "", "    "); err != nil {
		return err
	}

	f, err = os.OpenFile(name, os.O_RDWR, 0755)
	if err != nil {
		return err
	}
	if _, err := buf.WriteTo(f); err != nil {
		f.Close()
		return err
	}
	f.Close()

	exitcode, err := utils.WaitOnPid(pid)
	if err != nil {
		return fmt.Errorf("error waiting on child %s", err)
	}
	if err := network.DeleteNetworkNamespace("/root/nsroot/test"); err != nil {
		return err
	}
	os.Exit(exitcode)
	return nil
}
Beispiel #6
0
func execIn(container *libcontainer.Container) error {
	f, err := os.Open("/root/nsroot/test")
	if err != nil {
		return err
	}
	container.NetNsFd = f.Fd()
	pid, err := namespaces.ExecIn(container, &libcontainer.Command{
		Env: container.Command.Env,
		Args: []string{
			newCommand,
		},
	})
	if err != nil {
		return fmt.Errorf("error exexin container %s", err)
	}
	exitcode, err := utils.WaitOnPid(pid)
	if err != nil {
		return fmt.Errorf("error waiting on child %s", err)
	}
	os.Exit(exitcode)
	return nil
}
Beispiel #7
0
// RunInNamespace executes the action in the namespace
// specified by the fd passed
func RunInNamespace(fd uintptr, action Action) error {
	pid, err := fork()
	if err != nil {
		return err
	}
	if pid == 0 {
		if err := setns(fd, 0); err != nil {
			writeError("setns %s", err)
		}
		if err := action(); err != nil {
			writeError("action %s", err)
		}
		os.Exit(0)
	}
	exit, err := utils.WaitOnPid(pid)
	if err != nil {
		return err
	}
	if exit != 0 {
		fmt.Errorf("exit status %d", exit)
	}
	return nil
}