On 03/06/2015 01:48 PM, Tyler Hicks wrote:
> Signed-off-by: Tyler Hicks <tyhi...@canonical.com>
Acked-by: John Johansen <john.johan...@canonical.com>

> ---
>  libraries/libapparmor/include/sys/apparmor.h |  13 ++
>  libraries/libapparmor/src/Makefile.am        |   2 +-
>  libraries/libapparmor/src/libapparmor.map    |   7 +
>  libraries/libapparmor/src/policy_cache.c     | 279 
> +++++++++++++++++++++++++++
>  parser/policy_cache.c                        | 250 ------------------------
>  parser/policy_cache.h                        |  16 --
>  6 files changed, 300 insertions(+), 267 deletions(-)
>  create mode 100644 libraries/libapparmor/src/policy_cache.c
> 
> diff --git a/libraries/libapparmor/include/sys/apparmor.h 
> b/libraries/libapparmor/include/sys/apparmor.h
> index f7ff1a7..8aa6b0e 100644
> --- a/libraries/libapparmor/include/sys/apparmor.h
> +++ b/libraries/libapparmor/include/sys/apparmor.h
> @@ -139,6 +139,19 @@ int 
> aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface,
>                                     const char *fqname);
>  int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t 
> size);
>  
> +typedef struct aa_policy_cache aa_policy_cache;
> +int aa_policy_cache_new(aa_policy_cache **policy_cache,
> +                     aa_features *kernel_features, const char *path,
> +                     bool create);
> +aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
> +void aa_policy_cache_unref(aa_policy_cache *policy_cache);
> +
> +bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache);
> +int aa_policy_cache_create(aa_policy_cache *policy_cache);
> +int aa_policy_cache_remove(const char *path);
> +int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
> +                             aa_kernel_interface *kernel_interface);
> +
>  __END_DECLS
>  
>  #endif       /* sys/apparmor.h */
> diff --git a/libraries/libapparmor/src/Makefile.am 
> b/libraries/libapparmor/src/Makefile.am
> index 86996dd..baad1e9 100644
> --- a/libraries/libapparmor/src/Makefile.am
> +++ b/libraries/libapparmor/src/Makefile.am
> @@ -48,7 +48,7 @@ af_protos.h: /usr/include/netinet/in.h
>  lib_LTLIBRARIES = libapparmor.la
>  noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
>  
> -libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c 
> private.c features.c kernel_interface.c
> +libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c 
> private.c features.c kernel_interface.c policy_cache.c
>  libapparmor_la_LDFLAGS = -version-info 
> $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic 
> -pthread \
>       -Wl,--version-script=$(top_srcdir)/src/libapparmor.map
>  
> diff --git a/libraries/libapparmor/src/libapparmor.map 
> b/libraries/libapparmor/src/libapparmor.map
> index 5b06b54..0b7e72a 100644
> --- a/libraries/libapparmor/src/libapparmor.map
> +++ b/libraries/libapparmor/src/libapparmor.map
> @@ -82,6 +82,13 @@ APPARMOR_2.10 {
>          aa_kernel_interface_replace_policy_from_fd;
>          aa_kernel_interface_remove_policy;
>          aa_kernel_interface_write_policy;
> +        aa_policy_cache_new;
> +        aa_policy_cache_ref;
> +        aa_policy_cache_unref;
> +        aa_policy_cache_is_valid;
> +        aa_policy_cache_create;
> +        aa_policy_cache_remove;
> +        aa_policy_cache_replace_all;
>    local:
>          *;
>  } APPARMOR_2.9;
> diff --git a/libraries/libapparmor/src/policy_cache.c 
> b/libraries/libapparmor/src/policy_cache.c
> new file mode 100644
> index 0000000..d9ec4a1
> --- /dev/null
> +++ b/libraries/libapparmor/src/policy_cache.c
> @@ -0,0 +1,279 @@
> +/*
> + *   Copyright (c) 2014
> + *   Canonical, Ltd. (All rights reserved)
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of version 2 of the GNU General Public
> + *   License published by the Free Software Foundation.
> + *
> + *   This program 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 General Public License for more details.
> + *
> + *   You should have received a copy of the GNU General Public License
> + *   along with this program; if not, contact Novell, Inc. or Canonical
> + *   Ltd.
> + */
> +
> +#include <dirent.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +#include <sys/stat.h>
> +#include <sys/apparmor.h>
> +
> +#include "private.h"
> +
> +struct aa_policy_cache {
> +     unsigned int ref_count;
> +     aa_features *features;
> +     aa_features *kernel_features;
> +     char *path;
> +     char *features_path;
> +};
> +
> +static int clear_cache_cb(DIR *dir, const char *path, struct stat *st,
> +                       void *data unused)
> +{
> +     /* remove regular files */
> +     if (S_ISREG(st->st_mode))
> +             return unlinkat(dirfd(dir), path, 0);
> +
> +     /* do nothing with other file types */
> +     return 0;
> +}
> +
> +static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
> +{
> +     struct stat stat_file;
> +     autofclose FILE * f = NULL;
> +
> +     if (aa_policy_cache_remove(policy_cache->path))
> +             goto error;
> +
> +create_file:
> +     if (aa_features_write_to_file(features,
> +                                   policy_cache->features_path) == -1)
> +             goto error;
> +
> +     aa_features_unref(policy_cache->features);
> +     policy_cache->features = aa_features_ref(features);
> +     return 0;
> +
> +error:
> +     /* does the dir exist? */
> +     if (stat(policy_cache->path, &stat_file) == -1) {
> +             if (mkdir(policy_cache->path, 0700) == 0)
> +                     goto create_file;
> +             PERROR("Can't create cache directory: %s\n",
> +                    policy_cache->path);
> +     } else if (!S_ISDIR(stat_file.st_mode)) {
> +             PERROR("File in cache directory location: %s\n",
> +                    policy_cache->path);
> +     } else {
> +             PERROR("Can't update cache directory: %s\n",
> +                    policy_cache->path);
> +     }
> +
> +     return -1;
> +}
> +
> +static int init_cache_features(aa_policy_cache *policy_cache,
> +                            aa_features *kernel_features, bool create)
> +{
> +     if (aa_features_new(&policy_cache->features,
> +                         policy_cache->features_path)) {
> +             policy_cache->features = NULL;
> +             if (!create || errno != ENOENT)
> +                     return -1;
> +
> +             return create_cache(policy_cache, kernel_features);
> +     }
> +
> +     return 0;
> +}
> +
> +struct replace_all_cb_data {
> +     aa_policy_cache *policy_cache;
> +     aa_kernel_interface *kernel_interface;
> +};
> +
> +static int replace_all_cb(DIR *dir unused, const char *name, struct stat *st,
> +                      void *cb_data)
> +{
> +     int retval = 0;
> +
> +     if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name, NULL)) {
> +             struct replace_all_cb_data *data;
> +             autofree char *path = NULL;
> +
> +             data = (struct replace_all_cb_data *) cb_data;
> +             if (asprintf(&path, "%s/%s",
> +                          data->policy_cache->path, name) < 0) {
> +                     path = NULL;
> +                     errno = ENOMEM;
> +                     return -1;
> +             }
> +             retval = 
> aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
> +                                                                   path);
> +     }
> +
> +     return retval;
> +}
> +
> +/**
> + * aa_policy_cache_new - create a new policy_cache from a path
> + * @policy_cache: will point to the address of an allocated and initialized
> + *                aa_policy_cache_new object upon success
> + * @kernel_features: features representing the currently running kernel
> + * @path: path to the policy cache
> + * @create: true if the cache should be created if it doesn't already exist
> + *
> + * Returns: 0 on success, -1 on error with errno set and *@policy_cache
> + *          pointing to NULL
> + */
> +int aa_policy_cache_new(aa_policy_cache **policy_cache,
> +                     aa_features *kernel_features, const char *path,
> +                     bool create)
> +{
> +     aa_policy_cache *pc;
> +
> +     *policy_cache = NULL;
> +
> +     if (!path) {
> +             errno = EINVAL;
> +             return -1;
> +     }
> +
> +     pc = (aa_policy_cache *) calloc(1, sizeof(*pc));
> +     if (!pc) {
> +             errno = ENOMEM;
> +             return -1;
> +     }
> +     aa_policy_cache_ref(pc);
> +
> +     pc->path = strdup(path);
> +     if (!pc->path) {
> +             aa_policy_cache_unref(pc);
> +             errno = ENOMEM;
> +             return -1;
> +     }
> +
> +     if (asprintf(&pc->features_path, "%s/.features", pc->path) == -1) {
> +             pc->features_path = NULL;
> +             aa_policy_cache_unref(pc);
> +             errno = ENOMEM;
> +             return -1;
> +     }
> +
> +     if (init_cache_features(pc, kernel_features, create)) {
> +             int save = errno;
> +
> +             aa_policy_cache_unref(pc);
> +             errno = save;
> +             return -1;
> +     }
> +
> +     pc->kernel_features = aa_features_ref(kernel_features);
> +     *policy_cache = pc;
> +
> +     return 0;
> +}
> +
> +/**
> + * aa_policy_cache_ref - increments the ref count of a policy_cache
> + * @policy_cache: the policy_cache
> + *
> + * Returns: the policy_cache
> + */
> +aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
> +{
> +     atomic_inc(&policy_cache->ref_count);
> +     return policy_cache;
> +}
> +
> +/**
> + * aa_policy_cache_unref - decrements the ref count and frees the 
> policy_cache when 0
> + * @policy_cache: the policy_cache (can be NULL)
> + */
> +void aa_policy_cache_unref(aa_policy_cache *policy_cache)
> +{
> +     if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
> +             free(policy_cache->features_path);
> +             free(policy_cache->path);
> +             free(policy_cache);
> +     }
> +}
> +
> +/**
> + * aa_policy_cache_is_valid - checks if the policy_cache is valid for the 
> currently running kernel
> + * @policy_cache: the policy_cache
> + *
> + * Returns: true if the policy_cache is valid for the currently running 
> kernel,
> + *          false if not
> + */
> +bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache)
> +{
> +     return aa_features_is_equal(policy_cache->features,
> +                                 policy_cache->kernel_features);
> +}
> +
> +/**
> + * aa_policy_cache_create - creates a valid policy_cache for the currently 
> running kernel
> + * @policy_cache: the policy_cache
> + *
> + * Returns: 0 on success, -1 on error with errno set and features pointing to
> + *          NULL
> + */
> +int aa_policy_cache_create(aa_policy_cache *policy_cache)
> +{
> +     return create_cache(policy_cache, policy_cache->kernel_features);
> +}
> +
> +/**
> + * aa_policy_cache_remove - removes all policy cache files under a path
> + * @path: the path to a policy cache directory
> + *
> + * Returns: 0 on success, -1 on error with errno set
> + */
> +int aa_policy_cache_remove(const char *path)
> +{
> +     return _aa_dirat_for_each(NULL, path, NULL, clear_cache_cb);
> +}
> +
> +/**
> + * aa_policy_cache_replace_all - performs a kernel policy replacement of all 
> cached policies
> + * @policy_cache: the policy_cache
> + * @kernel_interface: the kernel interface to use when doing the replacement
> + *
> + * Returns: 0 on success, -1 on error with errno set and features pointing to
> + *          NULL
> + */
> +int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
> +                             aa_kernel_interface *kernel_interface)
> +{
> +     struct replace_all_cb_data cb_data;
> +     int retval;
> +
> +     if (kernel_interface) {
> +             aa_kernel_interface_ref(kernel_interface);
> +     } else if (aa_kernel_interface_new(&kernel_interface,
> +                                        policy_cache->kernel_features,
> +                                        NULL) == -1) {
> +             kernel_interface = NULL;
> +             return -1;
> +     }
> +
> +     cb_data.policy_cache = policy_cache;
> +     cb_data.kernel_interface = kernel_interface;
> +     retval = _aa_dirat_for_each(NULL, policy_cache->path, &cb_data,
> +                                 replace_all_cb);
> +
> +     aa_kernel_interface_unref(kernel_interface);
> +
> +     return retval;
> +}
> diff --git a/parser/policy_cache.c b/parser/policy_cache.c
> index c28a981..fc4912e 100644
> --- a/parser/policy_cache.c
> +++ b/parser/policy_cache.c
> @@ -32,14 +32,6 @@
>  
>  #define le16_to_cpu(x) ((uint16_t)(le16toh (*(uint16_t *) x)))
>  
> -struct aa_policy_cache {
> -     unsigned int ref_count;
> -     aa_features *features;
> -     aa_features *kernel_features;
> -     char *path;
> -     char *features_path;
> -};
> -
>  const char header_string[] = "\004\010\000version\000\002";
>  #define HEADER_STRING_SIZE 12
>  bool valid_cached_file_version(const char *cachename)
> @@ -96,52 +88,6 @@ void update_mru_tstamp(FILE *file, const char *name)
>         }
>  }
>  
> -static int clear_cache_cb(DIR *dir, const char *path, struct stat *st,
> -                       void *data unused)
> -{
> -     /* remove regular files */
> -     if (S_ISREG(st->st_mode))
> -             return unlinkat(dirfd(dir), path, 0);
> -
> -     /* do nothing with other file types */
> -     return 0;
> -}
> -
> -static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
> -{
> -     struct stat stat_file;
> -     autofclose FILE * f = NULL;
> -
> -     if (aa_policy_cache_remove(policy_cache->path))
> -             goto error;
> -
> -create_file:
> -     if (aa_features_write_to_file(features,
> -                                   policy_cache->features_path) == -1)
> -             goto error;
> -
> -     aa_features_unref(policy_cache->features);
> -     policy_cache->features = aa_features_ref(features);
> -     return 0;
> -
> -error:
> -     /* does the dir exist? */
> -     if (stat(policy_cache->path, &stat_file) == -1) {
> -             if (mkdir(policy_cache->path, 0700) == 0)
> -                     goto create_file;
> -             PERROR("Can't create cache directory: %s\n",
> -                    policy_cache->path);
> -     } else if (!S_ISDIR(stat_file.st_mode)) {
> -             PERROR("File in cache directory location: %s\n",
> -                    policy_cache->path);
> -     } else {
> -             PERROR("Can't update cache directory: %s\n",
> -                    policy_cache->path);
> -     }
> -
> -     return -1;
> -}
> -
>  char *cache_filename(const char *cachedir, const char *basename)
>  {
>       char *cachename;
> @@ -222,199 +168,3 @@ void install_cache(const char *cachetmpname, const char 
> *cachename)
>               }
>       }
>  }
> -
> -static int init_cache_features(aa_policy_cache *policy_cache,
> -                            aa_features *kernel_features, bool create)
> -{
> -     if (aa_features_new(&policy_cache->features,
> -                         policy_cache->features_path)) {
> -             policy_cache->features = NULL;
> -             if (!create || errno != ENOENT)
> -                     return -1;
> -
> -             return create_cache(policy_cache, kernel_features);
> -     }
> -
> -     return 0;
> -}
> -
> -struct replace_all_cb_data {
> -     aa_policy_cache *policy_cache;
> -     aa_kernel_interface *kernel_interface;
> -};
> -
> -static int replace_all_cb(DIR *dir unused, const char *name, struct stat *st,
> -                      void *cb_data)
> -{
> -     int retval = 0;
> -
> -     if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
> -             struct replace_all_cb_data *data;
> -             autofree char *path = NULL;
> -
> -             data = (struct replace_all_cb_data *) cb_data;
> -             if (asprintf(&path, "%s/%s",
> -                          data->policy_cache->path, name) < 0) {
> -                     path = NULL;
> -                     errno = ENOMEM;
> -                     return -1;
> -             }
> -             retval = 
> aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
> -                                                                   path);
> -     }
> -
> -     return retval;
> -}
> -
> -/**
> - * aa_policy_cache_new - create a new policy_cache from a path
> - * @policy_cache: will point to the address of an allocated and initialized
> - *                aa_policy_cache_new object upon success
> - * @kernel_features: features representing the currently running kernel
> - * @path: path to the policy cache
> - * @create: true if the cache should be created if it doesn't already exist
> - *
> - * Returns: 0 on success, -1 on error with errno set and *@policy_cache
> - *          pointing to NULL
> - */
> -int aa_policy_cache_new(aa_policy_cache **policy_cache,
> -                     aa_features *kernel_features, const char *path,
> -                     bool create)
> -{
> -     aa_policy_cache *pc;
> -
> -     *policy_cache = NULL;
> -
> -     if (!path) {
> -             errno = EINVAL;
> -             return -1;
> -     }
> -
> -     pc = (aa_policy_cache *) calloc(1, sizeof(*pc));
> -     if (!pc) {
> -             errno = ENOMEM;
> -             return -1;
> -     }
> -     aa_policy_cache_ref(pc);
> -
> -     pc->path = strdup(path);
> -     if (!pc->path) {
> -             aa_policy_cache_unref(pc);
> -             errno = ENOMEM;
> -             return -1;
> -     }
> -
> -     if (asprintf(&pc->features_path, "%s/.features", pc->path) == -1) {
> -             pc->features_path = NULL;
> -             aa_policy_cache_unref(pc);
> -             errno = ENOMEM;
> -             return -1;
> -     }
> -
> -     if (init_cache_features(pc, kernel_features, create)) {
> -             int save = errno;
> -
> -             aa_policy_cache_unref(pc);
> -             errno = save;
> -             return -1;
> -     }
> -
> -     pc->kernel_features = aa_features_ref(kernel_features);
> -     *policy_cache = pc;
> -
> -     return 0;
> -}
> -
> -/**
> - * aa_policy_cache_ref - increments the ref count of a policy_cache
> - * @policy_cache: the policy_cache
> - *
> - * Returns: the policy_cache
> - */
> -aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
> -{
> -     atomic_inc(&policy_cache->ref_count);
> -     return policy_cache;
> -}
> -
> -/**
> - * aa_policy_cache_unref - decrements the ref count and frees the 
> policy_cache when 0
> - * @policy_cache: the policy_cache (can be NULL)
> - */
> -void aa_policy_cache_unref(aa_policy_cache *policy_cache)
> -{
> -     if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
> -             free(policy_cache->features_path);
> -             free(policy_cache->path);
> -             free(policy_cache);
> -     }
> -}
> -
> -/**
> - * aa_policy_cache_is_valid - checks if the policy_cache is valid for the 
> currently running kernel
> - * @policy_cache: the policy_cache
> - *
> - * Returns: true if the policy_cache is valid for the currently running 
> kernel,
> - *          false if not
> - */
> -bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache)
> -{
> -     return aa_features_is_equal(policy_cache->features,
> -                                 policy_cache->kernel_features);
> -}
> -
> -/**
> - * aa_policy_cache_create - creates a valid policy_cache for the currently 
> running kernel
> - * @policy_cache: the policy_cache
> - *
> - * Returns: 0 on success, -1 on error with errno set and features pointing to
> - *          NULL
> - */
> -int aa_policy_cache_create(aa_policy_cache *policy_cache)
> -{
> -     return create_cache(policy_cache, policy_cache->kernel_features);
> -}
> -
> -/**
> - * aa_policy_cache_remove - removes all policy cache files under a path
> - * @path: the path to a policy cache directory
> - *
> - * Returns: 0 on success, -1 on error with errno set
> - */
> -int aa_policy_cache_remove(const char *path)
> -{
> -     return dirat_for_each(NULL, path, NULL, clear_cache_cb);
> -}
> -
> -/**
> - * aa_policy_cache_replace_all - performs a kernel policy replacement of all 
> cached policies
> - * @policy_cache: the policy_cache
> - * @kernel_interface: the kernel interface to use when doing the replacement
> - *
> - * Returns: 0 on success, -1 on error with errno set and features pointing to
> - *          NULL
> - */
> -int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
> -                             aa_kernel_interface *kernel_interface)
> -{
> -     struct replace_all_cb_data cb_data;
> -     int retval;
> -
> -     if (kernel_interface) {
> -             aa_kernel_interface_ref(kernel_interface);
> -     } else if (aa_kernel_interface_new(&kernel_interface,
> -                                        policy_cache->kernel_features,
> -                                        NULL) == -1) {
> -             kernel_interface = NULL;
> -             return -1;
> -     }
> -
> -     cb_data.policy_cache = policy_cache;
> -     cb_data.kernel_interface = kernel_interface;
> -     retval = dirat_for_each(NULL, policy_cache->path, &cb_data,
> -                             replace_all_cb);
> -
> -     aa_kernel_interface_unref(kernel_interface);
> -
> -     return retval;
> -}
> diff --git a/parser/policy_cache.h b/parser/policy_cache.h
> index 6b222da..3c3e85d 100644
> --- a/parser/policy_cache.h
> +++ b/parser/policy_cache.h
> @@ -19,8 +19,6 @@
>  #ifndef __AA_POLICY_CACHE_H
>  #define __AA_POLICY_CACHE_H
>  
> -#include "features.h"
> -
>  extern struct timespec mru_tstamp;
>  
>  /* returns true if time is more recent than mru_tstamp */
> @@ -47,18 +45,4 @@ int cache_hit(const char *cachename);
>  int setup_cache_tmp(const char **cachetmpname, const char *cachename);
>  void install_cache(const char *cachetmpname, const char *cachename);
>  
> -typedef struct aa_policy_cache aa_policy_cache;
> -
> -int aa_policy_cache_new(aa_policy_cache **policy_cache,
> -                     aa_features *kernel_features, const char *path,
> -                     bool create);
> -aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
> -void aa_policy_cache_unref(aa_policy_cache *policy_cache);
> -bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache);
> -int aa_policy_cache_create(aa_policy_cache *policy_cache);
> -int aa_policy_cache_remove(const char *path);
> -int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
> -                             aa_kernel_interface *kernel_interface);
> -
> -
>  #endif /* __AA_POLICY_CACHE_H */
> 


-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to