github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/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 }