[apparmor] [PATCH v2 36/42] libapparmor: Move the aa_features API
Tyler Hicks
tyhicks at canonical.com
Fri Mar 6 21:48:52 UTC 2015
Signed-off-by: Tyler Hicks <tyhicks at canonical.com>
---
libraries/libapparmor/include/sys/apparmor.h | 13 +
libraries/libapparmor/src/Makefile.am | 2 +-
libraries/libapparmor/src/features.c | 448 +++++++++++++++++++++++++++
libraries/libapparmor/src/libapparmor.map | 23 ++
libraries/libapparmor/src/private.h | 1 +
parser/Makefile | 9 +-
parser/features.c | 448 ---------------------------
parser/features.h | 34 --
parser/kernel_interface.h | 2 +
9 files changed, 491 insertions(+), 489 deletions(-)
create mode 100644 libraries/libapparmor/src/features.c
delete mode 100644 parser/features.c
delete mode 100644 parser/features.h
diff --git a/libraries/libapparmor/include/sys/apparmor.h b/libraries/libapparmor/include/sys/apparmor.h
index 361cde8..34507e4 100644
--- a/libraries/libapparmor/include/sys/apparmor.h
+++ b/libraries/libapparmor/include/sys/apparmor.h
@@ -18,6 +18,7 @@
#ifndef _SYS_APPARMOR_H
#define _SYS_APPARMOR_H 1
+#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -103,6 +104,18 @@ extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
#define aa_change_hat_vargs(T, X...) \
(aa_change_hat_vargs)(T, __macroarg_counter(X), X)
+typedef struct aa_features aa_features;
+int aa_features_new(aa_features **features, const char *path);
+int aa_features_new_from_string(aa_features **features,
+ const char *string, size_t size);
+int aa_features_new_from_kernel(aa_features **features);
+aa_features *aa_features_ref(aa_features *features);
+void aa_features_unref(aa_features *features);
+
+int aa_features_write_to_file(aa_features *features, const char *path);
+bool aa_features_is_equal(aa_features *features1, aa_features *features2);
+bool aa_features_supports(aa_features *features, char *str);
+
__END_DECLS
#endif /* sys/apparmor.h */
diff --git a/libraries/libapparmor/src/Makefile.am b/libraries/libapparmor/src/Makefile.am
index 42934d0..ac93bf5 100644
--- a/libraries/libapparmor/src/Makefile.am
+++ b/libraries/libapparmor/src/Makefile.am
@@ -48,7 +48,7 @@ af_protos.h: /usr/include/netinet/in.h
lib_LTLIBRARIES = libapparmor.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
-libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c scanner.c private.c
+libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c scanner.c private.c features.c
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
diff --git a/libraries/libapparmor/src/features.c b/libraries/libapparmor/src/features.c
new file mode 100644
index 0000000..cf2389c
--- /dev/null
+++ b/libraries/libapparmor/src/features.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2014
+ * Canonical, Ltd. (All rights reserved)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License published by the Free Software Foundation.
+ *
+ * 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, contact Novell, Inc. or Canonical
+ * Ltd.
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/apparmor.h>
+
+#include "private.h"
+
+#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
+
+#define STRING_SIZE 8192
+
+struct aa_features {
+ unsigned int ref_count;
+ char string[STRING_SIZE];
+};
+
+struct features_struct {
+ char *buffer;
+ int size;
+ char *pos;
+};
+
+static int features_snprintf(struct features_struct *fst, const char *fmt, ...)
+{
+ va_list args;
+ int i, remaining = fst->size - (fst->pos - fst->buffer);
+
+ if (remaining < 0) {
+ errno = EINVAL;
+ PERROR("Invalid features buffer offset\n");
+ return -1;
+ }
+
+ va_start(args, fmt);
+ i = vsnprintf(fst->pos, remaining, fmt, args);
+ va_end(args);
+
+ if (i < 0) {
+ errno = EIO;
+ PERROR("Failed to write to features buffer\n");
+ return -1;
+ } else if (i >= remaining) {
+ errno = ENOBUFS;
+ PERROR("Feature buffer full.");
+ return -1;
+ }
+
+ fst->pos += i;
+ return 0;
+}
+
+static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
+ void *data)
+{
+ struct features_struct *fst = (struct features_struct *) data;
+
+ /* skip dot files and files with no name */
+ if (*name == '.' || !strlen(name))
+ return 0;
+
+ if (features_snprintf(fst, "%s {", name) == -1)
+ return -1;
+
+ if (S_ISREG(st->st_mode)) {
+ autoclose int file = -1;
+ int len;
+ int remaining = fst->size - (fst->pos - fst->buffer);
+
+ file = openat(dirfd(dir), name, O_RDONLY);
+ if (file == -1) {
+ PDEBUG("Could not open '%s'", name);
+ return -1;
+ }
+ PDEBUG("Opened features \"%s\"\n", name);
+ if (st->st_size > remaining) {
+ PDEBUG("Feature buffer full.");
+ errno = ENOBUFS;
+ return -1;
+ }
+
+ do {
+ len = read(file, fst->pos, remaining);
+ if (len > 0) {
+ remaining -= len;
+ fst->pos += len;
+ *fst->pos = 0;
+ }
+ } while (len > 0);
+ if (len < 0) {
+ PDEBUG("Error reading feature file '%s'\n", name);
+ return -1;
+ }
+ } else if (S_ISDIR(st->st_mode)) {
+ if (_aa_dirat_for_each(dir, name, fst, features_dir_cb))
+ return -1;
+ }
+
+ if (features_snprintf(fst, "}\n") == -1)
+ return -1;
+
+ return 0;
+}
+
+static int handle_features_dir(const char *filename, char *buffer, int size,
+ char *pos)
+{
+ struct features_struct fst = { buffer, size, pos };
+
+ if (_aa_dirat_for_each(NULL, filename, &fst, features_dir_cb)) {
+ PDEBUG("Failed evaluating %s\n", filename);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int load_features_file(const char *name, char *buffer, size_t size)
+{
+ autofclose FILE *f = NULL;
+ size_t end;
+
+ f = fopen(name, "r");
+ if (!f)
+ return -1;
+
+ errno = 0;
+ end = fread(buffer, 1, size - 1, f);
+ if (ferror(f)) {
+ if (!errno)
+ errno = EIO;
+ return -1;
+ }
+ buffer[end] = 0;
+
+ return 0;
+}
+
+static bool walk_one(const char **str, const char *component, bool is_top_level)
+{
+ const char *cur = *str;
+ uint32_t bracket_count = 0;
+ int i = 0;
+
+ /* Empty strings are not accepted */
+ if (!*cur || !component[0])
+ return false;
+
+ /**
+ * If @component is not top-level, the first character in the string to
+ * search MUST be '{'
+ */
+ if (!is_top_level) {
+ if (*cur != '{')
+ return false;
+
+ cur++;
+ }
+
+ /**
+ * This loop tries to find the @component in *@str. When this loops
+ * completes, cur will either point one character past the end of the
+ * matched @component or to the NUL terminator of *@str.
+ */
+ while(*cur && component[i]) {
+ if (!isascii(*cur)) {
+ /* Only ASCII is expected */
+ return false;
+ } else if (*cur == '{') {
+ /* There's a limit to the number of opening brackets */
+ if (bracket_count == UINT32_MAX)
+ return false;
+
+ bracket_count++;
+ } else if (*cur == '}') {
+ /* Check for unexpected closing brackets */
+ if (bracket_count == 0)
+ return false;
+
+ bracket_count--;
+ }
+
+ /**
+ * Move to the next character in @component if we have a match
+ * and either @component is not top-level or, if @component is
+ * top-level, we're not inside of brackets
+ */
+ if (*cur == component[i] &&
+ (!is_top_level || bracket_count == 0))
+ i++;
+ else
+ i = 0;
+
+ cur++;
+ }
+
+ /* A full match was not found if component[i] is non-NUL */
+ if (component[i])
+ return false;
+
+ /**
+ * This loop eats up valid (ASCII) characters until a non-bracket or
+ * non-space character is found so that *@str is properly set to call
+ * back into this function, if necessary
+ */
+ while (*cur) {
+ if (!isascii(*cur))
+ return false;
+ else if (*cur == '{' || *cur == '}' || !isspace(*cur))
+ break;
+
+ cur++;
+ }
+
+ *str = cur;
+ return true;
+}
+
+/**
+ * aa_features_new - create a new features based on a path
+ * @features: will point to the address of an allocated and initialized
+ * aa_features object upon success
+ * @path: path to a features file or directory
+ *
+ * Returns: 0 on success, -1 on error with errno set and *@features pointing to
+ * NULL
+ */
+int aa_features_new(aa_features **features, const char *path)
+{
+ struct stat stat_file;
+ aa_features *f;
+ int retval;
+
+ *features = NULL;
+
+ if (stat(path, &stat_file) == -1)
+ return -1;
+
+ f = (aa_features *) calloc(1, sizeof(*f));
+ if (!f) {
+ errno = ENOMEM;
+ return -1;
+ }
+ aa_features_ref(f);
+
+ retval = S_ISDIR(stat_file.st_mode) ?
+ handle_features_dir(path, f->string, STRING_SIZE, f->string) :
+ load_features_file(path, f->string, STRING_SIZE);
+ if (retval) {
+ int save = errno;
+
+ aa_features_unref(f);
+ errno = save;
+ return -1;
+ }
+
+ *features = f;
+
+ return 0;
+}
+
+/**
+ * aa_features_new_from_string - create a new features based on a string
+ * @features: will point to the address of an allocated and initialized
+ * aa_features object upon success
+ * @string: a NUL-terminated string representation of features
+ * @size: the size of @string, not counting the NUL-terminator
+ *
+ * Returns: 0 on success, -1 on error with errno set and *@features pointing to
+ * NULL
+ */
+int aa_features_new_from_string(aa_features **features,
+ const char *string, size_t size)
+{
+ aa_features *f;
+
+ *features = NULL;
+
+ /* Require size to be less than STRING_SIZE so there's room for a NUL */
+ if (size >= STRING_SIZE)
+ return ENOBUFS;
+
+ f = (aa_features *) calloc(1, sizeof(*f));
+ if (!f) {
+ errno = ENOMEM;
+ return -1;
+ }
+ aa_features_ref(f);
+
+ memcpy(f->string, string, size);
+ f->string[size] = '\0';
+ *features = f;
+
+ return 0;
+}
+
+/**
+ * aa_features_new_from_kernel - create a new features based on the current kernel
+ * @features: will point to the address of an allocated and initialized
+ * aa_features object upon success
+ *
+ * Returns: 0 on success, -1 on error with errno set and *@features pointing to
+ * NULL
+ */
+int aa_features_new_from_kernel(aa_features **features)
+{
+ return aa_features_new(features, FEATURES_FILE);
+}
+
+/**
+ * aa_features_ref - increments the ref count of a features
+ * @features: the features
+ *
+ * Returns: the features
+ */
+aa_features *aa_features_ref(aa_features *features)
+{
+ atomic_inc(&features->ref_count);
+ return features;
+}
+
+/**
+ * aa_features_unref - decrements the ref count and frees the features when 0
+ * @features: the features (can be NULL)
+ */
+void aa_features_unref(aa_features *features)
+{
+ if (features && atomic_dec_and_test(&features->ref_count))
+ free(features);
+}
+
+/**
+ * aa_features_write_to_file - write a string representation to a file
+ * @features: the features
+ * @path: the path to write to
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_features_write_to_file(aa_features *features, const char *path)
+{
+ autoclose int fd = -1;
+ size_t size;
+ ssize_t retval;
+ char *string;
+
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd == -1)
+ return -1;
+
+ string = features->string;
+ size = strlen(string);
+ do {
+ retval = write(fd, string, size);
+ if (retval == -1)
+ return -1;
+
+ size -= retval;
+ string += retval;
+ } while (size);
+
+ return 0;
+}
+
+/**
+ * aa_features_is_equal - equality test for two features
+ * @features1: the first features (can be NULL)
+ * @features2: the second features (can be NULL)
+ *
+ * Returns: true if they're equal, false if they're not or either are NULL
+ */
+bool aa_features_is_equal(aa_features *features1, aa_features *features2)
+{
+ return features1 && features2 &&
+ strcmp(features1->string, features2->string) == 0;
+}
+
+/**
+ * aa_features_supports - provides features support status
+ * @features: the features
+ * @str: the string representation of a feature to check
+ *
+ * Example @str values are "dbus/mask/send", "caps/mask/audit_read", and
+ * "policy/versions/v7".
+ *
+ * Returns: a bool specifying the support status of @str feature
+ */
+bool aa_features_supports(aa_features *features, char *str)
+{
+ const char *features_string = features->string;
+ char *components[32];
+ char *saveptr = NULL;
+ size_t i;
+
+ /* Empty strings are not accepted. Neither are leading '/' chars. */
+ if (!str || str[0] == '/')
+ return false;
+
+ /**
+ * Break @str into an array of components. For example,
+ * "mount/mask/mount" would turn into "mount" as the first component,
+ * "mask" as the second, and "mount" as the third
+ */
+ for (i = 0; i < sizeof(components); i++) {
+ components[i] = strtok_r(str, "/", &saveptr);
+ if (!components[i])
+ break;
+
+ str = NULL;
+ }
+
+ /* At least one valid token is required */
+ if (!components[0])
+ return false;
+
+ /* Ensure that all components are valid and found */
+ for (i = 0; i < sizeof(components) && components[i]; i++) {
+ if (!walk_one(&features_string, components[i], i == 0))
+ return false;
+ }
+
+ return true;
+}
diff --git a/libraries/libapparmor/src/libapparmor.map b/libraries/libapparmor/src/libapparmor.map
index 1ea221f..d0020c7 100644
--- a/libraries/libapparmor/src/libapparmor.map
+++ b/libraries/libapparmor/src/libapparmor.map
@@ -52,6 +52,29 @@ APPARMOR_2.9 {
*;
} APPARMOR_1.1;
+APPARMOR_2.10 {
+ global:
+ aa_features_new;
+ aa_features_new_from_string;
+ aa_features_new_from_kernel;
+ aa_features_ref;
+ aa_features_unref;
+ aa_features_write_to_file;
+ aa_features_is_equal;
+ aa_features_supports_max_abi;
+ aa_features_supports_policydb;
+ aa_features_supports_set_load;
+ aa_features_supports_network;
+ aa_features_supports_af_unix;
+ aa_features_supports_mount;
+ aa_features_supports_dbus;
+ aa_features_supports_signal;
+ aa_features_supports_ptrace;
+ aa_features_supports_diff_encode;
+ local:
+ *;
+} APPARMOR_2.9;
+
PRIVATE {
global:
_aa_is_blacklisted;
diff --git a/libraries/libapparmor/src/private.h b/libraries/libapparmor/src/private.h
index 3a8beac..83813c4 100644
--- a/libraries/libapparmor/src/private.h
+++ b/libraries/libapparmor/src/private.h
@@ -18,6 +18,7 @@
#define _AA_PRIVATE_H 1
#include <stdbool.h>
+#include <sys/apparmor_private.h>
#define autofree __attribute((cleanup(_aa_autofree)))
#define autoclose __attribute((cleanup(_aa_autoclose)))
diff --git a/parser/Makefile b/parser/Makefile
index 372136d..120672f 100644
--- a/parser/Makefile
+++ b/parser/Makefile
@@ -75,10 +75,10 @@ SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
parser_alias.c common_optarg.c lib.c network.c \
mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \
- af_rule.cc af_unix.cc features.c policy_cache.c kernel_interface.c
+ af_rule.cc af_unix.cc policy_cache.c kernel_interface.c
HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h \
rule.h common_optarg.h signal.h ptrace.h network.h af_rule.h af_unix.h \
- features.h policy_cache.h kernel_interface.h
+ policy_cache.h kernel_interface.h
TOOLS = apparmor_parser
OBJECTS = $(patsubst %.cc, %.o, $(SRCS:.c=.o))
@@ -237,10 +237,7 @@ mount.o: mount.cc mount.h parser.h immunix.h rule.h
common_optarg.o: common_optarg.c common_optarg.h parser.h libapparmor_re/apparmor_re.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
-features.o: features.c features.h parser.h libapparmor_re/apparmor_re.h
- $(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
-
-policy_cache.o: policy_cache.c policy_cache.h parser.h features.h
+policy_cache.o: policy_cache.c policy_cache.h parser.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
kernel_interface.o: kernel_interface.c kernel_interface.h
diff --git a/parser/features.c b/parser/features.c
deleted file mode 100644
index 8b9844f..0000000
--- a/parser/features.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (c) 2014
- * Canonical, Ltd. (All rights reserved)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License published by the Free Software Foundation.
- *
- * 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, contact Novell, Inc. or Canonical
- * Ltd.
- */
-
-#include <errno.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "features.h"
-#include "lib.h"
-#include "parser.h"
-
-#define FEATURES_FILE "/sys/kernel/security/" MODULE_NAME "/features"
-
-#define STRING_SIZE 8192
-
-struct aa_features {
- unsigned int ref_count;
- char string[STRING_SIZE];
-};
-
-struct features_struct {
- char *buffer;
- int size;
- char *pos;
-};
-
-static int features_snprintf(struct features_struct *fst, const char *fmt, ...)
-{
- va_list args;
- int i, remaining = fst->size - (fst->pos - fst->buffer);
-
- if (remaining < 0) {
- errno = EINVAL;
- PERROR("Invalid features buffer offset\n");
- return -1;
- }
-
- va_start(args, fmt);
- i = vsnprintf(fst->pos, remaining, fmt, args);
- va_end(args);
-
- if (i < 0) {
- errno = EIO;
- PERROR("Failed to write to features buffer\n");
- return -1;
- } else if (i >= remaining) {
- errno = ENOBUFS;
- PERROR("Feature buffer full.");
- return -1;
- }
-
- fst->pos += i;
- return 0;
-}
-
-static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
- void *data)
-{
- struct features_struct *fst = (struct features_struct *) data;
-
- /* skip dot files and files with no name */
- if (*name == '.' || !strlen(name))
- return 0;
-
- if (features_snprintf(fst, "%s {", name) == -1)
- return -1;
-
- if (S_ISREG(st->st_mode)) {
- autoclose int file = -1;
- int len;
- int remaining = fst->size - (fst->pos - fst->buffer);
-
- file = openat(dirfd(dir), name, O_RDONLY);
- if (file == -1) {
- PDEBUG("Could not open '%s'", name);
- return -1;
- }
- PDEBUG("Opened features \"%s\"\n", name);
- if (st->st_size > remaining) {
- PDEBUG("Feature buffer full.");
- errno = ENOBUFS;
- return -1;
- }
-
- do {
- len = read(file, fst->pos, remaining);
- if (len > 0) {
- remaining -= len;
- fst->pos += len;
- *fst->pos = 0;
- }
- } while (len > 0);
- if (len < 0) {
- PDEBUG("Error reading feature file '%s'\n", name);
- return -1;
- }
- } else if (S_ISDIR(st->st_mode)) {
- if (dirat_for_each(dir, name, fst, features_dir_cb))
- return -1;
- }
-
- if (features_snprintf(fst, "}\n") == -1)
- return -1;
-
- return 0;
-}
-
-static int handle_features_dir(const char *filename, char *buffer, int size,
- char *pos)
-{
- struct features_struct fst = { buffer, size, pos };
-
- if (dirat_for_each(NULL, filename, &fst, features_dir_cb)) {
- PDEBUG("Failed evaluating %s\n", filename);
- return -1;
- }
-
- return 0;
-}
-
-static int load_features_file(const char *name, char *buffer, size_t size)
-{
- autofclose FILE *f = NULL;
- size_t end;
-
- f = fopen(name, "r");
- if (!f)
- return -1;
-
- errno = 0;
- end = fread(buffer, 1, size - 1, f);
- if (ferror(f)) {
- if (!errno)
- errno = EIO;
- return -1;
- }
- buffer[end] = 0;
-
- return 0;
-}
-
-static bool walk_one(const char **str, const char *component, bool is_top_level)
-{
- const char *cur = *str;
- uint32_t bracket_count = 0;
- int i = 0;
-
- /* Empty strings are not accepted */
- if (!*cur || !component[0])
- return false;
-
- /**
- * If @component is not top-level, the first character in the string to
- * search MUST be '{'
- */
- if (!is_top_level) {
- if (*cur != '{')
- return false;
-
- cur++;
- }
-
- /**
- * This loop tries to find the @component in *@str. When this loops
- * completes, cur will either point one character past the end of the
- * matched @component or to the NUL terminator of *@str.
- */
- while(*cur && component[i]) {
- if (!isascii(*cur)) {
- /* Only ASCII is expected */
- return false;
- } else if (*cur == '{') {
- /* There's a limit to the number of opening brackets */
- if (bracket_count == UINT32_MAX)
- return false;
-
- bracket_count++;
- } else if (*cur == '}') {
- /* Check for unexpected closing brackets */
- if (bracket_count == 0)
- return false;
-
- bracket_count--;
- }
-
- /**
- * Move to the next character in @component if we have a match
- * and either @component is not top-level or, if @component is
- * top-level, we're not inside of brackets
- */
- if (*cur == component[i] &&
- (!is_top_level || bracket_count == 0))
- i++;
- else
- i = 0;
-
- cur++;
- }
-
- /* A full match was not found if component[i] is non-NUL */
- if (component[i])
- return false;
-
- /**
- * This loop eats up valid (ASCII) characters until a non-bracket or
- * non-space character is found so that *@str is properly set to call
- * back into this function, if necessary
- */
- while (*cur) {
- if (!isascii(*cur))
- return false;
- else if (*cur == '{' || *cur == '}' || !isspace(*cur))
- break;
-
- cur++;
- }
-
- *str = cur;
- return true;
-}
-
-/**
- * aa_features_new - create a new features based on a path
- * @features: will point to the address of an allocated and initialized
- * aa_features object upon success
- * @path: path to a features file or directory
- *
- * Returns: 0 on success, -1 on error with errno set and *@features pointing to
- * NULL
- */
-int aa_features_new(aa_features **features, const char *path)
-{
- struct stat stat_file;
- aa_features *f;
- int retval;
-
- *features = NULL;
-
- if (stat(path, &stat_file) == -1)
- return -1;
-
- f = (aa_features *) calloc(1, sizeof(*f));
- if (!f) {
- errno = ENOMEM;
- return -1;
- }
- aa_features_ref(f);
-
- retval = S_ISDIR(stat_file.st_mode) ?
- handle_features_dir(path, f->string, STRING_SIZE, f->string) :
- load_features_file(path, f->string, STRING_SIZE);
- if (retval) {
- int save = errno;
-
- aa_features_unref(f);
- errno = save;
- return -1;
- }
-
- *features = f;
-
- return 0;
-}
-
-/**
- * aa_features_new_from_string - create a new features based on a string
- * @features: will point to the address of an allocated and initialized
- * aa_features object upon success
- * @string: a NUL-terminated string representation of features
- * @size: the size of @string, not counting the NUL-terminator
- *
- * Returns: 0 on success, -1 on error with errno set and *@features pointing to
- * NULL
- */
-int aa_features_new_from_string(aa_features **features,
- const char *string, size_t size)
-{
- aa_features *f;
-
- *features = NULL;
-
- /* Require size to be less than STRING_SIZE so there's room for a NUL */
- if (size >= STRING_SIZE)
- return ENOBUFS;
-
- f = (aa_features *) calloc(1, sizeof(*f));
- if (!f) {
- errno = ENOMEM;
- return -1;
- }
- aa_features_ref(f);
-
- memcpy(f->string, string, size);
- f->string[size] = '\0';
- *features = f;
-
- return 0;
-}
-
-/**
- * aa_features_new_from_kernel - create a new features based on the current kernel
- * @features: will point to the address of an allocated and initialized
- * aa_features object upon success
- *
- * Returns: 0 on success, -1 on error with errno set and *@features pointing to
- * NULL
- */
-int aa_features_new_from_kernel(aa_features **features)
-{
- return aa_features_new(features, FEATURES_FILE);
-}
-
-/**
- * aa_features_ref - increments the ref count of a features
- * @features: the features
- *
- * Returns: the features
- */
-aa_features *aa_features_ref(aa_features *features)
-{
- atomic_inc(&features->ref_count);
- return features;
-}
-
-/**
- * aa_features_unref - decrements the ref count and frees the features when 0
- * @features: the features (can be NULL)
- */
-void aa_features_unref(aa_features *features)
-{
- if (features && atomic_dec_and_test(&features->ref_count))
- free(features);
-}
-
-/**
- * aa_features_write_to_file - write a string representation to a file
- * @features: the features
- * @path: the path to write to
- *
- * Returns: 0 on success, -1 on error with errno set
- */
-int aa_features_write_to_file(aa_features *features, const char *path)
-{
- autoclose int fd = -1;
- size_t size;
- ssize_t retval;
- char *string;
-
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (fd == -1)
- return -1;
-
- string = features->string;
- size = strlen(string);
- do {
- retval = write(fd, string, size);
- if (retval == -1)
- return -1;
-
- size -= retval;
- string += retval;
- } while (size);
-
- return 0;
-}
-
-/**
- * aa_features_is_equal - equality test for two features
- * @features1: the first features (can be NULL)
- * @features2: the second features (can be NULL)
- *
- * Returns: true if they're equal, false if they're not or either are NULL
- */
-bool aa_features_is_equal(aa_features *features1, aa_features *features2)
-{
- return features1 && features2 &&
- strcmp(features1->string, features2->string) == 0;
-}
-
-/**
- * aa_features_supports - provides features support status
- * @features: the features
- * @str: the string representation of a feature to check
- *
- * Example @str values are "dbus/mask/send", "caps/mask/audit_read", and
- * "policy/versions/v7".
- *
- * Returns: a bool specifying the support status of @str feature
- */
-bool aa_features_supports(aa_features *features, char *str)
-{
- const char *features_string = features->string;
- char *components[32];
- char *saveptr = NULL;
- size_t i;
-
- /* Empty strings are not accepted. Neither are leading '/' chars. */
- if (!str || str[0] == '/')
- return false;
-
- /**
- * Break @str into an array of components. For example,
- * "mount/mask/mount" would turn into "mount" as the first component,
- * "mask" as the second, and "mount" as the third
- */
- for (i = 0; i < sizeof(components); i++) {
- components[i] = strtok_r(str, "/", &saveptr);
- if (!components[i])
- break;
-
- str = NULL;
- }
-
- /* At least one valid token is required */
- if (!components[0])
- return false;
-
- /* Ensure that all components are valid and found */
- for (i = 0; i < sizeof(components) && components[i]; i++) {
- if (!walk_one(&features_string, components[i], i == 0))
- return false;
- }
-
- return true;
-}
diff --git a/parser/features.h b/parser/features.h
deleted file mode 100644
index 1d3cf3f..0000000
--- a/parser/features.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2014
- * Canonical, Ltd. (All rights reserved)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License published by the Free Software Foundation.
- *
- * 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, contact Novell, Inc. or Canonical
- * Ltd.
- */
-
-#ifndef __AA_FEATURES_H
-#define __AA_FEATURES_H
-
-typedef struct aa_features aa_features;
-
-int aa_features_new(aa_features **features, const char *path);
-int aa_features_new_from_string(aa_features **features,
- const char *string, size_t size);
-int aa_features_new_from_kernel(aa_features **features);
-aa_features *aa_features_ref(aa_features *features);
-void aa_features_unref(aa_features *features);
-int aa_features_write_to_file(aa_features *features, const char *path);
-bool aa_features_is_equal(aa_features *features1, aa_features *features2);
-bool aa_features_supports(aa_features *features, char *str);
-
-#endif /* __AA_FEATURES_H */
diff --git a/parser/kernel_interface.h b/parser/kernel_interface.h
index 6dcd3ca..8e210d1 100644
--- a/parser/kernel_interface.h
+++ b/parser/kernel_interface.h
@@ -19,6 +19,8 @@
#ifndef __AA_KERNEL_INTERFACE_H
#define __AA_KERNEL_INTERFACE_H
+#include <sys/apparmor.h>
+
#include "features.h"
typedef struct aa_kernel_interface aa_kernel_interface;
--
2.1.4
More information about the AppArmor
mailing list