2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-28 21:07:56 +00:00

Use the gcc cleanup extension attribute to handle freeing temp allocations

While some of these allocations will go away as we convert to C++,
some of these need to stay C as the are going to be moved into a
library to support loading cache from init daemons etc.

For the bits that will eventually be C++ this helps clean things up,
in the interim.

TODO: apply to libapparmor as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2015-03-25 17:09:26 -05:00 committed by Tyler Hicks
parent 2dd3fa9383
commit 82904cf0e6
5 changed files with 31 additions and 51 deletions

View File

@ -33,6 +33,13 @@
#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);
}
/** /**
* dirat_for_each: iterate over a directory calling cb for each entry * dirat_for_each: iterate over a directory calling cb for each entry
* @dir: already opened directory (MAY BE NULL) * @dir: already opened directory (MAY BE NULL)
@ -62,7 +69,7 @@
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 *))
{ {
struct dirent *dirent = NULL; autofree struct dirent *dirent = NULL;
DIR *d = NULL; DIR *d = NULL;
int error; int error;
@ -132,7 +139,6 @@ int dirat_for_each(DIR *dir, const char *name, void *data,
if (d != dir) if (d != dir)
closedir(d); closedir(d);
free(dirent);
return 0; return 0;
@ -140,7 +146,6 @@ fail:
error = errno; error = errno;
if (d && d != dir) if (d && d != dir)
closedir(d); closedir(d);
free(dirent);
errno = error; errno = error;
return -1; return -1;

View File

@ -3,6 +3,9 @@
#include <dirent.h> #include <dirent.h>
#define autofree __attribute((cleanup(__autofree)))
void __autofree(void *p);
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 *));

View File

@ -28,6 +28,7 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include "lib.h"
#include "parser.h" #include "parser.h"
#include "profile.h" #include "profile.h"
#include "libapparmor_re/apparmor_re.h" #include "libapparmor_re/apparmor_re.h"
@ -374,13 +375,11 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
sd_write_struct(buf, "profile"); sd_write_struct(buf, "profile");
if (flattened) { if (flattened) {
assert(profile->parent); assert(profile->parent);
char *name = (char *) malloc(3 + strlen(profile->name) + autofree char *name = (char *) malloc(3 + strlen(profile->name) + strlen(profile->parent->name));
strlen(profile->parent->name));
if (!name) if (!name)
return; return;
sprintf(name, "%s//%s", profile->parent->name, profile->name); sprintf(name, "%s//%s", profile->parent->name, profile->name);
sd_write_string(buf, name, NULL); sd_write_string(buf, name, NULL);
free(name);
} else { } else {
sd_write_string(buf, profile->name, NULL); sd_write_string(buf, profile->name, NULL);
} }
@ -483,7 +482,7 @@ int __sd_serialize_profile(int option, Profile *prof)
int fd = -1; int fd = -1;
int error = -ENOMEM, size, wsize; int error = -ENOMEM, size, wsize;
std::ostringstream work_area; std::ostringstream work_area;
char *filename = NULL; autofree char *filename = NULL;
switch (option) { switch (option) {
case OPTION_ADD: case OPTION_ADD:
@ -523,8 +522,6 @@ int __sd_serialize_profile(int option, Profile *prof)
error = 0; error = 0;
free(filename);
if (option == OPTION_REMOVE) { if (option == OPTION_REMOVE) {
char *name, *ns = NULL; char *name, *ns = NULL;
int len = 0; int len = 0;
@ -646,7 +643,7 @@ int sd_load_buffer(int option, char *buffer, int size)
{ {
int fd = -1; int fd = -1;
int error, bsize; int error, bsize;
char *filename = NULL; autofree char *filename = NULL;
/* TODO: push backup into caller */ /* TODO: push backup into caller */
if (!kernel_load) if (!kernel_load)
@ -694,7 +691,5 @@ int sd_load_buffer(int option, char *buffer, int size)
close(fd); close(fd);
out: out:
free(filename);
return error; return error;
} }

View File

@ -125,15 +125,13 @@ static int include_dir_cb(DIR *dir unused, const char *name, struct stat *st,
{ {
struct cb_struct *d = (struct cb_struct *) data; struct cb_struct *d = (struct cb_struct *) data;
char *path; autofree char *path = NULL;
if (asprintf(&path, "%s/%s", d->fullpath, name) < 0) if (asprintf(&path, "%s/%s", d->fullpath, name) < 0)
yyerror("Out of memory"); yyerror("Out of memory");
if (is_blacklisted(name, path)) { if (is_blacklisted(name, path))
free(path);
return 0; return 0;
}
if (S_ISREG(st->st_mode)) { if (S_ISREG(st->st_mode)) {
if (!(yyin = fopen(path,"r"))) if (!(yyin = fopen(path,"r")))
@ -144,8 +142,6 @@ static int include_dir_cb(DIR *dir unused, const char *name, struct stat *st,
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
} }
free(path);
return 0; return 0;
} }
@ -153,7 +149,7 @@ void include_filename(char *filename, int search)
{ {
FILE *include_file = NULL; FILE *include_file = NULL;
struct stat my_stat; struct stat my_stat;
char *fullpath = NULL; autofree char *fullpath = NULL;
if (search) { if (search) {
if (preprocess_only) if (preprocess_only)
@ -188,9 +184,6 @@ void include_filename(char *filename, int search)
" '%s' in '%s'"), fullpath, filename);; " '%s' in '%s'"), fullpath, filename);;
} }
} }
if (fullpath)
free(fullpath);
} }
%} %}
@ -281,9 +274,8 @@ LT_EQUAL <=
<INCLUDE>{ <INCLUDE>{
(\<([^\> \t\n]+)\>|\"([^\" \t\n]+)\") { /* <filename> */ (\<([^\> \t\n]+)\>|\"([^\" \t\n]+)\") { /* <filename> */
char *filename = strndup(yytext, yyleng - 1); autofree char *filename = strndup(yytext, yyleng - 1);
include_filename(filename + 1, *filename == '<'); include_filename(filename + 1, *filename == '<');
free(filename);
POP_NODUMP(); POP_NODUMP();
} }

View File

@ -555,16 +555,13 @@ static void set_features_by_match_file(void)
{ {
FILE *ms = fopen(MATCH_FILE, "r"); FILE *ms = fopen(MATCH_FILE, "r");
if (ms) { if (ms) {
char *match_string = (char *) malloc(1000); autofree char *match_string = (char *) malloc(1000);
if (!match_string) if (!match_string)
goto no_match; goto no_match;
if (!fgets(match_string, 1000, ms)) { if (!fgets(match_string, 1000, ms))
free(match_string);
goto no_match; goto no_match;
}
if (strstr(match_string, " perms=c")) if (strstr(match_string, " perms=c"))
perms_create = 1; perms_create = 1;
free(match_string);
kernel_supports_network = 1; kernel_supports_network = 1;
goto out; goto out;
} }
@ -618,7 +615,7 @@ static void set_supported_features(void) {
int process_binary(int option, const char *profilename) int process_binary(int option, const char *profilename)
{ {
char *buffer = NULL; autofree char *buffer = NULL;
int retval = 0, size = 0, asize = 0, rsize; int retval = 0, size = 0, asize = 0, rsize;
int chunksize = 1 << 14; int chunksize = 1 << 14;
int fd; int fd;
@ -637,7 +634,7 @@ int process_binary(int option, const char *profilename)
do { do {
if (asize - size == 0) { if (asize - size == 0) {
buffer = (char *) realloc(buffer, chunksize); buffer = (char *) realloc(buffer, chunksize);
asize = chunksize; asize = chunksize;
chunksize <<= 1; chunksize <<= 1;
if (!buffer) { if (!buffer) {
@ -658,8 +655,6 @@ int process_binary(int option, const char *profilename)
else else
retval = rsize; retval = rsize;
free(buffer);
if (conf_verbose) { if (conf_verbose) {
switch (option) { switch (option) {
case OPTION_ADD: case OPTION_ADD:
@ -694,7 +689,7 @@ int test_for_dir_mode(const char *basename, const char *linkdir)
int rc = 0; int rc = 0;
if (!skip_mode_force) { if (!skip_mode_force) {
char *target = NULL; autofree char *target = NULL;
if (asprintf(&target, "%s/%s/%s", basedir, linkdir, basename) < 0) { if (asprintf(&target, "%s/%s/%s", basedir, linkdir, basename) < 0) {
perror("asprintf"); perror("asprintf");
exit(1); exit(1);
@ -702,8 +697,6 @@ int test_for_dir_mode(const char *basename, const char *linkdir)
if (access(target, R_OK) == 0) if (access(target, R_OK) == 0)
rc = 1; rc = 1;
free(target);
} }
return rc; return rc;
@ -713,8 +706,8 @@ int process_profile(int option, const char *profilename)
{ {
struct stat stat_bin; struct stat stat_bin;
int retval = 0; int retval = 0;
char * cachename = NULL; autofree char *cachename = NULL;
char * cachetemp = NULL; autofree char *cachetemp = NULL;
const char *basename = NULL; const char *basename = NULL;
/* per-profile states */ /* per-profile states */
@ -879,10 +872,8 @@ out:
unlink(cachetemp); unlink(cachetemp);
PERROR("Warning failed to create cache: %s\n", basename); PERROR("Warning failed to create cache: %s\n", basename);
} }
free(cachetemp);
} }
if (cachename)
free(cachename);
return retval; return retval;
} }
@ -894,11 +885,10 @@ static int profile_dir_cb(DIR *dir unused, const char *name, struct stat *st,
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) { if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
const char *dirname = (const char *)data; const char *dirname = (const char *)data;
char *path; autofree char *path = NULL;
if (asprintf(&path, "%s/%s", dirname, name) < 0) if (asprintf(&path, "%s/%s", dirname, name) < 0)
PERROR(_("Out of memory")); PERROR(_("Out of memory"));
rc = process_profile(option, path); rc = process_profile(option, path);
free(path);
} }
return rc; return rc;
} }
@ -911,19 +901,18 @@ static int binary_dir_cb(DIR *dir unused, const char *name, struct stat *st,
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) { if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
const char *dirname = (const char *)data; const char *dirname = (const char *)data;
char *path; autofree char *path = NULL;
if (asprintf(&path, "%s/%s", dirname, name) < 0) if (asprintf(&path, "%s/%s", dirname, name) < 0)
PERROR(_("Out of memory")); PERROR(_("Out of memory"));
rc = process_binary(option, path); rc = process_binary(option, path);
free(path);
} }
return rc; return rc;
} }
static void setup_flags(void) static void setup_flags(void)
{ {
char *cache_features_path = NULL; autofree char *cache_features_path = NULL;
char *cache_flags = NULL; autofree char *cache_flags = NULL;
/* Get the match string to determine type of regex support needed */ /* Get the match string to determine type of regex support needed */
set_supported_features(); set_supported_features();
@ -964,13 +953,9 @@ static void setup_flags(void)
skip_read_cache = 1; skip_read_cache = 1;
} }
} }
free(cache_flags);
cache_flags = NULL;
} else if (write_cache) { } else if (write_cache) {
create_cache(cacheloc, cache_features_path, features_string); create_cache(cacheloc, cache_features_path, features_string);
} }
free(cache_features_path);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])