| /* |
| * 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 <err.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/mman.h> |
| #include <sys/uio.h> |
| #include <sys/wait.h> |
| #include <unistd.h> |
| |
| #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); |
| } |