1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/*
* SPDX-FileCopyrightText: 2017 Francis Deslauriers <francis.deslauriers@efficios.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "utils.h"
#include <common/align.hpp>
#include <common/error.hpp>
#include <fcntl.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#define MAX_LEN 16
/*
* The LTTng system call tracing facilities can't handle page faults at the
* moment. If a fault would occur while reading a syscall argument, the
* tracer will report an empty string (""). Since the proper execution of the
* tests which use this generator depends on some syscall string arguments being
* present, this util allows us to mitigate the page-fault risk.
*
* This isn't a proper fix; it is simply the best we can do for now.
* See bug #1261 for more context.
*/
static void prefault_string(const char *p)
{
const char *const end = p + strlen(p) + 1;
while (p < end) {
/*
* Trigger a read attempt on *p, faulting-in the pages
* for reading.
*/
asm volatile("" : : "m"(*p));
p += sysconf(_SC_PAGE_SIZE);
}
}
static int open_read_close(const char *path)
{
int fd, ret;
char buf[MAX_LEN];
/*
* Start generating syscalls. We use syscall(2) to prevent libc from
* changing the underlying syscall (e.g. calling openat(2) instead of
* open(2)).
*/
prefault_string(path);
fd = syscall(SYS_openat, AT_FDCWD, path, O_RDONLY);
if (fd < 0) {
PERROR_NO_LOGGER("Failed to open file with openat(): path = '%s'", path);
ret = -1;
goto error;
}
ret = syscall(SYS_read, fd, buf, MAX_LEN);
if (ret < 0) {
PERROR_NO_LOGGER("Failed to read file: path = '%s', fd = %d, length = %d",
path,
fd,
MAX_LEN);
ret = -1;
goto error;
}
ret = syscall(SYS_close, fd);
if (ret == -1) {
PERROR_NO_LOGGER("Failed to close file: path = '%s', fd = %d", path, fd);
ret = -1;
goto error;
}
error:
return ret;
}
/*
* The process waits for the creation of a file passed as argument from an
* external processes to execute a syscall and exiting. This is useful for tests
* in combinaison with LTTng's PID tracker feature where we can trace the kernel
* events generated by our test process only.
*/
int main(int argc, char **argv)
{
int ret;
const char *start_file, *path1, *path2;
if (argc != 4) {
fprintf(stderr, "Error: Missing argument\n");
fprintf(stderr, "USAGE: %s PATH_WAIT_FILE PATH1_TO_OPEN PATH2_TO_OPEN\n", argv[0]);
ret = -1;
goto error;
}
start_file = argv[1];
path1 = argv[2];
path2 = argv[3];
/*
* Wait for the start_file to be created by an external process
* (typically the test script) before executing the syscalls.
*/
ret = wait_on_file(start_file);
if (ret != 0) {
goto error;
}
/*
* Start generating syscalls. We use syscall(2) to prevent libc to change
* the underlying syscall. e.g. calling openat(2) instead of open(2).
*/
ret = open_read_close(path1);
if (ret == -1) {
ret = -1;
goto error;
}
ret = open_read_close(path2);
if (ret == -1) {
ret = -1;
goto error;
}
error:
return ret;
}
|