// Copyright 2018 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include <signal.h> #include <stddef.h> #include <sys/syscall.h> #include <unistd.h> #include "gtest/gtest.h" #include "test/util/signal_util.h" #include "test/util/test_util.h" namespace gvisor { namespace testing { namespace { // Signals numbers used for testing. static constexpr int kTestSignal1 = SIGUSR1; static constexpr int kTestSignal2 = SIGUSR2; static int raw_sigprocmask(int how, const sigset_t* set, sigset_t* oldset) { return syscall(SYS_rt_sigprocmask, how, set, oldset, _NSIG / 8); } // count of the number of signals received int signal_count[kMaxSignal + 1]; // signal handler increments the signal counter void SigHandler(int sig, siginfo_t* info, void* context) { TEST_CHECK(sig > 0 && sig <= kMaxSignal); signal_count[sig] += 1; } // The test fixture saves and restores the signal mask and // sets up handlers for kTestSignal1 and kTestSignal2. class SigProcMaskTest : public ::testing::Test { protected: void SetUp() override { // Save the current signal mask. EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &mask_), SyscallSucceeds()); // Setup signal handlers for kTestSignal1 and kTestSignal2. struct sigaction sa; sa.sa_sigaction = SigHandler; sigfillset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; EXPECT_THAT(sigaction(kTestSignal1, &sa, &sa_test_sig_1_), SyscallSucceeds()); EXPECT_THAT(sigaction(kTestSignal2, &sa, &sa_test_sig_2_), SyscallSucceeds()); // Clear the signal counters. memset(signal_count, 0, sizeof(signal_count)); } void TearDown() override { // Restore the signal mask. EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, &mask_, nullptr), SyscallSucceeds()); // Restore the signal handlers for kTestSignal1 and kTestSignal2. EXPECT_THAT(sigaction(kTestSignal1, &sa_test_sig_1_, nullptr), SyscallSucceeds()); EXPECT_THAT(sigaction(kTestSignal2, &sa_test_sig_2_, nullptr), SyscallSucceeds()); } private: sigset_t mask_; struct sigaction sa_test_sig_1_; struct sigaction sa_test_sig_2_; }; // Both sigsets nullptr should succeed and do nothing. TEST_F(SigProcMaskTest, NullAddress) { EXPECT_THAT(raw_sigprocmask(SIG_BLOCK, nullptr, NULL), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_UNBLOCK, nullptr, NULL), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, NULL), SyscallSucceeds()); } // Bad address for either sigset should fail with EFAULT. TEST_F(SigProcMaskTest, BadAddress) { sigset_t* bad_addr = reinterpret_cast<sigset_t*>(-1); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, bad_addr, nullptr), SyscallFailsWithErrno(EFAULT)); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, bad_addr), SyscallFailsWithErrno(EFAULT)); } // Bad value of the "how" parameter should fail with EINVAL. TEST_F(SigProcMaskTest, BadParameter) { int bad_param_1 = -1; int bad_param_2 = 42; sigset_t set1; sigemptyset(&set1); EXPECT_THAT(raw_sigprocmask(bad_param_1, &set1, nullptr), SyscallFailsWithErrno(EINVAL)); EXPECT_THAT(raw_sigprocmask(bad_param_2, &set1, nullptr), SyscallFailsWithErrno(EINVAL)); } // Check that we can get the current signal mask. TEST_F(SigProcMaskTest, GetMask) { sigset_t set1; sigset_t set2; sigemptyset(&set1); sigfillset(&set2); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &set1), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &set2), SyscallSucceeds()); EXPECT_THAT(set1, EqualsSigset(set2)); } // Check that we can set the signal mask. TEST_F(SigProcMaskTest, SetMask) { sigset_t actual; sigset_t expected; // Try to mask all signals sigfillset(&expected); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, &expected, nullptr), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &actual), SyscallSucceeds()); // sigprocmask() should have silently ignored SIGKILL and SIGSTOP. sigdelset(&expected, SIGSTOP); sigdelset(&expected, SIGKILL); EXPECT_THAT(actual, EqualsSigset(expected)); // Try to clear the signal mask sigemptyset(&expected); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, &expected, nullptr), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &actual), SyscallSucceeds()); EXPECT_THAT(actual, EqualsSigset(expected)); // Try to set a mask with one signal. sigemptyset(&expected); sigaddset(&expected, kTestSignal1); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, &expected, nullptr), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &actual), SyscallSucceeds()); EXPECT_THAT(actual, EqualsSigset(expected)); } // Check that we can add and remove signals. TEST_F(SigProcMaskTest, BlockUnblock) { sigset_t actual; sigset_t expected; // Try to set a mask with one signal. sigemptyset(&expected); sigaddset(&expected, kTestSignal1); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, &expected, nullptr), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &actual), SyscallSucceeds()); EXPECT_THAT(actual, EqualsSigset(expected)); // Try to add another signal. sigset_t block; sigemptyset(&block); sigaddset(&block, kTestSignal2); EXPECT_THAT(raw_sigprocmask(SIG_BLOCK, &block, nullptr), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &actual), SyscallSucceeds()); sigaddset(&expected, kTestSignal2); EXPECT_THAT(actual, EqualsSigset(expected)); // Try to remove a signal. sigset_t unblock; sigemptyset(&unblock); sigaddset(&unblock, kTestSignal1); EXPECT_THAT(raw_sigprocmask(SIG_UNBLOCK, &unblock, nullptr), SyscallSucceeds()); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, nullptr, &actual), SyscallSucceeds()); sigdelset(&expected, kTestSignal1); EXPECT_THAT(actual, EqualsSigset(expected)); } // Test that the signal mask actually blocks signals. TEST_F(SigProcMaskTest, SignalHandler) { sigset_t mask; // clear the signal mask sigemptyset(&mask); EXPECT_THAT(raw_sigprocmask(SIG_SETMASK, &mask, nullptr), SyscallSucceeds()); // Check the initial signal counts. EXPECT_EQ(0, signal_count[kTestSignal1]); EXPECT_EQ(0, signal_count[kTestSignal2]); // Check that both kTestSignal1 and kTestSignal2 are not blocked. raise(kTestSignal1); raise(kTestSignal2); EXPECT_EQ(1, signal_count[kTestSignal1]); EXPECT_EQ(1, signal_count[kTestSignal2]); // Block kTestSignal1. sigaddset(&mask, kTestSignal1); EXPECT_THAT(raw_sigprocmask(SIG_BLOCK, &mask, nullptr), SyscallSucceeds()); // Check that kTestSignal1 is blocked. raise(kTestSignal1); raise(kTestSignal2); EXPECT_EQ(1, signal_count[kTestSignal1]); EXPECT_EQ(2, signal_count[kTestSignal2]); // Unblock kTestSignal1. sigaddset(&mask, kTestSignal1); EXPECT_THAT(raw_sigprocmask(SIG_UNBLOCK, &mask, nullptr), SyscallSucceeds()); // Check that the unblocked kTestSignal1 has been delivered. EXPECT_EQ(2, signal_count[kTestSignal1]); EXPECT_EQ(2, signal_count[kTestSignal2]); } // Check that sigprocmask correctly handles aliasing of the set and oldset // pointers. TEST_F(SigProcMaskTest, AliasedSets) { sigset_t mask; // Set a mask in which only kTestSignal1 is blocked. sigset_t mask1; sigemptyset(&mask1); sigaddset(&mask1, kTestSignal1); mask = mask1; ASSERT_THAT(raw_sigprocmask(SIG_SETMASK, &mask, nullptr), SyscallSucceeds()); // Exchange it with a mask in which only kTestSignal2 is blocked. sigset_t mask2; sigemptyset(&mask2); sigaddset(&mask2, kTestSignal2); mask = mask2; ASSERT_THAT(raw_sigprocmask(SIG_SETMASK, &mask, &mask), SyscallSucceeds()); // Check that the exchange succeeeded: // mask should now contain the previously-set mask blocking only kTestSignal1. EXPECT_THAT(mask, EqualsSigset(mask1)); // The current mask should block only kTestSignal2. ASSERT_THAT(raw_sigprocmask(0, nullptr, &mask), SyscallSucceeds()); EXPECT_THAT(mask, EqualsSigset(mask2)); } } // namespace } // namespace testing } // namespace gvisor