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  }