forked from snapcore/snapd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
squashfs.go
141 lines (120 loc) · 4.1 KB
/
squashfs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2018 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package sanity
import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"github.com/snapcore/snapd/logger"
"github.com/snapcore/snapd/osutil"
"github.com/snapcore/snapd/osutil/squashfs"
"github.com/snapcore/snapd/sandbox/selinux"
)
func init() {
checks = append(checks, checkSquashfsMount)
}
/* This image was created using:
#!/bin/sh
cd $(mktemp -d)
cat > canary.txt<<'EOF'
This file is used to check that snapd can read a squashfs image.
The squashfs was generated with:
EOF
cat $0 >> canary.txt
mksquashfs . /tmp/canary.squashfs -noappend -comp xz -no-xattrs -no-fragments >/dev/nul
cat /tmp/canary.squashfs | gzip - | base64
*/
var b64SquashfsImage = []byte(`
H4sIAGxdFVsAA8soLixmYmBgyIkVjWZgALEYGFgYBBkuMDECaQYGFQYI4INIMbBB6f9Q0MAI4R+D
0s+g9A8o/de8KiKKgYExU+meGfOB54wzmBUZuYDiVhPYbR4wTme4H8ugJcWpniK5waL4VLewwsUC
PgdVnS/pCycWn34g1rpj6bIywdLqaQdZFYQcYr7/vR1w9dTbDivRH3GahXc578hdW3Ri7mu9+KeF
PqYCrkk/5zepyFw0EjL+XxH/3ubc9E+/J0t0PxE+zv9J96pa0rt9CWyvX6aIvb3H65qo9mbikvjU
LZxrOupvcr32+2yYFzt1wTe2HdFfrOSmKXFFPf1i5ep7Wv+q+U+nBNWs/nu+UosO6PFvfl991nVG
R9XSJUxv/7/y2f2zid0+OnGi1+ey1/vatzDPvfbq+0LLwIu1Wx/u+m6/c8IN21vNCQwMX2dtWsHA
+BvodwaGpcmXftsZ8HaDg5ExMsqlgYlhCTisQDEAYiRAQxckNgMooADEjAwH4GqgEQCOK0UgBhrK
INcAFWRghMtyMiQn5iUWVeqVVJQIwOVh8QmLJ5aGF8wMsIgfBaNgFIyCUTAKRsEoGAWjYBSMglEw
bAEA+f+YuAAQAAA=
`)
var fuseBinary = "mount.fuse"
func firstCheckFuse() error {
if squashfs.NeedsFuse() {
if _, err := exec.LookPath(fuseBinary); err != nil {
return fmt.Errorf(`The "fuse" filesystem is required on this system but not available. Please try to install the fuse package.`)
}
}
return nil
}
func checkSquashfsMount() error {
if err := firstCheckFuse(); err != nil {
return err
}
tmpSquashfsFile, err := ioutil.TempFile("", "sanity-squashfs-")
if err != nil {
return err
}
defer os.Remove(tmpSquashfsFile.Name())
tmpMountDir, err := ioutil.TempDir("", "sanity-mountpoint-")
if err != nil {
return err
}
defer os.RemoveAll(tmpMountDir)
// write the squashfs image
b64dec := base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(b64SquashfsImage))
gzReader, err := gzip.NewReader(b64dec)
if err != nil {
return err
}
if _, err := io.Copy(tmpSquashfsFile, gzReader); err != nil {
return err
}
// the fstype can be squashfs or fuse.{snap,squash}fuse
fstype, _ := squashfs.FsType()
options := []string{"-t", fstype}
if selinux.ProbedLevel() != selinux.Unsupported {
if ctx := selinux.SnapMountContext(); ctx != "" {
options = append(options, "-o", "context="+ctx)
}
}
options = append(options, tmpSquashfsFile.Name(), tmpMountDir)
cmd := exec.Command("mount", options...)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("cannot mount squashfs image using %q: %v", fstype, osutil.OutputErr(output, err))
}
defer func() {
if output, err := exec.Command("umount", "-l", tmpMountDir).CombinedOutput(); err != nil {
// os.RemoveAll(tmpMountDir) will fail here if umount fails
logger.Noticef("cannot unmount sanity check squashfs image: %v", osutil.OutputErr(output, err))
}
}()
// sanity check the
content, err := ioutil.ReadFile(filepath.Join(tmpMountDir, "canary.txt"))
if err != nil {
return fmt.Errorf("squashfs mount returned no err but canary file cannot be read")
}
if !bytes.HasPrefix(content, []byte("This file is used to check that snapd can read a squashfs image.")) {
return fmt.Errorf("unexpected squashfs canary content: %q", content)
}
return nil
}