17
17
#include < errno.h>
18
18
#include < fcntl.h>
19
19
#include < sys/eventfd.h>
20
+ #include < sys/mman.h>
20
21
#include < sys/ptrace.h>
21
22
#include < sys/resource.h>
22
23
#include < sys/time.h>
33
34
#include " gmock/gmock.h"
34
35
#include " gtest/gtest.h"
35
36
#include " absl/strings/match.h"
37
+ #include " absl/strings/numbers.h"
36
38
#include " absl/strings/str_cat.h"
39
+ #include " absl/strings/str_format.h"
37
40
#include " absl/strings/str_split.h"
38
41
#include " absl/strings/string_view.h"
39
42
#include " absl/synchronization/mutex.h"
40
43
#include " absl/types/optional.h"
41
44
#include " test/util/file_descriptor.h"
42
45
#include " test/util/fs_util.h"
46
+ #include " test/util/logging.h"
47
+ #include " test/util/memory_util.h"
43
48
#include " test/util/multiprocess_util.h"
44
49
#include " test/util/posix_error.h"
50
+ #include " test/util/save_util.h"
45
51
#include " test/util/temp_path.h"
46
52
#include " test/util/test_util.h"
47
53
#include " test/util/thread_util.h"
@@ -63,6 +69,9 @@ constexpr char kPriorityWorkload[] = "test/syscalls/linux/priority_execve";
63
69
constexpr char kExit42 [] = " --exec_exit_42" ;
64
70
constexpr char kExecWithThread [] = " --exec_exec_with_thread" ;
65
71
constexpr char kExecFromThread [] = " --exec_exec_from_thread" ;
72
+ constexpr char kExecInParent [] = " --exec_exec_in_parent" ;
73
+ constexpr char kWriteAndWaitForPid [] = " --exec_write_and_wait_for_pid" ;
74
+ const unsigned int mmapAddr = 0xD0000000 ;
66
75
67
76
// Runs file specified by dirfd and pathname with argv and checks that the exit
68
77
// status is expect_status and that stderr contains expect_stderr.
@@ -851,6 +860,75 @@ TEST(ExecTest, Setpgid) {
851
860
EXPECT_THAT (setpgid (getpid (), pid), SyscallSucceeds ());
852
861
}
853
862
863
+ TEST (ExecTest, ReadProcMemAfterExecFromChild) {
864
+ // Fork and exec in the parent process.
865
+ CheckExec (" /proc/self/exe" , {" /proc/self/exe" , kExecInParent }, {},
866
+ W_EXITCODE (42 , 0 ), " " );
867
+ }
868
+
869
+ void execInParent () {
870
+ auto memfd = ASSERT_NO_ERRNO_AND_VALUE (Open (" /proc/self/mem" , O_RDONLY));
871
+ int pipe_fd[2 ] = {};
872
+ ASSERT_THAT (pipe (pipe_fd), SyscallSucceeds ());
873
+
874
+ const auto readSecret = [&] {
875
+ // Close writing end of the pipe.
876
+ close (pipe_fd[1 ]);
877
+ // Await parent OK to read the secret.
878
+ char ok = 0 ;
879
+ TEST_CHECK (ReadFd (pipe_fd[0 ], &ok, sizeof (ok)) == sizeof (ok));
880
+ // Close the reading end of the pipe.
881
+ TEST_PCHECK (close (pipe_fd[0 ]) == 0 );
882
+ // Parent sent the signal. Read the secret.
883
+ // Use /proc/mem fd from parent to try to read the secret.
884
+ char secret[] = " secret" ;
885
+ char output[sizeof (secret)];
886
+ TEST_PCHECK_MSG (
887
+ pread (memfd.get (), output, sizeof (output), mmapAddr) != sizeof (secret),
888
+ " pread succeeded. It should have failed." );
889
+ };
890
+ pid_t pid = fork ();
891
+ // In child process.
892
+ if (pid == 0 ) {
893
+ readSecret ();
894
+ TEST_CHECK_MSG (!::testing::Test::HasFailure (),
895
+ " EXPECT*/ASSERT* failed. These are not async-signal-safe "
896
+ " and must not be called from fn." );
897
+ _exit (0 );
898
+ }
899
+ // In parent process.
900
+ MaybeSave ();
901
+ ASSERT_THAT (pid, SyscallSucceeds ());
902
+
903
+ // Execve with args{function name, child_pid, pipe_fd[1]}
904
+ const ExecveArray argv = {" /proc/self/exe" , kWriteAndWaitForPid ,
905
+ absl::StrCat (pid) /* child_pid*/ ,
906
+ absl::StrCat (pipe_fd[1 ])};
907
+ const ExecveArray envv;
908
+ execve (" /proc/self/exe" , argv.get (), envv.get ());
909
+ }
910
+
911
+ void writeAndWaitForPid (int child_pid, int pipe_fd) {
912
+ // mmap the same address that the child process will try to read.
913
+ const Mapping m = ASSERT_NO_ERRNO_AND_VALUE (
914
+ Mmap (reinterpret_cast <void *>(mmapAddr), kPageSize , PROT_READ | PROT_WRITE,
915
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1 , 0 ));
916
+ const char secret[] = " secret" ;
917
+ absl::SNPrintF ((char *)m.addr (), sizeof (secret), " %s" , secret);
918
+
919
+ // Tell the child process to read the secret.
920
+ char ok = 1 ;
921
+ EXPECT_THAT (WriteFd (pipe_fd, &ok, sizeof (ok)),
922
+ SyscallSucceedsWithValue (sizeof (ok)));
923
+ EXPECT_THAT (close (pipe_fd), SyscallSucceeds ());
924
+
925
+ // Wait for child process to read the exit.
926
+ int status;
927
+ ASSERT_THAT (waitpid (child_pid, &status, 0 ), SyscallSucceeds ());
928
+ ASSERT_TRUE (WIFEXITED (status) && WEXITSTATUS (status) == 0 );
929
+ exit (42 );
930
+ }
931
+
854
932
void ExecWithThread () {
855
933
// Used to ensure that the thread has actually started.
856
934
absl::Mutex mu;
@@ -948,6 +1026,22 @@ int main(int argc, char** argv) {
948
1026
gvisor::testing::ExecFromThread ();
949
1027
return 1 ;
950
1028
}
1029
+ if (arg == gvisor::testing::kExecInParent ) {
1030
+ gvisor::testing::execInParent ();
1031
+ return 1 ;
1032
+ }
1033
+ if (arg == gvisor::testing::kWriteAndWaitForPid ) {
1034
+ int pid;
1035
+ if (!absl::SimpleAtoi (argv[i + 1 ], &pid)) {
1036
+ return 1 ;
1037
+ }
1038
+ int fd;
1039
+ if (!absl::SimpleAtoi (argv[i + 2 ], &fd)) {
1040
+ return 1 ;
1041
+ }
1042
+ gvisor::testing::writeAndWaitForPid (pid, fd);
1043
+ return 1 ;
1044
+ }
951
1045
}
952
1046
953
1047
gvisor::testing::TestInit (&argc, &argv);
0 commit comments