Files
fruix/tests/guile/posix-spawn-freebsd-diagnostics.c

135 lines
3.6 KiB
C

#include <errno.h>
#include <fcntl.h>
#include <spawn.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
extern char **environ;
static int native_spawn_closefrom_test(void) {
posix_spawn_file_actions_t actions;
pid_t pid;
int status;
char *argv[] = { "/usr/bin/true", NULL };
if (posix_spawn_file_actions_init(&actions) != 0)
return 1;
if (posix_spawn_file_actions_adddup2(&actions, STDIN_FILENO, STDIN_FILENO) != 0)
return 2;
if (posix_spawn_file_actions_adddup2(&actions, STDOUT_FILENO, STDOUT_FILENO) != 0)
return 3;
if (posix_spawn_file_actions_adddup2(&actions, STDERR_FILENO, STDERR_FILENO) != 0)
return 4;
if (posix_spawn_file_actions_addclosefrom_np(&actions, 3) != 0)
return 5;
if (posix_spawn(&pid, "/usr/bin/true", &actions, NULL, argv, environ) != 0)
return 6;
if (waitpid(pid, &status, 0) < 0)
return 7;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
return 8;
return 0;
}
static int adddup2_invalid_fd_accepted(void) {
posix_spawn_file_actions_t actions;
if (posix_spawn_file_actions_init(&actions) != 0)
return -1;
return posix_spawn_file_actions_adddup2(&actions, 10000000, 2) == 0;
}
static int addopen_invalid_fd_accepted(void) {
posix_spawn_file_actions_t actions;
if (posix_spawn_file_actions_init(&actions) != 0)
return -1;
return posix_spawn_file_actions_addopen(&actions, 10000000, "foo", 0, O_RDONLY) == 0;
}
static int write_script(char *path, size_t size) {
int fd;
const char script[] = ":\n";
if (snprintf(path, size, "/tmp/fruix-posix-spawn-script-XXXXXX") >= (int)size)
return -1;
fd = mkstemp(path);
if (fd < 0)
return -1;
if (write(fd, script, sizeof(script) - 1) != (ssize_t)(sizeof(script) - 1)) {
close(fd);
unlink(path);
return -1;
}
if (fchmod(fd, 0700) != 0) {
close(fd);
unlink(path);
return -1;
}
if (close(fd) != 0) {
unlink(path);
return -1;
}
return 0;
}
static int secure_exec_result(int use_path) {
char script[128];
pid_t child;
int err;
int status = 0;
char *argv[] = { script, NULL };
char *env[] = { "PATH=/tmp:/usr/bin:/bin", NULL };
if (write_script(script, sizeof(script)) != 0)
return -1;
err = use_path
? posix_spawnp(&child, script, NULL, NULL, argv, env)
: posix_spawn(&child, script, NULL, NULL, argv, env);
if (err == ENOEXEC) {
unlink(script);
return 0;
}
if (err != 0) {
unlink(script);
return 1;
}
while (waitpid(child, &status, 0) != child)
;
unlink(script);
if (!WIFEXITED(status))
return 2;
if (WEXITSTATUS(status) != 127)
return 3;
return 0;
}
int main(void) {
int native_ok = native_spawn_closefrom_test();
int dup2_broken = adddup2_invalid_fd_accepted();
int addopen_broken = addopen_invalid_fd_accepted();
int spawn_secure = secure_exec_result(0);
int spawnp_secure = secure_exec_result(1);
int issue_profile_match =
native_ok == 0 &&
dup2_broken == 1 &&
addopen_broken == 1 &&
spawn_secure == 0 &&
spawnp_secure == 3;
printf("native-spawn-closefrom=%s\n", native_ok == 0 ? "ok" : "fail");
printf("adddup2-invalid-fd-accepted=%s\n", dup2_broken == 1 ? "yes" : (dup2_broken == 0 ? "no" : "error"));
printf("addopen-invalid-fd-accepted=%s\n", addopen_broken == 1 ? "yes" : (addopen_broken == 0 ? "no" : "error"));
printf("posix_spawn-secure-exec-result=%d\n", spawn_secure);
printf("posix_spawnp-secure-exec-result=%d\n", spawnp_secure);
printf("issue-profile-match=%s\n", issue_profile_match ? "yes" : "no");
return issue_profile_match ? 0 : 1;
}