gitee.com/mysnapcore/mysnapd@v0.1.0/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  	"syscall"
    26  
    27  	"github.com/jessevdk/go-flags"
    28  
    29  	"gitee.com/mysnapcore/mysnapd/logger"
    30  )
    31  
    32  var opts struct {
    33  	FromSnapConfine bool `long:"from-snap-confine"`
    34  	UserMounts      bool `long:"user-mounts"`
    35  	UserID          int  `short:"u"`
    36  	Positionals     struct {
    37  		SnapName string `positional-arg-name:"SNAP_NAME" required:"yes"`
    38  	} `positional-args:"true"`
    39  }
    40  
    41  // IMPORTANT: all the code in main() until bootstrap is finished may be run
    42  // with elevated privileges when invoking snap-update-ns from the setuid
    43  // snap-confine.
    44  
    45  func main() {
    46  	logger.SimpleSetup()
    47  	if err := run(); err != nil {
    48  		fmt.Printf("cannot update snap namespace: %s\n", err)
    49  		os.Exit(1)
    50  	}
    51  	// END IMPORTANT
    52  }
    53  
    54  func parseArgs(args []string) error {
    55  	parser := flags.NewParser(&opts, flags.HelpFlag|flags.PassDoubleDash|flags.PassAfterNonOption)
    56  	_, err := parser.ParseArgs(args)
    57  	return err
    58  }
    59  
    60  // IMPORTANT: all the code in run() until BootStrapError() is finished may
    61  // be run with elevated privileges when invoking snap-update-ns from
    62  // the setuid snap-confine.
    63  
    64  func run() error {
    65  	// There is some C code that runs before main() is started.
    66  	// That code always runs and sets an error condition if it fails.
    67  	// Here we just check for the error.
    68  	if err := BootstrapError(); err != nil {
    69  		// If there is no mount namespace to transition to let's just quit
    70  		// instantly without any errors as there is nothing to do anymore.
    71  		if err == ErrNoNamespace {
    72  			logger.Debugf("no preserved mount namespace, nothing to update")
    73  			return nil
    74  		}
    75  		return err
    76  	}
    77  	// END IMPORTANT
    78  
    79  	if err := parseArgs(os.Args[1:]); err != nil {
    80  		return err
    81  	}
    82  
    83  	// Explicitly set the umask to 0 to prevent permission bits
    84  	// being masked out when creating files and directories.
    85  	//
    86  	// While snap-confine already does this for us, we inherit
    87  	// snapd's umask when it invokes us.
    88  	syscall.Umask(0)
    89  
    90  	var upCtx MountProfileUpdateContext
    91  	if opts.UserMounts {
    92  		upCtx = NewUserProfileUpdateContext(opts.Positionals.SnapName, opts.FromSnapConfine, os.Getuid())
    93  	} else {
    94  		upCtx = NewSystemProfileUpdateContext(opts.Positionals.SnapName, opts.FromSnapConfine)
    95  	}
    96  	return executeMountProfileUpdate(upCtx)
    97  }