[apparmor] [PATCH 27/31] parser: Shove binary file and fd reading into kernel_interface.c
Tyler Hicks
tyhicks at canonical.com
Sat Dec 6 00:22:26 UTC 2014
This is the start of the kernel_interface API that allows callers to
specify a buffer, a file path, or a file descriptor that should be
copied to the proper kernel interface for loading, replacing, or
removing in-kernel policies.
Support exists for reading from a file path or file descriptor into a
buffer and then writing that buffer to the appropriate apparmorfs
interface file.
An aa_kernel_interface_write_policy() function is also provided for
callers that want to route a buffer to an arbitrary file descriptor
instead of to an apparmorfs file. This is useful when an admin instructs
apparmor_parser to write to stdout or a file.
Additionally, it removes some parser-specific globals from the
kernel_interface.c file, such as OPTION_{ADD,REPLACE,REMOVE}, in
preparation for moving the code into a library.
Signed-off-by: Tyler Hicks <tyhicks at canonical.com>
---
parser/kernel_interface.c | 194 +++++++++++++++++++++++++++++++---------------
parser/kernel_interface.h | 10 ++-
parser/parser_interface.c | 2 +-
parser/parser_main.c | 73 ++++++++---------
4 files changed, 174 insertions(+), 105 deletions(-)
diff --git a/parser/kernel_interface.c b/parser/kernel_interface.c
index a33a6be..9d7406e 100644
--- a/parser/kernel_interface.c
+++ b/parser/kernel_interface.c
@@ -88,15 +88,12 @@ static const char *next_profile_buffer(const char *buffer, int size)
return NULL;
}
-static int write_buffer(int fd, const char *buffer, int size, int set)
+static int write_buffer(int fd, const char *buffer, int size)
{
- const char *err_str = set ? "profile set" : "profile";
int wsize = write(fd, buffer, size);
if (wsize < 0) {
- PERROR(_("%s: Unable to write %s\n"), progname, err_str);
return -1;
} else if (wsize < size) {
- PERROR(_("%s: Unable to write %s\n"), progname, err_str);
errno = EPROTO;
return -1;
}
@@ -124,7 +121,7 @@ static int write_policy_buffer(int fd, int atomic,
int rc;
if (atomic) {
- rc = write_buffer(fd, buffer, size, true);
+ rc = write_buffer(fd, buffer, size);
} else {
const char *b, *next;
@@ -136,7 +133,7 @@ static int write_policy_buffer(int fd, int atomic,
bsize = next - b;
else
bsize = size;
- if (write_buffer(fd, b, bsize, false) == -1)
+ if (write_buffer(fd, b, bsize) == -1)
return -1;
}
}
@@ -147,83 +144,156 @@ static int write_policy_buffer(int fd, int atomic,
return 0;
}
-/**
- * open_option_iface - open the interface file for @option
- * @aadir: apparmorfs dir
- * @option: load command option
- *
- * Returns: fd to interface or -1 on error, with errno set.
- */
-static int open_option_iface(int aadir, int option)
-{
- const char *name;
-
- switch (option) {
- case OPTION_ADD:
- name = ".load";
- break;
- case OPTION_REPLACE:
- name = ".replace";
- break;
- case OPTION_REMOVE:
- name = ".remove";
- break;
- default:
- errno = EINVAL;
- return -1;
- }
+#define AA_IFACE_FILE_LOAD ".load"
+#define AA_IFACE_FILE_REMOVE ".remove"
+#define AA_IFACE_FILE_REPLACE ".replace"
- return openat(aadir, name, O_WRONLY);
-
- /* TODO: push up */
- /*
- if (fd < 0) {
- PERROR(_("Unable to open %s - %s\n"), filename,
- strerror(errno));
- return -errno;
- }
- */
-}
-
-int aa_load_buffer(int option, char *buffer, int size)
+static int write_policy_buffer_to_iface(const char *iface_file,
+ const char *buffer, size_t size)
{
autoclose int dirfd = -1;
autoclose int fd = -1;
- /* TODO: push backup into caller */
- if (!kernel_load)
- return 0;
-
dirfd = open_iface_dir();
if (dirfd == -1)
return -1;
- fd = open_option_iface(dirfd, option);
+ fd = openat(dirfd, iface_file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return -1;
return write_policy_buffer(fd, kernel_supports_setload, buffer, size);
}
+static int write_policy_fd_to_iface(const char *iface_file, int fd)
+{
+ autofree char *buffer = NULL;
+ int size = 0, asize = 0, rsize;
+ int chunksize = 1 << 14;
+
+ do {
+ if (asize - size == 0) {
+ buffer = (char *) realloc(buffer, chunksize);
+ asize = chunksize;
+ chunksize <<= 1;
+ if (!buffer) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ rsize = read(fd, buffer + size, asize - size);
+ if (rsize)
+ size += rsize;
+ } while (rsize > 0);
+
+ if (rsize == -1)
+ return -1;
+
+ return write_policy_buffer_to_iface(iface_file, buffer, size);
+}
+
+static int write_policy_file_to_iface(const char *iface_file, const char *path)
+{
+ autoclose int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ return write_policy_fd_to_iface(iface_file, fd);
+}
+
/**
- * aa_remove_profile - remove a profile from the kernel
- * @fqname: the fully qualified name of the profile to remove
+ * aa_kernel_interface_load_policy - load a policy into the kernel
+ * @buffer: a buffer containing a policy
+ * @size: the size of the buffer
*
* Returns: 0 on success, -1 on error with errno set
*/
-int aa_remove_profile(const char *fqname)
+int aa_kernel_interface_load_policy(const char *buffer, size_t size)
{
- autoclose int dirfd = -1;
- autoclose int fd = -1;
+ return write_policy_buffer_to_iface(AA_IFACE_FILE_LOAD, buffer, size);
+}
- dirfd = open_iface_dir();
- if (dirfd == -1)
- return -1;
+/**
+ * aa_kernel_interface_load_policy_from_file - load a policy into the kernel
+ * @path: path to a policy binary
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_load_policy_from_file(const char *path)
+{
+ return write_policy_file_to_iface(AA_IFACE_FILE_LOAD, path);
+}
- fd = open_option_iface(dirfd, OPTION_REMOVE);
- if (fd == -1)
- return -1;
+/**
+ * aa_kernel_interface_load_policy_from_fd - load a policy into the kernel
+ * @fd: a pre-opened, readable file descriptor at the correct offset
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_load_policy_from_fd(int fd)
+{
+ return write_policy_fd_to_iface(AA_IFACE_FILE_LOAD, fd);
+}
+
+/**
+ * aa_kernel_interface_replace_policy - replace a policy in the kernel
+ * @buffer: a buffer containing a policy
+ * @size: the size of the buffer
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_replace_policy(const char *buffer, size_t size)
+{
+ return write_policy_buffer_to_iface(AA_IFACE_FILE_REPLACE,
+ buffer, size);
+}
+
+/**
+ * aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel
+ * @path: path to a policy binary
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_replace_policy_from_file(const char *path)
+{
+ return write_policy_file_to_iface(AA_IFACE_FILE_REPLACE, path);
+}
+
+/**
+ * aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel
+ * @fd: a pre-opened, readable file descriptor at the correct offset
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_replace_policy_from_fd(int fd)
+{
+ return write_policy_fd_to_iface(AA_IFACE_FILE_REPLACE, fd);
+}
+
+/**
+ * aa_kernel_interface_remove_policy - remove a policy from the kernel
+ * @fqname: nul-terminated fully qualified name of the policy to remove
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_remove_policy(const char *fqname)
+{
+ return write_policy_buffer_to_iface(AA_IFACE_FILE_REMOVE,
+ fqname, strlen(fqname) + 1);
+}
- /* include trailing \0 in buffer write */
- return write_buffer(fd, fqname, strlen(fqname) + 1, 0);
+/**
+ * aa_kernel_interface_write_policy - write a policy to a file descriptor
+ * @fd: a pre-opened, writeable file descriptor at the correct offset
+ * @buffer: a buffer containing a policy
+ * @size: the size of the buffer
+ *
+ * Returns: 0 on success, -1 on error with errno set
+ */
+int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size)
+{
+ return write_policy_buffer(fd, 1, buffer, size);
}
diff --git a/parser/kernel_interface.h b/parser/kernel_interface.h
index 3d53238..52e537e 100644
--- a/parser/kernel_interface.h
+++ b/parser/kernel_interface.h
@@ -20,7 +20,13 @@
#define __AA_KERNEL_INTERFACE_H
int aa_find_iface_dir(char **dir);
-int aa_load_buffer(int option, char *buffer, int size);
-int aa_remove_profile(const char *fqname);
+int aa_kernel_interface_load_policy(const char *buffer, size_t size);
+int aa_kernel_interface_load_policy_from_file(const char *path);
+int aa_kernel_interface_load_policy_from_fd(int fd);
+int aa_kernel_interface_replace_policy(const char *buffer, size_t size);
+int aa_kernel_interface_replace_policy_from_file(const char *path);
+int aa_kernel_interface_replace_policy_from_fd(int fd);
+int aa_kernel_interface_remove_policy(const char *fqname);
+int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size);
#endif /* __AA_KERNEL_INTERFACE_H */
diff --git a/parser/parser_interface.c b/parser/parser_interface.c
index be279b1..49c8748 100644
--- a/parser/parser_interface.c
+++ b/parser/parser_interface.c
@@ -522,7 +522,7 @@ int __sd_serialize_profile(int option, Profile *prof, int cache_fd)
if (option == OPTION_REMOVE) {
if (kernel_load) {
- if (aa_remove_profile(prof->fqname().c_str()) == -1)
+ if (aa_kernel_interface_remove_policy(prof->fqname().c_str()) == -1)
error = -errno;
}
} else {
diff --git a/parser/parser_main.c b/parser/parser_main.c
index 00b0bad..8e10bd4 100644
--- a/parser/parser_main.c
+++ b/parser/parser_main.c
@@ -590,62 +590,55 @@ static void set_supported_features(void)
int process_binary(int option, const char *profilename)
{
- autofree char *buffer = NULL;
- int retval = 0, size = 0, asize = 0, rsize;
- int chunksize = 1 << 14;
- autoclose int fd = -1;
-
- if (profilename) {
- fd = open(profilename, O_RDONLY);
- if (fd == -1) {
- retval = errno;
- PERROR(_("Error: Could not read binary profile or cache file %s: %s.\n"),
- profilename, strerror(errno));
- return retval;
- }
- } else {
- fd = dup(0);
- }
-
- do {
- if (asize - size == 0) {
- buffer = (char *) realloc(buffer, chunksize);
- asize = chunksize;
- chunksize <<= 1;
- if (!buffer) {
- PERROR(_("Memory allocation error."));
- return ENOMEM;
+ const char *printed_name;
+ int retval;
+
+ printed_name = profilename ? profilename : "stdin";
+
+ if (kernel_load) {
+ if (option == OPTION_ADD) {
+ retval = profilename ?
+ aa_kernel_interface_load_policy_from_file(profilename) :
+ aa_kernel_interface_load_policy_from_fd(0);
+ if (retval == -1) {
+ retval = errno;
+ PERROR(_("Error: Could not load profile %s: %s\n"),
+ printed_name, strerror(retval));
+ return retval;
}
+ } else if (option == OPTION_REPLACE) {
+ retval = profilename ?
+ aa_kernel_interface_replace_policy_from_file(profilename) :
+ aa_kernel_interface_replace_policy_from_fd(0);
+ if (retval == -1) {
+ retval = errno;
+ PERROR(_("Error: Could not replace profile %s: %s\n"),
+ printed_name, strerror(retval));
+ return retval;
+ }
+ } else {
+ PERROR(_("Error: Invalid load option specified: %d\n"),
+ option);
+ return EINVAL;
}
-
- rsize = read(fd, buffer + size, asize - size);
- if (rsize)
- size += rsize;
- } while (rsize > 0);
-
- if (rsize == 0) {
- retval = aa_load_buffer(option, buffer, size);
- if (retval == -1)
- retval = -errno;
- } else
- retval = rsize;
+ }
if (conf_verbose) {
switch (option) {
case OPTION_ADD:
printf(_("Cached load succeeded for \"%s\".\n"),
- profilename ? profilename : "stdin");
+ printed_name);
break;
case OPTION_REPLACE:
printf(_("Cached reload succeeded for \"%s\".\n"),
- profilename ? profilename : "stdin");
+ printed_name);
break;
default:
break;
}
}
- return retval;
+ return 0;
}
void reset_parser(const char *filename)
--
2.1.0
More information about the AppArmor
mailing list