// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package impl

// The app invoker is responsible for managing the state of applications on the
// device manager.  The device manager manages the applications it installs and
// runs using the following directory structure.  Permissions and owners are
// noted as parentheses enclosed octal perms with an 'a' or 'd' suffix for app
// or device manager respectively.  For example: (755d)
//
// TODO(caprita): Not all is yet implemented.
//
// <config.Root>(711d)/
//   app-<hash 1>(711d)/                  - the application dir is named using a hash of the application title
//     installation-<id 1>(711d)/         - installations are labelled with ids
//       acls(700d)/
//         data(700d)                     - the AccessList data for this
//                                          installation. Controls access to
//                                          Instantiate, Uninstall, Update,
//                                          UpdateTo and Revert.
//         signature(700d)                - the signature for the AccessLists in data
//       <status>(700d)                   - one of the values for InstallationState enum
//       origin(700d)                     - object name for application envelope
//       config(700d)                     - Config provided by the installer
//       packages(700d)                   - set of packages specified by the installer
//       pkg(700d)/                       - downloaded packages
//         <pkg name>(700d)
//         <pkg name>.__info(700d)
//         ...
//       <version 1 timestamp>(711d)/     - timestamp of when the version was downloaded
//         bin(755d)                      - application binary
//         previous                       - symbolic link to previous version directory
//         envelope                       - application envelope (JSON-encoded)
//         packages(755d)/                - installed packages (from envelope+installer)
//           <pkg name>(755d)/
//           ...
//       <version 2 timestamp>(711d)
//       ...
//       current                          - symbolic link to the current version
//       instances(711d)/
//         instance-<id a>(711d)/         - instances are labelled with ids
//           credentials(700d)/           - holds vanadium credentials (unless running
//                                          through security agent)
//           root(700a)/                  - workspace that the instance is run from
//             packages                   - symbolic link to version's packages
//           logs(755a)/                  - stderr/stdout and log files generated by instance
//           info(700d)                   - metadata for the instance (such as app
//                                          cycle manager name and process id)
//           installation                 - symbolic link to installation for the instance
//           version                      - symbolic link to installation version for the instance
//           acls(700d)/
//             data(700d)                 - the AccessLists for this instance. These
//                                          AccessLists control access to Run,
//                                          Kill and Delete.
//             signature(700d)            - the signature for these AccessLists.
//           <status>(700d)               - one of the values for InstanceState enum
//           systemname(700d)             - the system name used to execute this instance
//           debugacls (711d)/
//             data(644)/                 - the Permissions for Debug access to the application. Shared
//                                          with the application.
//             signature(644)/            - the signature for these Permissions.
//         instance-<id b>(711d)
//         ...
//     installation-<id 2>(711d)
//     ...
//   app-<hash 2>(711d)
//   ...
//
// The device manager uses the suid helper binary to invoke an application as a
// specified user.  The path to the helper is specified as config.Helper.

// When device manager starts up, it goes through all instances and launches the
// ones that are not running.  If an instance fails to launch, it stays not
// running.
//
// Instantiate creates an instance.  Run launches the process.  Kill kills the
// process but leaves the workspace untouched.  Delete prevents future launches
// (it also eventually gc's the workspace, logs, and other instance state).
//
// If the process dies on its own, it stays dead and is assumed not running.
// TODO(caprita): Later, we'll add auto-restart option.
//
// Concurrency model: installations can be created independently of one another;
// installations can be removed at any time (TODO(caprita): ensure all instances
// are Deleted).  The first call to Uninstall will rename the installation dir
// as a first step; subsequent Uninstall's will fail.  Instances can be created
// independently of one another, as long as the installation exists (if it gets
// Uninstall'ed during a Instantiate, the Instantiate call may fail).
//
// The status file present in each instance is used to flag the state of the
// instance and prevent concurrent operations against the instance:
//
// - when an instance is created with Instantiate, it is placed in state
// 'not-running'.
//
// - Run attempts to transition from 'not-running' to 'launching' (if the
// instance was not in 'not-running' state, Run fails).  From 'launching', the
// instance transitions to 'running' upon success or back to 'not-running' upon
// failure.
//
// - Kill attempts to transition from 'running' to 'dying' (if the
// instance was not in 'running' state, Kill fails).  From 'dying', the
// instance transitions to 'not-running' upon success or back to 'running' upon
// failure.
//
// - Delete transitions from 'not-running' to 'deleted'.  If the initial
// state is not 'not-running', Delete fails.
//
// TODO(caprita): There is room for synergy between how device manager organizes
// its own workspace and that for the applications it runs.  In particular,
// previous, origin, and envelope could be part of a single config.  We'll
// refine that later.

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/services/appcycle"
	"v.io/v23/services/application"
	"v.io/v23/services/device"
	"v.io/v23/verror"
	"v.io/x/ref"
	vexec "v.io/x/ref/lib/exec"
	"v.io/x/ref/lib/mgmt"
	vsecurity "v.io/x/ref/lib/security"
	"v.io/x/ref/services/agent/agentlib"
	"v.io/x/ref/services/agent/keymgr"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/device/internal/errors"
	"v.io/x/ref/services/internal/packages"
	"v.io/x/ref/services/internal/pathperms"
)

// instanceInfo holds state about a running instance.
type instanceInfo struct {
	AppCycleMgrName          string
	Pid                      int
	DeviceManagerPeerPattern string
	SecurityAgentHandle      []byte
	Restarts                 int32
	RestartWindowBegan       time.Time
}

func saveInstanceInfo(ctx *context.T, dir string, info *instanceInfo) error {
	jsonInfo, err := json.Marshal(info)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Marshal(%v) failed: %v", info, err))
	}
	infoPath := filepath.Join(dir, "info")
	if err := ioutil.WriteFile(infoPath, jsonInfo, 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WriteFile(%v) failed: %v", infoPath, err))
	}
	return nil
}

func loadInstanceInfo(ctx *context.T, dir string) (*instanceInfo, error) {
	infoPath := filepath.Join(dir, "info")
	info := new(instanceInfo)
	if infoBytes, err := ioutil.ReadFile(infoPath); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("ReadFile(%v) failed: %v", infoPath, err))
	} else if err := json.Unmarshal(infoBytes, info); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Unmarshal(%v) failed: %v", infoBytes, err))
	}
	return info, nil
}

type securityAgentState struct {
	// Security agent key manager client.
	keyMgrAgent *keymgr.Agent
}

// appRunner is the subset of the appService object needed to
// (re)start an application.
type appRunner struct {
	callback *callbackState
	// securityAgent holds state related to the security agent (nil if not
	// using the agent).
	securityAgent *securityAgentState
	// reap is the app process monitoring subsystem.
	reap *reaper
	// mtAddress is the address of the local mounttable.
	mtAddress string
	// appServiceName is a name by which the appService can be reached
	appServiceName string
}

// appService implements the Device manager's Application interface.
type appService struct {
	config *config.State
	// suffix contains the name components of the current invocation name
	// suffix.  It is used to identify an application, installation, or
	// instance.
	suffix     []string
	uat        BlessingSystemAssociationStore
	permsStore *pathperms.PathStore
	// Reference to the devicemanager top-level AccessList list.
	deviceAccessList access.Permissions
	// State needed to (re)start an application.
	runner *appRunner
}

func saveEnvelope(ctx *context.T, dir string, envelope *application.Envelope) error {
	jsonEnvelope, err := json.Marshal(envelope)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Marshal(%v) failed: %v", envelope, err))
	}
	path := filepath.Join(dir, "envelope")
	if err := ioutil.WriteFile(path, jsonEnvelope, 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WriteFile(%v) failed: %v", path, err))
	}
	return nil
}

func loadEnvelope(ctx *context.T, dir string) (*application.Envelope, error) {
	path := filepath.Join(dir, "envelope")
	envelope := new(application.Envelope)
	if envelopeBytes, err := ioutil.ReadFile(path); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("ReadFile(%v) failed: %v", path, err))
	} else if err := json.Unmarshal(envelopeBytes, envelope); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Unmarshal(%v) failed: %v", envelopeBytes, err))
	}
	return envelope, nil
}

func loadEnvelopeForInstance(ctx *context.T, instanceDir string) (*application.Envelope, error) {
	versionLink := filepath.Join(instanceDir, "version")
	versionDir, err := filepath.EvalSymlinks(versionLink)
	if err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
	}
	return loadEnvelope(ctx, versionDir)
}

func saveConfig(ctx *context.T, dir string, config device.Config) error {
	jsonConfig, err := json.Marshal(config)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Marshal(%v) failed: %v", config, err))
	}
	path := filepath.Join(dir, "config")
	if err := ioutil.WriteFile(path, jsonConfig, 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WriteFile(%v) failed: %v", path, err))
	}
	return nil
}

func loadConfig(ctx *context.T, dir string) (device.Config, error) {
	path := filepath.Join(dir, "config")
	var config device.Config
	if configBytes, err := ioutil.ReadFile(path); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("ReadFile(%v) failed: %v", path, err))
	} else if err := json.Unmarshal(configBytes, &config); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Unmarshal(%v) failed: %v", configBytes, err))
	}
	return config, nil
}

func savePackages(ctx *context.T, dir string, packages application.Packages) error {
	jsonPackages, err := json.Marshal(packages)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Marshal(%v) failed: %v", packages, err))
	}
	path := filepath.Join(dir, "packages")
	if err := ioutil.WriteFile(path, jsonPackages, 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WriteFile(%v) failed: %v", path, err))
	}
	return nil
}

func loadPackages(ctx *context.T, dir string) (application.Packages, error) {
	path := filepath.Join(dir, "packages")
	var packages application.Packages
	if packagesBytes, err := ioutil.ReadFile(path); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("ReadFile(%v) failed: %v", path, err))
	} else if err := json.Unmarshal(packagesBytes, &packages); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Unmarshal(%v) failed: %v", packagesBytes, err))
	}
	return packages, nil
}

func saveOrigin(ctx *context.T, dir, originVON string) error {
	path := filepath.Join(dir, "origin")
	if err := ioutil.WriteFile(path, []byte(originVON), 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WriteFile(%v) failed: %v", path, err))
	}
	return nil
}

func loadOrigin(ctx *context.T, dir string) (string, error) {
	path := filepath.Join(dir, "origin")
	if originBytes, err := ioutil.ReadFile(path); err != nil {
		return "", verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("ReadFile(%v) failed: %v", path, err))
	} else {
		return string(originBytes), nil
	}
}

// generateID returns a new unique id string.  The uniqueness is based on the
// current timestamp.  Not cryptographically secure.
func generateID() string {
	const timeFormat = "20060102-15:04:05.0000"
	return time.Now().UTC().Format(timeFormat)
}

// generateRandomString returns a cryptographically-strong random string.
func generateRandomString() (string, error) {
	b := make([]byte, 16)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(b), nil
}

// TODO(caprita): Nothing prevents different applications from sharing the same
// title, and thereby being installed in the same app dir.  Do we want to
// prevent that for the same user or across users?

const (
	appDirPrefix       = "app-"
	installationPrefix = "installation-"
	instancePrefix     = "instance-"
)

// applicationDirName generates a cryptographic hash of the application title,
// to be used as a directory name for installations of the application with the
// given title.
func applicationDirName(title string) string {
	h := md5.New()
	h.Write([]byte(title))
	hash := strings.TrimRight(base64.URLEncoding.EncodeToString(h.Sum(nil)), "=")
	return appDirPrefix + hash
}

func installationDirName(installationID string) string {
	return installationPrefix + installationID
}

func instanceDirName(instanceID string) string {
	return instancePrefix + instanceID
}

func mkdir(ctx *context.T, dir string) error {
	return mkdirPerm(ctx, dir, 0700)
}

func mkdirPerm(ctx *context.T, dir string, permissions int) error {
	perm := os.FileMode(permissions)
	if err := os.MkdirAll(dir, perm); err != nil {
		ctx.Errorf("MkdirAll(%v, %v) failed: %v", dir, perm, err)
		return err
	}
	return nil
}

func fetchAppEnvelope(ctx *context.T, origin string) (*application.Envelope, error) {
	envelope, err := fetchEnvelope(ctx, origin)
	if err != nil {
		return nil, err
	}
	if envelope.Title == application.DeviceManagerTitle {
		// Disallow device manager apps from being installed like a
		// regular app.
		return nil, verror.New(errors.ErrInvalidOperation, ctx, "DeviceManager apps cannot be installed")
	}
	return envelope, nil
}

// newVersion sets up the directory for a new application version.
func newVersion(ctx *context.T, installationDir string, envelope *application.Envelope, oldVersionDir string) (string, error) {
	versionDir := filepath.Join(installationDir, generateVersionDirName())
	if err := mkdirPerm(ctx, versionDir, 0711); err != nil {
		return "", verror.New(errors.ErrOperationFailed, ctx, err)
	}
	if err := saveEnvelope(ctx, versionDir, envelope); err != nil {
		return versionDir, err
	}
	pkgDir := filepath.Join(versionDir, "pkg")
	if err := mkdir(ctx, pkgDir); err != nil {
		return "", verror.New(errors.ErrOperationFailed, ctx, err)
	}
	publisher := envelope.Publisher
	// TODO(caprita): Share binaries if already existing locally.
	if err := downloadBinary(ctx, publisher, &envelope.Binary, versionDir, "bin"); err != nil {
		return versionDir, err
	}
	if err := downloadPackages(ctx, publisher, envelope.Packages, pkgDir); err != nil {
		return versionDir, err
	}
	if err := installPackages(ctx, installationDir, versionDir); err != nil {
		return versionDir, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("installPackages(%v, %v) failed: %v", installationDir, versionDir, err))
	}
	if err := os.RemoveAll(pkgDir); err != nil {
		return versionDir, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("RemoveAll(%v) failed: %v", pkgDir, err))
	}
	if oldVersionDir != "" {
		previousLink := filepath.Join(versionDir, "previous")
		if err := os.Symlink(oldVersionDir, previousLink); err != nil {
			return versionDir, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Symlink(%v, %v) failed: %v", oldVersionDir, previousLink, err))
		}
	}
	// UpdateLink should be the last thing we do, after we've ensured the
	// new version is viable (currently, that just means it installs
	// properly).
	return versionDir, UpdateLink(versionDir, filepath.Join(installationDir, "current"))
}

func (i *appService) Install(ctx *context.T, call rpc.ServerCall, applicationVON string, config device.Config, packages application.Packages) (string, error) {
	if len(i.suffix) > 0 {
		return "", verror.New(errors.ErrInvalidSuffix, ctx)
	}
	ctx, cancel := context.WithTimeout(ctx, rpcContextLongTimeout)
	defer cancel()
	envelope, err := fetchAppEnvelope(ctx, applicationVON)
	if err != nil {
		return "", err
	}
	installationID := generateID()
	installationDir := filepath.Join(i.config.Root, applicationDirName(envelope.Title), installationDirName(installationID))
	deferrer := func() {
		CleanupDir(ctx, installationDir, "")
	}
	if err := mkdirPerm(ctx, installationDir, 0711); err != nil {
		return "", verror.New(errors.ErrOperationFailed, nil)
	}
	defer func() {
		if deferrer != nil {
			deferrer()
		}
	}()
	if newOrigin, ok := config[mgmt.AppOriginConfigKey]; ok {
		delete(config, mgmt.AppOriginConfigKey)
		applicationVON = newOrigin
	}
	if err := saveOrigin(ctx, installationDir, applicationVON); err != nil {
		return "", err
	}
	if err := saveConfig(ctx, installationDir, config); err != nil {
		return "", err
	}
	if err := savePackages(ctx, installationDir, packages); err != nil {
		return "", err
	}
	pkgDir := filepath.Join(installationDir, "pkg")
	if err := mkdir(ctx, pkgDir); err != nil {
		return "", verror.New(errors.ErrOperationFailed, ctx, err)
	}
	// We use a zero value publisher, meaning that any signatures present in the
	// package files are not verified.
	// TODO(caprita): Issue warnings when signatures are present and ignored.
	if err := downloadPackages(ctx, security.Blessings{}, packages, pkgDir); err != nil {
		return "", err
	}
	if _, err := newVersion(ctx, installationDir, envelope, ""); err != nil {
		return "", err
	}
	// TODO(caprita,rjkroege): Should the installation AccessLists really be
	// seeded with the device AccessList? Instead, might want to hide the deviceAccessList
	// from the app?
	blessings, _ := security.RemoteBlessingNames(ctx, call.Security())
	if err := i.initializeSubAccessLists(installationDir, blessings, i.deviceAccessList.Copy()); err != nil {
		return "", err
	}
	if err := initializeInstallation(installationDir, device.InstallationStateActive); err != nil {
		return "", err
	}
	deferrer = nil
	// TODO(caprita): Using the title without cleaning out slashes
	// introduces extra name components that mess up the device manager's
	// apps object space.  We should fix this either by santizing the title,
	// or disallowing slashes in titles to begin with.
	return naming.Join(envelope.Title, installationID), nil
}

func openWriteFile(path string) (*os.File, error) {
	perm := os.FileMode(0644)
	return os.OpenFile(path, os.O_WRONLY|os.O_CREATE, perm)
}

// TODO(gauthamt): Make sure we pass the context to installationDirCore.
func installationDirCore(components []string, root string) (string, error) {
	if nComponents := len(components); nComponents != 2 {
		return "", verror.New(errors.ErrInvalidSuffix, nil)
	}
	app, installation := components[0], components[1]
	installationDir := filepath.Join(root, applicationDirName(app), installationDirName(installation))
	if _, err := os.Stat(installationDir); err != nil {
		if os.IsNotExist(err) {
			return "", verror.New(verror.ErrNoExist, nil, naming.Join(components...))
		}
		return "", verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Stat(%v) failed: %v", installationDir, err))
	}
	return installationDir, nil
}

// agentPrincipal creates a Principal backed by the given agent connection,
// taking ownership of the connection.  The returned cancel function is to be
// called when the Principal is no longer in use.
func agentPrincipal(ctx *context.T, conn *os.File) (security.Principal, func(), error) {
	agentctx, cancel := context.WithCancel(ctx)
	var err error
	if agentctx, err = v23.WithNewStreamManager(agentctx); err != nil {
		cancel()
		conn.Close()
		return nil, nil, err
	}
	// TODO: This should use the same network as the agent we're using,
	// not whatever this process was compiled with.
	ep, err := v23.NewEndpoint(agentlib.AgentEndpoint(int(conn.Fd())))
	if err != nil {
		cancel()
		conn.Close()
		return nil, nil, err
	}
	p, err := agentlib.NewAgentPrincipal(agentctx, ep, v23.GetClient(agentctx))
	if err != nil {
		cancel()
		conn.Close()
		return nil, nil, err
	}
	conn.Close()
	return p, cancel, nil
}

// setupPrincipal sets up the instance's principal, with the right blessings.
func setupPrincipal(ctx *context.T, instanceDir string, call device.ApplicationInstantiateServerCall, securityAgent *securityAgentState, info *instanceInfo) error {
	var p security.Principal
	if securityAgent != nil {
		// TODO(caprita): Part of the cleanup upon destroying an
		// instance, we should tell the agent to drop the principal.
		handle, conn, err := securityAgent.keyMgrAgent.NewPrincipal(ctx, false)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("NewPrincipal() failed %v", err))
		}
		var cancel func()
		if p, cancel, err = agentPrincipal(ctx, conn); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("agentPrincipal failed: %v", err))
		}
		defer cancel()
		info.SecurityAgentHandle = handle
		// conn will be closed when the connection to the agent is shut
		// down, as a result of cancel() shutting down the stream
		// manager.  No need to call conn.Close().
	} else {
		credentialsDir := filepath.Join(instanceDir, "credentials")
		// TODO(caprita): The app's system user id needs access to this dir.
		// Use the suidhelper to chown it.
		var err error
		if p, err = vsecurity.CreatePersistentPrincipal(credentialsDir, nil); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("CreatePersistentPrincipal(%v, nil) failed: %v", credentialsDir, err))
		}
	}
	mPubKey, err := p.PublicKey().MarshalBinary()
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("PublicKey().MarshalBinary() failed: %v", err))
	}
	if err := call.SendStream().Send(device.BlessServerMessageInstancePublicKey{Value: mPubKey}); err != nil {
		return err
	}
	if !call.RecvStream().Advance() {
		return verror.New(errors.ErrInvalidBlessing, ctx, fmt.Sprintf("no blessings on stream: %v", call.RecvStream().Err()))
	}
	msg := call.RecvStream().Value()
	appBlessingsFromInstantiator, ok := msg.(device.BlessClientMessageAppBlessings)
	if !ok {
		return verror.New(errors.ErrInvalidBlessing, ctx, fmt.Sprintf("wrong message type: %#v", msg))
	}
	// Should we move this after the addition of publisher blessings, and thus allow
	// apps to run with only publisher blessings?
	if appBlessingsFromInstantiator.Value.IsZero() {
		return verror.New(errors.ErrInvalidBlessing, ctx)
	}
	if err := p.BlessingStore().SetDefault(appBlessingsFromInstantiator.Value); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.SetDefault() failed: %v", err))
	}
	// If there were any publisher blessings in the envelope, add those to the set of blessings
	// sent to servers by default
	appBlessings, err := addPublisherBlessings(ctx, instanceDir, p, appBlessingsFromInstantiator.Value)
	if _, err := p.BlessingStore().Set(appBlessings, security.AllPrincipals); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.Set() failed: %v", err))
	}
	if err := p.AddToRoots(appBlessings); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("AddToRoots() failed: %v", err))
	}
	// In addition, we give the app separate blessings for the purpose of
	// communicating with the device manager.
	//
	// NOTE(caprita/ataly): Giving the app an unconstrained blessing from
	// the device manager's default presents the app with a blessing that's
	// potentially more powerful than what is strictly needed to allow
	// communication between device manager and app (which could be more
	// narrowly accomplished by using a custom-purpose self-signed blessing
	// that the device manger produces solely to talk to the app).
	dmPrincipal := v23.GetPrincipal(ctx)
	dmBlessings, err := dmPrincipal.Bless(p.PublicKey(), dmPrincipal.BlessingStore().Default(), "callback", security.UnconstrainedUse())
	// Put the names of the device manager's default blessings as patterns
	// for the child, so that the child uses the right blessing when talking
	// back to the device manager.
	for n, _ := range dmPrincipal.BlessingsInfo(dmPrincipal.BlessingStore().Default()) {
		if _, err := p.BlessingStore().Set(dmBlessings, security.BlessingPattern(n)); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.Set() failed: %v", err))
		}
	}
	// We also want to override the app cycle manager's server blessing in
	// the child (so that the device manager can send RPCs to it).  We
	// signal to the child's app manager to use a randomly generated pattern
	// to extract the right blessing to use from its store for this purpose.
	randomPattern, err := generateRandomString()
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("generateRandomString() failed: %v", err))
	}
	if _, err := p.BlessingStore().Set(dmBlessings, security.BlessingPattern(randomPattern)); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.Set() failed: %v", err))
	}
	info.DeviceManagerPeerPattern = randomPattern
	if err := p.AddToRoots(dmBlessings); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("AddToRoots() failed: %v", err))
	}
	return nil
}

func addPublisherBlessings(ctx *context.T, instanceDir string, p security.Principal, b security.Blessings) (security.Blessings, error) {
	// Load the envelope for the instance, and get the publisher blessings in it
	envelope, err := loadEnvelopeForInstance(ctx, instanceDir)
	if err != nil {
		return security.Blessings{}, err
	}

	// Extend the device manager blessing with each publisher blessing provided
	dmPrincipal := v23.GetPrincipal(ctx)

	blessings, _ := publisherBlessingNames(ctx, *envelope)
	for _, s := range blessings {
		ctx.VI(2).Infof("adding publisher blessing %v for app %v", s, envelope.Title)
		tmpBlessing, err := dmPrincipal.Bless(p.PublicKey(), dmPrincipal.BlessingStore().Default(), "a/"+s, security.UnconstrainedUse())
		if b, err = security.UnionOfBlessings(b, tmpBlessing); err != nil {
			return b, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("UnionOfBlessings failed: %v %v", b, tmpBlessing))
		}
	}

	return b, nil
}

// installationDir returns the path to the directory containing the app
// installation referred to by the invoker's suffix.  Returns an error if the
// suffix does not name an installation or if the named installation does not
// exist.
func (i *appService) installationDir() (string, error) {
	return installationDirCore(i.suffix, i.config.Root)
}

// installPackages installs all the packages for a new version.
func installPackages(ctx *context.T, installationDir, versionDir string) error {
	overridePackages, err := loadPackages(ctx, installationDir)
	if err != nil {
		return err
	}
	envelope, err := loadEnvelope(ctx, versionDir)
	if err != nil {
		return err
	}
	for pkg, _ := range overridePackages {
		delete(envelope.Packages, pkg)
	}
	packagesDir := filepath.Join(versionDir, "packages")
	if err := os.MkdirAll(packagesDir, os.FileMode(0755)); err != nil {
		return err
	}
	installFrom := func(pkgs application.Packages, sourceDir string) error {
		for pkg, _ := range pkgs {
			pkgFile := filepath.Join(sourceDir, "pkg", pkg)
			dst := filepath.Join(packagesDir, pkg)
			if err := packages.Install(pkgFile, dst); err != nil {
				return err
			}
		}
		return nil
	}
	if err := installFrom(envelope.Packages, versionDir); err != nil {
		return err
	}
	return installFrom(overridePackages, installationDir)
}

// initializeSubAccessLists updates the provided perms for instance-specific
// Permissions.
func (i *appService) initializeSubAccessLists(instanceDir string, blessings []string, perms access.Permissions) error {
	for _, b := range blessings {
		b = b + string(security.ChainSeparator) + string(security.NoExtension)
		for _, tag := range access.AllTypicalTags() {
			perms.Add(security.BlessingPattern(b), string(tag))
		}
	}
	permsDir := path.Join(instanceDir, "acls")
	return i.permsStore.Set(permsDir, perms, "")
}

func (i *appService) newInstance(ctx *context.T, call device.ApplicationInstantiateServerCall) (string, string, error) {
	installationDir, err := i.installationDir()
	if err != nil {
		return "", "", err
	}
	if !installationStateIs(installationDir, device.InstallationStateActive) {
		return "", "", verror.New(errors.ErrInvalidOperation, ctx)
	}
	instanceID := generateID()
	instanceDir := filepath.Join(installationDir, "instances", instanceDirName(instanceID))
	// Set permissions for app to have access.
	if mkdirPerm(ctx, instanceDir, 0711) != nil {
		return "", "", verror.New(errors.ErrOperationFailed, ctx)
	}
	rootDir := filepath.Join(instanceDir, "root")
	if err := mkdir(ctx, rootDir); err != nil {
		return instanceDir, instanceID, verror.New(errors.ErrOperationFailed, ctx, err)
	}
	installationLink := filepath.Join(instanceDir, "installation")
	if err := os.Symlink(installationDir, installationLink); err != nil {
		return instanceDir, instanceID, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Symlink(%v, %v) failed: %v", installationDir, installationLink, err))
	}
	currLink := filepath.Join(installationDir, "current")
	versionDir, err := filepath.EvalSymlinks(currLink)
	if err != nil {
		return instanceDir, instanceID, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", currLink, err))
	}
	versionLink := filepath.Join(instanceDir, "version")
	if err := os.Symlink(versionDir, versionLink); err != nil {
		return instanceDir, instanceID, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Symlink(%v, %v) failed: %v", versionDir, versionLink, err))
	}
	packagesDir, packagesLink := filepath.Join(versionLink, "packages"), filepath.Join(rootDir, "packages")
	if err := os.Symlink(packagesDir, packagesLink); err != nil {
		return instanceDir, instanceID, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Symlink(%v, %v) failed: %v", packagesDir, packagesLink, err))
	}
	instanceInfo := new(instanceInfo)
	if err := setupPrincipal(ctx, instanceDir, call, i.runner.securityAgent, instanceInfo); err != nil {
		return instanceDir, instanceID, err
	}
	if err := saveInstanceInfo(ctx, instanceDir, instanceInfo); err != nil {
		return instanceDir, instanceID, err
	}
	blessings, _ := security.RemoteBlessingNames(ctx, call.Security())
	permsCopy := i.deviceAccessList.Copy()
	if err := i.initializeSubAccessLists(instanceDir, blessings, permsCopy); err != nil {
		return instanceDir, instanceID, err
	}
	if err := initializeInstance(instanceDir, device.InstanceStateNotRunning); err != nil {
		return instanceDir, instanceID, err
	}
	// TODO(rjkroege): Divide the permission lists into those used by the device manager
	// and those used by the application itself.
	dmBlessings := security.LocalBlessingNames(ctx, call.Security())
	if err := setPermsForDebugging(dmBlessings, permsCopy, instanceDir, i.permsStore); err != nil {
		return instanceDir, instanceID, err
	}
	return instanceDir, instanceID, nil
}

func genCmd(ctx *context.T, instanceDir string, nsRoot string) (*exec.Cmd, error) {
	systemName, err := readSystemNameForInstance(instanceDir)
	if err != nil {
		return nil, err
	}

	versionLink := filepath.Join(instanceDir, "version")
	versionDir, err := filepath.EvalSymlinks(versionLink)
	if err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
	}
	envelope, err := loadEnvelope(ctx, versionDir)
	if err != nil {
		return nil, err
	}
	binPath := filepath.Join(versionDir, "bin")
	if _, err := os.Stat(binPath); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Stat(%v) failed: %v", binPath, err))
	}

	saArgs := suidAppCmdArgs{targetUser: systemName, binpath: binPath}

	// Pass the displayed name of the program (argv0 as seen in ps output)
	// Envelope data comes from the user so we sanitize it for safety
	_, relativeBinaryName := naming.SplitAddressName(envelope.Binary.File)
	rawAppName := envelope.Title + "@" + relativeBinaryName + "/app"
	sanitize := func(r rune) rune {
		if strconv.IsPrint(r) {
			return r
		} else {
			return '_'
		}
	}
	appName := strings.Map(sanitize, rawAppName)
	saArgs.progname = appName

	// Set the app's default namespace root to the local namespace.
	saArgs.env = []string{ref.EnvNamespacePrefix + "=" + nsRoot}
	saArgs.env = append(saArgs.env, envelope.Env...)
	rootDir := filepath.Join(instanceDir, "root")
	saArgs.dir = rootDir
	saArgs.workspace = rootDir

	logDir := filepath.Join(instanceDir, "logs")
	suidHelper.chownTree(ctx, suidHelper.getCurrentUser(), instanceDir, os.Stdout, os.Stdin)
	if err := mkdirPerm(ctx, logDir, 0755); err != nil {
		return nil, err
	}
	saArgs.logdir = logDir
	timestamp := time.Now().UnixNano()

	stdoutLog := filepath.Join(logDir, fmt.Sprintf("STDOUT-%d", timestamp))
	if saArgs.stdout, err = openWriteFile(stdoutLog); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("OpenFile(%v) failed: %v", stdoutLog, err))
	}
	stderrLog := filepath.Join(logDir, fmt.Sprintf("STDERR-%d", timestamp))
	if saArgs.stderr, err = openWriteFile(stderrLog); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("OpenFile(%v) failed: %v", stderrLog, err))
	}

	// Args to be passed by helper to the app.
	appArgs := []string{"--log_dir=../logs"}
	appArgs = append(appArgs, envelope.Args...)

	saArgs.appArgs = appArgs
	return suidHelper.getAppCmd(ctx, &saArgs)
}

// instanceNameFromDir returns the instance name, given the instanceDir.
func instanceNameFromDir(ctx *context.T, instanceDir string) (string, error) {
	_, _, installation, instance := parseInstanceDir(instanceDir)
	if installation == "" || instance == "" {
		return "", fmt.Errorf("Unable to parse instanceDir %v", instanceDir)
	}

	env, err := loadEnvelopeForInstance(ctx, instanceDir)
	if err != nil {
		return "", err
	}
	return env.Title + "/" + installation + "/" + instance, nil
}

func (i *appRunner) startCmd(ctx *context.T, instanceDir string, cmd *exec.Cmd) (int, error) {
	info, err := loadInstanceInfo(ctx, instanceDir)
	if err != nil {
		return 0, err
	}
	// Setup up the child process callback.
	callbackState := i.callback
	listener := callbackState.listenFor(mgmt.AppCycleManagerConfigKey)
	defer listener.cleanup()
	cfg := vexec.NewConfig()
	installationLink := filepath.Join(instanceDir, "installation")
	installationDir, err := filepath.EvalSymlinks(installationLink)
	if err != nil {
		return 0, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", installationLink, err))
	}
	config, err := loadConfig(ctx, installationDir)
	if err != nil {
		return 0, err
	}
	for k, v := range config {
		cfg.Set(k, v)
	}
	cfg.Set(mgmt.ParentNameConfigKey, listener.name())
	cfg.Set(mgmt.ProtocolConfigKey, "tcp")
	cfg.Set(mgmt.AddressConfigKey, "127.0.0.1:0")
	cfg.Set(mgmt.ParentBlessingConfigKey, info.DeviceManagerPeerPattern)
	cfg.Set(mgmt.PublisherBlessingPrefixesKey,
		v23.GetPrincipal(ctx).BlessingStore().Default().String())

	if instanceName, err := instanceNameFromDir(ctx, instanceDir); err != nil {
		return 0, err
	} else {
		cfg.Set(mgmt.InstanceNameKey, naming.Join(i.appServiceName, instanceName))
	}

	appPermsDir := filepath.Join(instanceDir, "debugacls", "data")
	cfg.Set("v23.permissions.file", "runtime:"+appPermsDir)

	// This adds to cmd.Extrafiles. The helper expects a fixed fd, so this call needs
	// to go before anything that conditionally adds to Extrafiles, like the agent
	// setup code immediately below.
	var handshaker appHandshaker
	handshaker.prepareToStart(ctx, cmd)
	defer handshaker.cleanup()

	// Set up any agent-specific state.
	// NOTE(caprita): This ought to belong in genCmd.
	var agentCleaner func()
	if sa := i.securityAgent; sa != nil {
		file, err := sa.keyMgrAgent.NewConnection(info.SecurityAgentHandle)
		if err != nil {
			ctx.Errorf("NewConnection(%v) failed: %v", info.SecurityAgentHandle, err)
			return 0, err
		}
		agentCleaner = func() {
			file.Close()
		}
		// We need to account for the file descriptors corresponding to
		// std{err|out|in} as well as the implementation-specific pipes
		// that the vexec library adds to ExtraFiles during
		// handle.Start.  vexec.FileOffset properly offsets fd
		// accordingly.
		fd := len(cmd.ExtraFiles) + vexec.FileOffset
		cmd.ExtraFiles = append(cmd.ExtraFiles, file)
		ep := agentlib.AgentEndpoint(fd)
		cfg.Set(mgmt.SecurityAgentEndpointConfigKey, ep)
	} else {
		cmd.Env = append(cmd.Env, ref.EnvCredentials+"="+filepath.Join(instanceDir, "credentials"))
	}
	handle := vexec.NewParentHandle(cmd, vexec.ConfigOpt{Config: cfg})
	defer func() {
		if handle != nil {
			if err := handle.Clean(); err != nil {
				ctx.Errorf("Clean() failed: %v", err)
			}
		}
	}()

	// Start the child process.
	startErr := handle.Start()
	// Perform unconditional cleanup before dealing with any error from
	// handle.Start()
	if agentCleaner != nil {
		agentCleaner()
	}
	// Now react to any error in handle.Start()
	if startErr != nil {
		return 0, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Start() failed: %v", err))
	}

	// Wait for the suidhelper to exit. This is blocking as we assume the
	// helper won't get stuck.
	if err := handle.Wait(0); err != nil {
		return 0, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Wait() on suidhelper failed: %v", err))
	}

	pid, childName, err := handshaker.doHandshake(ctx, handle, listener)

	if err != nil {
		return 0, err
	}

	info.AppCycleMgrName, info.Pid = childName, pid
	if err := saveInstanceInfo(ctx, instanceDir, info); err != nil {
		return 0, err
	}
	handle = nil
	return pid, nil
}

func (i *appRunner) run(ctx *context.T, instanceDir string) error {
	if err := transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateLaunching); err != nil {
		return err
	}
	var pid int

	cmd, err := genCmd(ctx, instanceDir, i.mtAddress)
	if err == nil {
		pid, err = i.startCmd(ctx, instanceDir, cmd)
	}
	if err != nil {
		transitionInstance(instanceDir, device.InstanceStateLaunching, device.InstanceStateNotRunning)
		return err
	}
	if err := transitionInstance(instanceDir, device.InstanceStateLaunching, device.InstanceStateRunning); err != nil {
		return err
	}
	i.reap.startWatching(instanceDir, pid)
	return nil
}

func synchronizedShouldRestart(ctx *context.T, instanceDir string) bool {
	info, err := loadInstanceInfo(nil, instanceDir)
	if err != nil {
		ctx.Error(err)
		return false
	}

	envelope, err := loadEnvelopeForInstance(nil, instanceDir)
	if err != nil {
		ctx.Error(err)
		return false
	}

	shouldRestart := newBasicRestartPolicy().decide(envelope, info)

	if err := saveInstanceInfo(nil, instanceDir, info); err != nil {
		ctx.Error(err)
		return false
	}
	return shouldRestart
}

// restartAppIfNecessary restarts an application if its daemon
// configuration indicates that it should be running but the reaping
// functionality has previously determined that it is not.
// TODO(rjkroege): This routine has a low-likelyhood race condition in
// which it fails to restart an application when the app crashes and the
// device manager then crashes between the reaper marking the app not
// running and the go routine invoking this function having a chance to
// complete.
func (i *appRunner) restartAppIfNecessary(ctx *context.T, instanceDir string) {
	if err := transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateLaunching); err != nil {
		ctx.Error(err)
		return
	}

	shouldRestart := synchronizedShouldRestart(ctx, instanceDir)

	if err := transitionInstance(instanceDir, device.InstanceStateLaunching, device.InstanceStateNotRunning); err != nil {
		ctx.Error(err)
		return
	}

	if !shouldRestart {
		return
	}

	if err := i.run(ctx, instanceDir); err != nil {
		ctx.Error(err)
	}
}

func (i *appService) Instantiate(ctx *context.T, call device.ApplicationInstantiateServerCall) (string, error) {
	helper := i.config.Helper
	instanceDir, instanceID, err := i.newInstance(ctx, call)
	if err != nil {
		CleanupDir(ctx, instanceDir, helper)
		return "", err
	}
	systemName := suidHelper.usernameForPrincipal(ctx, call.Security(), i.uat)
	if err := saveSystemNameForInstance(instanceDir, systemName); err != nil {
		CleanupDir(ctx, instanceDir, helper)
		return "", err
	}
	return instanceID, nil
}

// instanceDir returns the path to the directory containing the app instance
// referred to by the given suffix relative to the given root directory.
// TODO(gauthamt): Make sure we pass the context to instanceDir.
func instanceDir(root string, suffix []string) (string, error) {
	if nComponents := len(suffix); nComponents != 3 {
		return "", verror.New(errors.ErrInvalidSuffix, nil)
	}
	app, installation, instance := suffix[0], suffix[1], suffix[2]
	instancesDir := filepath.Join(root, applicationDirName(app), installationDirName(installation), "instances")
	instanceDir := filepath.Join(instancesDir, instanceDirName(instance))
	return instanceDir, nil
}

// parseInstanceDir is a partial inverse of instanceDir. It cannot retrieve the app name,
// as that has been hashed so it returns an appDir instead.
func parseInstanceDir(dir string) (prefix, appDir, installation, instance string) {
	dirRE := regexp.MustCompile("(/.*)(/" + appDirPrefix + "[^/]+)/" + installationPrefix + "([^/]+)/" + "instances/" + instancePrefix + "([^/]+)$")
	matches := dirRE.FindStringSubmatch(dir)
	if len(matches) < 5 {
		return "", "", "", ""
	}
	return matches[1], matches[2], matches[3], matches[4]
}

// instanceDir returns the path to the directory containing the app instance
// referred to by the invoker's suffix, as well as the corresponding not-running
// instance dir.  Returns an error if the suffix does not name an instance.
func (i *appService) instanceDir() (string, error) {
	return instanceDir(i.config.Root, i.suffix)
}

func (i *appService) Run(ctx *context.T, call rpc.ServerCall) error {
	instanceDir, err := i.instanceDir()
	if err != nil {
		return err
	}

	systemName := suidHelper.usernameForPrincipal(ctx, call.Security(), i.uat)
	startSystemName, err := readSystemNameForInstance(instanceDir)
	if err != nil {
		return err
	}

	if startSystemName != systemName {
		return verror.New(verror.ErrNoAccess, ctx, "Not allowed to resume an application under a different system name.")
	}
	return i.runner.run(ctx, instanceDir)
}

func stopAppRemotely(ctx *context.T, appVON string, deadline time.Duration) error {
	appStub := appcycle.AppCycleClient(appVON)
	ctx, cancel := context.WithTimeout(ctx, deadline)
	defer cancel()
	stream, err := appStub.Stop(ctx)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("%v.Stop() failed: %v", appVON, err))
	}
	rstream := stream.RecvStream()
	for rstream.Advance() {
		ctx.VI(2).Infof("%v.Stop() task update: %v", appVON, rstream.Value())
	}
	if err := rstream.Err(); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Advance() failed: %v", err))
	}
	if err := stream.Finish(); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Finish() failed: %v", err))
	}
	return nil
}

func stop(ctx *context.T, instanceDir string, reap *reaper, deadline time.Duration) error {
	info, err := loadInstanceInfo(ctx, instanceDir)
	if err != nil {
		return err
	}
	err = stopAppRemotely(ctx, info.AppCycleMgrName, deadline)
	reap.forciblySuspend(instanceDir)
	if err == nil {
		reap.stopWatching(instanceDir)
	}
	return err
}

func (i *appService) Delete(ctx *context.T, _ rpc.ServerCall) error {
	instanceDir, err := i.instanceDir()
	if err != nil {
		return err
	}
	return transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateDeleted)
}

func (i *appService) Kill(ctx *context.T, _ rpc.ServerCall, deadline time.Duration) error {
	instanceDir, err := i.instanceDir()
	if err != nil {
		return err
	}
	if err := transitionInstance(instanceDir, device.InstanceStateRunning, device.InstanceStateDying); err != nil {
		return err
	}
	if err := stop(ctx, instanceDir, i.runner.reap, deadline); err != nil {
		transitionInstance(instanceDir, device.InstanceStateDying, device.InstanceStateRunning)
		return err
	}
	return transitionInstance(instanceDir, device.InstanceStateDying, device.InstanceStateNotRunning)
}

func (i *appService) Uninstall(*context.T, rpc.ServerCall) error {
	installationDir, err := i.installationDir()
	if err != nil {
		return err
	}
	return transitionInstallation(installationDir, device.InstallationStateActive, device.InstallationStateUninstalled)
}

func updateInstance(ctx *context.T, instanceDir string) (err error) {
	// Only not-running instances can be updated.
	if err := transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateUpdating); err != nil {
		return err
	}
	defer func() {
		terr := transitionInstance(instanceDir, device.InstanceStateUpdating, device.InstanceStateNotRunning)
		if err == nil {
			err = terr
		}
	}()
	// Check if a newer version of the installation is available.
	versionLink := filepath.Join(instanceDir, "version")
	versionDir, err := filepath.EvalSymlinks(versionLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
	}
	latestVersionLink := filepath.Join(instanceDir, "installation", "current")
	latestVersionDir, err := filepath.EvalSymlinks(latestVersionLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", latestVersionLink, err))
	}
	if versionDir == latestVersionDir {
		return verror.New(errors.ErrUpdateNoOp, ctx)
	}
	// Update to the newer version.  Note, this is the only mutation
	// performed to the instance, and, since it's atomic, the state of the
	// instance is consistent at all times.
	return UpdateLink(latestVersionDir, versionLink)
}

func updateInstallation(ctx *context.T, installationDir string) error {
	if !installationStateIs(installationDir, device.InstallationStateActive) {
		return verror.New(errors.ErrInvalidOperation, ctx)
	}
	originVON, err := loadOrigin(ctx, installationDir)
	if err != nil {
		return err
	}
	ctx, cancel := context.WithTimeout(ctx, rpcContextLongTimeout)
	defer cancel()
	newEnvelope, err := fetchAppEnvelope(ctx, originVON)
	if err != nil {
		return err
	}
	currLink := filepath.Join(installationDir, "current")
	oldVersionDir, err := filepath.EvalSymlinks(currLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", currLink, err))
	}
	// NOTE(caprita): A race can occur between two competing updates, where
	// both use the old version as their baseline.  This can result in both
	// updates succeeding even if they are updating the app installation to
	// the same new envelope.  This will result in one of the updates
	// becoming the new 'current'.  Both versions will point their
	// 'previous' link to the old version.  This doesn't appear to be of
	// practical concern, so we avoid the complexity of synchronizing
	// updates.
	oldEnvelope, err := loadEnvelope(ctx, oldVersionDir)
	if err != nil {
		return err
	}
	if oldEnvelope.Title != newEnvelope.Title {
		return verror.New(errors.ErrAppTitleMismatch, ctx)
	}
	if reflect.DeepEqual(oldEnvelope, newEnvelope) {
		return verror.New(errors.ErrUpdateNoOp, ctx)
	}
	versionDir, err := newVersion(ctx, installationDir, newEnvelope, oldVersionDir)
	if err != nil {
		CleanupDir(ctx, versionDir, "")
		return err
	}
	return nil
}

func (i *appService) Update(ctx *context.T, _ rpc.ServerCall) error {
	if installationDir, err := i.installationDir(); err == nil {
		return updateInstallation(ctx, installationDir)
	}
	if instanceDir, err := i.instanceDir(); err == nil {
		return updateInstance(ctx, instanceDir)
	}
	return verror.New(errors.ErrInvalidSuffix, nil)
}

func (*appService) UpdateTo(_ *context.T, _ rpc.ServerCall, von string) error {
	// TODO(jsimsa): Implement.
	return nil
}

func revertInstance(ctx *context.T, instanceDir string) (err error) {
	// Only not-running instances can be reverted.
	if err := transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateUpdating); err != nil {
		return err
	}
	defer func() {
		terr := transitionInstance(instanceDir, device.InstanceStateUpdating, device.InstanceStateNotRunning)
		if err == nil {
			err = terr
		}
	}()
	versionLink := filepath.Join(instanceDir, "version")
	versionDir, err := filepath.EvalSymlinks(versionLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
	}
	previousLink := filepath.Join(versionDir, "previous")
	if _, err := os.Lstat(previousLink); err != nil {
		if os.IsNotExist(err) {
			// No 'previous' link -- must be the first version.
			return verror.New(errors.ErrUpdateNoOp, ctx)
		}
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Lstat(%v) failed: %v", previousLink, err))
	}
	prevVersionDir, err := filepath.EvalSymlinks(previousLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", previousLink, err))
	}
	return UpdateLink(prevVersionDir, versionLink)
}

func revertInstallation(ctx *context.T, installationDir string) error {
	if !installationStateIs(installationDir, device.InstallationStateActive) {
		return verror.New(errors.ErrInvalidOperation, ctx)
	}
	// NOTE(caprita): A race can occur between an update and a revert, where
	// both use the same current version as their starting point.  This will
	// render the update inconsequential.  This doesn't appear to be of
	// practical concern, so we avoid the complexity of synchronizing
	// updates and revert operations.
	currLink := filepath.Join(installationDir, "current")
	currVersionDir, err := filepath.EvalSymlinks(currLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", currLink, err))
	}
	previousLink := filepath.Join(currVersionDir, "previous")
	if _, err := os.Lstat(previousLink); err != nil {
		if os.IsNotExist(err) {
			// No 'previous' link -- must be the first version.
			return verror.New(errors.ErrUpdateNoOp, ctx)
		}
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Lstat(%v) failed: %v", previousLink, err))
	}
	prevVersionDir, err := filepath.EvalSymlinks(previousLink)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", previousLink, err))
	}
	return UpdateLink(prevVersionDir, currLink)
}

func (i *appService) Revert(ctx *context.T, _ rpc.ServerCall) error {
	if installationDir, err := i.installationDir(); err == nil {
		return revertInstallation(ctx, installationDir)
	}
	if instanceDir, err := i.instanceDir(); err == nil {
		return revertInstance(ctx, instanceDir)
	}
	return verror.New(errors.ErrInvalidSuffix, nil)
}

type treeNode struct {
	children map[string]*treeNode
}

func newTreeNode() *treeNode {
	return &treeNode{children: make(map[string]*treeNode)}
}

func (n *treeNode) find(names []string, create bool) *treeNode {
	for {
		if len(names) == 0 {
			return n
		}
		if next, ok := n.children[names[0]]; ok {
			n = next
			names = names[1:]
			continue
		}
		if create {
			nn := newTreeNode()
			n.children[names[0]] = nn
			n = nn
			names = names[1:]
			continue
		}
		return nil
	}
}

func (i *appService) scanEnvelopes(ctx *context.T, tree *treeNode, appDir string) {
	// Find all envelopes, extract installID.
	envGlob := []string{i.config.Root, appDir, installationPrefix + "*", "*", "envelope"}
	envelopes, err := filepath.Glob(filepath.Join(envGlob...))
	if err != nil {
		ctx.Errorf("unexpected error: %v", err)
		return
	}
	for _, path := range envelopes {
		env, err := loadEnvelope(ctx, filepath.Dir(path))
		if err != nil {
			continue
		}
		relpath, _ := filepath.Rel(i.config.Root, path)
		elems := strings.Split(relpath, string(filepath.Separator))
		if len(elems) != len(envGlob)-1 {
			ctx.Errorf("unexpected number of path components: %q (%q)", elems, path)
			continue
		}
		installID := strings.TrimPrefix(elems[1], installationPrefix)
		tree.find([]string{env.Title, installID}, true)
	}
	return
}

func (i *appService) scanInstances(ctx *context.T, tree *treeNode) {
	if len(i.suffix) < 2 {
		return
	}
	title := i.suffix[0]
	installDir, err := installationDirCore(i.suffix[:2], i.config.Root)
	if err != nil {
		return
	}
	// Add the node corresponding to the installation itself.
	tree.find(i.suffix[:2], true)
	// Find all instances.
	infoGlob := []string{installDir, "instances", instancePrefix + "*", "info"}
	instances, err := filepath.Glob(filepath.Join(infoGlob...))
	if err != nil {
		ctx.Errorf("unexpected error: %v", err)
		return
	}
	for _, path := range instances {
		instanceDir := filepath.Dir(path)
		i.scanInstance(ctx, tree, title, instanceDir)
	}
	return
}

func (i *appService) scanInstance(ctx *context.T, tree *treeNode, title, instanceDir string) {
	if _, err := loadInstanceInfo(ctx, instanceDir); err != nil {
		return
	}
	rootDir, _, installID, instanceID := parseInstanceDir(instanceDir)
	if installID == "" || instanceID == "" || filepath.Clean(i.config.Root) != filepath.Clean(rootDir) {
		ctx.Errorf("failed to parse instanceDir %v (got: %v %v %v)", instanceDir, rootDir, installID, instanceID)
		return
	}

	tree.find([]string{title, installID, instanceID, "logs"}, true)
	if instanceStateIs(instanceDir, device.InstanceStateRunning) {
		for _, obj := range []string{"pprof", "stats"} {
			tree.find([]string{title, installID, instanceID, obj}, true)
		}
	}
}

func (i *appService) GlobChildren__(ctx *context.T, _ rpc.ServerCall) (<-chan string, error) {
	tree := newTreeNode()
	switch len(i.suffix) {
	case 0:
		i.scanEnvelopes(ctx, tree, appDirPrefix+"*")
	case 1:
		appDir := applicationDirName(i.suffix[0])
		i.scanEnvelopes(ctx, tree, appDir)
	case 2:
		i.scanInstances(ctx, tree)
	case 3:
		dir, err := i.instanceDir()
		if err != nil {
			break
		}
		i.scanInstance(ctx, tree, i.suffix[0], dir)
	default:
		return nil, verror.New(verror.ErrNoExist, nil, i.suffix)
	}
	n := tree.find(i.suffix, false)
	if n == nil {
		return nil, verror.New(errors.ErrInvalidSuffix, nil)
	}
	ch := make(chan string)
	go func() {
		for child, _ := range n.children {
			ch <- child
		}
		close(ch)
	}()
	return ch, nil
}

// TODO(rjkroege): Refactor to eliminate redundancy with newAppSpecificAuthorizer.
func dirFromSuffix(ctx *context.T, suffix []string, root string) (string, bool, error) {
	if len(suffix) == 2 {
		p, err := installationDirCore(suffix, root)
		if err != nil {
			ctx.Errorf("dirFromSuffix failed: %v", err)
			return "", false, err
		}
		return p, false, nil
	} else if len(suffix) > 2 {
		p, err := instanceDir(root, suffix[0:3])
		if err != nil {
			ctx.Errorf("dirFromSuffix failed: %v", err)
			return "", false, err
		}
		return p, true, nil
	}
	return "", false, verror.New(errors.ErrInvalidSuffix, nil)
}

// TODO(rjkroege): Consider maintaining an in-memory Permissions cache.
func (i *appService) SetPermissions(ctx *context.T, call rpc.ServerCall, perms access.Permissions, version string) error {
	dir, isInstance, err := dirFromSuffix(ctx, i.suffix, i.config.Root)
	if err != nil {
		return err
	}
	if isInstance {
		dmBlessings := security.LocalBlessingNames(ctx, call.Security())
		if err := setPermsForDebugging(dmBlessings, perms, dir, i.permsStore); err != nil {
			return err
		}
	}
	return i.permsStore.Set(path.Join(dir, "acls"), perms, version)
}

func (i *appService) GetPermissions(ctx *context.T, _ rpc.ServerCall) (perms access.Permissions, version string, err error) {
	dir, _, err := dirFromSuffix(ctx, i.suffix, i.config.Root)
	if err != nil {
		return nil, "", err
	}
	return i.permsStore.Get(path.Join(dir, "acls"))
}

func (i *appService) Debug(ctx *context.T, call rpc.ServerCall) (string, error) {
	switch len(i.suffix) {
	case 2:
		return i.installationDebug(ctx)
	case 3:
		return i.instanceDebug(ctx, call.Security())
	default:
		return "", verror.New(errors.ErrInvalidSuffix, nil)
	}
}

func (i *appService) installationDebug(ctx *context.T) (string, error) {
	const installationDebug = `Installation dir: {{.InstallationDir}}

Origin: {{.Origin}}

Envelope: {{printf "%+v" .Envelope}}

Config: {{printf "%+v" .Config}}
`
	installationDebugTemplate, err := template.New("installation-debug").Parse(installationDebug)
	if err != nil {
		return "", err
	}

	installationDir, err := i.installationDir()
	if err != nil {
		return "", err
	}
	debugInfo := struct {
		InstallationDir, Origin string
		Envelope                *application.Envelope
		Config                  device.Config
	}{}
	debugInfo.InstallationDir = installationDir

	if origin, err := loadOrigin(ctx, installationDir); err != nil {
		return "", err
	} else {
		debugInfo.Origin = origin
	}

	currLink := filepath.Join(installationDir, "current")
	if envelope, err := loadEnvelope(ctx, currLink); err != nil {
		return "", err
	} else {
		debugInfo.Envelope = envelope
	}

	if config, err := loadConfig(ctx, installationDir); err != nil {
		return "", err
	} else {
		debugInfo.Config = config
	}

	var buf bytes.Buffer
	if err := installationDebugTemplate.Execute(&buf, debugInfo); err != nil {
		return "", err
	}
	return buf.String(), nil

}

func (i *appService) instanceDebug(ctx *context.T, call security.Call) (string, error) {
	const instanceDebug = `Instance dir: {{.InstanceDir}}

System name / start system name: {{.SystemName}} / {{.StartSystemName}}

Cmd: {{printf "%+v" .Cmd}}

Info: {{printf "%+v" .Info}}

Principal: {{.PrincipalType}}
Public Key: {{.Principal.PublicKey}}
Blessing Store: {{.Principal.BlessingStore.DebugString}}
Roots: {{.Principal.Roots.DebugString}}
`
	instanceDebugTemplate, err := template.New("instance-debug").Parse(instanceDebug)
	if err != nil {
		return "", err
	}

	instanceDir, err := i.instanceDir()
	if err != nil {
		return "", err
	}
	debugInfo := struct {
		InstanceDir, SystemName, StartSystemName string
		Cmd                                      *exec.Cmd
		Info                                     *instanceInfo
		Principal                                security.Principal
		PrincipalType                            string
	}{}
	debugInfo.InstanceDir = instanceDir

	debugInfo.SystemName = suidHelper.usernameForPrincipal(ctx, call, i.uat)
	if startSystemName, err := readSystemNameForInstance(instanceDir); err != nil {
		return "", err
	} else {
		debugInfo.StartSystemName = startSystemName
	}

	if info, err := loadInstanceInfo(ctx, instanceDir); err != nil {
		return "", err
	} else {
		debugInfo.Info = info
	}
	if cmd, err := genCmd(ctx, instanceDir, i.runner.mtAddress); err != nil {
		return "", err
	} else {
		debugInfo.Cmd = cmd
	}

	if sa := i.runner.securityAgent; sa != nil {
		file, err := sa.keyMgrAgent.NewConnection(debugInfo.Info.SecurityAgentHandle)
		if err != nil {
			ctx.Errorf("NewConnection(%v) failed: %v", debugInfo.Info.SecurityAgentHandle, err)
			return "", err
		}
		var cancel func()
		if debugInfo.Principal, cancel, err = agentPrincipal(ctx, file); err != nil {
			return "", err
		}
		defer cancel()
		debugInfo.PrincipalType = "Agent-based"
	} else {
		credentialsDir := filepath.Join(instanceDir, "credentials")
		var err error
		if debugInfo.Principal, err = vsecurity.LoadPersistentPrincipal(credentialsDir, nil); err != nil {
			return "", err
		}
		debugInfo.PrincipalType = fmt.Sprintf("Credentials dir-based (%v)", credentialsDir)
	}
	var buf bytes.Buffer
	if err := instanceDebugTemplate.Execute(&buf, debugInfo); err != nil {
		return "", err
	}
	return buf.String(), nil
}

func (i *appService) Status(ctx *context.T, _ rpc.ServerCall) (device.Status, error) {
	switch len(i.suffix) {
	case 2:
		status, err := i.installationStatus(ctx)
		return device.StatusInstallation{Value: status}, err
	case 3:
		status, err := i.instanceStatus(ctx)
		return device.StatusInstance{Value: status}, err
	default:
		return nil, verror.New(errors.ErrInvalidSuffix, ctx)
	}
}

func (i *appService) installationStatus(ctx *context.T) (device.InstallationStatus, error) {
	installationDir, err := i.installationDir()
	if err != nil {
		return device.InstallationStatus{}, err
	}
	state, err := getInstallationState(installationDir)
	if err != nil {
		return device.InstallationStatus{}, err
	}
	versionLink := filepath.Join(installationDir, "current")
	versionDir, err := filepath.EvalSymlinks(versionLink)
	if err != nil {
		return device.InstallationStatus{}, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
	}
	return device.InstallationStatus{
		State:   state,
		Version: filepath.Base(versionDir),
	}, nil
}

func (i *appService) instanceStatus(ctx *context.T) (device.InstanceStatus, error) {
	instanceDir, err := i.instanceDir()
	if err != nil {
		return device.InstanceStatus{}, err
	}
	state, err := getInstanceState(instanceDir)
	if err != nil {
		return device.InstanceStatus{}, err
	}
	versionLink := filepath.Join(instanceDir, "version")
	versionDir, err := filepath.EvalSymlinks(versionLink)
	if err != nil {
		return device.InstanceStatus{}, verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
	}
	return device.InstanceStatus{
		State:   state,
		Version: filepath.Base(versionDir),
	}, nil
}
