github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/cmd/snap-update-ns/main.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2017 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package main
    21  
    22  import (
    23  	"fmt"
    24  	"os"
    25  
    26  	"github.com/jessevdk/go-flags"
    27  
    28  	"github.com/snapcore/snapd/logger"
    29  )
    30  
    31  var opts struct {
    32  	FromSnapConfine bool `long:"from-snap-confine"`
    33  	UserMounts      bool `long:"user-mounts"`
    34  	UserID          int  `short:"u"`
    35  	Positionals     struct {
    36  		SnapName string `positional-arg-name:"SNAP_NAME" required:"yes"`
    37  	} `positional-args:"true"`
    38  }
    39  
    40  // IMPORTANT: all the code in main() until bootstrap is finished may be run
    41  // with elevated privileges when invoking snap-update-ns from the setuid
    42  // snap-confine.
    43  
    44  func main() {
    45  	logger.SimpleSetup()
    46  	if err := run(); err != nil {
    47  		fmt.Printf("cannot update snap namespace: %s\n", err)
    48  		os.Exit(1)
    49  	}
    50  	// END IMPORTANT
    51  }
    52  
    53  func parseArgs(args []string) error {
    54  	parser := flags.NewParser(&opts, flags.HelpFlag|flags.PassDoubleDash|flags.PassAfterNonOption)
    55  	_, err := parser.ParseArgs(args)
    56  	return err
    57  }
    58  
    59  // IMPORTANT: all the code in run() until BootStrapError() is finished may
    60  // be run with elevated privileges when invoking snap-update-ns from
    61  // the setuid snap-confine.
    62  
    63  func run() error {
    64  	// There is some C code that runs before main() is started.
    65  	// That code always runs and sets an error condition if it fails.
    66  	// Here we just check for the error.
    67  	if err := BootstrapError(); err != nil {
    68  		// If there is no mount namespace to transition to let's just quit
    69  		// instantly without any errors as there is nothing to do anymore.
    70  		if err == ErrNoNamespace {
    71  			logger.Debugf("no preserved mount namespace, nothing to update")
    72  			return nil
    73  		}
    74  		return err
    75  	}
    76  	// END IMPORTANT
    77  
    78  	if err := parseArgs(os.Args[1:]); err != nil {
    79  		return err
    80  	}
    81  	var upCtx MountProfileUpdateContext
    82  	if opts.UserMounts {
    83  		upCtx = NewUserProfileUpdateContext(opts.Positionals.SnapName, opts.FromSnapConfine, os.Getuid())
    84  	} else {
    85  		upCtx = NewSystemProfileUpdateContext(opts.Positionals.SnapName, opts.FromSnapConfine)
    86  	}
    87  	return executeMountProfileUpdate(upCtx)
    88  }