mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 18:17:09 +00:00
libapparmor: Move over the lib functions needed by cache loading code
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@canonical.com> Acked-by: Seth Arnold <seth.arnold@canonical.com> Acked-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
6b200b6f08
commit
deec20512b
@ -17,10 +17,21 @@
|
|||||||
#ifndef _SYS_APPARMOR_PRIVATE_H
|
#ifndef _SYS_APPARMOR_PRIVATE_H
|
||||||
#define _SYS_APPARMOR_PRIVATE_H 1
|
#define _SYS_APPARMOR_PRIVATE_H 1
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
int _aa_is_blacklisted(const char *name, const char *path);
|
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
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* sys/apparmor_private.h */
|
#endif /* sys/apparmor_private.h */
|
||||||
|
@ -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" $< > $@
|
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
|
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_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 \
|
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
|
||||||
|
@ -55,6 +55,10 @@ APPARMOR_2.9 {
|
|||||||
PRIVATE {
|
PRIVATE {
|
||||||
global:
|
global:
|
||||||
_aa_is_blacklisted;
|
_aa_is_blacklisted;
|
||||||
|
_aa_autofree;
|
||||||
|
_aa_autoclose;
|
||||||
|
_aa_autofclose;
|
||||||
|
_aa_dirat_for_each;
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
@ -14,12 +14,21 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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 <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
struct ignored_suffix_t {
|
struct ignored_suffix_t {
|
||||||
const char * text;
|
const char * text;
|
||||||
@ -98,3 +107,139 @@ int _aa_is_blacklisted(const char *name, const char *path)
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#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
|
#if ENABLE_DEBUG_OUTPUT
|
||||||
|
|
||||||
#define PERROR(fmt, args...) print_error(true, "libapparmor", fmt, ## args)
|
#define PERROR(fmt, args...) print_error(true, "libapparmor", fmt, ## args)
|
||||||
@ -31,6 +35,12 @@
|
|||||||
|
|
||||||
#endif /* ENABLE_DEBUG_OUTPUT */
|
#endif /* ENABLE_DEBUG_OUTPUT */
|
||||||
|
|
||||||
|
#define MY_TEST(statement, error) \
|
||||||
|
if (!(statement)) { \
|
||||||
|
fprintf(stderr, "FAIL: %s\n", error); \
|
||||||
|
rc = 1; \
|
||||||
|
}
|
||||||
|
|
||||||
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...);
|
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...);
|
||||||
void print_debug(const char *fmt, ...);
|
void print_debug(const char *fmt, ...);
|
||||||
|
|
||||||
|
@ -20,13 +20,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <aalogparse.h>
|
#include <aalogparse.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
#define MY_TEST(statement, error) \
|
|
||||||
if (!(statement)) { \
|
|
||||||
fprintf(stderr, "FAIL: %s\n", error); \
|
|
||||||
rc = 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
140
parser/lib.c
140
parser/lib.c
@ -17,46 +17,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <sys/apparmor_private.h>
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "parser.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)
|
void atomic_inc(unsigned int *v)
|
||||||
{
|
{
|
||||||
__sync_add_and_fetch(v, 1);
|
__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;
|
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 dirat_for_each(DIR *dir, const char *name, void *data,
|
||||||
int (* cb)(DIR *, const char *, struct stat *, void *))
|
int (* cb)(DIR *, const char *, struct stat *, void *))
|
||||||
{
|
{
|
||||||
autofree struct dirent *dirent = NULL;
|
int retval = _aa_dirat_for_each(dir, name, data, cb);
|
||||||
DIR *d = NULL;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (!cb || (!dir && !name)) {
|
if (retval)
|
||||||
errno = EINVAL;
|
PDEBUG("dirat_for_each failed: %m\n");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir && (!name || *name != '/')) {
|
return retval;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
11
parser/lib.h
11
parser/lib.h
@ -1,14 +1,11 @@
|
|||||||
#ifndef __AA_LIB_H_
|
#ifndef __AA_LIB_H_
|
||||||
#define __AA_LIB_H_
|
#define __AA_LIB_H_
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <sys/apparmor_private.h>
|
||||||
|
|
||||||
#define autofree __attribute((cleanup(__autofree)))
|
#define autofree __attribute((cleanup(_aa_autofree)))
|
||||||
#define autoclose __attribute((cleanup(__autoclose)))
|
#define autoclose __attribute((cleanup(_aa_autoclose)))
|
||||||
#define autofclose __attribute((cleanup(__autofclose)))
|
#define autofclose __attribute((cleanup(_aa_autofclose)))
|
||||||
void __autofree(void *p);
|
|
||||||
void __autoclose(int *fd);
|
|
||||||
void __autofclose(FILE **f);
|
|
||||||
|
|
||||||
void atomic_inc(unsigned int *v);
|
void atomic_inc(unsigned int *v);
|
||||||
bool atomic_dec_and_test(unsigned int *v);
|
bool atomic_dec_and_test(unsigned int *v);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user