[apparmor] [PATCH v2 33/42] libapparmor: Move over the lib functions needed by cache loading code
Tyler Hicks
tyhicks at canonical.com
Fri Mar 6 21:48:49 UTC 2015
The function names must be prepended with "_aa_" since they're going to
be exported from libapparmor. The code bases using the _aa_autofree(),
_aa_autoclose(), and _aa_autofclose() will need to internally alias
those functions to the previously used autofree, autoclose, and
autofclose names.
Signed-off-by: Tyler Hicks <tyhicks at canonical.com>
Acked-by: Seth Arnold <seth.arnold at canonical.com>
---
.../libapparmor/include/sys/apparmor_private.h | 11 ++
libraries/libapparmor/src/Makefile.am | 2 +-
libraries/libapparmor/src/libapparmor.map | 4 +
libraries/libapparmor/src/private.c | 145 +++++++++++++++++++++
libraries/libapparmor/src/private.h | 4 +
parser/lib.c | 140 +-------------------
parser/lib.h | 11 +-
7 files changed, 175 insertions(+), 142 deletions(-)
diff --git a/libraries/libapparmor/include/sys/apparmor_private.h b/libraries/libapparmor/include/sys/apparmor_private.h
index 6138b2c..5cf4c25 100644
--- a/libraries/libapparmor/include/sys/apparmor_private.h
+++ b/libraries/libapparmor/include/sys/apparmor_private.h
@@ -17,10 +17,21 @@
#ifndef _SYS_APPARMOR_PRIVATE_H
#define _SYS_APPARMOR_PRIVATE_H 1
+#include <dirent.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
__BEGIN_DECLS
int _aa_is_blacklisted(const char *name, const char *path);
+void _aa_autofree(void *p);
+void _aa_autoclose(int *fd);
+void _aa_autofclose(FILE **f);
+
+int _aa_dirat_for_each(DIR *dir, const char *name, void *data,
+ int (* cb)(DIR *, const char *, struct stat *, void *));
+
__END_DECLS
#endif /* sys/apparmor_private.h */
diff --git a/libraries/libapparmor/src/Makefile.am b/libraries/libapparmor/src/Makefile.am
index e1d1fac..42934d0 100644
--- a/libraries/libapparmor/src/Makefile.am
+++ b/libraries/libapparmor/src/Makefile.am
@@ -46,7 +46,7 @@ af_protos.h: /usr/include/netinet/in.h
LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" $< > $@
lib_LTLIBRARIES = libapparmor.la
-noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h
+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_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
diff --git a/libraries/libapparmor/src/libapparmor.map b/libraries/libapparmor/src/libapparmor.map
index c7bc606..1ea221f 100644
--- a/libraries/libapparmor/src/libapparmor.map
+++ b/libraries/libapparmor/src/libapparmor.map
@@ -55,6 +55,10 @@ APPARMOR_2.9 {
PRIVATE {
global:
_aa_is_blacklisted;
+ _aa_autofree;
+ _aa_autoclose;
+ _aa_autofclose;
+ _aa_dirat_for_each;
local:
*;
};
diff --git a/libraries/libapparmor/src/private.c b/libraries/libapparmor/src/private.c
index eb3c0f8..6431270 100644
--- a/libraries/libapparmor/src/private.c
+++ b/libraries/libapparmor/src/private.c
@@ -14,12 +14,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "private.h"
struct ignored_suffix_t {
const char * text;
@@ -98,3 +107,139 @@ int _aa_is_blacklisted(const char *name, const char *path)
return 0;
}
+
+/* automaticly free allocated variables tagged with autofree on fn exit */
+void _aa_autofree(void *p)
+{
+ void **_p = (void**)p;
+ free(*_p);
+}
+
+void _aa_autoclose(int *fd)
+{
+ if (*fd != -1) {
+ /* if close was interrupted retry */
+ while(close(*fd) == -1 && errno == EINTR);
+ *fd = -1;
+ }
+}
+
+void _aa_autofclose(FILE **f)
+{
+ if (*f) {
+ fclose(*f);
+ *f = NULL;
+ }
+}
+
+/**
+ * _aa_dirat_for_each: iterate over a directory calling cb for each entry
+ * @dir: already opened directory (MAY BE NULL)
+ * @name: name of the directory (MAY BE NULL)
+ * @data: data pointer to pass to the callback fn (MAY BE NULL)
+ * @cb: the callback to pass entry too (NOT NULL)
+ *
+ * Iterate over the entries in a directory calling cb for each entry.
+ * The directory to iterate is determined by a combination of @dir and
+ * @name.
+ *
+ * IF @name is a relative path it is determine relative to at @dir if it
+ * is specified, else it the lookup is done relative to the current
+ * working directory.
+ *
+ * If @name is not specified then @dir is used as the directory to iterate
+ * over.
+ *
+ * It is an error if both @name and @dir are null
+ *
+ * The cb function is called with the DIR in use and the name of the
+ * file in that directory. If the file is to be opened it should
+ * use the openat, fstatat, and related fns.
+ *
+ * Returns: 0 on success, else -1 and errno is set to the error code
+ */
+int _aa_dirat_for_each(DIR *dir, const char *name, void *data,
+ int (* cb)(DIR *, const char *, struct stat *, void *))
+{
+ autofree struct dirent *dirent = NULL;
+ DIR *d = NULL;
+ int error;
+
+ if (!cb || (!dir && !name)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (dir && (!name || *name != '/')) {
+ dirent = (struct dirent *)
+ malloc(offsetof(struct dirent, d_name) +
+ fpathconf(dirfd(dir), _PC_NAME_MAX) + 1);
+ } else {
+ dirent = (struct dirent *)
+ malloc(offsetof(struct dirent, d_name) +
+ pathconf(name, _PC_NAME_MAX) + 1);
+ }
+ if (!dirent) {
+ errno = ENOMEM;
+ PDEBUG("could not alloc dirent: %m\n");
+ return -1;
+ }
+
+ if (name) {
+ if (dir && *name != '/') {
+ int fd = openat(dirfd(dir), name, O_RDONLY);
+ if (fd == -1)
+ goto fail;
+ d = fdopendir(fd);
+ } else {
+ d = opendir(name);
+ }
+ PDEBUG("Open dir '%s': %s\n", name, d ? "succeeded" : "failed");
+ if (!(d))
+ goto fail;
+ } else { /* dir && !name */
+ PDEBUG("Recieved cache directory\n");
+ d = dir;
+ }
+
+ for (;;) {
+ struct dirent *ent;
+ struct stat my_stat;
+
+ error = readdir_r(d, dirent, &ent);
+ if (error) {
+ errno = error; /* readdir_r directly returns an errno */
+ PDEBUG("readdir_r failed: %m\n");
+ goto fail;
+ } else if (!ent) {
+ break;
+ }
+
+ if (strcmp(ent->d_name, ".") == 0 ||
+ strcmp(ent->d_name, "..") == 0)
+ continue;
+
+ if (fstatat(dirfd(d), ent->d_name, &my_stat, 0)) {
+ PDEBUG("stat failed for '%s': %m\n", name);
+ goto fail;
+ }
+
+ if (cb(d, ent->d_name, &my_stat, data)) {
+ PDEBUG("dir_for_each callback failed\n");
+ goto fail;
+ }
+ }
+
+ if (d != dir)
+ closedir(d);
+
+ return 0;
+
+fail:
+ error = errno;
+ if (d && d != dir)
+ closedir(d);
+ errno = error;
+
+ return -1;
+}
diff --git a/libraries/libapparmor/src/private.h b/libraries/libapparmor/src/private.h
index a3c582d..d4dc0ef 100644
--- a/libraries/libapparmor/src/private.h
+++ b/libraries/libapparmor/src/private.h
@@ -19,6 +19,10 @@
#include <stdbool.h>
+#define autofree __attribute((cleanup(_aa_autofree)))
+#define autoclose __attribute((cleanup(_aa_autoclose)))
+#define autofclose __attribute((cleanup(_aa_autofclose)))
+
#if ENABLE_DEBUG_OUTPUT
#define PERROR(fmt, args...) print_error(true, "libapparmor", fmt, ## args)
diff --git a/parser/lib.c b/parser/lib.c
index 008027b..15e975d 100644
--- a/parser/lib.c
+++ b/parser/lib.c
@@ -17,46 +17,18 @@
*/
#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
#include <string.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <cstdint>
+#include <sys/apparmor_private.h>
+
#include "lib.h"
#include "parser.h"
-/* automaticly free allocated variables tagged with autofree on fn exit */
-void __autofree(void *p)
-{
- void **_p = (void**)p;
- free(*_p);
-}
-
-void __autoclose(int *fd)
-{
- if (*fd != -1) {
- /* if close was interrupted retry */
- while(close(*fd) == -1 && errno == EINTR);
- *fd = -1;
- }
-}
-
-void __autofclose(FILE **f)
-{
- if (*f) {
- fclose(*f);
- *f = NULL;
- }
-}
-
void atomic_inc(unsigned int *v)
{
__sync_add_and_fetch(v, 1);
@@ -67,115 +39,15 @@ bool atomic_dec_and_test(unsigned int *v)
return __sync_sub_and_fetch(v, 1) == 0;
}
-/**
- * dirat_for_each: iterate over a directory calling cb for each entry
- * @dir: already opened directory (MAY BE NULL)
- * @name: name of the directory (MAY BE NULL)
- * @data: data pointer to pass to the callback fn (MAY BE NULL)
- * @cb: the callback to pass entry too (NOT NULL)
- *
- * Iterate over the entries in a directory calling cb for each entry.
- * The directory to iterate is determined by a combination of @dir and
- * @name.
- *
- * IF @name is a relative path it is determine relative to at @dir if it
- * is specified, else it the lookup is done relative to the current
- * working directory.
- *
- * If @name is not specified then @dir is used as the directory to iterate
- * over.
- *
- * It is an error if both @name and @dir are null
- *
- * The cb function is called with the DIR in use and the name of the
- * file in that directory. If the file is to be opened it should
- * use the openat, fstatat, and related fns.
- *
- * Returns: 0 on success, else -1 and errno is set to the error code
- */
int dirat_for_each(DIR *dir, const char *name, void *data,
int (* cb)(DIR *, const char *, struct stat *, void *))
{
- autofree struct dirent *dirent = NULL;
- DIR *d = NULL;
- int error;
+ int retval = _aa_dirat_for_each(dir, name, data, cb);
- if (!cb || (!dir && !name)) {
- errno = EINVAL;
- return -1;
- }
+ if (retval)
+ PDEBUG("dirat_for_each failed: %m\n");
- if (dir && (!name || *name != '/')) {
- dirent = (struct dirent *)
- malloc(offsetof(struct dirent, d_name) +
- fpathconf(dirfd(dir), _PC_NAME_MAX) + 1);
- } else {
- dirent = (struct dirent *)
- malloc(offsetof(struct dirent, d_name) +
- pathconf(name, _PC_NAME_MAX) + 1);
- }
- if (!dirent) {
- PDEBUG("could not alloc dirent");
- return -1;
- }
-
- if (name) {
- if (dir && *name != '/') {
- int fd = openat(dirfd(dir), name, O_RDONLY);
- if (fd == -1)
- goto fail;
- d = fdopendir(fd);
- } else {
- d = opendir(name);
- }
- PDEBUG("Open dir '%s': %s\n", name, d ? "succeeded" : "failed");
- if (!(d))
- goto fail;
- } else { /* dir && !name */
- PDEBUG("Recieved cache directory\n");
- d = dir;
- }
-
- for (;;) {
- struct dirent *ent;
- struct stat my_stat;
-
- error = readdir_r(d, dirent, &ent);
- if (error) {
- PDEBUG("readdir_r failed");
- errno = error; /* readdir_r directly returns an errno */
- goto fail;
- } else if (!ent) {
- break;
- }
-
- if (strcmp(ent->d_name, ".") == 0 ||
- strcmp(ent->d_name, "..") == 0)
- continue;
-
- if (fstatat(dirfd(d), ent->d_name, &my_stat, 0)) {
- PDEBUG("stat failed for '%s'", name);
- goto fail;
- }
-
- if (cb(d, ent->d_name, &my_stat, data)) {
- PDEBUG("dir_for_each callback failed\n");
- goto fail;
- }
- }
-
- if (d != dir)
- closedir(d);
-
- return 0;
-
-fail:
- error = errno;
- if (d && d != dir)
- closedir(d);
- errno = error;
-
- return -1;
+ return retval;
}
/**
diff --git a/parser/lib.h b/parser/lib.h
index bfe53f8..2ec745c 100644
--- a/parser/lib.h
+++ b/parser/lib.h
@@ -1,14 +1,11 @@
#ifndef __AA_LIB_H_
#define __AA_LIB_H_
-#include <dirent.h>
+#include <sys/apparmor_private.h>
-#define autofree __attribute((cleanup(__autofree)))
-#define autoclose __attribute((cleanup(__autoclose)))
-#define autofclose __attribute((cleanup(__autofclose)))
-void __autofree(void *p);
-void __autoclose(int *fd);
-void __autofclose(FILE **f);
+#define autofree __attribute((cleanup(_aa_autofree)))
+#define autoclose __attribute((cleanup(_aa_autoclose)))
+#define autofclose __attribute((cleanup(_aa_autofclose)))
void atomic_inc(unsigned int *v);
bool atomic_dec_and_test(unsigned int *v);
--
2.1.4
More information about the AppArmor
mailing list