jaitest - simple sandbox testing utility program

This commit is contained in:
netblue30 2021-02-20 10:06:58 -05:00
parent 836989bf18
commit 42e2db1275
14 changed files with 794 additions and 5 deletions

2
.gitignore vendored
View file

@ -22,6 +22,7 @@ firejail-users.5
firejail.1
firemon.1
firecfg.1
jailtest.5
mkdeb.sh
src/firejail/firejail
src/firemon/firemon
@ -40,6 +41,7 @@ src/fbuilder/fbuilder
src/profstats/profstats
src/bash_completion/firejail.bash_completion
src/zsh_completion/_firejail
src/jailtest/jailtest
uids.h
seccomp
seccomp.debug

View file

@ -23,13 +23,13 @@ endif
COMPLETIONDIRS = src/zsh_completion src/bash_completion
all: all_items mydirs $(MAN_TARGET) filters
APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats
APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats src/jailtest/jailtest
SBOX_APPS = src/faudit/faudit src/fbuilder/fbuilder src/ftee/ftee
SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter
MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS)
MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so
COMPLETIONS = src/zsh_completion/_firejail src/bash_completion/firejail.bash_completion
MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 firejail-users.5
MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 firejail-users.5 jailtest.5
SBOX_APPS_NON_DUMPABLE += src/fsec-optimize/fsec-optimize src/fsec-print/fsec-print src/fseccomp/fseccomp
SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.block_secondary seccomp.mdwx seccomp.mdwx.32
ALL_ITEMS = $(APPS) $(SBOX_APPS) $(SBOX_APPS_NON_DUMPABLE) $(MYLIBS)
@ -109,6 +109,8 @@ endif
install -m 0755 src/firemon/firemon $(DESTDIR)$(bindir)
# firecfg executable
install -m 0755 src/firecfg/firecfg $(DESTDIR)$(bindir)
# jailtest executable
install -m 0755 src/jailtest/jailtest $(DESTDIR)$(bindir)
# libraries and plugins
install -m 0755 -d $(DESTDIR)$(libdir)/firejail
install -m 0644 -t $(DESTDIR)$(libdir)/firejail $(MYLIBS) $(SECCOMP_FILTERS) src/firecfg/firecfg.config
@ -177,6 +179,7 @@ uninstall:
rm -f $(DESTDIR)$(bindir)/firemon
rm -f $(DESTDIR)$(bindir)/firecfg
rm -fr $(DESTDIR)$(libdir)/firejail
rm -fr $(DESTDIR)$(libdir)/jailtest
rm -fr $(DESTDIR)$(datarootdir)/doc/firejail
for man in $(MANPAGES); do \
rm -f $(DESTDIR)$(mandir)/man5/$$man*; \

View file

@ -198,7 +198,84 @@ We also keep a list of profile fixes for previous released versions in [etc-fixe
Milestone page: https://github.com/netblue30/firejail/milestone/1
Release discussion: https://github.com/netblue30/firejail/issues/3696
### jailtest
`````
JAILTEST(1) JAILTEST man page JAILTEST(1)
NAME
jailtest - Simple utility program to test running sandboxes
SYNOPSIS
sudo jailtest [OPTIONS] [directory]
DESCRIPTION
WORK IN PROGRESS! jailtest attaches itself to all sandboxes started by
the user and performs some basic tests on the sandbox filesystem:
1. Virtual directories
jailtest extracts a list with the main virtual directories in
stalled by the sandbox. These directories are build by firejail
at startup using --private* and --whitelist commands.
2. Noexec test
jailtest inserts executable programs in /home/username, /tmp,
and /var/tmp directories and tries to run them form inside the
sandbox, thus testing if the directory is executable or not.
3. Read access test
jailtest creates test files in the directories specified by the
user and tries to read them from inside the sandbox.
The program is running as root exclusively under sudo.
OPTIONS
--debug
Print debug messages
-?, --help
Print options end exit.
--version
Print program version and exit.
[directory]
One or more directories in user home to test for read access.
OUTPUT
For each sandbox detected we print the following line:
PID:USER:Sandbox Name:Command
It is followed by relevant sandbox information, such as the virtual di
rectories and various warnings.
EXAMPLE
$ sudo jailtest ~/.ssh ~/.gnupg
1429:netblue::/usr/bin/firejail /opt/firefox/firefox
Virtual dirs: /home/netblue, /tmp, /var/tmp, /dev, /etc,
5602:netblue::/usr/bin/firejail /usr/bin/ssh netblue@x.y.z.net
Virtual dirs: /var/tmp, /dev,
Warning: I can read ~/.ssh
5926:netblue::/usr/bin/firejail /usr/bin/gimp-2.10
Virtual dirs: /tmp, /var/tmp, /dev,
Warning: I can run programs in /home/netblue
6394:netblue:libreoffice:/usr/bin/firejail libreoffice
Virtual dirs: /tmp, /var/tmp, /dev,
LICENSE
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
Homepage: https://firejail.wordpress.com
SEE ALSO
firejail(1), firecfg(1), firejail-profile(5), firejail-login(5) fire
jail-users(5)
0.9.65 Feb 2021 JAILTEST(1)
`````
### Profile Statistics

5
configure vendored
View file

@ -4269,7 +4269,7 @@ fi
ac_config_files="$ac_config_files mkdeb.sh"
ac_config_files="$ac_config_files Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile"
ac_config_files="$ac_config_files Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile src/jailtest/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@ -5000,7 +5000,10 @@ do
"src/fsec-optimize/Makefile") CONFIG_FILES="$CONFIG_FILES src/fsec-optimize/Makefile" ;;
"src/profstats/Makefile") CONFIG_FILES="$CONFIG_FILES src/profstats/Makefile" ;;
"src/man/Makefile") CONFIG_FILES="$CONFIG_FILES src/man/Makefile" ;;
"src/zsh_completion/Makefile") CONFIG_FILES="$CONFIG_FILES src/zsh_completion/Makefile" ;;
"src/bash_completion/Makefile") CONFIG_FILES="$CONFIG_FILES src/bash_completion/Makefile" ;;
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
"src/jailtest/Makefile") CONFIG_FILES="$CONFIG_FILES src/jailtest/Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View file

@ -234,7 +234,8 @@ AC_CONFIG_FILES([mkdeb.sh], [chmod +x mkdeb.sh])
AC_OUTPUT(Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile \
src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \
src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile \
src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile)
src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile \
src/jailtest/Makefile)
echo
echo "Configuration options:"

14
src/jailtest/Makefile.in Normal file
View file

@ -0,0 +1,14 @@
all: jailtest
include ../common.mk
%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/pid.h
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
jailtest: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/pid.o $(LIBS) $(EXTRA_LDFLAGS)
clean:; rm -fr *.o jailtest *.gcov *.gcda *.gcno *.plist
distclean: clean
rm -fr Makefile

124
src/jailtest/access.c Normal file
View file

@ -0,0 +1,124 @@
#include "jailtest.h"
#include <dirent.h>
#include <sys/wait.h>
typedef struct {
char *tfile;
char *tdir;
} TestDir;
#define MAX_TEST_FILES 16
TestDir td[MAX_TEST_FILES];
static int files_cnt = 0;
void access_setup(const char *directory) {
// I am root!
assert(directory);
assert(user_home_dir);
if (files_cnt >= MAX_TEST_FILES) {
fprintf(stderr, "Error: maximum number of test directories exceded\n");
exit(1);
}
char *fname = strdup(directory);
if (!fname)
errExit("strdup");
if (strncmp(fname, "~/", 2) == 0) {
free(fname);
if (asprintf(&fname, "%s/%s", user_home_dir, directory + 2) == -1)
errExit("asprintf");
}
char *path = realpath(fname, NULL);
free(fname);
if (path == NULL) {
fprintf(stderr, "Warning: invalid directory %s, skipping...\n", directory);
return;
}
// file in home directory
if (strncmp(path, user_home_dir, strlen(user_home_dir)) != 0) {
fprintf(stderr, "Warning: file %s is not in user home directory, skipping...\n", directory);
free(path);
return;
}
// try to open the dir as root
DIR *dir = opendir(path);
if (!dir) {
fprintf(stderr, "Warning: directory %s not found, skipping\n", directory);
free(path);
return;
}
closedir(dir);
// create a test file
char *test_file;
if (asprintf(&test_file, "%s/jailtest-access-%d", path, getpid()) == -1)
errExit("asprintf");
FILE *fp = fopen(test_file, "w");
if (!fp) {
printf("Warning: I cannot create test file in directory %s, skipping...\n", directory);
return;
}
fprintf(fp, "this file was created by firetest utility, you can safely delete it\n");
fclose(fp);
int rv = chown(test_file, user_uid, user_gid);
if (rv)
errExit("chown");
char *dname = strdup(directory);
if (!dname)
errExit("strdup");
td[files_cnt].tdir = dname;
td[files_cnt].tfile = test_file;
files_cnt++;
}
void access_destroy(void) {
// remove test files
int i;
for (i = 0; i < files_cnt; i++) {
int rv = unlink(td[i].tfile);
(void) rv;
}
files_cnt = 0;
}
void access_test(void) {
// I am root in sandbox mount namespace
assert(user_uid);
int i;
pid_t child = fork();
if (child == -1)
errExit("fork");
if (child == 0) { // child
// drop privileges
if (setgid(user_gid) != 0)
errExit("setgid");
if (setuid(user_uid) != 0)
errExit("setuid");
for (i = 0; i < files_cnt; i++) {
assert(td[i].tfile);
// try to open the file for reading
FILE *fp = fopen(td[i].tfile, "r");
if (fp) {
printf(" Warning: I can read %s\n", td[i].tdir);
fclose(fp);
}
}
exit(0);
}
// wait for the child to finish
int status;
wait(&status);
}

32
src/jailtest/jailtest.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef JAILTEST_H
#define JAILTEST_H
#include "../include/common.h"
// main.c
extern uid_t user_uid;
extern gid_t user_gid;
extern char *user_name;
extern char *user_home_dir;
// access.c
void access_setup(const char *directory);
void access_test(void);
void access_destroy(void);
// noexec.c
void noexec_setup(void);
void noexec_test(const char *msg);
// virtual.c
void virtual_setup(const char *directory);
void virtual_destroy(void);
void virtual_test(void);
// utils.c
char *get_sudo_user(void);
char *get_homedir(const char *user, uid_t *uid, gid_t *gid);
int find_child(pid_t parent, pid_t *child);
pid_t switch_to_child(pid_t pid);
#endif

134
src/jailtest/main.c Normal file
View file

@ -0,0 +1,134 @@
#include "jailtest.h"
#include "../include/firejail_user.h"
#include "../include/pid.h"
#include <sys/wait.h>
uid_t user_uid = 0;
gid_t user_gid = 0;
char *user_name = NULL;
char *user_home_dir = NULL;
int arg_debug = 0;
static char *usage_str =
"Usage: jailtest [options] directory [directory]\n\n"
"Options:\n"
" --debug - print debug messages.\n"
" --help, -? - this help screen.\n"
" --version - print program version and exit.\n";
static void usage(void) {
printf("firetest - version %s\n\n", VERSION);
puts(usage_str);
}
static void cleanup(void) {
// running only as root
if (getuid() == 0) {
if (arg_debug)
printf("cleaning up!\n");
access_destroy();
virtual_destroy();
}
}
int main(int argc, char **argv) {
int i;
int findex = 0;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "--help") == 0) {
usage();
return 0;
}
else if (strcmp(argv[i], "--version") == 0) {
printf("firetest version %s\n\n", VERSION);
return 0;
}
else if (strncmp(argv[i], "--hello=", 8) == 0) { // used by noexec test
printf(" Warning: I can run programs in %s\n", argv[i] + 8);
return 0;
}
else if (strcmp(argv[i], "--debug") == 0)
arg_debug = 1;
else if (strncmp(argv[i], "--", 2) == 0) {
fprintf(stderr, "Error: invalid option\n");
return 1;
}
else {
findex = i;
break;
}
}
// user setup
if (getuid() != 0) {
fprintf(stderr, "Error: you need to be root (via sudo) to run this program\n");
exit(1);
}
user_name = get_sudo_user();
assert(user_name);
user_home_dir = get_homedir(user_name, &user_uid, &user_gid);
if (user_uid == 0) {
fprintf(stderr, "Error: root user not supported\n");
exit(1);
}
// test setup
atexit(cleanup);
if (findex > 0) {
for (i = findex; i < argc; i++)
access_setup(argv[i]);
}
noexec_setup();
virtual_setup(user_home_dir);
virtual_setup("/tmp");
virtual_setup("/var/tmp");
virtual_setup("/dev");
virtual_setup("/etc");
virtual_setup("/bin");
// print processes
pid_read(0);
for (i = 0; i < max_pids; i++) {
if (pids[i].level == 1) {
uid_t uid = pid_get_uid(i);
if (uid != user_uid) // not interested in other user sandboxes
continue;
// in case the pid is that of a firejail process, use the pid of the first child process
uid_t pid = switch_to_child(i);
pid_print_list(i, 0); // no wrapping
pid_t child = fork();
if (child == -1)
errExit("fork");
if (child == 0) {
int rv = join_namespace(pid, "mnt");
if (rv == 0) {
virtual_test();
noexec_test(user_home_dir);
noexec_test("/tmp");
noexec_test("/var/tmp");
access_test();
}
else {
printf(" Error: I cannot join the process mount space\n");
exit(1);
}
// drop privileges in order not to trigger cleanup()
if (setgid(user_gid) != 0)
errExit("setgid");
if (setuid(user_uid) != 0)
errExit("setuid");
return 0;
}
int status;
wait(&status);
}
}
return 0;
}

94
src/jailtest/noexec.c Normal file
View file

@ -0,0 +1,94 @@
#include "jailtest.h"
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
static unsigned char *execfile = NULL;
static int execfile_len = 0;
void noexec_setup(void) {
// grab a copy of myself
char *self = realpath("/proc/self/exe", NULL);
if (self) {
struct stat s;
if (access(self, X_OK) == 0 && stat(self, &s) == 0) {
assert(s.st_size);
execfile = malloc(s.st_size);
int fd = open(self, O_RDONLY);
if (fd == -1)
errExit("open");
int len = 0;
do {
int rv = read(fd, execfile + len, s.st_size - len);
if (rv == -1)
errExit("read");
if (rv == 0) {
// something went wrong!
free(execfile);
execfile = NULL;
printf("Warning: I cannot grab a copy of myself, skipping noexec test...\n");
break;
}
len += rv;
}
while (len < s.st_size);
execfile_len = s.st_size;
close(fd);
}
}
}
void noexec_test(const char *path) {
assert(user_uid);
// I am root in sandbox mount namespace
if (!execfile)
return;
char *fname;
if (asprintf(&fname, "%s/jailtest-noexec-%d", path, getpid()) == -1)
errExit("asprintf");
pid_t child = fork();
if (child == -1)
errExit("fork");
if (child == 0) { // child
// drop privileges
if (setgid(user_gid) != 0)
errExit("setgid");
if (setuid(user_uid) != 0)
errExit("setuid");
int fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0700);
if (fd == -1) {
printf(" I cannot create files in %s, skipping noexec...\n", path);
exit(1);
}
int len = 0;
while (len < execfile_len) {
int rv = write(fd, execfile + len, execfile_len - len);
if (rv == -1 || rv == 0) {
printf(" I cannot create files in %s, skipping noexec....\n", path);
exit(1);
}
len += rv;
}
fchmod(fd, 0700);
close(fd);
char *arg;
if (asprintf(&arg, "--hello=%s", path) == -1)
errExit("asprintf");
int rv = execl(fname, fname, arg, NULL);
(void) rv; // if we get here execl failed
exit(0);
}
int status;
wait(&status);
int rv = unlink(fname);
(void) rv;
}

124
src/jailtest/utils.c Normal file
View file

@ -0,0 +1,124 @@
#include "jailtest.h"
#include <errno.h>
#include <pwd.h>
#include <dirent.h>
#define BUFLEN 4096
char *get_sudo_user(void) {
char *user = getenv("SUDO_USER");
if (!user) {
user = getpwuid(getuid())->pw_name;
if (!user) {
fprintf(stderr, "Error: cannot detect login user\n");
exit(1);
}
}
return user;
}
char *get_homedir(const char *user, uid_t *uid, gid_t *gid) {
// find home directory
struct passwd *pw = getpwnam(user);
if (!pw)
goto errexit;
char *home = pw->pw_dir;
if (!home)
goto errexit;
*uid = pw->pw_uid;
*gid = pw->pw_gid;
return home;
errexit:
fprintf(stderr, "Error: cannot find home directory for user %s\n", user);
exit(1);
}
int find_child(pid_t parent, pid_t *child) {
*child = 0; // use it to flag a found child
DIR *dir;
if (!(dir = opendir("/proc"))) {
// sleep 2 seconds and try again
sleep(2);
if (!(dir = opendir("/proc"))) {
fprintf(stderr, "Error: cannot open /proc directory\n");
exit(1);
}
}
struct dirent *entry;
char *end;
while (*child == 0 && (entry = readdir(dir))) {
pid_t pid = strtol(entry->d_name, &end, 10);
if (end == entry->d_name || *end)
continue;
if (pid == parent)
continue;
// open stat file
char *file;
if (asprintf(&file, "/proc/%u/status", pid) == -1) {
perror("asprintf");
exit(1);
}
FILE *fp = fopen(file, "r");
if (!fp) {
free(file);
continue;
}
// look for firejail executable name
char buf[BUFLEN];
while (fgets(buf, BUFLEN - 1, fp)) {
if (strncmp(buf, "PPid:", 5) == 0) {
char *ptr = buf + 5;
while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
ptr++;
}
if (*ptr == '\0') {
fprintf(stderr, "Error: cannot read /proc file\n");
exit(1);
}
if (parent == atoi(ptr)) {
// we don't want /usr/bin/xdg-dbus-proxy!
char *cmdline = pid_proc_cmdline(pid);
if (strncmp(cmdline, XDG_DBUS_PROXY_PATH, strlen(XDG_DBUS_PROXY_PATH)) != 0)
*child = pid;
free(cmdline);
}
break; // stop reading the file
}
}
fclose(fp);
free(file);
}
closedir(dir);
return (*child)? 0:1; // 0 = found, 1 = not found
}
pid_t switch_to_child(pid_t pid) {
pid_t rv = pid;
errno = 0;
char *comm = pid_proc_comm(pid);
if (!comm) {
if (errno == ENOENT)
fprintf(stderr, "Error: cannot find process with pid %d\n", pid);
else
fprintf(stderr, "Error: cannot read /proc file\n");
exit(1);
}
if (strcmp(comm, "firejail") == 0) {
if (find_child(pid, &rv) == 1) {
fprintf(stderr, "Error: no valid sandbox\n");
exit(1);
}
}
free(comm);
return rv;
}

99
src/jailtest/virtual.c Normal file
View file

@ -0,0 +1,99 @@
#include "jailtest.h"
#include <dirent.h>
#include <sys/wait.h>
#define MAX_TEST_FILES 16
static char *dirs[MAX_TEST_FILES];
static char *files[MAX_TEST_FILES];
static int files_cnt = 0;
void virtual_setup(const char *directory) {
// I am root!
assert(directory);
assert(*directory == '/');
assert(files_cnt < MAX_TEST_FILES);
// try to open the dir as root
DIR *dir = opendir(directory);
if (!dir) {
fprintf(stderr, "Warning: directory %s not found, skipping\n", directory);
return;
}
closedir(dir);
// create a test file
char *test_file;
if (asprintf(&test_file, "%s/jailtest-private-%d", directory, getpid()) == -1)
errExit("asprintf");
FILE *fp = fopen(test_file, "w");
if (!fp) {
printf("Warning: I cannot create test file in directory %s, skipping...\n", directory);
return;
}
fprintf(fp, "this file was created by firetest utility, you can safely delete it\n");
fclose(fp);
if (strcmp(directory, user_home_dir) == 0) {
int rv = chown(test_file, user_uid, user_gid);
if (rv)
errExit("chown");
}
char *dname = strdup(directory);
if (!dname)
errExit("strdup");
dirs[files_cnt] = dname;
files[files_cnt] = test_file;
files_cnt++;
}
void virtual_destroy(void) {
// remove test files
int i;
for (i = 0; i < files_cnt; i++) {
int rv = unlink(files[i]);
(void) rv;
}
files_cnt = 0;
}
void virtual_test(void) {
// I am root in sandbox mount namespace
assert(user_uid);
int i;
printf(" Virtual dirs: "); fflush(0);
for (i = 0; i < files_cnt; i++) {
assert(files[i]);
// I am root!
pid_t child = fork();
if (child == -1)
errExit("fork");
if (child == 0) { // child
// drop privileges
if (setgid(user_gid) != 0)
errExit("setgid");
if (setuid(user_uid) != 0)
errExit("setuid");
// try to open the file for reading
FILE *fp = fopen(files[i], "r");
if (fp)
fclose(fp);
else
printf("%s, ", dirs[i]);
fflush(0);
exit(0);
}
// wait for the child to finish
int status;
wait(&status);
}
printf("\n");
}

View file

@ -1,4 +1,4 @@
all: firecfg.man firejail.man firejail-login.man firejail-users.man firejail-profile.man firemon.man
all: firecfg.man firejail.man firejail-login.man firejail-users.man firejail-profile.man firemon.man jailtest.man
include ../common.mk
%.man: %.txt

82
src/man/jailtest.txt Normal file
View file

@ -0,0 +1,82 @@
.TH JAILTEST 1 "MONTH YEAR" "VERSION" "JAILTEST man page"
.SH NAME
jailtest \- Simple utility program to test running sandboxes
.SH SYNOPSIS
sudo jailtest [OPTIONS] [directory]
.SH DESCRIPTION
WORK IN PROGRESS!
jailtest attaches itself to all sandboxes started by the user and performs some basic tests
on the sandbox filesystem:
.TP
\fB1. Virtual directories
jailtest extracts a list with the main virtual directories installed by the sandbox.
These directories are build by firejail at startup using --private* and --whitelist commands.
.TP
\fB2. Noexec test
jailtest inserts executable programs in /home/username, /tmp, and /var/tmp directories
and tries to run them form inside the sandbox, thus testing if the directory is executable or not.
.TP
\fB3. Read access test
jailtest creates test files in the directories specified by the user and tries to read
them from inside the sandbox.
.TP
The program is running as root exclusively under sudo.
.SH OPTIONS
.TP
\fB\-\-debug
Print debug messages
.TP
\fB\-?\fR, \fB\-\-help\fR
Print options end exit.
.TP
\fB\-\-version
Print program version and exit.
.TP
\fB[directory]
One or more directories in user home to test for read access.
.SH OUTPUT
For each sandbox detected we print the following line:
PID:USER:Sandbox Name:Command
It is followed by relevant sandbox information, such as the virtual directories and various warnings.
.SH EXAMPLE
.br
$ sudo jailtest ~/.ssh ~/.gnupg
.br
1429:netblue::/usr/bin/firejail /opt/firefox/firefox
.br
Virtual dirs: /home/netblue, /tmp, /var/tmp, /dev, /etc,
.br
5602:netblue::/usr/bin/firejail /usr/bin/ssh netblue@x.y.z.net
.br
Virtual dirs: /var/tmp, /dev,
.br
Warning: I can read ~/.ssh
.br
5926:netblue::/usr/bin/firejail /usr/bin/gimp-2.10
.br
Virtual dirs: /tmp, /var/tmp, /dev,
.br
Warning: I can run programs in /home/netblue
.br
6394:netblue:libreoffice:/usr/bin/firejail libreoffice
.br
Virtual dirs: /tmp, /var/tmp, /dev,
.br
.SH LICENSE
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
.PP
Homepage: https://firejail.wordpress.com
.SH SEE ALSO
\&\flfirejail\fR\|(1),
\&\flfirecfg\fR\|(1),
\&\flfirejail-profile\fR\|(5),
\&\flfirejail-login\fR\|(5)
\&\flfirejail-users\fR\|(5)