blob: 42cac62be124efbcc7d52c20ffbee5be1a4b459b [file] [log] [blame]
// Copyright 2021 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 hwsec
import (
"context"
"time"
"chromiumos/tast/common/hwsec"
"chromiumos/tast/ctxutil"
hwseclocal "chromiumos/tast/local/hwsec"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: DaemonsRestartStress,
Desc: "Verifies that restarting hwsec daemons wouldn't cause problems",
Contacts: []string{
"cros-hwsec@chromium.org",
"yich@chromium.org",
},
SoftwareDeps: []string{"tpm"},
Attr: []string{"group:mainline"},
Params: []testing.Param{{
Name: "tpm1",
ExtraSoftwareDeps: []string{"tpm1"},
ExtraAttr: []string{"informational"},
Timeout: 4 * time.Minute,
}, {
Name: "vm",
ExtraSoftwareDeps: []string{"tpm2", "qemu"},
ExtraAttr: []string{"informational"},
Timeout: 4 * time.Minute,
}, {
Name: "tpm2",
ExtraSoftwareDeps: []string{"tpm2", "no_qemu"},
// No ExtraAttr; this test is critical.
}},
})
}
// DaemonsRestartStress checks that restarting hwsec daemons wouldn't cause problems.
func DaemonsRestartStress(ctx context.Context, s *testing.State) {
cmdRunner := hwseclocal.NewCmdRunner()
helper, err := hwseclocal.NewHelper(cmdRunner)
if err != nil {
s.Fatal("Failed to create hwsec local helper: ", err)
}
tpmManager := helper.TPMManagerClient()
daemonController := helper.DaemonController()
// Check that lockout shouldn't be in effect.
info, err := tpmManager.GetDAInfo(ctx)
if err != nil {
s.Fatal("Failed to get dictionary attack info: ", err)
}
if info.InEffect {
s.Fatal("Lockout in effect before testing")
}
ctxForResumeDaemons := ctx
ctx, cancel := ctxutil.Shorten(ctx, time.Minute)
defer cancel()
// Drop the DA reset permission.
restorePermCall, err := helper.DropResetLockPermissions(ctx)
if err != nil {
s.Fatal("Failed to drop the DA reset permission: ", err)
}
defer func(ctx context.Context) {
// Restore the DA reset permission.
if err = restorePermCall(ctx); err != nil {
s.Log("Failed to restore lockout permission: ", err)
}
}(ctxForResumeDaemons)
tpmVer, err := helper.GetTPMVersion(ctx)
if err != nil {
s.Fatal("Failed to get TPM version: ", err)
}
// Restart TPM related daemons multiple times.
for i := 0; i < 10; i++ {
func() {
if err := daemonController.Stop(ctx, hwsec.CryptohomeDaemon); err != nil {
s.Fatal("Failed to stop cryptohomed: ", err)
}
defer func() {
if err := daemonController.Start(ctx, hwsec.CryptohomeDaemon); err != nil {
s.Fatal("Failed to start cryptohomed: ", err)
}
}()
if err := daemonController.Stop(ctx, hwsec.AttestationDaemon); err != nil {
s.Fatal("Failed to stop attestationd: ", err)
}
defer func() {
if err := daemonController.Start(ctx, hwsec.AttestationDaemon); err != nil {
s.Fatal("Failed to start attestationd: ", err)
}
}()
if err := daemonController.Stop(ctx, hwsec.TPMManagerDaemon); err != nil {
s.Fatal("Failed to stop tpm_managerd: ", err)
}
defer func() {
if err := daemonController.Start(ctx, hwsec.TPMManagerDaemon); err != nil {
s.Fatal("Failed to start tpm_managerd: ", err)
}
}()
switch tpmVer {
case "1.2":
if daemonController.Restart(ctx, hwsec.TcsdDaemon); err != nil {
s.Fatal("Failed to restart tcsd: ", err)
}
case "2.0":
if daemonController.Restart(ctx, hwsec.TrunksDaemon); err != nil {
s.Fatal("Failed to restart trunksd: ", err)
}
default:
s.Fatal("Unknown TPM version: ")
}
}()
}
// Check counter didn't increase too much, and lockout shouldn't be in effect.
newInfo, err := tpmManager.GetDAInfo(ctx)
if err != nil {
s.Fatal("Failed to get dictionary attack info: ", err)
}
// The counter shouldn't constantly increase when we restart daemons multiple time.
// But it's acceptable to increase a little bit.
// For example: we need one quota to check the validity of empty password.
if newInfo.Counter > info.Counter+1 {
s.Fatalf("Unexpected counter increase, %d -> %d", info.Counter, newInfo.Counter)
}
if newInfo.InEffect {
s.Fatal("Lockout in effect after testing")
}
}