|
Packit |
4f15d5 |
# -*- Autotest -*-
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_BANNER([/proc helpers])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## -------------------- ##
|
|
Packit |
4f15d5 |
## get_env_variable_ext ##
|
|
Packit |
4f15d5 |
## -------------------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_env_variable_ext],
|
|
Packit |
4f15d5 |
[[
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void test_delim(char delim)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
const char *test_data[][2] = {
|
|
Packit |
4f15d5 |
{ "EMPTY", "" },
|
|
Packit |
4f15d5 |
{ "SATYR", "awesome" },
|
|
Packit |
4f15d5 |
{ "STUFF", "" },
|
|
Packit |
4f15d5 |
{ "OPENSOURCE", "brilliant" },
|
|
Packit |
4f15d5 |
{ "LIBREPORT", "great" },
|
|
Packit |
4f15d5 |
{ "TRICK", "" },
|
|
Packit |
4f15d5 |
{ "ABRT", "fabulous" },
|
|
Packit |
4f15d5 |
{ "SENTINEL", NULL}
|
|
Packit |
4f15d5 |
};
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char fdname[] = "/tmp/libreprt-testsuite.XXXXXX";
|
|
Packit |
4f15d5 |
int fd = mkstemp(fdname);
|
|
Packit |
4f15d5 |
assert(fd >= 0);
|
|
Packit |
4f15d5 |
printf("Temporary file: %s\n", fdname);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int fddup = dup(fd);
|
|
Packit |
4f15d5 |
assert(fddup >= 0);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
FILE *f = fdopen(fddup, "w");
|
|
Packit |
4f15d5 |
assert(f);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
for (size_t i = 0; i < ARRAY_SIZE(test_data); ++i)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (test_data[i][1] == NULL)
|
|
Packit |
4f15d5 |
continue;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fprintf(f, "%s=%s", test_data[i][0], test_data[i][1]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Do not add delimiter after the last entry */
|
|
Packit |
4f15d5 |
if (i < ARRAY_SIZE(test_data) - 1)
|
|
Packit |
4f15d5 |
fputc(delim, f);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fclose(f);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
for (size_t i = ARRAY_SIZE(test_data); i != 0; --i)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
lseek(fd, 0, SEEK_SET);
|
|
Packit |
4f15d5 |
char *value = NULL;
|
|
Packit |
4f15d5 |
printf("Looking for '%s'\n", test_data[i-1][0]);
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(get_env_variable_ext(fd, delim, test_data[i-1][0], &value));
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(value, test_data[i-1][1], "Environment value at 'i'");
|
|
Packit |
4f15d5 |
free(value);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(fd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
test_delim('\n');
|
|
Packit |
4f15d5 |
test_delim('\0');
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ---------------- ##
|
|
Packit |
4f15d5 |
## get_env_variable ##
|
|
Packit |
4f15d5 |
## ---------------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_env_variable],
|
|
Packit |
4f15d5 |
[[
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char cwd[257];
|
|
Packit |
4f15d5 |
getcwd(cwd, sizeof(cwd));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *value = NULL;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(get_env_variable(getpid(), "PWD", &value));
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(value, cwd, "Test environment variable - PWD");
|
|
Packit |
4f15d5 |
free(value);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ----------- ##
|
|
Packit |
4f15d5 |
## get_cmdline ##
|
|
Packit |
4f15d5 |
## ----------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_cmdline], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void test(const char *program, const char *args[], const char *expected)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int inout[2];
|
|
Packit |
4f15d5 |
xpipe(inout);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
pid_t pid = fork();
|
|
Packit |
4f15d5 |
if (pid < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "fork");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (pid == 0) {
|
|
Packit |
4f15d5 |
close(STDOUT_FILENO);
|
|
Packit |
4f15d5 |
xdup2(inout[1], STDOUT_FILENO);
|
|
Packit |
4f15d5 |
close(inout[0]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
execv(program, (char **)args);
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "exec(%s)", program);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(inout[1]);
|
|
Packit |
4f15d5 |
int status = 0;
|
|
Packit |
4f15d5 |
if (safe_waitpid(pid, &status, 0) < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "waitpid");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (WEXITSTATUS(status) != 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "Child not exited with 0");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const size_t buffer_size = strlen(expected) * 2;
|
|
Packit |
4f15d5 |
char cmdline[buffer_size];
|
|
Packit |
4f15d5 |
const ssize_t total = full_read(inout[0], cmdline, buffer_size);
|
|
Packit |
4f15d5 |
close(inout[0]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (total < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "full_read");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
cmdline[total] = '\0';
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(cmdline, expected, "/proc/[pid]/cmd");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (argc > 1) {
|
|
Packit |
4f15d5 |
char *cmdline = NULL;
|
|
Packit |
4f15d5 |
if (strcmp(argv[0], "get_cmdline") == 0) {
|
|
Packit |
4f15d5 |
cmdline = get_cmdline(getpid());
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else if (strcmp(argv[0], "get_cmdline_at") == 0) {
|
|
Packit |
4f15d5 |
int pid_proc_fd = open("/proc/self", O_DIRECTORY);
|
|
Packit |
4f15d5 |
if (pid_proc_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open(/proc/self, O_DIRECTORY)");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
cmdline = get_cmdline_at(pid_proc_fd);
|
|
Packit |
4f15d5 |
close(pid_proc_fd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "Unsupported function type '%s'", argv[0]);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fprintf(stdout, "%s", cmdline);
|
|
Packit |
4f15d5 |
fflush(stdout);
|
|
Packit |
4f15d5 |
exit(EXIT_SUCCESS);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *binary = malloc_readlink("/proc/self/exe");
|
|
Packit |
4f15d5 |
const char *args[] = { NULL, "!fo\" \"o", "@blah", "b\na'r", "g\rea\t", "regular", NULL };
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#define EXPECTED " '!fo\\\" \\\"o' @blah 'b\\na\\'r' 'g\\rea\\t' regular"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
args[0] = "get_cmdline";
|
|
Packit |
4f15d5 |
test(binary, args, "get_cmdline" EXPECTED);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
args[0] = "get_cmdline_at";
|
|
Packit |
4f15d5 |
test(binary, args, "get_cmdline_at" EXPECTED);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free(binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## -------------- ##
|
|
Packit |
4f15d5 |
## get_executable ##
|
|
Packit |
4f15d5 |
## -------------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_executable], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#define PRELINK_BASENAME "/tmp/libreport.testsuite.get_executable"
|
|
Packit |
4f15d5 |
#
|
|
Packit |
4f15d5 |
void test(const char *program, const char *expected, const char *function, const char *argv1)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int inout[2];
|
|
Packit |
4f15d5 |
xpipe(inout);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
pid_t pid = fork();
|
|
Packit |
4f15d5 |
if (pid < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "fork");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (pid == 0) {
|
|
Packit |
4f15d5 |
close(STDOUT_FILENO);
|
|
Packit |
4f15d5 |
xdup2(inout[1], STDOUT_FILENO);
|
|
Packit |
4f15d5 |
close(inout[0]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const char *args[3] = { function, argv1, NULL };
|
|
Packit |
4f15d5 |
execv(program, (char **)args);
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "execv(%s) : %d", program, errno);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(inout[1]);
|
|
Packit |
4f15d5 |
int status = 0;
|
|
Packit |
4f15d5 |
if (safe_waitpid(pid, &status, 0) < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "waitpid");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (WEXITSTATUS(status) != 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "Child not exited with 0");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const size_t buffer_size = strlen(expected) * 2;
|
|
Packit |
4f15d5 |
char executable[buffer_size];
|
|
Packit |
4f15d5 |
const ssize_t total = full_read(inout[0], executable, buffer_size);
|
|
Packit |
4f15d5 |
close(inout[0]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (total < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "full_read");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
executable[total] = '\0';
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(executable, expected, "/proc/[pid]/exe");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int copy_to_temporary(const char *source, char *dest)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int dest_fd = mkstemp(dest);
|
|
Packit |
4f15d5 |
if (dest_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "mkstemp(%s)", dest);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int src_fd = open(source, O_RDONLY);
|
|
Packit |
4f15d5 |
if (src_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open(%s, O_RDONLY)", source);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct stat src_stat;
|
|
Packit |
4f15d5 |
if (fstat(src_fd, &src_stat) < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "fstat(%s)", source);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (sendfile(dest_fd, src_fd, NULL, src_stat.st_size) < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "splice(%s, %s, %zu)", source, dest, src_stat.st_size);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(src_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fchmod(dest_fd, src_stat.st_mode);
|
|
Packit |
4f15d5 |
return dest_fd;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (argc > 1) {
|
|
Packit |
4f15d5 |
if (strcmp(argv[1], "delete") == 0) {
|
|
Packit |
4f15d5 |
char *binary = malloc_readlink("/proc/self/exe");
|
|
Packit |
4f15d5 |
unlink(binary);
|
|
Packit |
4f15d5 |
if (access(binary, R_OK) != -1 && errno != !ENOENT) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "failed to remove %s", binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
free(binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *executable = NULL;
|
|
Packit |
4f15d5 |
if (strcmp(argv[0], "get_executable") == 0) {
|
|
Packit |
4f15d5 |
executable = get_executable(getpid());
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else if (strcmp(argv[0], "get_executable_at") == 0) {
|
|
Packit |
4f15d5 |
int pid_proc_fd = open("/proc/self", O_DIRECTORY);
|
|
Packit |
4f15d5 |
if (pid_proc_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open(/proc/self, O_DIRECTORY)");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
executable = get_executable_at(pid_proc_fd);
|
|
Packit |
4f15d5 |
close(pid_proc_fd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "Unsupported function type '%s'", argv[0]);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fprintf(stdout, "%s", executable);
|
|
Packit |
4f15d5 |
fflush(stdout);
|
|
Packit |
4f15d5 |
exit(EXIT_SUCCESS);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *binary = malloc_readlink("/proc/self/exe");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, binary, "get_executable", "keep");
|
|
Packit |
4f15d5 |
test(binary, binary, "get_executable_at", "keep");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free(binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char binary[] = PRELINK_BASENAME ".#prelink#.XXXXXX";
|
|
Packit |
4f15d5 |
int binary_fd = copy_to_temporary("/proc/self/exe", binary);
|
|
Packit |
4f15d5 |
close(binary_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, PRELINK_BASENAME, "get_executable", "keep");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char binary[] = PRELINK_BASENAME ".#prelink#.XXXXXX";
|
|
Packit |
4f15d5 |
int binary_fd = copy_to_temporary("/proc/self/exe", binary);
|
|
Packit |
4f15d5 |
close(binary_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, PRELINK_BASENAME, "get_executable_at", "keep");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char binary[] = PRELINK_BASENAME ".#prelink#.XXXXXX";
|
|
Packit |
4f15d5 |
int binary_fd = copy_to_temporary("/proc/self/exe", binary);
|
|
Packit |
4f15d5 |
close(binary_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, PRELINK_BASENAME, "get_executable", "delete");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (unlink(binary) == 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "should be already removed %s", binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char binary[] = PRELINK_BASENAME ".#prelink#.XXXXXX";
|
|
Packit |
4f15d5 |
int binary_fd = copy_to_temporary("/proc/self/exe", binary);
|
|
Packit |
4f15d5 |
close(binary_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, PRELINK_BASENAME, "get_executable_at", "delete");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (unlink(binary) == 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "should be already removed %s", binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char binary[] = "/tmp/libreport.testsuite.get_executable.XXXXXX";
|
|
Packit |
4f15d5 |
int binary_fd = copy_to_temporary("/proc/self/exe", binary);
|
|
Packit |
4f15d5 |
close(binary_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, binary, "get_executable", "delete");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (unlink(binary) == 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "should be already removed %s", binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char binary[] = "/tmp/libreport.testsuite.get_executable.XXXXXX";
|
|
Packit |
4f15d5 |
int binary_fd = copy_to_temporary("/proc/self/exe", binary);
|
|
Packit |
4f15d5 |
close(binary_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test(binary, binary, "get_executable_at", "delete");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (unlink(binary) == 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "should be already removed %s", binary);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ------- ##
|
|
Packit |
4f15d5 |
## get_cwd ##
|
|
Packit |
4f15d5 |
## ------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_cwd], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char wd[PATH_MAX];
|
|
Packit |
4f15d5 |
getcwd(wd, sizeof(wd));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *cwd = get_cwd(getpid());
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(cwd, wd, "get_cwd(getpid())");
|
|
Packit |
4f15d5 |
free(cwd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int pid_proc_fd = open("/proc/self", O_DIRECTORY | O_PATH);
|
|
Packit |
4f15d5 |
if (pid_proc_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open(/proc/self, O_DIRECTORY | O_PATH)");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *cwd_at = get_cwd_at(pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(cwd_at, wd, "get_cwd_at(open(/proc/self))");
|
|
Packit |
4f15d5 |
close(pid_proc_fd);
|
|
Packit |
4f15d5 |
free(cwd_at);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ----------- ##
|
|
Packit |
4f15d5 |
## get_rootdir ##
|
|
Packit |
4f15d5 |
## ----------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_rootdir], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *proc_self_root = malloc_readlink("/proc/self/root");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *root_dir = get_rootdir(getpid());
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(root_dir, proc_self_root, "get_rootdir(getpid())");
|
|
Packit |
4f15d5 |
free(root_dir);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int pid_proc_fd = open("/proc/self", O_DIRECTORY | O_PATH);
|
|
Packit |
4f15d5 |
if (pid_proc_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open(/proc/self, O_DIRECTORY | O_PATH)");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *root_dir_at = get_rootdir_at(pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(root_dir_at, proc_self_root, "get_rootdir_at(open(/proc/self))");
|
|
Packit |
4f15d5 |
close(pid_proc_fd);
|
|
Packit |
4f15d5 |
free(root_dir_at);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ------------ ##
|
|
Packit |
4f15d5 |
## dump_fd_info ##
|
|
Packit |
4f15d5 |
## ------------ ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([dump_fd_info], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#define FILENAME_FORMAT "/tmp/libreport.testsuite.fdinfo.%d.%s"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
pid_t prepare_process(void)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int toparent[2];
|
|
Packit |
4f15d5 |
xpipe(toparent);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *binary = malloc_readlink("/proc/self/exe");
|
|
Packit |
4f15d5 |
pid_t pid = fork();
|
|
Packit |
4f15d5 |
if (pid < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "fork");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (pid == 0) {
|
|
Packit |
4f15d5 |
close(STDOUT_FILENO);
|
|
Packit |
4f15d5 |
xdup2(toparent[1], STDOUT_FILENO);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
DIR *fddir = opendir("/proc/self/fd");
|
|
Packit |
4f15d5 |
struct dirent *dent;
|
|
Packit |
4f15d5 |
while ((dent = readdir(fddir))) {
|
|
Packit |
4f15d5 |
const int fd = atoi(dent->d_name);
|
|
Packit |
4f15d5 |
if (fd != STDOUT_FILENO) {
|
|
Packit |
4f15d5 |
close(fd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
execl(binary, "wait", NULL);
|
|
Packit |
4f15d5 |
exit(EXIT_FAILURE);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(toparent[1]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
free(binary);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Wait for child */
|
|
Packit |
4f15d5 |
char buf[8];
|
|
Packit |
4f15d5 |
if (full_read(toparent[0], buf, 8) < 0) {
|
|
Packit |
4f15d5 |
fprintf(stderr, "Failed to read from child: %s\n", strerror(errno));
|
|
Packit |
4f15d5 |
fflush(stderr);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(toparent[0]);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return pid;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void kill_process(pid_t pid)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* Notify child */
|
|
Packit |
4f15d5 |
kill(pid, SIGTERM);
|
|
Packit |
4f15d5 |
int status = 0;
|
|
Packit |
4f15d5 |
if (safe_waitpid(pid, &status, 0) < 0) {
|
|
Packit |
4f15d5 |
fprintf(stderr, "Couldn't wait for child\n");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGTERM) {
|
|
Packit |
4f15d5 |
fprintf(stderr, "Child was not TERMinated - %d\n", status);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void check_file_contents(const char *fdinfo_filename)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
struct fd {
|
|
Packit |
4f15d5 |
int fd;
|
|
Packit |
4f15d5 |
const char *file;
|
|
Packit |
4f15d5 |
} fds[] = {
|
|
Packit |
4f15d5 |
{ .fd = 0, .file = "/etc/services", },
|
|
Packit |
4f15d5 |
{ .fd = 2, .file = "/etc/passwd", },
|
|
Packit |
4f15d5 |
{ .fd = 3, .file = "/etc/group", },
|
|
Packit |
4f15d5 |
};
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *file = xmalloc_xopen_read_close(fdinfo_filename, NULL);
|
|
Packit |
4f15d5 |
int fdno = 0;
|
|
Packit |
4f15d5 |
char *cursor = file;
|
|
Packit |
4f15d5 |
char *line = file;
|
|
Packit |
4f15d5 |
char *end = file + strlen(file);
|
|
Packit |
4f15d5 |
while (cursor < end) {
|
|
Packit |
4f15d5 |
cursor = strchrnul(line, '\n');
|
|
Packit |
4f15d5 |
if (*cursor != '\0') {
|
|
Packit |
4f15d5 |
*cursor = '\0';
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
++cursor;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (fdno < (sizeof(fds)/sizeof(fds[0]))) {
|
|
Packit |
4f15d5 |
int fd = 0;
|
|
Packit |
4f15d5 |
char *file = NULL;
|
|
Packit |
4f15d5 |
const int res = sscanf(line, "%d:%ms", &fd, &file;;
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(res, 2);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(fd, fds[fdno].fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(file, fds[fdno].file, "FD file name");
|
|
Packit |
4f15d5 |
free(file);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
line = cursor;
|
|
Packit |
4f15d5 |
int fieldscnt = 0;
|
|
Packit |
4f15d5 |
while (line < end) {
|
|
Packit |
4f15d5 |
cursor = strchrnul(line, '\n');
|
|
Packit |
4f15d5 |
if (*cursor != '\0') {
|
|
Packit |
4f15d5 |
*cursor = '\0';
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
++cursor;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (strcmp(line, "") == 0) {
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int col = 0;
|
|
Packit |
4f15d5 |
for (; col < strlen(line); ++col) {
|
|
Packit |
4f15d5 |
if (line[col] == ':') {
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_ASSERT_TRUE(line[col] != ' ' && line[col] != '\t');
|
|
Packit |
4f15d5 |
if (!g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_NEQ(col, 0);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_LT(col, strlen(line));
|
|
Packit |
4f15d5 |
if (g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
TS_ASSERT_CHAR_EQ(line[col], ':');
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fieldscnt += g_testsuite_last_ok;
|
|
Packit |
4f15d5 |
line = cursor;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_GT(fieldscnt, 2);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
++fdno;
|
|
Packit |
4f15d5 |
line = cursor;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(fdno, sizeof(fds)/sizeof(fds[0]));
|
|
Packit |
4f15d5 |
free(file);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (strcmp(argv[0], "wait") == 0) {
|
|
Packit |
4f15d5 |
FILE *services = fopen("/etc/services", "r");
|
|
Packit |
4f15d5 |
FILE *passwd = fopen("/etc/passwd", "r");
|
|
Packit |
4f15d5 |
FILE *group = fopen("/etc/group", "r");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Notify parent */
|
|
Packit |
4f15d5 |
close(STDOUT_FILENO);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Wait for parent */
|
|
Packit |
4f15d5 |
while (1) {
|
|
Packit |
4f15d5 |
sleep(1);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fclose(group);
|
|
Packit |
4f15d5 |
fclose(passwd);
|
|
Packit |
4f15d5 |
fclose(services);
|
|
Packit |
4f15d5 |
exit(EXIT_SUCCESS);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
pid_t pid = prepare_process();
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char proc_dir_path[strlen("/proc/%d/fd") + sizeof(pid_t) * 3];
|
|
Packit |
4f15d5 |
if (sizeof(proc_dir_path) <= snprintf(proc_dir_path, sizeof(proc_dir_path), "/proc/%d/fd", pid)) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for proc dir path");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "dump_fd_info");
|
|
Packit |
4f15d5 |
char fdinfo_filename[strlen(FILENAME_FORMAT) + sizeof(pid_t) * 3 + strlen("dump_fd_info")];
|
|
Packit |
4f15d5 |
if (sizeof(fdinfo_filename) <= snprintf(fdinfo_filename, sizeof(fdinfo_filename), FILENAME_FORMAT, pid, "dump_fd_info")) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for file name");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(dump_fd_info(fdinfo_filename, proc_dir_path));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(stat(fdinfo_filename, &st);;
|
|
Packit |
4f15d5 |
if (g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(st.st_mode & 0777, 0600);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
check_file_contents(fdinfo_filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(fdinfo_filename);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "dump_fd_info_ext");
|
|
Packit |
4f15d5 |
char fdinfo_filename[strlen(FILENAME_FORMAT) + sizeof(pid_t) * 3 + strlen("dump_fd_info_ext")];
|
|
Packit |
4f15d5 |
if (sizeof(fdinfo_filename) <= snprintf(fdinfo_filename, sizeof(fdinfo_filename), FILENAME_FORMAT, pid, "dump_fd_info_ext")) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for file name");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const uid_t uid = getuid();
|
|
Packit |
4f15d5 |
const gid_t gid = getgid();
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(dump_fd_info_ext(fdinfo_filename, proc_dir_path, uid, gid));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(stat(fdinfo_filename, &st);;
|
|
Packit |
4f15d5 |
if (g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(st.st_mode & 0777, 0600);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
check_file_contents(fdinfo_filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(fdinfo_filename);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "dump_fd_info_at");
|
|
Packit |
4f15d5 |
char fdinfo_filename[strlen(FILENAME_FORMAT) + sizeof(pid_t) * 3 + strlen("dump_fd_info_at")];
|
|
Packit |
4f15d5 |
if (sizeof(fdinfo_filename) <= snprintf(fdinfo_filename, sizeof(fdinfo_filename), FILENAME_FORMAT, pid, "dump_fd_info_at")) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for file name");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
FILE *dest = fopen(fdinfo_filename, "w");
|
|
Packit |
4f15d5 |
const int pid_proc_fd = open_proc_pid_dir(pid);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(dump_fd_info_at(pid_proc_fd, dest));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(pid_proc_fd);
|
|
Packit |
4f15d5 |
fclose(dest);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
check_file_contents(fdinfo_filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(fdinfo_filename);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
kill_process(pid);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ------------- ##
|
|
Packit |
4f15d5 |
## get_fs-u_g-id ##
|
|
Packit |
4f15d5 |
## ------------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_fs-u_g-id], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *proc_pid_status = xmalloc_xopen_read_close("/proc/self/status", NULL);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(get_fsuid(proc_pid_status), getuid());
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(get_fsgid(proc_pid_status), getgid());
|
|
Packit |
4f15d5 |
free(proc_pid_status);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ---------- ##
|
|
Packit |
4f15d5 |
## get_ns_ids ##
|
|
Packit |
4f15d5 |
## ---------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_ns_ids], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void check(struct ns_ids *ids)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
const int nsfd = open("/proc/self/ns", O_DIRECTORY);
|
|
Packit |
4f15d5 |
assert(nsfd >= 0);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
for (size_t i = 0; i < ARRAY_SIZE(libreport_proc_namespaces); ++i) {
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
if (fstatat(nsfd, libreport_proc_namespaces[i], &st, 0) < 0) {
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_OP_MESSAGE(ids->nsi_ids[i], ==, PROC_NS_UNSUPPORTED, libreport_proc_namespaces[i]);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else {
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_OP_MESSAGE(ids->nsi_ids[i], ==, st.st_ino, libreport_proc_namespaces[i]);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
DIR *nsdir = fdopendir(nsfd);
|
|
Packit |
4f15d5 |
assert(nsdir != NULL);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct dirent *dent = NULL;
|
|
Packit |
4f15d5 |
while ((dent = readdir(nsdir))) {
|
|
Packit |
4f15d5 |
if (dot_or_dotdot(dent->d_name))
|
|
Packit |
4f15d5 |
continue;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
size_t i = 0;
|
|
Packit |
4f15d5 |
for (; i < ARRAY_SIZE(libreport_proc_namespaces); ++i) {
|
|
Packit |
4f15d5 |
if (strcmp(libreport_proc_namespaces[i], dent->d_name) == 0) {
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_OP_MESSAGE(i, <, ARRAY_SIZE(libreport_proc_namespaces), dent->d_name);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(fstatat(nsfd, dent->d_name, &st, 0));
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_OP_MESSAGE(ids->nsi_ids[i], ==, st.st_ino, dent->d_name);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
closedir(nsdir);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "get_ns_ids");
|
|
Packit |
4f15d5 |
struct ns_ids pid_ids;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(get_ns_ids(getpid(), &pid_ids));
|
|
Packit |
4f15d5 |
check(&pid_ids);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "get_ns_ids_at");
|
|
Packit |
4f15d5 |
const int pid_proc_dir = open_proc_pid_dir(getpid());
|
|
Packit |
4f15d5 |
struct ns_ids proc_ids;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(get_ns_ids_at(pid_proc_dir, &proc_ids));
|
|
Packit |
4f15d5 |
check(&proc_ids);
|
|
Packit |
4f15d5 |
close(pid_proc_dir);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ------------------------------ ##
|
|
Packit |
4f15d5 |
## get_mountinfo_for_mount_point ##
|
|
Packit |
4f15d5 |
## ------------------------------ ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([get_mountinfo_for_mount_point], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
const char *mount_point,
|
|
Packit |
4f15d5 |
const char *description,
|
|
Packit |
4f15d5 |
const char *input,
|
|
Packit |
4f15d5 |
const char *error,
|
|
Packit |
4f15d5 |
int exp_r,
|
|
Packit |
4f15d5 |
const struct mountinfo *exp_mntnf)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("++++ %s\n", description);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *buf = NULL;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
FILE *mntnf_file = fmemopen((void *)input, strlen(input), "r");
|
|
Packit |
4f15d5 |
if (mntnf_file == NULL) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open_memstream");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct mountinfo mntnf;
|
|
Packit |
4f15d5 |
int r;
|
|
Packit |
4f15d5 |
TS_ASSERT_STREAM_FD_CONTENTS_EQ_BEGIN(STDERR_FILENO);
|
|
Packit |
4f15d5 |
r = get_mountinfo_for_mount_point(mntnf_file, &mntnf, mount_point);
|
|
Packit |
4f15d5 |
TS_ASSERT_STREAM_FD_CONTENTS_EQ_END(error, description);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_OP_MESSAGE(r, ==, exp_r, description);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (r == 0 && exp_mntnf != NULL) {
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[0], exp_mntnf->mntnf_items[0], "Item 0");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[1], exp_mntnf->mntnf_items[1], "Item 1");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[2], exp_mntnf->mntnf_items[2], "Item 2");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[3], exp_mntnf->mntnf_items[3], "Item 3");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[4], exp_mntnf->mntnf_items[4], "Item 4");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[5], exp_mntnf->mntnf_items[5], "Item 5");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[6], exp_mntnf->mntnf_items[6], "Item 6");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[7], exp_mntnf->mntnf_items[7], "Item 7");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[8], exp_mntnf->mntnf_items[8], "Item 8");
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(mntnf.mntnf_items[9], exp_mntnf->mntnf_items[9], "Item 9");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fclose(mntnf_file);
|
|
Packit |
4f15d5 |
free(buf);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_PRINTF("---- %s\n", description);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#define TS_MOUNT_INFO(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
|
|
Packit |
4f15d5 |
((struct mountinfo){ .mntnf_items = { (char *)f0, (char *)f1, (char *)f2, \
|
|
Packit |
4f15d5 |
(char *)f3, (char *)f4, (char *)f5, \
|
|
Packit |
4f15d5 |
(char *)f6, (char *)f7, (char *)f8, \
|
|
Packit |
4f15d5 |
(char *)f9 } })
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Empty file",
|
|
Packit |
4f15d5 |
/* input */ "",
|
|
Packit |
4f15d5 |
/* error */ "Mountinfo line does not have enough fields 0\n",
|
|
Packit |
4f15d5 |
/* exp_r */ 1,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ NULL
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Not-enough fields",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 ",
|
|
Packit |
4f15d5 |
/* error */ "Mountinfo line does not have enough fields 3\n",
|
|
Packit |
4f15d5 |
/* exp_r */ 1,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ NULL
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Missing the mount point field",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo ",
|
|
Packit |
4f15d5 |
/* error */ "Mountinfo line does not have the mount point field\n",
|
|
Packit |
4f15d5 |
/* exp_r */ 2,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ NULL
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Not found mount point",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo /bar ",
|
|
Packit |
4f15d5 |
/* error */ "",
|
|
Packit |
4f15d5 |
/* exp_r */ -ENOKEY,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ NULL
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Unexpected end of file",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo / rw,noatime",
|
|
Packit |
4f15d5 |
/* error */ "Unexpected end of file\n",
|
|
Packit |
4f15d5 |
/* exp_r */ -ENODATA,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ NULL
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Escaped path: no mount point field",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo\\ bar ",
|
|
Packit |
4f15d5 |
/* error */ "Mountinfo line does not have the mount point field\n",
|
|
Packit |
4f15d5 |
/* exp_r */ 2,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ NULL
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Correct, matching line",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo / rw,noatime shared:1 - xfs /dev/sda1 rw,seclabel,attr2",
|
|
Packit |
4f15d5 |
/* error */ "",
|
|
Packit |
4f15d5 |
/* exp_r */ 0,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ &TS_MOUNT_INFO("12", "34", "567:10", "/foo", "/", "rw,noatime", "shared:1", "xfs", "/dev/sda1", "rw,seclabel,attr2")
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Correct, matching line, empty optional fields",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo / rw,noatime - xfs /dev/sda1 rw,seclabel,attr2",
|
|
Packit |
4f15d5 |
/* error */ "",
|
|
Packit |
4f15d5 |
/* exp_r */ 0,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ &TS_MOUNT_INFO("12", "34", "567:10", "/foo", "/", "rw,noatime", "", "xfs", "/dev/sda1", "rw,seclabel,attr2")
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Correct, matching line, several optional fields",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo / rw,noatime shared:1 master:2 unbindable:3 - xfs /dev/sda1 rw,seclabel,attr2",
|
|
Packit |
4f15d5 |
/* error */ "",
|
|
Packit |
4f15d5 |
/* exp_r */ 0,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ &TS_MOUNT_INFO("12", "34", "567:10", "/foo", "/", "rw,noatime", "shared:1 master:2 unbindable:3", "xfs", "/dev/sda1", "rw,seclabel,attr2")
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Escaped path: correct, matching line",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo\\ bar / rw,noatime shared:1 - xfs /dev/sda1 rw,seclabel,attr2",
|
|
Packit |
4f15d5 |
/* error */ "",
|
|
Packit |
4f15d5 |
/* exp_r */ 0,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ &TS_MOUNT_INFO("12", "34", "567:10", "/foo\\ bar", "/", "rw,noatime", "shared:1", "xfs", "/dev/sda1", "rw,seclabel,attr2")
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
test_get_mountinfo_for_mount_point(
|
|
Packit |
4f15d5 |
/* mount point */ "/",
|
|
Packit |
4f15d5 |
/* description */ "Escaped path: correct, matching line + escaped mount source",
|
|
Packit |
4f15d5 |
/* input */ "12 34 567:10 /foo\\ bar / rw,noatime shared:1 - xfs /dev/sda\\ 1 rw,seclabel,attr2",
|
|
Packit |
4f15d5 |
/* error */ "",
|
|
Packit |
4f15d5 |
/* exp_r */ 0,
|
|
Packit |
4f15d5 |
/* exp_mntnf */ &TS_MOUNT_INFO("12", "34", "567:10", "/foo\\ bar", "/", "rw,noatime", "shared:1", "xfs", "/dev/sda\\ 1", "rw,seclabel,attr2")
|
|
Packit |
4f15d5 |
);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## ------------------- ##
|
|
Packit |
4f15d5 |
## dump_namespace_diff ##
|
|
Packit |
4f15d5 |
## ------------------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([dump_namespace_diff], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#define FILENAME_FORMAT "/tmp/libreport.testsuite.namespace_diff.%d.%s"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void check_file_contents(const char *filename)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char *expected;
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char const *pid_for_children = "default";
|
|
Packit |
4f15d5 |
char const *cgroup = "default";
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (stat("/proc/self/ns/cgroup", &st) < 0 && errno == ENOENT)
|
|
Packit |
4f15d5 |
cgroup = "unknown";
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (stat("/proc/self/ns/pid_for_children", &st) < 0 && errno == ENOENT)
|
|
Packit |
4f15d5 |
pid_for_children = "unknown";
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
expected = xasprintf("ipc : default\n"
|
|
Packit |
4f15d5 |
"mnt : default\n"
|
|
Packit |
4f15d5 |
"net : default\n"
|
|
Packit |
4f15d5 |
"pid : default\n"
|
|
Packit |
4f15d5 |
"uts : default\n"
|
|
Packit |
4f15d5 |
"user : default\n"
|
|
Packit |
4f15d5 |
"cgroup : %s\n"
|
|
Packit |
4f15d5 |
"pid_for_children : %s\n", cgroup, pid_for_children);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *file = xmalloc_xopen_read_close(filename, NULL);
|
|
Packit |
4f15d5 |
TS_ASSERT_STRING_EQ(file, expected, "Namespaces");
|
|
Packit |
4f15d5 |
free(file);
|
|
Packit |
4f15d5 |
free(expected);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "dump_namespace_diff");
|
|
Packit |
4f15d5 |
char filename[strlen(FILENAME_FORMAT) + sizeof(pid_t) * 3 + strlen("dump_namespace_diff")];
|
|
Packit |
4f15d5 |
if (sizeof(filename) <= snprintf(filename, sizeof(filename), FILENAME_FORMAT, getpid(), "dump_namespace_diff")) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for file name");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(dump_namespace_diff(filename, getpid(), getppid()));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(stat(filename, &st);;
|
|
Packit |
4f15d5 |
if (g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(st.st_mode & 0777, 0600);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
check_file_contents(filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(filename);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "dump_namespace_diff_ext");
|
|
Packit |
4f15d5 |
char filename[strlen(FILENAME_FORMAT) + sizeof(pid_t) * 3 + strlen("dump_namespace_diff_ext")];
|
|
Packit |
4f15d5 |
if (sizeof(filename) <= snprintf(filename, sizeof(filename), FILENAME_FORMAT, getpid(), "dump_namespace_diff_ext")) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for file name");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const uid_t uid = getuid();
|
|
Packit |
4f15d5 |
const gid_t gid = getgid();
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(dump_namespace_diff_ext(filename, getpid(), getppid(), uid, gid));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
struct stat st;
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(stat(filename, &st);;
|
|
Packit |
4f15d5 |
if (g_testsuite_last_ok) {
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(st.st_mode & 0777, 0600);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
check_file_contents(filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(filename);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
TS_PRINTF("%s\n", "dump_namespace_diff_at");
|
|
Packit |
4f15d5 |
char filename[strlen(FILENAME_FORMAT) + sizeof(pid_t) * 3 + strlen("dump_namespace_diff_at")];
|
|
Packit |
4f15d5 |
if (sizeof(filename) <= snprintf(filename, sizeof(filename), FILENAME_FORMAT, getppid(), "dump_namespace_diff_at")) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "too small buffer for file name");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
FILE *dest = fopen(filename, "w");
|
|
Packit |
4f15d5 |
assert(dest != NULL);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const int pid_proc_fd = open_proc_pid_dir(getppid());
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_ASSERT_FUNCTION(dump_namespace_diff_at(pid_proc_fd, pid_proc_fd, dest));
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(pid_proc_fd);
|
|
Packit |
4f15d5 |
fclose(dest);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
check_file_contents(filename);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
unlink(filename);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
## -------------------- ##
|
|
Packit |
4f15d5 |
## process_has_own_root ##
|
|
Packit |
4f15d5 |
## -------------------- ##
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
AT_TESTFUN([process_has_own_root], [[
|
|
Packit |
4f15d5 |
#include "testsuite.h"
|
|
Packit |
4f15d5 |
#include <sys/sendfile.h>
|
|
Packit |
4f15d5 |
#include <err.h>
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
void write_cmd_output_to_fd(int fd, const char *cmd)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
FILE *proc = popen(cmd, "r");
|
|
Packit |
4f15d5 |
if (proc == NULL) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "popen(%s)", cmd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char *output = xmalloc_fgetline(proc);
|
|
Packit |
4f15d5 |
TS_PRINTF("%s : %s\n", cmd, output);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const int retcode = pclose(proc);
|
|
Packit |
4f15d5 |
if (retcode == -1) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "pclose(%s)", cmd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (retcode != 0) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "non-0 status %d of '%s'", cmd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (output == NULL) {
|
|
Packit |
4f15d5 |
errx(EXIT_FAILURE, "no output of '%s'", cmd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
full_write_str(fd, output);
|
|
Packit |
4f15d5 |
free(output);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_MAIN
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
char mock_pid_proc[] = "/tmp/libreport.testsuite.pid.XXXXXX";
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (mkdtemp(mock_pid_proc) == NULL) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "mkdtemp(%s)", mock_pid_proc);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const int mock_pid_proc_fd = open(mock_pid_proc, O_DIRECTORY);
|
|
Packit |
4f15d5 |
if (mock_pid_proc_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "open(%s, O_DIRECTORY)", mock_pid_proc);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* TODO: add test for open file descriptors */
|
|
Packit |
4f15d5 |
const int r = process_has_own_root_at(mock_pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(r, -ENOENT);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Please, notice that the mode is intentionally 0000 - no read, no write,
|
|
Packit |
4f15d5 |
* no execute access */
|
|
Packit |
4f15d5 |
int mntnf_fd = openat(mock_pid_proc_fd, "mountinfo", O_RDWR | O_CREAT | O_EXCL, 0000);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* TODO: add test for open file descriptors */
|
|
Packit |
4f15d5 |
const int r = process_has_own_root_at(mock_pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(r, -EACCES);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Make the file readable & writable */
|
|
Packit |
4f15d5 |
fchmod(mntnf_fd, 0600);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* TODO: add test for open file descriptors */
|
|
Packit |
4f15d5 |
const int r = process_has_own_root_at(mock_pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(r, -ENOKEY);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
full_write_str(mntnf_fd, "36 35 98:0 /madeuproot /foo rw,noatime master:1 - ext3 /dev/myroot rw,errors=continue\n");
|
|
Packit |
4f15d5 |
full_write_str(mntnf_fd, "37 38 99:0 /mnt3 /mnt4 rw,noatime master:2 - ext3 /dev/boot rw,errors=continue\n");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fsync(mntnf_fd);
|
|
Packit |
4f15d5 |
lseek(mntnf_fd, 0, SEEK_SET);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_PRINTF("Made-up mountinfo created in %s\n", mock_pid_proc);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* TODO: add test for open file descriptors */
|
|
Packit |
4f15d5 |
const int r = process_has_own_root_at(mock_pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(r, -ENOKEY);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_PRINTF("Going to copy /proc/1/mountinfo to %s\n", mock_pid_proc);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
const int pid1_mntnf_fd = open("/proc/1/mountinfo", O_RDONLY);
|
|
Packit |
4f15d5 |
if (pid1_mntnf_fd < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "/proc/1/mountinfo");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_PRINTF("Copying /proc/1/mountinfo to %s\n", mock_pid_proc);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int r = 0;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
while ((r = sendfile(mntnf_fd, pid1_mntnf_fd, NULL, 65535)) > 0)
|
|
Packit |
4f15d5 |
;
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (r < 0) {
|
|
Packit |
4f15d5 |
err(EXIT_FAILURE, "Cannot copy /proc/1/mountinfo to %s", mock_pid_proc);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(pid1_mntnf_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fsync(mntnf_fd);
|
|
Packit |
4f15d5 |
lseek(mntnf_fd, 0, SEEK_SET);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
TS_PRINTF("Copied /proc/1/mountinfo to %s\n", mock_pid_proc);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* TODO: add test for open file descriptors */
|
|
Packit |
4f15d5 |
const int r = process_has_own_root_at(mock_pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(r, 0);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Test different source directory. Swap / with \ in the mock mountinfo. */
|
|
Packit |
4f15d5 |
fsync(mntnf_fd);
|
|
Packit |
4f15d5 |
lseek(mntnf_fd, 0, SEEK_SET);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
full_write_str(mntnf_fd, "12 34 567:89 /madeuproot / ");
|
|
Packit |
4f15d5 |
write_cmd_output_to_fd(mntnf_fd, "findmnt -F /proc/1/mountinfo -r -n -o VFS-OPTIONS,OPT-FIELDS -T /");
|
|
Packit |
4f15d5 |
full_write_str(mntnf_fd, " - ");
|
|
Packit |
4f15d5 |
write_cmd_output_to_fd(mntnf_fd, "findmnt -F /proc/1/mountinfo -r -n -o FSTYPE,SOURCE,FS-OPTIONS -T /");
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
fsync(mntnf_fd);
|
|
Packit |
4f15d5 |
lseek(mntnf_fd, 0, SEEK_SET);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* TODO: add test for open file descriptors */
|
|
Packit |
4f15d5 |
const int r = process_has_own_root_at(mock_pid_proc_fd);
|
|
Packit |
4f15d5 |
TS_ASSERT_SIGNED_EQ(r, 1);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(mntnf_fd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (unlinkat(mock_pid_proc_fd, "mountinfo", 0) < 0) {
|
|
Packit |
4f15d5 |
perror("unlinkat(fd, mountinfo)");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (rmdir(mock_pid_proc) < 0) {
|
|
Packit |
4f15d5 |
perror("rmdir(/mock_pid_dir)");
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
TS_RETURN_MAIN
|
|
Packit |
4f15d5 |
]])
|