Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <spawn.h>
     18 
     19 #include <errno.h>
     20 #include <fcntl.h>
     21 #include <gtest/gtest.h>
     22 
     23 #include "ScopedSignalHandler.h"
     24 #include "utils.h"
     25 
     26 #include <android-base/file.h>
     27 #include <android-base/strings.h>
     28 
     29 // Old versions of glibc didn't have POSIX_SPAWN_SETSID.
     30 #if __GLIBC__
     31 # if !defined(POSIX_SPAWN_SETSID)
     32 #  define POSIX_SPAWN_SETSID 0
     33 # endif
     34 #endif
     35 
     36 TEST(spawn, posix_spawnattr_init_posix_spawnattr_destroy) {
     37   posix_spawnattr_t sa;
     38   ASSERT_EQ(0, posix_spawnattr_init(&sa));
     39   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
     40 }
     41 
     42 TEST(spawn, posix_spawnattr_setflags_EINVAL) {
     43   posix_spawnattr_t sa;
     44   ASSERT_EQ(0, posix_spawnattr_init(&sa));
     45   ASSERT_EQ(EINVAL, posix_spawnattr_setflags(&sa, ~0));
     46   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
     47 }
     48 
     49 TEST(spawn, posix_spawnattr_setflags_posix_spawnattr_getflags) {
     50   posix_spawnattr_t sa;
     51   ASSERT_EQ(0, posix_spawnattr_init(&sa));
     52 
     53   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_RESETIDS));
     54   short flags;
     55   ASSERT_EQ(0, posix_spawnattr_getflags(&sa, &flags));
     56   ASSERT_EQ(POSIX_SPAWN_RESETIDS, flags);
     57 
     58   constexpr short all_flags = POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF |
     59                               POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSCHEDPARAM |
     60                               POSIX_SPAWN_SETSCHEDULER | POSIX_SPAWN_USEVFORK | POSIX_SPAWN_SETSID;
     61   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, all_flags));
     62   ASSERT_EQ(0, posix_spawnattr_getflags(&sa, &flags));
     63   ASSERT_EQ(all_flags, flags);
     64 
     65   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
     66 }
     67 
     68 TEST(spawn, posix_spawnattr_setpgroup_posix_spawnattr_getpgroup) {
     69   posix_spawnattr_t sa;
     70   ASSERT_EQ(0, posix_spawnattr_init(&sa));
     71 
     72   ASSERT_EQ(0, posix_spawnattr_setpgroup(&sa, 123));
     73   pid_t g;
     74   ASSERT_EQ(0, posix_spawnattr_getpgroup(&sa, &g));
     75   ASSERT_EQ(123, g);
     76 
     77   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
     78 }
     79 
     80 TEST(spawn, posix_spawnattr_setsigmask_posix_spawnattr_getsigmask) {
     81   posix_spawnattr_t sa;
     82   ASSERT_EQ(0, posix_spawnattr_init(&sa));
     83 
     84   sigset_t sigs;
     85   ASSERT_EQ(0, posix_spawnattr_getsigmask(&sa, &sigs));
     86   ASSERT_FALSE(sigismember(&sigs, SIGALRM));
     87 
     88   sigset_t just_SIGALRM;
     89   sigemptyset(&just_SIGALRM);
     90   sigaddset(&just_SIGALRM, SIGALRM);
     91   ASSERT_EQ(0, posix_spawnattr_setsigmask(&sa, &just_SIGALRM));
     92 
     93   ASSERT_EQ(0, posix_spawnattr_getsigmask(&sa, &sigs));
     94   ASSERT_TRUE(sigismember(&sigs, SIGALRM));
     95 
     96   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
     97 }
     98 
     99 TEST(spawn, posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64) {
    100   posix_spawnattr_t sa;
    101   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    102 
    103   sigset64_t sigs;
    104   ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
    105   ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
    106 
    107   sigset64_t just_SIGRTMIN;
    108   sigemptyset64(&just_SIGRTMIN);
    109   sigaddset64(&just_SIGRTMIN, SIGRTMIN);
    110   ASSERT_EQ(0, posix_spawnattr_setsigmask64(&sa, &just_SIGRTMIN));
    111 
    112   ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
    113   ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
    114 
    115   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    116 }
    117 
    118 TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) {
    119   posix_spawnattr_t sa;
    120   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    121 
    122   sigset_t sigs;
    123   ASSERT_EQ(0, posix_spawnattr_getsigdefault(&sa, &sigs));
    124   ASSERT_FALSE(sigismember(&sigs, SIGALRM));
    125 
    126   sigset_t just_SIGALRM;
    127   sigemptyset(&just_SIGALRM);
    128   sigaddset(&just_SIGALRM, SIGALRM);
    129   ASSERT_EQ(0, posix_spawnattr_setsigdefault(&sa, &just_SIGALRM));
    130 
    131   ASSERT_EQ(0, posix_spawnattr_getsigdefault(&sa, &sigs));
    132   ASSERT_TRUE(sigismember(&sigs, SIGALRM));
    133 
    134   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    135 }
    136 
    137 TEST(spawn, posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64) {
    138   posix_spawnattr_t sa;
    139   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    140 
    141   sigset64_t sigs;
    142   ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
    143   ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
    144 
    145   sigset64_t just_SIGRTMIN;
    146   sigemptyset64(&just_SIGRTMIN);
    147   sigaddset64(&just_SIGRTMIN, SIGRTMIN);
    148   ASSERT_EQ(0, posix_spawnattr_setsigdefault64(&sa, &just_SIGRTMIN));
    149 
    150   ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
    151   ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
    152 
    153   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    154 }
    155 
    156 TEST(spawn, posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam) {
    157   posix_spawnattr_t sa;
    158   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    159 
    160   sched_param sp;
    161   ASSERT_EQ(0, posix_spawnattr_getschedparam(&sa, &sp));
    162   ASSERT_EQ(0, sp.sched_priority);
    163 
    164   sched_param sp123 = { .sched_priority = 123 };
    165   ASSERT_EQ(0, posix_spawnattr_setschedparam(&sa, &sp123));
    166 
    167   ASSERT_EQ(0, posix_spawnattr_getschedparam(&sa, &sp));
    168   ASSERT_EQ(123, sp.sched_priority);
    169 
    170   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    171 }
    172 
    173 TEST(spawn, posix_spawnattr_setschedpolicy_posix_spawnattr_getschedpolicy) {
    174   posix_spawnattr_t sa;
    175   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    176 
    177   int p;
    178   ASSERT_EQ(0, posix_spawnattr_getschedpolicy(&sa, &p));
    179   ASSERT_EQ(0, p);
    180 
    181   ASSERT_EQ(0, posix_spawnattr_setschedpolicy(&sa, SCHED_FIFO));
    182 
    183   ASSERT_EQ(0, posix_spawnattr_getschedpolicy(&sa, &p));
    184   ASSERT_EQ(SCHED_FIFO, p);
    185 
    186   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    187 }
    188 
    189 TEST(spawn, posix_spawn) {
    190   ExecTestHelper eth;
    191   eth.SetArgs({BIN_DIR "true", nullptr});
    192   pid_t pid;
    193   ASSERT_EQ(0, posix_spawn(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
    194   AssertChildExited(pid, 0);
    195 }
    196 
    197 TEST(spawn, posix_spawn_not_found) {
    198   ExecTestHelper eth;
    199   eth.SetArgs({"true", nullptr});
    200   pid_t pid;
    201   ASSERT_EQ(0, posix_spawn(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
    202   AssertChildExited(pid, 127);
    203 }
    204 
    205 TEST(spawn, posix_spawnp) {
    206   ExecTestHelper eth;
    207   eth.SetArgs({"true", nullptr});
    208   pid_t pid;
    209   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
    210   AssertChildExited(pid, 0);
    211 }
    212 
    213 TEST(spawn, posix_spawnp_not_found) {
    214   ExecTestHelper eth;
    215   eth.SetArgs({"does-not-exist", nullptr});
    216   pid_t pid;
    217   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
    218   AssertChildExited(pid, 127);
    219 }
    220 
    221 TEST(spawn, posix_spawn_environment) {
    222   ExecTestHelper eth;
    223   eth.SetArgs({"sh", "-c", "exit $posix_spawn_environment_test", nullptr});
    224   eth.SetEnv({"posix_spawn_environment_test=66", nullptr});
    225   pid_t pid;
    226   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), eth.GetEnv()));
    227   AssertChildExited(pid, 66);
    228 }
    229 
    230 TEST(spawn, posix_spawn_file_actions) {
    231   int fds[2];
    232   ASSERT_NE(-1, pipe(fds));
    233 
    234   posix_spawn_file_actions_t fa;
    235   ASSERT_EQ(0, posix_spawn_file_actions_init(&fa));
    236 
    237   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
    238   ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
    239   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
    240   // Check that close(2) failures are ignored by closing the same fd again.
    241   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
    242   ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 56, "/proc/version", O_RDONLY, 0));
    243 
    244   ExecTestHelper eth;
    245   eth.SetArgs({"ls", "-l", "/proc/self/fd", nullptr});
    246   pid_t pid;
    247   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), &fa, nullptr, eth.GetArgs(), eth.GetEnv()));
    248   ASSERT_EQ(0, posix_spawn_file_actions_destroy(&fa));
    249 
    250   ASSERT_EQ(0, close(fds[1]));
    251   std::string content;
    252   ASSERT_TRUE(android::base::ReadFdToString(fds[0], &content));
    253   ASSERT_EQ(0, close(fds[0]));
    254 
    255   AssertChildExited(pid, 0);
    256 
    257   // We'll know the dup2 worked if we see any ls(1) output in our pipe.
    258   // The open we can check manually...
    259   bool open_to_fd_56_worked = false;
    260   for (const auto& line : android::base::Split(content, "\n")) {
    261     if (line.find(" 56 -> /proc/version") != std::string::npos) open_to_fd_56_worked = true;
    262   }
    263   ASSERT_TRUE(open_to_fd_56_worked);
    264 }
    265 
    266 static void CatFileToString(posix_spawnattr_t* sa, const char* path, std::string* content) {
    267   int fds[2];
    268   ASSERT_NE(-1, pipe(fds));
    269 
    270   posix_spawn_file_actions_t fa;
    271   ASSERT_EQ(0, posix_spawn_file_actions_init(&fa));
    272   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
    273   ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
    274   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
    275 
    276   ExecTestHelper eth;
    277   eth.SetArgs({"cat", path, nullptr});
    278   pid_t pid;
    279   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), &fa, sa, eth.GetArgs(), nullptr));
    280   ASSERT_EQ(0, posix_spawn_file_actions_destroy(&fa));
    281 
    282   ASSERT_EQ(0, close(fds[1]));
    283   ASSERT_TRUE(android::base::ReadFdToString(fds[0], content));
    284   ASSERT_EQ(0, close(fds[0]));
    285   AssertChildExited(pid, 0);
    286 }
    287 
    288 struct ProcStat {
    289   pid_t pid;
    290   pid_t ppid;
    291   pid_t pgrp;
    292   pid_t sid;
    293 };
    294 
    295 static void GetChildStat(posix_spawnattr_t* sa, ProcStat* ps) {
    296   std::string content;
    297   CatFileToString(sa, "/proc/self/stat", &content);
    298 
    299   ASSERT_EQ(4, sscanf(content.c_str(), "%d (cat) %*c %d %d %d", &ps->pid, &ps->ppid, &ps->pgrp,
    300                       &ps->sid));
    301 
    302   ASSERT_EQ(getpid(), ps->ppid);
    303 }
    304 
    305 struct ProcStatus {
    306   uint64_t sigblk;
    307   uint64_t sigign;
    308 };
    309 
    310 static void GetChildStatus(posix_spawnattr_t* sa, ProcStatus* ps) {
    311   std::string content;
    312   CatFileToString(sa, "/proc/self/status", &content);
    313 
    314   bool saw_blk = false;
    315   bool saw_ign = false;
    316   for (const auto& line : android::base::Split(content, "\n")) {
    317     if (sscanf(line.c_str(), "SigBlk: %" SCNx64, &ps->sigblk) == 1) saw_blk = true;
    318     if (sscanf(line.c_str(), "SigIgn: %" SCNx64, &ps->sigign) == 1) saw_ign = true;
    319   }
    320   ASSERT_TRUE(saw_blk);
    321   ASSERT_TRUE(saw_ign);
    322 }
    323 
    324 TEST(spawn, posix_spawn_POSIX_SPAWN_SETSID_clear) {
    325   pid_t parent_sid = getsid(0);
    326 
    327   posix_spawnattr_t sa;
    328   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    329   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, 0));
    330 
    331   ProcStat ps = {};
    332   GetChildStat(&sa, &ps);
    333   ASSERT_EQ(parent_sid, ps.sid);
    334   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    335 }
    336 
    337 TEST(spawn, posix_spawn_POSIX_SPAWN_SETSID_set) {
    338   pid_t parent_sid = getsid(0);
    339 
    340   posix_spawnattr_t sa;
    341   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    342   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSID));
    343 
    344   ProcStat ps = {};
    345   GetChildStat(&sa, &ps);
    346   ASSERT_NE(parent_sid, ps.sid);
    347   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    348 }
    349 
    350 TEST(spawn, posix_spawn_POSIX_SPAWN_SETPGROUP_clear) {
    351   pid_t parent_pgrp = getpgrp();
    352 
    353   posix_spawnattr_t sa;
    354   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    355   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, 0));
    356 
    357   ProcStat ps = {};
    358   GetChildStat(&sa, &ps);
    359   ASSERT_EQ(parent_pgrp, ps.pgrp);
    360   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    361 }
    362 
    363 TEST(spawn, posix_spawn_POSIX_SPAWN_SETPGROUP_set) {
    364   pid_t parent_pgrp = getpgrp();
    365 
    366   posix_spawnattr_t sa;
    367   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    368   ASSERT_EQ(0, posix_spawnattr_setpgroup(&sa, 0));
    369   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETPGROUP));
    370 
    371   ProcStat ps = {};
    372   GetChildStat(&sa, &ps);
    373   ASSERT_NE(parent_pgrp, ps.pgrp);
    374   // Setting pgid 0 means "the same as the caller's pid".
    375   ASSERT_EQ(ps.pid, ps.pgrp);
    376   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    377 }
    378 
    379 TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGMASK) {
    380   // Block SIGBUS in the parent...
    381   sigset_t just_SIGBUS;
    382   sigemptyset(&just_SIGBUS);
    383   sigaddset(&just_SIGBUS, SIGBUS);
    384   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGBUS, nullptr));
    385 
    386   posix_spawnattr_t sa;
    387   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    388 
    389   // Ask for only SIGALRM to be blocked in the child...
    390   sigset_t just_SIGALRM;
    391   sigemptyset(&just_SIGALRM);
    392   sigaddset(&just_SIGALRM, SIGALRM);
    393   ASSERT_EQ(0, posix_spawnattr_setsigmask(&sa, &just_SIGALRM));
    394   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGMASK));
    395 
    396   // Check that's what happens...
    397   ProcStatus ps = {};
    398   GetChildStatus(&sa, &ps);
    399   EXPECT_EQ(static_cast<uint64_t>(1 << (SIGALRM - 1)), ps.sigblk);
    400   EXPECT_EQ(static_cast<uint64_t>(0), ps.sigign);
    401 
    402   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    403 }
    404 
    405 TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGDEF) {
    406   // Ignore SIGALRM and SIGCONT in the parent...
    407   ASSERT_NE(SIG_ERR, signal(SIGALRM, SIG_IGN));
    408   ASSERT_NE(SIG_ERR, signal(SIGCONT, SIG_IGN));
    409 
    410   posix_spawnattr_t sa;
    411   ASSERT_EQ(0, posix_spawnattr_init(&sa));
    412 
    413   // Ask for SIGALRM to be defaulted in the child...
    414   sigset_t just_SIGALRM;
    415   sigemptyset(&just_SIGALRM);
    416   sigaddset(&just_SIGALRM, SIGALRM);
    417 
    418   ASSERT_EQ(0, posix_spawnattr_setsigdefault(&sa, &just_SIGALRM));
    419   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGDEF));
    420 
    421   // Check that's what happens...
    422   ProcStatus ps = {};
    423   GetChildStatus(&sa, &ps);
    424   EXPECT_EQ(static_cast<uint64_t>(0), ps.sigblk);
    425   EXPECT_EQ(static_cast<uint64_t>(1 << (SIGCONT - 1)), ps.sigign);
    426 
    427   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
    428 }
    429 
    430 TEST(spawn, signal_stress) {
    431   // Ensure that posix_spawn doesn't restore the caller's signal mask in the
    432   // child without first defaulting any caught signals (http://b/68707996).
    433   static pid_t parent = getpid();
    434 
    435   setpgid(0, 0);
    436   signal(SIGRTMIN, SIG_IGN);
    437 
    438   pid_t pid = fork();
    439   ASSERT_NE(-1, pid);
    440 
    441   if (pid == 0) {
    442     for (size_t i = 0; i < 1024; ++i) {
    443       kill(0, SIGRTMIN);
    444       usleep(10);
    445     }
    446     _exit(99);
    447   }
    448 
    449   // We test both with and without attributes, because they used to be
    450   // different codepaths. We also test with an empty `sigdefault` set.
    451   posix_spawnattr_t attr1;
    452   posix_spawnattr_init(&attr1);
    453 
    454   sigset_t empty_mask = {};
    455   posix_spawnattr_t attr2;
    456   posix_spawnattr_init(&attr2);
    457   posix_spawnattr_setflags(&attr2, POSIX_SPAWN_SETSIGDEF);
    458   posix_spawnattr_setsigdefault(&attr2, &empty_mask);
    459 
    460   posix_spawnattr_t* attrs[] = { nullptr, &attr1, &attr2 };
    461 
    462   // We use a real-time signal because that's a tricky case for LP32
    463   // because our sigset_t was too small.
    464   ScopedSignalHandler ssh(SIGRTMIN, [](int) { ASSERT_EQ(getpid(), parent); });
    465 
    466   const size_t pid_count = 128;
    467   pid_t spawned_pids[pid_count];
    468 
    469   ExecTestHelper eth;
    470   eth.SetArgs({"true", nullptr});
    471   for (size_t i = 0; i < pid_count; ++i) {
    472     pid_t spawned_pid;
    473     ASSERT_EQ(0, posix_spawn(&spawned_pid, "true", nullptr, attrs[i % 3], eth.GetArgs(), nullptr));
    474     spawned_pids[i] = spawned_pid;
    475   }
    476 
    477   for (pid_t spawned_pid : spawned_pids) {
    478     ASSERT_EQ(spawned_pid, TEMP_FAILURE_RETRY(waitpid(spawned_pid, nullptr, 0)));
    479   }
    480 
    481   AssertChildExited(pid, 99);
    482 }
    483