Skip to content

Commit

Permalink
libselinux: move functions out of header file
Browse files Browse the repository at this point in the history
When building libselinux from its own directory GCC complains about the
two functions free_spec_node() and sort_spec_node(), which are not tiny
and also recursive.

    In file included from label_file.c:27:
    In function ‘load_mmap’,
       inlined from ‘process_file’ at label_file.c:1106:9:
    label_file.h:816:20: error: inlining failed in call to ‘free_spec_node’: --param max-inline-insns-single limit reached [-Werror=inline]
      816 | static inline void free_spec_node(struct spec_node *node)
          |                    ^~~~~~~~~~~~~~
    label_file.c:899:17: note: called from here
      899 |                 free_spec_node(data->root);
          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~
    label_file.h:816:20: error: inlining failed in call to ‘free_spec_node’: --param max-inline-insns-single limit reached [-Werror=inline]
      816 | static inline void free_spec_node(struct spec_node *node)
          |                    ^~~~~~~~~~~~~~
    label_file.c:908:17: note: called from here
      908 |                 free_spec_node(root);
          |                 ^~~~~~~~~~~~~~~~~~~~
  In function ‘sort_specs’,
      inlined from ‘init’ at label_file.c:1350:3:
    label_file.h:404:20: error: inlining failed in call to ‘sort_spec_node’: --param max-inline-insns-single limit reached [-Werror=inline]
      404 | static inline void sort_spec_node(struct spec_node *node, struct spec_node *parent)
          |                    ^~~~~~~~~~~~~~
    label_file.h:433:9: note: called from here
      433 |         sort_spec_node(data->root, NULL);
          |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In function ‘sort_specs’,
        inlined from ‘init’ at label_file.c:1370:3:
    label_file.h:404:20: error: inlining failed in call to ‘sort_spec_node’: --param max-inline-insns-single limit reached [-Werror=inline]
      404 | static inline void sort_spec_node(struct spec_node *node, struct spec_node *parent)
          |                    ^~~~~~~~~~~~~~
    label_file.h:433:9: note: called from here
      433 |         sort_spec_node(data->root, NULL);
          |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Fixes: 92306da ("libselinux: rework selabel_file(5) database")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
  • Loading branch information
cgzones authored and jwcart2 committed Dec 4, 2024
1 parent 8efed46 commit 856895c
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 68 deletions.
68 changes: 68 additions & 0 deletions libselinux/src/label_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,74 @@
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */


void free_spec_node(struct spec_node *node)
{
for (uint32_t i = 0; i < node->literal_specs_num; i++) {
struct literal_spec *lspec = &node->literal_specs[i];

free(lspec->lr.ctx_raw);
free(lspec->lr.ctx_trans);
__pthread_mutex_destroy(&lspec->lr.lock);

if (lspec->from_mmap)
continue;

free(lspec->literal_match);
free(lspec->regex_str);
}
free(node->literal_specs);

for (uint32_t i = 0; i < node->regex_specs_num; i++) {
struct regex_spec *rspec = &node->regex_specs[i];

free(rspec->lr.ctx_raw);
free(rspec->lr.ctx_trans);
__pthread_mutex_destroy(&rspec->lr.lock);
regex_data_free(rspec->regex);
__pthread_mutex_destroy(&rspec->regex_lock);

if (rspec->from_mmap)
continue;

free(rspec->regex_str);
}
free(node->regex_specs);

for (uint32_t i = 0; i < node->children_num; i++)
free_spec_node(&node->children[i]);
free(node->children);

if (!node->from_mmap)
free(node->stem);
}

void sort_spec_node(struct spec_node *node, struct spec_node *parent)
{
/* A node should not be its own parent */
assert(node != parent);
/* Only root node has NULL stem */
assert((!parent && !node->stem) || (parent && node->stem && node->stem[0] != '\0'));
/* A non-root node should not be empty */
assert(!parent || (node->literal_specs_num || node->regex_specs_num || node->children_num));


node->parent = parent;

/* Sort for comparison support and binary search lookup */

if (node->literal_specs_num > 1)
qsort(node->literal_specs, node->literal_specs_num, sizeof(struct literal_spec), compare_literal_spec);

if (node->regex_specs_num > 1)
qsort(node->regex_specs, node->regex_specs_num, sizeof(struct regex_spec), compare_regex_spec);

if (node->children_num > 1)
qsort(node->children, node->children_num, sizeof(struct spec_node), compare_spec_node);

for (uint32_t i = 0; i < node->children_num; i++)
sort_spec_node(&node->children[i], node);
}

/*
* Warn about duplicate specifications.
*/
Expand Down
71 changes: 3 additions & 68 deletions libselinux/src/label_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ struct saved_data {
struct selabel_sub *subs;
};

void free_spec_node(struct spec_node *node);
void sort_spec_node(struct spec_node *node, struct spec_node *parent);

static inline mode_t string_to_file_kind(const char *mode)
{
if (mode[0] != '-' || mode[1] == '\0' || mode[2] != '\0')
Expand Down Expand Up @@ -401,33 +404,6 @@ static inline int compare_spec_node(const void *p1, const void *p2)
return rc;
}

static inline void sort_spec_node(struct spec_node *node, struct spec_node *parent)
{
/* A node should not be its own parent */
assert(node != parent);
/* Only root node has NULL stem */
assert((!parent && !node->stem) || (parent && node->stem && node->stem[0] != '\0'));
/* A non-root node should not be empty */
assert(!parent || (node->literal_specs_num || node->regex_specs_num || node->children_num));


node->parent = parent;

/* Sort for comparison support and binary search lookup */

if (node->literal_specs_num > 1)
qsort(node->literal_specs, node->literal_specs_num, sizeof(struct literal_spec), compare_literal_spec);

if (node->regex_specs_num > 1)
qsort(node->regex_specs, node->regex_specs_num, sizeof(struct regex_spec), compare_regex_spec);

if (node->children_num > 1)
qsort(node->children, node->children_num, sizeof(struct spec_node), compare_spec_node);

for (uint32_t i = 0; i < node->children_num; i++)
sort_spec_node(&node->children[i], node);
}

static inline void sort_specs(struct saved_data *data)
{
sort_spec_node(data->root, NULL);
Expand Down Expand Up @@ -813,47 +789,6 @@ static int insert_spec(const struct selabel_handle *rec, struct saved_data *data

#undef GROW_ARRAY

static inline void free_spec_node(struct spec_node *node)
{
for (uint32_t i = 0; i < node->literal_specs_num; i++) {
struct literal_spec *lspec = &node->literal_specs[i];

free(lspec->lr.ctx_raw);
free(lspec->lr.ctx_trans);
__pthread_mutex_destroy(&lspec->lr.lock);

if (lspec->from_mmap)
continue;

free(lspec->literal_match);
free(lspec->regex_str);
}
free(node->literal_specs);

for (uint32_t i = 0; i < node->regex_specs_num; i++) {
struct regex_spec *rspec = &node->regex_specs[i];

free(rspec->lr.ctx_raw);
free(rspec->lr.ctx_trans);
__pthread_mutex_destroy(&rspec->lr.lock);
regex_data_free(rspec->regex);
__pthread_mutex_destroy(&rspec->regex_lock);

if (rspec->from_mmap)
continue;

free(rspec->regex_str);
}
free(node->regex_specs);

for (uint32_t i = 0; i < node->children_num; i++)
free_spec_node(&node->children[i]);
free(node->children);

if (!node->from_mmap)
free(node->stem);
}

/* This will always check for buffer over-runs and either read the next entry
* if buf != NULL or skip over the entry (as these areas are mapped in the
* current buffer). */
Expand Down

0 comments on commit 856895c

Please sign in to comment.