[apparmor] [PATCH 17/31] parser: Make match file interface suitable for a library

John Johansen john.johansen at canonical.com
Thu Jan 22 18:17:55 UTC 2015


On 12/05/2014 04:22 PM, Tyler Hicks wrote:
> The aa_match_new_from_kernel() function creates an aa_match object. It
> can be thought of as the constructor of aa_match objects.
> 
> The default match file path is hidden from the caller so that it doesn't
> become part of our ABI when we move this code into libapparmor later.
> If, for example, another match file location was needed to be checked in
> the future, we can transparently do it behind the
> aa_match_new_from_kernel() call instead of breaking ABI by changing the
> macro.
> 
> The aa_match_ref() and aa_match_unref() functions are used to grab and
> give up references to an aa_match. When the ref count hits zero, all
> allocated memory is freed. Like with free(), aa_match_unref() can be
> called with a NULL pointer for convenience.
> 
> A set of aa_match_supports_*() functions are added for checking the
> features represented by a match file.
> 
We do not want this interface showing up as part of the library. We want
to hide support for the match file as much as possible. It is deprecated
and doesn't exist in newer kernels.

We need to support it to support older kernels as an upstream but we
really don't want this becoming part of a new public api

> Signed-off-by: Tyler Hicks <tyhicks at canonical.com>
> ---
>  parser/match.c       | 118 +++++++++++++++++++++++++++++++++++++++++++++------
>  parser/match.h       |   9 +++-
>  parser/parser_main.c |  18 +++++---
>  3 files changed, 124 insertions(+), 21 deletions(-)
> 
> diff --git a/parser/match.c b/parser/match.c
> index 770d548..e5a3ede 100644
> --- a/parser/match.c
> +++ b/parser/match.c
> @@ -24,23 +24,113 @@
>  #include "lib.h"
>  #include "parser.h"
>  
> +#define AA_MATCH_FILE "/sys/kernel/security/" MODULE_NAME "/matching"
> +
>  #define MATCH_STRING_SIZE 1000
>  
> -void set_features_by_match_file(void)
> +#define SUPPORT_PERMS_CREATE	(1<<1)
> +#define SUPPORT_NETWORK		(1<<2)
> +
> +struct aa_match {
> +	unsigned int ref_count;
> +	uint8_t support;
> +};
> +
> +/**
> + * aa_match_new_from_kernel - create a new match based on the current kernel
> + * @match: will point to the address of an allocated and initialized aa_match
> + *         object upon success
> + *
> + * Returns: 0 on success, -1 on error with errno set and *@match pointing to
> + *          NULL
> + */
> +int aa_match_new_from_kernel(aa_match **match)
>  {
> -	autofclose FILE *ms = fopen(MATCH_FILE, "r");
> -	if (ms) {
> -		autofree char *match_string = (char *) malloc(MATCH_STRING_SIZE);
> -		if (!match_string)
> -			goto no_match;
> -		if (!fgets(match_string, MATCH_STRING_SIZE, ms))
> -			goto no_match;
> -		if (strstr(match_string, " perms=c"))
> -			perms_create = 1;
> -		kernel_supports_network = 1;
> -		return;
> +	autofclose FILE *match_file = NULL;
> +	autofree char *match_string = NULL;
> +	aa_match *m;
> +
> +	*match = NULL;
> +
> +	m = (aa_match *) calloc(1, sizeof(*m));
> +	if (!m) {
> +		aa_match_unref(m);
> +		errno = ENOMEM;
> +		return -1;
> +	}
> +	aa_match_ref(m);
> +
> +	match_file = fopen(AA_MATCH_FILE, "r");
> +	if (!match_file) {
> +		int save = errno;
> +
> +		aa_match_unref(m);
> +		errno = save;
> +		return -1;
> +	}
> +
> +	match_string = (char *) malloc(MATCH_STRING_SIZE);
> +	if (!match_string) {
> +		aa_match_unref(m);
> +		errno = ENOMEM;
> +		return -1;
> +	}
> +
> +	if (!fgets(match_string, MATCH_STRING_SIZE, match_file)) {
> +		aa_match_unref(m);
> +		errno = EIO;
> +		return -1;
>  	}
>  
> -no_match:
> -	perms_create = 1;
> +	if (strstr(match_string, " perms=c"))
> +		m->support |= SUPPORT_PERMS_CREATE;
> +
> +	m->support |= SUPPORT_NETWORK;
> +	*match = m;
> +
> +	return 0;
> +}
> +
> +/**
> + * aa_match_ref - increments the ref count of a match
> + * @match: the match
> + *
> + * Returns: the match
> + */
> +aa_match *aa_match_ref(aa_match *match)
> +{
> +	atomic_inc(&match->ref_count);
> +	return match;
> +}
> +
> +/**
> + * aa_match_unref - decrements the ref count and frees the match when 0
> + * @match: the match (can be NULL)
> + */
> +void aa_match_unref(aa_match *match)
> +{
> +	if (match && atomic_dec_and_test(&match->ref_count))
> +		free(match);
> +}
> +
> +/**
> + * aa_match_supports_perms_create - provides match support status of perms_create
> + * @match: the match
> + *
> + * Returns: true if perms_create is supported, false if not
> + */
> +bool aa_match_supports_perms_create(aa_match *match)
> +{
> +	return match->support & SUPPORT_PERMS_CREATE;
> +}
> +
> +/**
> + * aa_match_supports_network - provides match supports status of network
> + * @match: the match
> + *
> + * Returns: true if network is supported, false if not
> + */
> +bool aa_match_supports_network(aa_match *match)
> +{
> +	return match->support & SUPPORT_NETWORK;
>  }
> diff --git a/parser/match.h b/parser/match.h
> index deb7c00..6ad157a 100644
> --- a/parser/match.h
> +++ b/parser/match.h
> @@ -19,8 +19,13 @@
>  #ifndef __AA_MATCH_H
>  #define __AA_MATCH_H
>  
> -#define MATCH_FILE "/sys/kernel/security/" MODULE_NAME "/matching"
> +typedef struct aa_match aa_match;
>  
> -void set_features_by_match_file(void);
> +int aa_match_new_from_kernel(aa_match **match);
> +aa_match *aa_match_ref(aa_match *);
> +void aa_match_unref(aa_match *match);
> +
> +bool aa_match_supports_perms_create(aa_match *match);
> +bool aa_match_supports_network(aa_match *match);
>  
>  #endif /* __AA_MATCH_H */
> diff --git a/parser/parser_main.c b/parser/parser_main.c
> index 2888a1a..f9fbfe0 100644
> --- a/parser/parser_main.c
> +++ b/parser/parser_main.c
> @@ -546,14 +546,22 @@ int have_enough_privilege(void)
>  	return 0;
>  }
>  
> -static void set_supported_features(void) {
> -
> +static void set_supported_features(void)
> +{
>  	/* has process_args() already assigned a match string? */
> -	if (!features_string) {
> -		if (load_features(FEATURES_FILE) == -1) {
> -			set_features_by_match_file();
> +	if (!features_string && load_features(FEATURES_FILE) == -1) {
> +		aa_match *match;
> +
> +		if (aa_match_new_from_kernel(&match)) {
> +			perms_create = 1;
>  			return;
>  		}
> +
> +		perms_create = aa_match_supports_perms_create(match);
> +		kernel_supports_network = aa_match_supports_network(match);
> +
> +		aa_match_unref(match);
> +		return;
>  	}
>  
>  	perms_create = 1;
> 





More information about the AppArmor mailing list