blob: ec47209d872bca05be67ed1925b715ea4ec4d168 [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 kernel
import (
"context"
"io/ioutil"
"strconv"
"strings"
"golang.org/x/sys/unix"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: Limits,
Desc: "Checks kernel limits and settings in /proc",
Contacts: []string{"chromeos-kernel-test@google.com"},
Attr: []string{"group:mainline"},
})
}
func Limits(ctx context.Context, s *testing.State) {
type op int
const (
eq op = iota
ge
)
// Check limits stored in /proc files.
for _, tc := range []struct {
path string // path in /proc
op op // comparison operator
val int64 // value to compare against
}{
{"/proc/sys/fs/file-max", ge, 50000}, // MemTotal-kb / 10
{"/proc/sys/fs/leases-enable", eq, 1},
{"/proc/sys/fs/nr_open", ge, 1048576},
{"/proc/sys/fs/protected_hardlinks", eq, 1},
{"/proc/sys/fs/protected_symlinks", eq, 1},
{"/proc/sys/fs/suid_dumpable", eq, 2},
{"/proc/sys/kernel/kptr_restrict", ge, 1},
{"/proc/sys/kernel/ngroups_max", ge, 65536},
{"/proc/sys/kernel/panic", eq, -1},
{"/proc/sys/kernel/panic_on_oops", eq, 1},
{"/proc/sys/kernel/pid_max", ge, 32768},
{"/proc/sys/kernel/randomize_va_space", eq, 2},
{"/proc/sys/kernel/sched_rt_period_us", eq, 1000000},
{"/proc/sys/kernel/sched_rt_runtime_us", eq, 850000},
{"/proc/sys/kernel/sysrq", eq, 1},
{"/proc/sys/kernel/threads-max", ge, 7000}, // MemTotal-kb / 64
{"/proc/sys/kernel/yama/ptrace_scope", eq, 1},
{"/proc/sys/net/ipv4/tcp_syncookies", eq, 1},
{"/proc/sys/vm/mmap_min_addr", ge, 32768},
} {
b, err := ioutil.ReadFile(tc.path)
if err != nil {
s.Errorf("Failed to read %v: %v", tc.path, err)
continue
}
val, err := strconv.ParseInt(strings.TrimSpace(string(b)), 10, 64)
if err != nil {
s.Errorf("Failed to parse %q from %v: %v", b, tc.path, err)
continue
}
if tc.op == eq && val != tc.val {
s.Errorf("%v contains %v; want %v", tc.path, val, tc.val)
} else if tc.op == ge && val < tc.val {
s.Errorf("%v contains %v; want at least %v", tc.path, val, tc.val)
} else {
s.Logf("%v contains %v", tc.path, val)
}
}
// Check rlimits (rather than parsing /proc/self/limits).
for _, tc := range []struct {
name string // human-readable name
res int // resource ID
min uint64 // minimum acceptable value
}{
{"RLIMIT_NOFILE", unix.RLIMIT_NOFILE, 1024},
{"RLIMIT_NPROC", unix.RLIMIT_NPROC, 3000}, // MemTotal-kb / 128
} {
var rlimit unix.Rlimit
if err := unix.Getrlimit(tc.res, &rlimit); err != nil {
s.Errorf("Failed to get %v: %v", tc.name, err)
} else if rlimit.Cur < tc.min {
s.Errorf("%v is %v; want at least %v", tc.name, rlimit.Cur, tc.min)
} else {
s.Logf("%v is %v", tc.name, rlimit.Cur)
}
}
}