github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/sandbox/selinux/label_linux.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 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 selinux 21 22 import ( 23 "os" 24 "os/exec" 25 "regexp" 26 27 "github.com/snapcore/snapd/osutil" 28 ) 29 30 var ( 31 // actual matchpathcon -V output: 32 // /home/guest/snap has context unconfined_u:object_r:user_home_t:s0, should be unconfined_u:object_r:snappy_home_t:s0 33 matchIncorrectLabel = regexp.MustCompile("^.* has context .* should be .*\n$") 34 ) 35 36 // VerifyPathContext checks whether a given path is labeled according to its default 37 // SELinux context 38 func VerifyPathContext(aPath string) (bool, error) { 39 if _, err := os.Stat(aPath); err != nil { 40 // path that cannot be accessed cannot be verified 41 return false, err 42 } 43 // matchpathcon -V verifies whether the context of a path matches the 44 // default 45 cmd := exec.Command("matchpathcon", "-V", aPath) 46 cmd.Env = append(os.Environ(), "LC_ALL=C") 47 out, err := cmd.Output() 48 if err == nil { 49 // the path was verified 50 return true, nil 51 } 52 exit, _ := osutil.ExitCode(err) 53 // exits with 1 when the verification failed or other error occurred, 54 // when verification failed a message like this will be printed to 55 // stdout: 56 // <the-path> has context <some-context>, should be <some-other-context> 57 // match the message so that we can distinguish a failed verification 58 // case from other errors 59 if exit == 1 && matchIncorrectLabel.Match(out) { 60 return false, nil 61 } 62 return false, err 63 } 64 65 // RestoreContext restores the default SELinux context of given path 66 func RestoreContext(aPath string, mode RestoreMode) error { 67 if _, err := os.Stat(aPath); err != nil { 68 // path that cannot be accessed cannot be restored 69 return err 70 } 71 72 args := make([]string, 0, 2) 73 if mode.Recursive { 74 // -R: recursive 75 args = append(args, "-R") 76 } 77 args = append(args, aPath) 78 79 return exec.Command("restorecon", args...).Run() 80 } 81 82 // SnapMountContext finds out the right context for mounting snaps 83 func SnapMountContext() string { 84 // TODO: consider reading this from an external configuration file, such 85 // as per app contexts, from 86 // /etc/selinux/targeted/contexts/snapd_contexts like go-selinux and 87 // podman do for container volumes. 88 return "system_u:object_r:snappy_snap_t:s0" 89 }