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 <[email protected]> --- .../libapparmor/include/sys/apparmor_private.h | 11 ++ libraries/libapparmor/src/Makefile.am | 2 +- libraries/libapparmor/src/libapparmor.map | 4 + libraries/libapparmor/src/private.c | 135 +++++++++++++++++++++ libraries/libapparmor/src/private.h | 26 ++++ parser/lib.c | 133 +------------------- parser/lib.h | 11 +- 7 files changed, 187 insertions(+), 135 deletions(-) create mode 100644 libraries/libapparmor/src/private.h 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 2a7f600..0a55b34 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 f6f40b5..1143a34 100644 --- a/libraries/libapparmor/src/private.c +++ b/libraries/libapparmor/src/private.c @@ -14,7 +14,18 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> #include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "private.h" struct ignored_suffix_t { const char * text; @@ -64,3 +75,127 @@ 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; + } +} + +/** + * 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; + struct dirent *ent; + DIR *d = NULL; + int error = 0; + + 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; + 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); + } + if (!(d)) + goto fail; + } else { /* dir && !name */ + d = dir; + } + + for (error = readdir_r(d, dirent, &ent); + error == 0 && ent != NULL; + error = readdir_r(d, dirent, &ent)) { + struct stat my_stat; + + if (strcmp(ent->d_name, ".") == 0 || + strcmp(ent->d_name, "..") == 0) + continue; + + if (fstatat(dirfd(d), ent->d_name, &my_stat, 0)) { + goto fail; + } + + if (cb(d, ent->d_name, &my_stat, data)) { + goto fail; + } + } + + if (d != dir) + closedir(d); + + return error; + +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 new file mode 100644 index 0000000..3007294 --- /dev/null +++ b/libraries/libapparmor/src/private.h @@ -0,0 +1,26 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * The libapparmor library is licensed under the terms of the GNU + * Lesser General Public License, version 2.1. Please see the file + * COPYING.LGPL. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _AA_PRIVATE_H +#define _AA_PRIVATE_H 1 + +#include <sys/apparmor_private.h> + +#define autofree __attribute((cleanup(_aa_autofree))) +#define autoclose __attribute((cleanup(_aa_autoclose))) +#define autofclose __attribute((cleanup(_aa_autofclose))) + +#endif /* _AA_PRIVATE_H */ diff --git a/parser/lib.c b/parser/lib.c index 37d0172..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,108 +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; - struct dirent *ent; - DIR *d = NULL; - int error = 0; - - 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) { - PDEBUG("could not alloc dirent"); - return -1; - } + int retval = _aa_dirat_for_each(dir, name, data, cb); - 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 (error = readdir_r(d, dirent, &ent); - error == 0 && ent != NULL; - error = readdir_r(d, dirent, &ent)) { - struct stat my_stat; - - if (strcmp(ent->d_name, ".") == 0 || - strcmp(ent->d_name, "..") == 0) - continue; + if (retval) + PDEBUG("dirat_for_each failed: %m\n"); - 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 error; - -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.0 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
