removed IDS feature, it was never enabled by default in our builds

This commit is contained in:
netblue30 2025-12-17 09:09:44 -05:00
parent 489cc25c2f
commit 5e962ff78e
15 changed files with 1 additions and 990 deletions

View file

@ -27,7 +27,7 @@ endif
COMPLETIONDIRS = src/zsh_completion src/bash_completion
APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats src/jailcheck/jailcheck src/etc-cleanup/etc-cleanup
SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee src/fids/fids
SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee
SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter src/fzenity/fzenity
SBOX_APPS_NON_DUMPABLE += src/fsec-optimize/fsec-optimize src/fsec-print/fsec-print src/fseccomp/fseccomp
SBOX_APPS_NON_DUMPABLE += src/fnettrace/fnettrace src/fnettrace-dns/fnettrace-dns src/fnettrace-sni/fnettrace-sni

View file

@ -36,7 +36,6 @@ HAVE_CHROOT=@HAVE_CHROOT@
HAVE_DBUSPROXY=@HAVE_DBUSPROXY@
HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@
HAVE_IDS=@HAVE_IDS@
HAVE_LANDLOCK=@HAVE_LANDLOCK@
HAVE_NETWORK=@HAVE_NETWORK@
HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@
@ -56,7 +55,6 @@ MANFLAGS = \
$(HAVE_DBUSPROXY) \
$(HAVE_FILE_TRANSFER) \
$(HAVE_FORCE_NONEWPRIVS) \
$(HAVE_IDS) \
$(HAVE_LANDLOCK) \
$(HAVE_NETWORK) \
$(HAVE_ONLY_SYSCFG_PROFILES) \

19
configure vendored
View file

@ -671,7 +671,6 @@ PKG_CONFIG_LIBDIR
PKG_CONFIG_PATH
PKG_CONFIG
HAVE_APPARMOR
HAVE_IDS
HAVE_SANDBOX_CHECK
DEPS_CFLAGS
TAR
@ -733,7 +732,6 @@ enable_option_checking
enable_analyzer
enable_sanitizer
enable_sandbox_check
enable_ids
enable_apparmor
enable_selinux
enable_landlock
@ -1393,7 +1391,6 @@ Optional Features:
--disable-sandbox-check disable checking if firejail is running within a
sandbox, only use this when developing firejail
inside of a sandbox
--enable-ids enable ids
--enable-apparmor enable apparmor
--enable-selinux SELinux labeling support
--disable-landlock disable Landlock self-restriction support
@ -3972,21 +3969,6 @@ then :
fi
HAVE_IDS=""
# Check whether --enable-ids was given.
if test ${enable_ids+y}
then :
enableval=$enable_ids;
fi
if test "x$enable_ids" = "xyes"
then :
HAVE_IDS="-DHAVE_IDS"
fi
HAVE_APPARMOR=""
# Check whether --enable-apparmor was given.
@ -5776,7 +5758,6 @@ Features:
disable user profiles: $HAVE_ONLY_SYSCFG_PROFILES
enable --output logging: $HAVE_OUTPUT
file transfer support: $HAVE_FILE_TRANSFER
IDS support: $HAVE_IDS
Landlock support: $HAVE_LANDLOCK
manpage support: $HAVE_MAN
network: $HAVE_NETWORK

View file

@ -79,14 +79,6 @@ AS_IF([test "x$enable_sandbox_check" != "xno"], [
HAVE_SANDBOX_CHECK="-DHAVE_SANDBOX_CHECK"
])
HAVE_IDS=""
AC_SUBST([HAVE_IDS])
AC_ARG_ENABLE([ids],
[AS_HELP_STRING([--enable-ids], [enable ids])])
AS_IF([test "x$enable_ids" = "xyes"], [
HAVE_IDS="-DHAVE_IDS"
])
HAVE_APPARMOR=""
AC_SUBST([HAVE_APPARMOR])
AC_ARG_ENABLE([apparmor],
@ -308,7 +300,6 @@ Features:
disable user profiles: $HAVE_ONLY_SYSCFG_PROFILES
enable --output logging: $HAVE_OUTPUT
file transfer support: $HAVE_FILE_TRANSFER
IDS support: $HAVE_IDS
Landlock support: $HAVE_LANDLOCK
manpage support: $HAVE_MAN
network: $HAVE_NETWORK

View file

@ -1,10 +0,0 @@
.SUFFIXES:
ROOT = ../..
-include $(ROOT)/config.mk
MOD = fids
MOD_DIR = $(ROOT)/src/$(MOD)
PROG = $(MOD_DIR)/$(MOD)
TARGET = $(PROG)
include $(ROOT)/src/prog.mk

View file

@ -1,176 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* A simple unkeyed BLAKE2b Implementation based on the official reference
* from https://github.com/BLAKE2/BLAKE2.
*
* The original code was released under CC0 1.0 Universal license (Creative Commons),
* a public domain license.
*/
#include "fids.h"
// little-endian vs big-endian is irrelevant since the checksum is calculated and checked on the same computer.
static inline uint64_t load64( const void *src ) {
uint64_t w;
memcpy( &w, src, sizeof( w ) );
return w;
}
// mixing function
#define ROTR64(x, y) (((x) >> (y)) ^ ((x) << (64 - (y))))
#define G(a, b, c, d, x, y) { \
v[a] = v[a] + v[b] + x; \
v[d] = ROTR64(v[d] ^ v[a], 32); \
v[c] = v[c] + v[d]; \
v[b] = ROTR64(v[b] ^ v[c], 24); \
v[a] = v[a] + v[b] + y; \
v[d] = ROTR64(v[d] ^ v[a], 16); \
v[c] = v[c] + v[d]; \
v[b] = ROTR64(v[b] ^ v[c], 63); }
// init vector
static const uint64_t iv[8] = {
0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
};
const uint8_t sigma[12][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
};
// blake2b context
typedef struct {
uint8_t b[128]; // input buffer
uint64_t h[8]; // chained state
uint64_t t[2]; // total number of bytes
size_t c; // pointer for b[]
size_t outlen; // digest size
} CTX;
// compress function
static void compress(CTX *ctx, int last) {
uint64_t m[16];
uint64_t v[16];
size_t i;
for (i = 0; i < 16; i++)
m[i] = load64(&ctx->b[8 * i]);
for (i = 0; i < 8; i++) {
v[i] = ctx->h[i];
v[i + 8] = iv[i];
}
v[12] ^= ctx->t[0];
v[13] ^= ctx->t[1];
if (last)
v[14] = ~v[14];
for (i = 0; i < 12; i++) {
G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]);
G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]);
G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]);
G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]);
G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]);
G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]);
G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]);
G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]);
}
for( i = 0; i < 8; ++i )
ctx->h[i] ^= v[i] ^ v[i + 8];
}
static int init(CTX *ctx, size_t outlen) { // (keylen=0: no key)
size_t i;
if (outlen == 0 || outlen > 64)
return -1;
for (i = 0; i < 8; i++)
ctx->h[i] = iv[i];
ctx->h[0] ^= 0x01010000 ^ outlen;
ctx->t[0] = 0;
ctx->t[1] = 0;
ctx->c = 0;
ctx->outlen = outlen;
return 0;
}
static void update(CTX *ctx, const void *in, size_t inlen) {
size_t i;
for (i = 0; i < inlen; i++) {
if (ctx->c == 128) {
ctx->t[0] += ctx->c;
if (ctx->t[0] < ctx->c)
ctx->t[1]++;
compress(ctx, 0);
ctx->c = 0;
}
ctx->b[ctx->c++] = ((const uint8_t *) in)[i];
}
}
static void final(CTX *ctx, void *out) {
size_t i;
ctx->t[0] += ctx->c;
if (ctx->t[0] < ctx->c)
ctx->t[1]++;
while (ctx->c < 128)
ctx->b[ctx->c++] = 0;
compress(ctx, 1);
for (i = 0; i < ctx->outlen; i++) {
((uint8_t *) out)[i] =
(ctx->h[i >> 3] >> (8 * (i & 7))) & 0xFF;
}
}
// public function
int blake2b(void *out, size_t outlen, const void *in, size_t inlen) {
CTX ctx;
if (init(&ctx, outlen))
return -1;
update(&ctx, in, inlen);
final(&ctx, out);
return 0;
}

View file

@ -1,15 +0,0 @@
/bin
/sbin
/usr/bin
/usr/sbin
/usr/games
/opt
/usr/share/ca-certificates
/home/netblue/.bashrc
/home/netblue/.config/firejail
/home/netblue/.config/autostart
/home/netblue/Desktop/*.desktop
/home/netblue/.ssh
/home/netblue/.gnupg

View file

@ -1,157 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include"fids.h"
typedef struct db_t {
struct db_t *next;
char *fname;
char *checksum;
char *mode;
int checked;
} DB;
#define MAXBUF 4096
static DB *database[HASH_MAX] = {NULL};
// djb2 hash function by Dan Bernstein
static unsigned hash(const char *str) {
unsigned long hash = 5381;
int c;
while ((c = *str++) != '\0')
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash & (HASH_MAX - 1);
}
#if 0
// for testing the hash table
static void db_print(void) {
int i;
for (i = 0; i < HASH_MAX; i++) {
int cnt = 0;
DB *ptr = database[i];
while (ptr) {
cnt++;
ptr = ptr->next;
}
printf("%d ", cnt);
fflush(0);
}
printf("\n");
}
#endif
static void db_add(const char *fname, const char *checksum, const char *mode) {
DB *ptr = malloc(sizeof(DB));
if (!ptr)
errExit("malloc");
ptr->fname = strdup(fname);
ptr->checksum = strdup(checksum);
ptr->mode = strdup(mode);
ptr->checked = 0;
if (!ptr->fname || !ptr->checksum || !ptr->mode)
errExit("strdup");
unsigned h = hash(fname);
ptr->next = database[h];
database[h] = ptr;
}
void db_check(const char *fname, const char *checksum, const char *mode) {
assert(fname);
assert(checksum);
assert(mode);
unsigned h =hash(fname);
DB *ptr = database[h];
while (ptr) {
if (strcmp(fname, ptr->fname) == 0) {
ptr->checked = 1;
break;
}
ptr = ptr->next;
}
if (ptr ) {
if (strcmp(checksum, ptr->checksum)) {
f_modified++;
fprintf(stderr, "\nWarning: modified %s\n", fname);
}
if (strcmp(mode, ptr->mode)) {
f_permissions++;
fprintf(stderr, "\nWarning: permissions %s: old %s, new %s\n",
fname, ptr->mode, mode);
}
}
else {
f_new++;
fprintf(stderr, "\nWarning: new file %s\n", fname);
}
}
void db_missing(void) {
int i;
for (i = 0; i < HASH_MAX; i++) {
DB *ptr = database[i];
while (ptr) {
if (!ptr->checked) {
f_removed++;
fprintf(stderr, "Warning: removed %s\n", ptr->fname);
}
ptr = ptr->next;
}
}
}
// return 0 if ok, 1 if error
int db_init(void) {
char buf[MAXBUF];
while(fgets(buf, MAXBUF, stdin)) {
// split - tab separated
char *mode = buf;
char *ptr = strchr(buf, '\t');
if (!ptr)
goto errexit;
*ptr = '\0';
char *checksum = ptr + 1;
ptr = strchr(checksum, '\t');
if (!ptr)
goto errexit;
*ptr = '\0';
char *fname = ptr + 1;
ptr = strchr(fname, '\n');
if (!ptr)
goto errexit;
*ptr = '\0';
db_add(fname, checksum, mode);
}
// db_print();
return 0;
errexit:
fprintf(stderr, "Error fids: database corrupted\n");
exit(1);
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include"fids.h"
typedef struct db_exclude_t {
struct db_exclude_t *next;
char *fname;
int len;
} DB_EXCLUDE;
static DB_EXCLUDE *database = NULL;
void db_exclude_add(const char *fname) {
assert(fname);
DB_EXCLUDE *ptr = malloc(sizeof(DB_EXCLUDE));
if (!ptr)
errExit("malloc");
ptr->fname = strdup(fname);
if (!ptr->fname)
errExit("strdup");
ptr->len = strlen(fname);
ptr->next = database;
database = ptr;
}
int db_exclude_check(const char *fname) {
assert(fname);
DB_EXCLUDE *ptr = database;
while (ptr != NULL) {
if (strncmp(fname, ptr->fname, ptr->len) == 0)
return 1;
ptr = ptr->next;
}
return 0;
}

View file

@ -1,51 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef FIDS_H
#define FIDS_H
#include "../include/common.h"
// main.c
#define MAX_DIR_LEVEL 20 // max directory tree depth
#define MAX_INCLUDE_LEVEL 10 // max include level for config files
extern int f_scanned;
extern int f_modified;
extern int f_new;
extern int f_removed;
extern int f_permissions;
// db.c
#define HASH_MAX 2048 // power of 2
int db_init(void);
void db_check(const char *fname, const char *checksum, const char *mode);
void db_missing(void);
// db_exclude.c
void db_exclude_add(const char *fname);
int db_exclude_check(const char *fname);
// blake2b.c
//#define KEY_SIZE 128 // key size in bytes
#define KEY_SIZE 256
//#define KEY_SIZE 512
int blake2b(void *out, size_t outlen, const void *in, size_t inlen);
#endif

View file

@ -1,379 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "fids.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <dirent.h>
#include <glob.h>
#define MAXBUF 4096
static int dir_level = 1;
static int include_level = 0;
int arg_init = 0;
int arg_check = 0;
char *arg_homedir = NULL;
char *arg_dbfile = NULL;
int f_scanned = 0;
int f_modified = 0;
int f_new = 0;
int f_removed = 0;
int f_permissions = 0;
static inline int is_dir(const char *fname) {
assert(fname);
struct stat s;
if (stat(fname, &s) == 0) {
if (S_ISDIR(s.st_mode))
return 1;
}
return 0;
}
static inline int is_link(const char *fname) {
assert(fname);
char c;
ssize_t rv = readlink(fname, &c, 1);
return (rv != -1);
}
// mode is an array of 10 chars or more
static inline void file_mode(const char *fname, char *mode) {
assert(fname);
assert(mode);
struct stat s;
if (stat(fname, &s)) {
*mode = '\0';
return;
}
sprintf(mode, (s.st_mode & S_IRUSR) ? "r" : "-");
sprintf(mode + 1, (s.st_mode & S_IWUSR) ? "w" : "-");
sprintf(mode + 2, (s.st_mode & S_IXUSR) ? "x" : "-");
sprintf(mode + 3, (s.st_mode & S_IRGRP) ? "r" : "-");
sprintf(mode + 4, (s.st_mode & S_IWGRP) ? "w" : "-");
sprintf(mode + 5, (s.st_mode & S_IXGRP) ? "x" : "-");
sprintf(mode + 6, (s.st_mode & S_IROTH) ? "r" : "-");
sprintf(mode + 7, (s.st_mode & S_IWOTH) ? "w" : "-");
sprintf(mode + 8, (s.st_mode & S_IXOTH) ? "x" : "-");
}
static void file_checksum(const char *fname) {
assert(fname);
int fd = open(fname, O_RDONLY);
if (fd == -1)
return;
off_t size = lseek(fd, 0, SEEK_END);
if (size < 0) {
close(fd);
return;
}
char *content = "empty";
int mmapped = 0;
if (size == 0) {
// empty files don't mmap - use "empty" string as the file content
size = 6; // strlen("empty") + 1
}
else {
content = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
mmapped = 1;
}
close(fd);
unsigned char checksum[KEY_SIZE / 8];
blake2b(checksum, sizeof(checksum), content, size);
if (mmapped)
munmap(content, size);
// calculate blake2 checksum
char str_checksum[(KEY_SIZE / 8) * 2 + 1];
int long unsigned i;
char *ptr = str_checksum;
for (i = 0; i < sizeof(checksum); i++, ptr += 2)
sprintf(ptr, "%02x", (unsigned char ) checksum[i]);
// build permissions string
char mode[10];
file_mode(fname, mode);
if (arg_init)
printf("%s\t%s\t%s\n", mode, str_checksum, fname);
else if (arg_check)
db_check(fname, str_checksum, mode);
else
assert(0);
f_scanned++;
if (f_scanned % 500 == 0)
fprintf(stderr, "%d ", f_scanned);
fflush(0);
}
void list_directory(const char *fname) {
assert(fname);
if (dir_level > MAX_DIR_LEVEL) {
fprintf(stderr, "Warning fids: maximum depth level exceeded for %s\n", fname);
return;
}
if (db_exclude_check(fname))
return;
if (is_link(fname))
return;
if (!is_dir(fname)) {
file_checksum(fname);
return;
}
DIR *dir;
struct dirent *entry;
if (!(dir = opendir(fname)))
return;
dir_level++;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
char *path;
if (asprintf(&path, "%s/%s", fname, entry->d_name) == -1)
errExit("asprintf");
list_directory(path);
free(path);
}
closedir(dir);
dir_level--;
}
void globbing(const char *fname) {
assert(fname);
// filter top directory
if (strcmp(fname, "/") == 0)
return;
glob_t globbuf;
int globerr = glob(fname, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf);
if (globerr) {
fprintf(stderr, "Error fids: failed to glob pattern %s\n", fname);
exit(1);
}
long unsigned i;
for (i = 0; i < globbuf.gl_pathc; i++) {
char *path = globbuf.gl_pathv[i];
assert(path);
list_directory(path);
}
globfree(&globbuf);
}
static void process_config(const char *fname) {
assert(fname);
if (++include_level >= MAX_INCLUDE_LEVEL) {
fprintf(stderr, "Error ids: maximum include level for config files exceeded\n");
exit(1);
}
fprintf(stderr, "Opening config file %s\n", fname);
int fd = open(fname, O_RDONLY|O_CLOEXEC);
if (fd < 0) {
if (include_level == 1) {
fprintf(stderr, "Error ids: cannot open config file %s\n", fname);
exit(1);
}
return;
}
// make sure the file is owned by root
struct stat s;
if (fstat(fd, &s)) {
fprintf(stderr, "Error ids: cannot stat config file %s\n", fname);
exit(1);
}
if (s.st_uid || s.st_gid) {
fprintf(stderr, "Error ids: config file not owned by root\n");
exit(1);
}
fprintf(stderr, "Loading config file %s\n", fname);
FILE *fp = fdopen(fd, "r");
if (!fp) {
fprintf(stderr, "Error fids: cannot open config file %s\n", fname);
exit(1);
}
char buf[MAXBUF];
int line = 0;
while (fgets(buf, MAXBUF, fp)) {
line++;
// trim \n
char *ptr = strchr(buf, '\n');
if (ptr)
*ptr = '\0';
// comments
ptr = strchr(buf, '#');
if (ptr)
*ptr = '\0';
// empty space
ptr = buf;
while (*ptr == ' ' || *ptr == '\t')
ptr++;
char *start = ptr;
// empty line
if (*start == '\0')
continue;
// trailing spaces
ptr = start + strlen(start);
ptr--;
while (*ptr == ' ' || *ptr == '\t')
*ptr-- = '\0';
// replace ${HOME}
if (strncmp(start, "include", 7) == 0) {
ptr = start + 7;
if ((*ptr != ' ' && *ptr != '\t') || *ptr == '\0') {
fprintf(stderr, "Error fids: invalid line %d in %s\n", line, fname);
exit(1);
}
while (*ptr == ' ' || *ptr == '\t')
ptr++;
if (*ptr == '/')
process_config(ptr);
else {
// assume the file is in /etc/firejail
char *tmp;
if (asprintf(&tmp, "/etc/firejail/%s", ptr) == -1)
errExit("asprintf");
process_config(tmp);
free(tmp);
}
}
else if (*start == '!') {
// exclude file or dir
start++;
if (strncmp(start, "${HOME}", 7))
db_exclude_add(start);
else {
char *fname;
if (asprintf(&fname, "%s%s", arg_homedir, start + 7) == -1)
errExit("asprintf");
db_exclude_add(fname);
free(fname);
}
}
else if (strncmp(start, "${HOME}", 7))
globbing(start);
else {
char *fname;
if (asprintf(&fname, "%s%s", arg_homedir, start + 7) == -1)
errExit("asprintf");
globbing(fname);
free(fname);
}
}
fclose(fp);
include_level--;
}
static const char *const usage_str =
"Usage: fids [--help|-h|-?] --init|--check homedir\n";
void usage(void) {
puts(usage_str);
}
int main(int argc, char **argv) {
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 ||
strcmp(argv[i], "-?") == 0 ||
strcmp(argv[i], "--help") == 0) {
usage();
return 0;
}
else if (strcmp(argv[i], "--init") == 0)
arg_init = 1;
else if (strcmp(argv[i], "--check") == 0)
arg_check = 1;
else if (strncmp(argv[i], "--", 2) == 0) {
fprintf(stderr, "Error fids: invalid argument %s\n", argv[i]);
exit(1);
}
}
if (argc != 3) {
fprintf(stderr, "Error fids: invalid number of arguments\n");
exit(1);
}
arg_homedir = argv[2];
int op = arg_check + arg_init;
if (op == 0 || op == 2) {
fprintf(stderr, "Error fids: use either --init or --check\n");
exit(1);
}
if (arg_init) {
process_config(SYSCONFDIR"/ids.config");
fprintf(stderr, "\n%d files scanned\n", f_scanned);
fprintf(stderr, "IDS database initialized\n");
}
else if (arg_check) {
if (db_init()) {
fprintf(stderr, "Error: IDS database not initialized, please run \"firejail --ids-init\"\n");
exit(1);
}
process_config(SYSCONFDIR"/ids.config");
fprintf(stderr, "\n%d files scanned: modified %d, permissions %d, new %d, removed %d\n",
f_scanned, f_modified, f_permissions, f_new, f_removed);
db_missing();
}
else
assert(0);
return 0;
}

View file

@ -388,13 +388,6 @@ static const char *const compiletime_support =
"disabled"
#endif
"\n\t- IDS support is "
#ifdef HAVE_IDS
"enabled"
#else
"disabled"
#endif
"\n\t- Landlock support is "
#ifdef HAVE_LANDLOCK
"enabled"

View file

@ -915,8 +915,6 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
#define PATH_FLDD (RUN_FIREJAIL_LIB_DIR "/fldd")
#define PATH_FIDS (LIBDIR "/firejail/fids")
// bitmapped filters for sbox_run
#define SBOX_ROOT (1 << 0) // run the sandbox as root
#define SBOX_USER (1 << 1) // run the sandbox as a regular user
@ -962,9 +960,6 @@ void dhcp_start(void);
// selinux.c
void selinux_relabel_path(const char *path, const char *inside_path);
// ids.c
void run_ids(int argc, char **argv);
// oom.c
void oom_set(const char *oom_string);

View file

@ -1,91 +0,0 @@
/*
* Copyright (C) 2014-2025 Firejail Authors
*
* This file is part of firejail project
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "firejail.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static void ids_init(void) {
// store checksums as root in /var/lib/firejail/${USERNAME}.ids
char *fname;
if (asprintf(&fname, VARDIR"/%s.ids", cfg.username) == -1)
errExit("asprintf");
int rv = unlink(fname);
(void) rv;
int fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd < 0) {
fprintf(stderr, "Error: cannot create %s\n", fname);
exit(1);
}
// redirect output
close(STDOUT_FILENO);
if (dup(fd) != STDOUT_FILENO)
errExit("dup");
close(fd);
free(fname);
sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FIDS, "--init", cfg.homedir);
}
static void ids_check(void) {
// store checksums as root in /var/lib/firejail/${USERNAME}.ids
char *fname;
if (asprintf(&fname, VARDIR"/%s.ids", cfg.username) == -1)
errExit("asprintf");
int fd = open(fname, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error: cannot open %s\n", fname);
exit(1);
}
// redirect input
close(STDIN_FILENO);
if (dup(fd) != STDIN_FILENO)
errExit("dup");
close(fd);
free(fname);
sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP| SBOX_ALLOW_STDIN, 3, PATH_FIDS, "--check", cfg.homedir);
}
void run_ids(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Error: only one IDS command expected\n");
exit(1);
}
EUID_ROOT();
struct stat s;
if (stat(VARDIR, &s)) // /var/lib/firejail
create_empty_dir_as_root(VARDIR, 0700);
if (strcmp(argv[1], "--ids-init") == 0)
ids_init();
else if (strcmp(argv[1], "--ids-check") == 0)
ids_check();
else
fprintf(stderr, "Error: unrecognized IDS command\n");
exit(0);
}

View file

@ -1143,19 +1143,6 @@ int main(int argc, char **argv, char **envp) {
if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename
run_builder(argc, argv); // this function will not return
// intrusion detection system
#ifdef HAVE_IDS
if (check_arg(argc, argv, "--ids-", 0)) // supports both --ids-init and --ids-check
run_ids(argc, argv); // this function will not return
#else
if (check_arg(argc, argv, "--ids-", 0)) { // supports both --ids-init and --ids-check
fprintf(stderr, "Error: IDS features disabled in your Firejail build.\n"
"\tTo enable it, configure your build system using --enable-ids.\n"
"\tExample: ./configure --prefix=/usr --enable-ids\n\n");
exit(1);
}
#endif
EUID_ROOT();
#ifndef HAVE_SUID
if (geteuid() != 0) {