The aa_policy_cache_new() and aa_policy_cache_remove() functions are changed to accept a dirfd parameter.
The cache dirfd (by default, /etc/apparmor.d/cache) is opened earlier in aa_policy_cache_new(). Previously, the directory wasn't accessed until later in the following call chain: aa_policy_cache_new() -> init_cache_features() -> create_cache() Because of this change, the logic to create the cache dir must be moved from create_cache() to aa_policy_cache_new(). Signed-off-by: Tyler Hicks <tyhi...@canonical.com> --- libraries/libapparmor/include/sys/apparmor.h | 6 +- libraries/libapparmor/src/policy_cache.c | 91 +++++++++++----------------- parser/parser_main.c | 6 +- tests/regression/apparmor/aa_policy_cache.c | 10 +-- 4 files changed, 48 insertions(+), 65 deletions(-) diff --git a/libraries/libapparmor/include/sys/apparmor.h b/libraries/libapparmor/include/sys/apparmor.h index 435fb09..d37ba6e 100644 --- a/libraries/libapparmor/include/sys/apparmor.h +++ b/libraries/libapparmor/include/sys/apparmor.h @@ -142,14 +142,14 @@ 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_features *kernel_features, + int dirfd, 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_make_valid(aa_policy_cache *policy_cache); -int aa_policy_cache_remove(const char *path); +int aa_policy_cache_remove(int dirfd, const char *path); int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, aa_kernel_interface *kernel_interface); diff --git a/libraries/libapparmor/src/policy_cache.c b/libraries/libapparmor/src/policy_cache.c index a5eff24..b3126d5 100644 --- a/libraries/libapparmor/src/policy_cache.c +++ b/libraries/libapparmor/src/policy_cache.c @@ -28,12 +28,13 @@ #include "private.h" +#define CACHE_FEATURES_FILE ".features" + struct aa_policy_cache { unsigned int ref_count; aa_features *features; aa_features *kernel_features; - char *path; - char *features_path; + int dirfd; }; static int clear_cache_cb(int dirfd, const char *path, struct stat *st, @@ -49,44 +50,23 @@ static int clear_cache_cb(int dirfd, const char *path, struct stat *st, 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; + if (aa_policy_cache_remove(policy_cache->dirfd, ".")) + return -1; -create_file: - if (aa_features_write_to_file(features, -1, - policy_cache->features_path) == -1) - goto error; + if (aa_features_write_to_file(features, policy_cache->dirfd, + CACHE_FEATURES_FILE) == -1) + return -1; 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, -1, - policy_cache->features_path)) { + if (aa_features_new(&policy_cache->features, policy_cache->dirfd, + CACHE_FEATURES_FILE)) { policy_cache->features = NULL; if (!create || errno != ENOENT) return -1; @@ -109,17 +89,11 @@ static int replace_all_cb(int dirfd unused, const char *name, struct stat *st, 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, - -1, path); + data->policy_cache->dirfd, + name); } return retval; @@ -131,6 +105,7 @@ static int replace_all_cb(int dirfd unused, const char *name, struct stat *st, * aa_policy_cache_new object upon success * @kernel_features: features representing a kernel (may be NULL if you want to * use the features of the currently running kernel) + * @dirfd: directory file descriptor or AT_FDCWD (see openat(2)) * @path: path to the policy cache * @create: true if the cache should be created if it doesn't already exist * @@ -138,8 +113,8 @@ static int replace_all_cb(int dirfd unused, const char *name, struct stat *st, * pointing to NULL */ int aa_policy_cache_new(aa_policy_cache **policy_cache, - aa_features *kernel_features, const char *path, - bool create) + aa_features *kernel_features, + int dirfd, const char *path, bool create) { aa_policy_cache *pc; @@ -155,19 +130,26 @@ int aa_policy_cache_new(aa_policy_cache **policy_cache, errno = ENOMEM; return -1; } + pc->dirfd = -1; aa_policy_cache_ref(pc); - pc->path = strdup(path); - if (!pc->path) { - aa_policy_cache_unref(pc); - errno = ENOMEM; - return -1; - } +open: + pc->dirfd = openat(dirfd, path, O_RDONLY | O_CLOEXEC | O_DIRECTORY); + if (pc->dirfd < 0) { + int save; + + /* does the dir exist? */ + if (create && errno == ENOENT) { + if (mkdirat(dirfd, path, 0700) == 0) + goto open; + PERROR("Can't create cache directory '%s': %m\n", path); + } else { + PERROR("Can't update cache directory '%s': %m\n", path); + } - if (asprintf(&pc->features_path, "%s/.features", pc->path) == -1) { - pc->features_path = NULL; + save = errno; aa_policy_cache_unref(pc); - errno = ENOMEM; + errno = save; return -1; } @@ -216,8 +198,8 @@ void aa_policy_cache_unref(aa_policy_cache *policy_cache) if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) { aa_features_unref(policy_cache->features); aa_features_unref(policy_cache->kernel_features); - free(policy_cache->features_path); - free(policy_cache->path); + if (policy_cache->dirfd != -1) + close(policy_cache->dirfd); free(policy_cache); } } @@ -249,13 +231,14 @@ int aa_policy_cache_make_valid(aa_policy_cache *policy_cache) /** * aa_policy_cache_remove - removes all policy cache files under a path + * @dirfd: directory file descriptor or AT_FDCWD (see openat(2)) * @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) +int aa_policy_cache_remove(int dirfd, const char *path) { - return _aa_dirat_for_each(AT_FDCWD, path, NULL, clear_cache_cb); + return _aa_dirat_for_each(dirfd, path, NULL, clear_cache_cb); } /** @@ -285,7 +268,7 @@ int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, cb_data.policy_cache = policy_cache; cb_data.kernel_interface = kernel_interface; - retval = _aa_dirat_for_each(AT_FDCWD, policy_cache->path, &cb_data, + retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &cb_data, replace_all_cb); aa_kernel_interface_unref(kernel_interface); diff --git a/parser/parser_main.c b/parser/parser_main.c index 555620d..7ec1d95 100644 --- a/parser/parser_main.c +++ b/parser/parser_main.c @@ -903,7 +903,7 @@ int main(int argc, char *argv[]) } if (force_clear_cache) { - if (aa_policy_cache_remove(cacheloc)) { + if (aa_policy_cache_remove(AT_FDCWD, cacheloc)) { PERROR(_("Failed to clear cache files (%s): %s\n"), cacheloc, strerror(errno)); return 1; @@ -915,8 +915,8 @@ int main(int argc, char *argv[]) if (create_cache_dir) pwarn(_("The --create-cache-dir option is deprecated. Please use --write-cache.\n")); - retval = aa_policy_cache_new(&policy_cache, features, cacheloc, - write_cache); + retval = aa_policy_cache_new(&policy_cache, features, + AT_FDCWD, cacheloc, write_cache); if (retval) { if (errno != ENOENT) { PERROR(_("Failed setting up policy cache (%s): %s\n"), diff --git a/tests/regression/apparmor/aa_policy_cache.c b/tests/regression/apparmor/aa_policy_cache.c index b221c98..fafe758 100644 --- a/tests/regression/apparmor/aa_policy_cache.c +++ b/tests/regression/apparmor/aa_policy_cache.c @@ -50,7 +50,7 @@ static int test_make_valid(const char *path) aa_policy_cache *policy_cache = NULL; int rc = 1; - if (aa_policy_cache_new(&policy_cache, NULL, path, false)) { + if (aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, path, false)) { perror("FAIL - aa_policy_cache_new"); goto out; } @@ -71,7 +71,7 @@ static int test_is_valid(const char *path) aa_policy_cache *policy_cache = NULL; int rc = 1; - if (aa_policy_cache_new(&policy_cache, NULL, path, false)) { + if (aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, path, false)) { perror("FAIL - aa_policy_cache_new"); goto out; } @@ -93,7 +93,7 @@ static int test_new(const char *path, bool create) aa_policy_cache *policy_cache = NULL; int rc = 1; - if (aa_policy_cache_new(&policy_cache, NULL, path, create)) { + if (aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, path, create)) { perror("FAIL - aa_policy_cache_new"); goto out; } @@ -108,7 +108,7 @@ static int test_remove(const char *path) { int rc = 1; - if (aa_policy_cache_remove(path)) { + if (aa_policy_cache_remove(AT_FDCWD, path)) { perror("FAIL - aa_policy_cache_remove"); goto out; } @@ -144,7 +144,7 @@ static int test_replace_all(const char *path) aa_policy_cache *policy_cache = NULL; int rc = 1; - if (aa_policy_cache_new(&policy_cache, NULL, path, false)) { + if (aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, path, false)) { perror("FAIL - aa_policy_cache_new"); goto out; } -- 2.1.4 -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor