[apparmor] [PATCH 1/3] Generate the features list from the features directory
John Johansen
john.johansen at canonical.com
Wed Feb 22 23:04:56 UTC 2012
Newer versions of AppArmor use a features directory instead of a file
update the parser to use this to determine features and match string
This is just a first pass at this to get things up quickly. A much
more comprehensive rework that can parse and use the full information
set is needed.
Signed-off-by: John Johansen <john.johansen at canonical.com>
---
parser/parser.h | 1 +
parser/parser_common.c | 1 +
parser/parser_main.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 122 insertions(+), 1 deletions(-)
diff --git a/parser/parser.h b/parser/parser.h
index 8d3ef6c..7be0f83 100644
--- a/parser/parser.h
+++ b/parser/parser.h
@@ -247,6 +247,7 @@ extern int perms_create;
extern int net_af_max_override;
extern int kernel_load;
extern int kernel_supports_network;
+extern int kernel_supports_mount;
extern int flag_changehat_version;
extern int conf_verbose;
extern int conf_quiet;
diff --git a/parser/parser_common.c b/parser/parser_common.c
index df78a10..572eaad 100644
--- a/parser/parser_common.c
+++ b/parser/parser_common.c
@@ -27,6 +27,7 @@ int perms_create = 0; /* perms contain create flag */
int net_af_max_override = -1; /* use kernel to determine af_max */
int kernel_load = 1;
int kernel_supports_network = 1; /* kernel supports network rules */
+int kernel_supports_mount = 0; /* kernel supports mount rules */
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
int conf_verbose = 0;
int conf_quiet = 0;
diff --git a/parser/parser_main.c b/parser/parser_main.c
index 721582d..94ad2b9 100644
--- a/parser/parser_main.c
+++ b/parser/parser_main.c
@@ -30,6 +30,7 @@
#include <mntent.h>
#include <libintl.h>
#include <locale.h>
+#include <dirent.h>
#define _(s) gettext(s)
/* enable the following line to get voluminous debug info */
@@ -667,17 +668,134 @@ int have_enough_privilege(void)
return 0;
}
+static char *handle_features_dir(const char *filename, char **buffer, int size,
+ char *pos)
+{
+ DIR *dir = NULL;
+ char *dirent_path = NULL;
+ struct dirent *dirent;
+ struct stat my_stat;
+ int len;
+
+ PDEBUG("Opened features directory \"%s\"\n", filename);
+ if (!(dir = opendir(filename))) {
+ PDEBUG("opendir failed '%s'", filename);
+ exit(1);
+ }
+
+ while ((dirent = readdir(dir)) != NULL) {
+ int name_len, remaining;
+ /* skip dotfiles silently. */
+ if (dirent->d_name[0] == '.')
+ continue;
+
+ if (dirent_path)
+ free(dirent_path);
+ if (asprintf(&dirent_path, "%s/%s", filename, dirent->d_name) < 0)
+ {
+ PERROR(_("Memory allocation error."));
+ exit(1);
+ }
+
+ name_len = strlen(dirent->d_name);
+ if (!name_len)
+ continue;
+
+ if (stat(dirent_path, &my_stat)) {
+ PERROR(_("stat failed for '%s'"), dirent_path);
+ exit(1);
+ }
+
+ remaining = size - (pos - *buffer);
+ len = snprintf(pos, remaining, "%s { ", dirent->d_name);
+ if (len > remaining) {
+ PERROR(_("Feature buffer full."));
+ exit(1);
+ }
+ pos += len;
+
+ if (S_ISREG(my_stat.st_mode)) {
+ int file;
+ int remaining = size - (pos - *buffer);
+ if (!(file = open(dirent_path, O_RDONLY))) {
+ PDEBUG("Could not open '%s' in '%s'", dirent_path, filename);
+ exit(1);
+ break;
+ }
+ PDEBUG("Opened features \"%s\" in \"%s\"\n", dirent_path, filename);
+ if (my_stat.st_size > remaining) {
+ PERROR(_("Feature buffer full."));
+ exit(1);
+ }
+
+ do {
+ len = read(file, pos, remaining);
+ if (pos > 0) {
+ remaining -= len;
+ pos += len;
+ *pos = 0;
+ }
+ } while (len > 0);
+ if (len < 0) {
+ PDEBUG("Error reading feature file '%s'\n",
+ dirent_path);
+ exit(1);
+ }
+ close(file);
+
+ } else if (S_ISDIR(my_stat.st_mode)) {
+ pos = handle_features_dir(dirent_path, buffer, size,
+ pos);
+ if (!pos)
+ break;
+
+ }
+
+ remaining = size - (pos - *buffer);
+ len = snprintf(pos, remaining, " }\n");
+ if (len > remaining) {
+ PERROR(_("Feature buffer full."));
+ exit(1);
+ }
+ pos += len;
+ }
+ if (dirent_path)
+ free(dirent_path);
+ closedir(dir);
+
+ return pos;
+}
+
/* match_string == NULL --> no match_string available
match_string != NULL --> either a matching string specified on the
command line, or the kernel supplied a match string */
static void get_match_string(void) {
FILE *ms = NULL;
+ struct stat stat_file;
/* has process_args() already assigned a match string? */
if (match_string)
goto out;
+ if (stat(FLAGS_FILE, &stat_file) == -1)
+ goto out;
+
+ if (S_ISDIR(stat_file.st_mode)) {
+ /* if we have a features directory default to */
+ regex_type = AARE_DFA;
+ perms_create = 1;
+ flag_changehat_version = FLAG_CHANGEHAT_1_4;
+
+ flags_string = malloc(1024);
+ handle_features_dir(FLAGS_FILE, &flags_string, 2048, flags_string);
+ if (strstr(flags_string, "network"))
+ kernel_supports_network = 1;
+ if (strstr(flags_string, "mount"))
+ kernel_supports_mount = 1;
+ return;
+ }
+
ms = fopen(MATCH_STRING, "r");
if (!ms)
goto out;
@@ -718,7 +836,8 @@ static void get_flags_string(char **flags, char *flags_file) {
FILE *f = NULL;
/* abort if missing or already set */
- if (!flags || *flags) return;
+ if (!flags || *flags)
+ return;
f = fopen(flags_file, "r");
if (!f)
--
1.7.9
More information about the AppArmor
mailing list