github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/stage1_fly/enter/main.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "flag" 19 "fmt" 20 "io/ioutil" 21 "os" 22 "runtime" 23 "syscall" 24 25 "github.com/appc/spec/schema" 26 "github.com/appc/spec/schema/types" 27 "github.com/rkt/rkt/common" 28 rktlog "github.com/rkt/rkt/pkg/log" 29 stage1commontypes "github.com/rkt/rkt/stage1/common/types" 30 stage1initcommon "github.com/rkt/rkt/stage1/init/common" 31 "github.com/rkt/rkt/stage1_fly" 32 ) 33 34 var ( 35 debug bool 36 podPid string 37 appName string 38 39 log *rktlog.Logger 40 diag *rktlog.Logger 41 ) 42 43 func init() { 44 flag.BoolVar(&debug, "debug", false, "Run in debug mode") 45 flag.StringVar(&podPid, "pid", "", "Pod PID") 46 flag.StringVar(&appName, "appname", "", "Application name") 47 48 log, diag, _ = rktlog.NewLogSet("fly-enter", false) 49 } 50 51 func getRootDir(pid string) (string, error) { 52 rootLink := fmt.Sprintf("/proc/%s/root", pid) 53 54 return os.Readlink(rootLink) 55 } 56 57 func getRuntimeApp(pm *schema.PodManifest) (*schema.RuntimeApp, error) { 58 if len(pm.Apps) != 1 { 59 return nil, fmt.Errorf("fly only supports 1 application per Pod for now") 60 } 61 62 return &pm.Apps[0], nil 63 } 64 65 func execArgs(envv []string) error { 66 argv0 := flag.Arg(0) 67 argv := flag.Args() 68 69 return syscall.Exec(argv0, argv, envv) 70 } 71 72 func main() { 73 flag.Parse() 74 75 log.SetDebug(debug) 76 diag.SetDebug(debug) 77 78 if !debug { 79 diag.SetOutput(ioutil.Discard) 80 } 81 82 // lock the current goroutine to its current OS thread. 83 // This will force the subsequent syscalls *made by this goroutine only* 84 // to be executed in the same OS thread as Setresuid, and Setresgid, 85 // see https://github.com/golang/go/issues/1435#issuecomment-66054163. 86 runtime.LockOSThread() 87 88 root, err := getRootDir(podPid) 89 if err != nil { 90 log.FatalE("Failed to get pod root", err) 91 } 92 93 pm, err := stage1commontypes.LoadPodManifest(".") 94 if err != nil { 95 log.FatalE("Failed to load pod manifest", err) 96 } 97 98 ra, err := getRuntimeApp(pm) 99 if err != nil { 100 log.FatalE("Failed to get app", err) 101 } 102 103 // mock up a pod so we can call LookupProcessCredentials 104 pod := &stage1commontypes.Pod{ 105 Root: root, 106 } 107 credentials, err := stage1_fly.LookupProcessCredentials(pod, ra, root) 108 if err != nil { 109 log.FatalE("failed to lookup process credentials", err) 110 } 111 112 cwd, err := os.Getwd() 113 if err != nil { 114 log.FatalE("Failed to get cwd", err) 115 } 116 117 env, err := common.ReadEnvFileRaw(stage1initcommon.EnvFilePath(cwd, types.ACName(appName))) 118 if err != nil { 119 log.FatalE("Failed to read app env", err) 120 } 121 122 if err := os.Chdir(root); err != nil { 123 log.FatalE("Failed to change to new root", err) 124 } 125 126 if err := syscall.Chroot(root); err != nil { 127 log.FatalE("Failed to chroot", err) 128 } 129 130 diag.Printf("setting credentials: %+v", credentials) 131 if err := stage1_fly.SetProcessCredentials(credentials); err != nil { 132 log.FatalE("can't set process credentials", err) 133 } 134 135 diag.Println("PID:", podPid) 136 diag.Println("APP:", appName) 137 diag.Println("ARGS:", flag.Args()) 138 139 if err := execArgs(env); err != nil { 140 log.PrintE("exec failed", err) 141 } 142 143 os.Exit(254) 144 }