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

Reply via email to