Instead of only accepting a path in the aa_features API, accept a directory file descriptor and a path like then openat() family of syscalls. This type of interface is better since it can operate exactly like a path-only interface, by passing AT_FDCWD or -1 as the dirfd. However, using the dirfd/path combination, it can eliminate string allocations needed to open files in subdirectories along with the even more important benefits mentioned in the open(2) man page.
Signed-off-by: Tyler Hicks <[email protected]> Acked-by: Seth Arnold <[email protected]> --- libraries/libapparmor/include/sys/apparmor.h | 5 +++-- libraries/libapparmor/src/features.c | 20 ++++++++++++-------- libraries/libapparmor/src/policy_cache.c | 4 ++-- parser/parser_main.c | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/libraries/libapparmor/include/sys/apparmor.h b/libraries/libapparmor/include/sys/apparmor.h index 743d967..ba20071 100644 --- a/libraries/libapparmor/include/sys/apparmor.h +++ b/libraries/libapparmor/include/sys/apparmor.h @@ -105,14 +105,15 @@ extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow, (aa_change_hat_vargs)(T, __macroarg_counter(X), X) typedef struct aa_features aa_features; -int aa_features_new(aa_features **features, const char *path); +int aa_features_new(aa_features **features, int dirfd, const char *path); int aa_features_new_from_string(aa_features **features, const char *string, size_t size); int aa_features_new_from_kernel(aa_features **features); aa_features *aa_features_ref(aa_features *features); void aa_features_unref(aa_features *features); -int aa_features_write_to_file(aa_features *features, const char *path); +int aa_features_write_to_file(aa_features *features, + int dirfd, const char *path); bool aa_features_is_equal(aa_features *features1, aa_features *features2); bool aa_features_supports(aa_features *features, const char *str); diff --git a/libraries/libapparmor/src/features.c b/libraries/libapparmor/src/features.c index 0bb90ee..12a708b 100644 --- a/libraries/libapparmor/src/features.c +++ b/libraries/libapparmor/src/features.c @@ -359,12 +359,13 @@ static bool walk_one(const char **str, const struct component *component, * aa_features_new - create a new features based on a path * @features: will point to the address of an allocated and initialized * aa_features object upon success + * @dirfd: directory file descriptor or AT_FDCWD (see openat(2)) * @path: path to a features file or directory * * Returns: 0 on success, -1 on error with errno set and *@features pointing to * NULL */ -int aa_features_new(aa_features **features, const char *path) +int aa_features_new(aa_features **features, int dirfd, const char *path) { struct stat stat_file; aa_features *f; @@ -372,7 +373,7 @@ int aa_features_new(aa_features **features, const char *path) *features = NULL; - if (stat(path, &stat_file) == -1) + if (fstatat(dirfd, path, &stat_file, 0) == -1) return -1; f = calloc(1, sizeof(*f)); @@ -383,8 +384,8 @@ int aa_features_new(aa_features **features, const char *path) aa_features_ref(f); retval = S_ISDIR(stat_file.st_mode) ? - load_features_dir(AT_FDCWD, path, f->string, STRING_SIZE) : - load_features_file(AT_FDCWD, path, f->string, STRING_SIZE); + load_features_dir(dirfd, path, f->string, STRING_SIZE) : + load_features_file(dirfd, path, f->string, STRING_SIZE); if (retval == -1) { int save = errno; @@ -443,7 +444,7 @@ int aa_features_new_from_string(aa_features **features, */ int aa_features_new_from_kernel(aa_features **features) { - return aa_features_new(features, FEATURES_FILE); + return aa_features_new(features, -1, FEATURES_FILE); } /** @@ -471,19 +472,22 @@ void aa_features_unref(aa_features *features) /** * aa_features_write_to_file - write a string representation to a file * @features: the features + * @dirfd: directory file descriptor or AT_FDCWD (see openat(2)) * @path: the path to write to * * Returns: 0 on success, -1 on error with errno set */ -int aa_features_write_to_file(aa_features *features, const char *path) +int aa_features_write_to_file(aa_features *features, + int dirfd, const char *path) { autoclose int fd = -1; size_t size; ssize_t retval; char *string; - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + fd = openat(dirfd, path, + O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd == -1) return -1; diff --git a/libraries/libapparmor/src/policy_cache.c b/libraries/libapparmor/src/policy_cache.c index 5ddc640..e91388c 100644 --- a/libraries/libapparmor/src/policy_cache.c +++ b/libraries/libapparmor/src/policy_cache.c @@ -56,7 +56,7 @@ static int create_cache(aa_policy_cache *policy_cache, aa_features *features) goto error; create_file: - if (aa_features_write_to_file(features, + if (aa_features_write_to_file(features, -1, policy_cache->features_path) == -1) goto error; @@ -87,7 +87,7 @@ static int init_cache_features(aa_policy_cache *policy_cache, { bool call_create_cache = false; - if (aa_features_new(&policy_cache->features, + if (aa_features_new(&policy_cache->features, -1, policy_cache->features_path)) { policy_cache->features = NULL; if (!create || errno != ENOENT) diff --git a/parser/parser_main.c b/parser/parser_main.c index af00fd4..0ae5812 100644 --- a/parser/parser_main.c +++ b/parser/parser_main.c @@ -397,7 +397,7 @@ static int process_arg(int c, char *optarg) } break; case 'M': - if (aa_features_new(&features, optarg)) { + if (aa_features_new(&features, AT_FDCWD, optarg)) { fprintf(stderr, "Failed to load features from '%s': %m\n", optarg); -- 2.1.4 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
