blob: 72f58e36e7978f45dadba5adb10730404a436061 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package security
import (
"context"
"io/ioutil"
"os"
"syscall"
"chromiumos/tast/local/bundles/cros/security/filesetup"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: SystemDirs,
Desc: "Checks permissions of various system directories",
Contacts: []string{
"jorgelo@chromium.org", // Security team
"chromeos-security@google.com",
},
Attr: []string{"group:mainline"},
})
}
func SystemDirs(ctx context.Context, s *testing.State) {
// If partitions have been remounted, there's no point in continuing.
if ro, err := filesetup.ReadOnlyRootPartition(); err != nil {
s.Fatal("Failed to check if root partition is mounted read-only: ", err)
} else if !ro {
s.Fatal("Root partition is mounted read/write; rootfs verification disabled?")
}
// Check that root-owned dirs have the expected ownership and permissions.
for dir, mode := range map[string]os.FileMode{
"/": 0755,
"/bin": 0755,
"/boot": 0755,
"/dev": 0755,
"/etc": 0755,
"/home": 0755,
"/lib": 0755,
"/media": 0777,
"/mnt": 0755,
"/mnt/stateful_partition": 0755,
"/opt": 0755,
"/proc": 0555,
"/run": 0755,
"/sbin": 0755,
"/sys": 0555, // 0555 since 3.4: https://crbug.com/213395
"/tmp": 0777,
"/usr": 0755,
"/usr/bin": 0755,
"/usr/lib": 0755,
"/usr/local": 0755,
"/usr/sbin": 0755,
"/usr/share": 0755,
"/var": 0755,
"/var/cache": 0755,
} {
fi, err := os.Stat(dir)
if err != nil {
if !os.IsNotExist(err) {
s.Errorf("Failed to stat %v: %v", dir, err)
}
continue
}
st := fi.Sys().(*syscall.Stat_t)
if st.Uid != 0 || st.Gid != 0 {
s.Errorf("%v is owned by %d:%d; want 0:0", dir, st.Uid, st.Gid)
}
if m := fi.Mode() & os.ModePerm; m != mode {
s.Errorf("%v has mode %04o; want %04o", dir, m, mode)
}
}
// tryWrite attempts to create and remove a file in dir.
tryWrite := func(dir string) error {
f, err := ioutil.TempFile(dir, ".tast.security.MountPerms.")
if err != nil {
return err
}
// Clean up the file.
if err := f.Close(); err != nil {
s.Error("Failed to close temp file: ", err)
}
if err := os.Remove(f.Name()); err != nil {
s.Error("Failed to remove temp file: ", err)
}
return nil
}
// Check that root can't create files in read-only directories.
for _, dir := range []string{
"/",
"/bin",
"/boot",
"/etc",
"/lib",
"/mnt",
"/opt",
"/sbin",
"/usr",
"/usr/bin",
"/usr/lib",
"/usr/sbin",
"/usr/share",
} {
if err := tryWrite(dir); err == nil {
s.Error("Unexpectedly able to create file in read-only dir ", dir)
}
}
// Check that root can create files in read/write dirs.
for _, dir := range []string{
"/run",
"/usr/local",
"/var",
"/var/cache",
"/var/lib",
"/var/log",
} {
if err := tryWrite(dir); err != nil {
s.Errorf("Failed to create file in read/write dir %v: %v", dir, err)
}
}
}