11package main
22
33import (
4+ "fmt"
45 "io/ioutil"
56 "os"
67 "path/filepath"
78
89 "github.com/opencontainers/runtime-tools/validation/util"
10+ "golang.org/x/sys/unix"
911)
1012
11- func main () {
13+ func checkReadonlyPaths () error {
1214 g , err := util .GetDefaultGenerator ()
1315 if err != nil {
14- util . Fatal ( err )
16+ return err
1517 }
16- g .AddLinuxReadonlyPaths ("/readonly-dir" )
17- g .AddLinuxReadonlyPaths ("/readonly-file" )
18+
19+ readonlyDir := "readonly-dir"
20+ readonlySubDir := "readonly-subdir"
21+ readonlyFile := "readonly-file"
22+
23+ readonlyDirTop := filepath .Join ("/" , readonlyDir )
24+ readonlyFileTop := filepath .Join ("/" , readonlyFile )
25+
26+ readonlyDirSub := filepath .Join (readonlyDirTop , readonlySubDir )
27+ readonlyFileSub := filepath .Join (readonlyDirTop , readonlyFile )
28+ readonlyFileSubSub := filepath .Join (readonlyDirSub , readonlyFile )
29+
30+ g .AddLinuxReadonlyPaths (readonlyDirTop )
31+ g .AddLinuxReadonlyPaths (readonlyFileTop )
32+ g .AddLinuxReadonlyPaths (readonlyDirSub )
33+ g .AddLinuxReadonlyPaths (readonlyFileSub )
34+ g .AddLinuxReadonlyPaths (readonlyFileSubSub )
1835 err = util .RuntimeInsideValidate (g , func (path string ) error {
19- testDir := filepath .Join (path , "readonly-dir" )
36+ testDir := filepath .Join (path , readonlyDirSub )
2037 err = os .MkdirAll (testDir , 0777 )
2138 if err != nil {
2239 return err
@@ -28,13 +45,130 @@ func main() {
2845 }
2946 defer os .Remove (tmpfile .Name ())
3047
31- testFile := filepath .Join (path , "readonly-file" )
32-
3348 // runtimetest cannot check the readability of empty files, so
3449 // write something.
50+ testSubSubFile := filepath .Join (path , readonlyFileSubSub )
51+ if err := ioutil .WriteFile (testSubSubFile , []byte ("immutable" ), 0777 ); err != nil {
52+ return err
53+ }
54+
55+ testSubFile := filepath .Join (path , readonlyFileSub )
56+ if err := ioutil .WriteFile (testSubFile , []byte ("immutable" ), 0777 ); err != nil {
57+ return err
58+ }
59+
60+ testFile := filepath .Join (path , readonlyFile )
3561 return ioutil .WriteFile (testFile , []byte ("immutable" ), 0777 )
3662 })
63+ return err
64+ }
65+
66+ func checkReadonlyRelPaths () error {
67+ g , err := util .GetDefaultGenerator ()
68+ if err != nil {
69+ return err
70+ }
71+
72+ // Deliberately set a relative path to be read-only, and expect an error
73+ readonlyRelPath := "readonly-relpath"
74+
75+ g .AddLinuxReadonlyPaths (readonlyRelPath )
76+ err = util .RuntimeInsideValidate (g , func (path string ) error {
77+ testFile := filepath .Join (path , readonlyRelPath )
78+ if _ , err := os .Stat (testFile ); err != nil && os .IsNotExist (err ) {
79+ return err
80+ }
81+
82+ return nil
83+ })
84+ if err != nil {
85+ return nil
86+ }
87+ return fmt .Errorf ("expected: err != nil, actual: err == nil" )
88+ }
89+
90+ func checkReadonlySymlinks () error {
91+ g , err := util .GetDefaultGenerator ()
3792 if err != nil {
93+ return err
94+ }
95+
96+ // Deliberately create a read-only symlink that points an invalid file,
97+ // and expect an error.
98+ readonlySymlink := "/readonly-symlink"
99+
100+ g .AddLinuxReadonlyPaths (readonlySymlink )
101+ err = util .RuntimeInsideValidate (g , func (path string ) error {
102+ testFile := filepath .Join (path , readonlySymlink )
103+ // ln -s .. /readonly-symlink ; readlink -f /readonly-symlink; ls -L /readonly-symlink
104+ if err := os .Symlink ("../readonly-symlink" , testFile ); err != nil {
105+ return err
106+ }
107+ rPath , errR := os .Readlink (testFile )
108+ if errR != nil {
109+ return errR
110+ }
111+ _ , errS := os .Stat (rPath )
112+ if errS != nil && os .IsNotExist (errS ) {
113+ return errS
114+ }
115+
116+ return nil
117+ })
118+ if err != nil {
119+ return nil
120+ }
121+ return fmt .Errorf ("expected: err != nil, actual: err == nil" )
122+ }
123+
124+ func checkReadonlyDeviceNodes (mode uint32 ) error {
125+ g , err := util .GetDefaultGenerator ()
126+ if err != nil {
127+ return err
128+ }
129+
130+ readonlyDevice := "/readonly-device"
131+
132+ g .AddLinuxReadonlyPaths (readonlyDevice )
133+ return util .RuntimeInsideValidate (g , func (path string ) error {
134+ testFile := filepath .Join (path , readonlyDevice )
135+
136+ if err := unix .Mknod (testFile , mode , 0 ); err != nil {
137+ return err
138+ }
139+
140+ if _ , err := os .Stat (testFile ); err != nil && os .IsNotExist (err ) {
141+ return err
142+ }
143+
144+ return nil
145+ })
146+ }
147+
148+ func main () {
149+ if err := checkReadonlyPaths (); err != nil {
150+ util .Fatal (err )
151+ }
152+
153+ if err := checkReadonlyRelPaths (); err != nil {
38154 util .Fatal (err )
39155 }
156+
157+ if err := checkReadonlySymlinks (); err != nil {
158+ util .Fatal (err )
159+ }
160+
161+ // test creation of different type of devices, i.e. block device,
162+ // character device, and FIFO.
163+ modes := []uint32 {
164+ unix .S_IFBLK | 0666 ,
165+ unix .S_IFCHR | 0666 ,
166+ unix .S_IFIFO | 0666 ,
167+ }
168+
169+ for _ , m := range modes {
170+ if err := checkReadonlyDeviceNodes (m ); err != nil {
171+ util .Fatal (err )
172+ }
173+ }
40174}
0 commit comments