|
@@ -4,169 +4,17 @@ import (
|
|
"encoding/json"
|
|
"encoding/json"
|
|
"flag"
|
|
"flag"
|
|
"fmt"
|
|
"fmt"
|
|
- "github.com/dotcloud/docker/mount"
|
|
|
|
- "github.com/dotcloud/docker/pkg/netlink"
|
|
|
|
- "github.com/dotcloud/docker/utils"
|
|
|
|
- "github.com/syndtr/gocapability/capability"
|
|
|
|
|
|
+ "github.com/dotcloud/docker/execdriver"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"log"
|
|
"log"
|
|
- "net"
|
|
|
|
"os"
|
|
"os"
|
|
- "os/exec"
|
|
|
|
- "strconv"
|
|
|
|
"strings"
|
|
"strings"
|
|
- "syscall"
|
|
|
|
)
|
|
)
|
|
|
|
|
|
-type DockerInitArgs struct {
|
|
|
|
- user string
|
|
|
|
- gateway string
|
|
|
|
- ip string
|
|
|
|
- workDir string
|
|
|
|
- privileged bool
|
|
|
|
- env []string
|
|
|
|
- args []string
|
|
|
|
- mtu int
|
|
|
|
- driver string
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func setupHostname(args *DockerInitArgs) error {
|
|
|
|
- hostname := getEnv(args, "HOSTNAME")
|
|
|
|
- if hostname == "" {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- return setHostname(hostname)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// Setup networking
|
|
|
|
-func setupNetworking(args *DockerInitArgs) error {
|
|
|
|
- if args.ip != "" {
|
|
|
|
- // eth0
|
|
|
|
- iface, err := net.InterfaceByName("eth0")
|
|
|
|
- if err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
- ip, ipNet, err := net.ParseCIDR(args.ip)
|
|
|
|
- if err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
- if err := netlink.NetworkLinkAddIp(iface, ip, ipNet); err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
- if err := netlink.NetworkSetMTU(iface, args.mtu); err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set MTU: %v", err)
|
|
|
|
- }
|
|
|
|
- if err := netlink.NetworkLinkUp(iface); err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // loopback
|
|
|
|
- iface, err = net.InterfaceByName("lo")
|
|
|
|
- if err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
- if err := netlink.NetworkLinkUp(iface); err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if args.gateway != "" {
|
|
|
|
- gw := net.ParseIP(args.gateway)
|
|
|
|
- if gw == nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking, %s is not a valid gateway IP", args.gateway)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := netlink.AddDefaultGw(gw); err != nil {
|
|
|
|
- return fmt.Errorf("Unable to set up networking: %v", err)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// Setup working directory
|
|
|
|
-func setupWorkingDirectory(args *DockerInitArgs) error {
|
|
|
|
- if args.workDir == "" {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- if err := syscall.Chdir(args.workDir); err != nil {
|
|
|
|
- return fmt.Errorf("Unable to change dir to %v: %v", args.workDir, err)
|
|
|
|
- }
|
|
|
|
- return nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func setupMounts(args *DockerInitArgs) error {
|
|
|
|
- return mount.ForceMount("proc", "proc", "proc", "")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// Takes care of dropping privileges to the desired user
|
|
|
|
-func changeUser(args *DockerInitArgs) error {
|
|
|
|
- if args.user == "" {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- userent, err := utils.UserLookup(args.user)
|
|
|
|
- if err != nil {
|
|
|
|
- return fmt.Errorf("Unable to find user %v: %v", args.user, err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- uid, err := strconv.Atoi(userent.Uid)
|
|
|
|
- if err != nil {
|
|
|
|
- return fmt.Errorf("Invalid uid: %v", userent.Uid)
|
|
|
|
- }
|
|
|
|
- gid, err := strconv.Atoi(userent.Gid)
|
|
|
|
- if err != nil {
|
|
|
|
- return fmt.Errorf("Invalid gid: %v", userent.Gid)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := syscall.Setgid(gid); err != nil {
|
|
|
|
- return fmt.Errorf("setgid failed: %v", err)
|
|
|
|
- }
|
|
|
|
- if err := syscall.Setuid(uid); err != nil {
|
|
|
|
- return fmt.Errorf("setuid failed: %v", err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func setupCapabilities(args *DockerInitArgs) error {
|
|
|
|
-
|
|
|
|
- if args.privileged {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- drop := []capability.Cap{
|
|
|
|
- capability.CAP_SETPCAP,
|
|
|
|
- capability.CAP_SYS_MODULE,
|
|
|
|
- capability.CAP_SYS_RAWIO,
|
|
|
|
- capability.CAP_SYS_PACCT,
|
|
|
|
- capability.CAP_SYS_ADMIN,
|
|
|
|
- capability.CAP_SYS_NICE,
|
|
|
|
- capability.CAP_SYS_RESOURCE,
|
|
|
|
- capability.CAP_SYS_TIME,
|
|
|
|
- capability.CAP_SYS_TTY_CONFIG,
|
|
|
|
- capability.CAP_MKNOD,
|
|
|
|
- capability.CAP_AUDIT_WRITE,
|
|
|
|
- capability.CAP_AUDIT_CONTROL,
|
|
|
|
- capability.CAP_MAC_OVERRIDE,
|
|
|
|
- capability.CAP_MAC_ADMIN,
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- c, err := capability.NewPid(os.Getpid())
|
|
|
|
- if err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- c.Unset(capability.CAPS|capability.BOUNDS, drop...)
|
|
|
|
-
|
|
|
|
- if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- return nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
// Clear environment pollution introduced by lxc-start
|
|
// Clear environment pollution introduced by lxc-start
|
|
-func setupEnv(args *DockerInitArgs) {
|
|
|
|
|
|
+func setupEnv(args *execdriver.DockerInitArgs) {
|
|
os.Clearenv()
|
|
os.Clearenv()
|
|
- for _, kv := range args.env {
|
|
|
|
|
|
+ for _, kv := range args.Env {
|
|
parts := strings.SplitN(kv, "=", 2)
|
|
parts := strings.SplitN(kv, "=", 2)
|
|
if len(parts) == 1 {
|
|
if len(parts) == 1 {
|
|
parts = append(parts, "")
|
|
parts = append(parts, "")
|
|
@@ -175,66 +23,18 @@ func setupEnv(args *DockerInitArgs) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func getEnv(args *DockerInitArgs, key string) string {
|
|
|
|
- for _, kv := range args.env {
|
|
|
|
- parts := strings.SplitN(kv, "=", 2)
|
|
|
|
- if parts[0] == key && len(parts) == 2 {
|
|
|
|
- return parts[1]
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return ""
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func executeProgram(args *DockerInitArgs) error {
|
|
|
|
|
|
+func executeProgram(args *execdriver.DockerInitArgs) error {
|
|
setupEnv(args)
|
|
setupEnv(args)
|
|
-
|
|
|
|
- if args.driver == "lxc" {
|
|
|
|
- if err := setupHostname(args); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := setupNetworking(args); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := setupCapabilities(args); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- if err := setupWorkingDirectory(args); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := changeUser(args); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- } else if args.driver == "chroot" {
|
|
|
|
- if err := setupMounts(args); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- defer mount.ForceUnmount("proc")
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- path, err := exec.LookPath(args.args[0])
|
|
|
|
|
|
+ dockerInitFct, err := execdriver.GetDockerInitFct(args.Driver)
|
|
if err != nil {
|
|
if err != nil {
|
|
- log.Printf("Unable to locate %v", args.args[0])
|
|
|
|
- os.Exit(127)
|
|
|
|
|
|
+ panic(err)
|
|
}
|
|
}
|
|
|
|
+ return dockerInitFct(args)
|
|
|
|
|
|
- if args.driver == "lxc" {
|
|
|
|
- if err := syscall.Exec(path, args.args, os.Environ()); err != nil {
|
|
|
|
- panic(err)
|
|
|
|
- }
|
|
|
|
|
|
+ if args.Driver == "lxc" {
|
|
// Will never reach
|
|
// Will never reach
|
|
- } else if args.driver == "chroot" {
|
|
|
|
- cmd := exec.Command(path, args.args[1:]...)
|
|
|
|
-
|
|
|
|
- cmd.Stderr = os.Stderr
|
|
|
|
- cmd.Stdout = os.Stdout
|
|
|
|
- cmd.Stdin = os.Stdin
|
|
|
|
-
|
|
|
|
- return cmd.Run()
|
|
|
|
|
|
+ } else if args.Driver == "chroot" {
|
|
}
|
|
}
|
|
- panic("Should not be here")
|
|
|
|
|
|
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
@@ -271,16 +71,16 @@ func SysInit() {
|
|
// Propagate the plugin-specific container env variable
|
|
// Propagate the plugin-specific container env variable
|
|
env = append(env, "container="+os.Getenv("container"))
|
|
env = append(env, "container="+os.Getenv("container"))
|
|
|
|
|
|
- args := &DockerInitArgs{
|
|
|
|
- user: *user,
|
|
|
|
- gateway: *gateway,
|
|
|
|
- ip: *ip,
|
|
|
|
- workDir: *workDir,
|
|
|
|
- privileged: *privileged,
|
|
|
|
- env: env,
|
|
|
|
- args: flag.Args(),
|
|
|
|
- mtu: *mtu,
|
|
|
|
- driver: *driver,
|
|
|
|
|
|
+ args := &execdriver.DockerInitArgs{
|
|
|
|
+ User: *user,
|
|
|
|
+ Gateway: *gateway,
|
|
|
|
+ Ip: *ip,
|
|
|
|
+ WorkDir: *workDir,
|
|
|
|
+ Privileged: *privileged,
|
|
|
|
+ Env: env,
|
|
|
|
+ Args: flag.Args(),
|
|
|
|
+ Mtu: *mtu,
|
|
|
|
+ Driver: *driver,
|
|
}
|
|
}
|
|
|
|
|
|
if err := executeProgram(args); err != nil {
|
|
if err := executeProgram(args); err != nil {
|