Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

semodule utils #392

Closed
wants to merge 44 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d95bc8b
libselinux: migrating hashtab from policycoreutils
Mar 8, 2023
4a42050
libselinux: adapting hashtab to libselinux
Mar 8, 2023
2c7b71d
libselinux: performance optimization for duplicate detection
Mar 8, 2023
2d5f97b
checkpolicy: drop unused token CLONE
cgzones May 12, 2023
c646f39
checkpolicy: reject condition with bool and tunable in expression
cgzones May 12, 2023
00728e1
checkpolicy: only set declared permission bits for wildcards
cgzones May 12, 2023
f5d664e
libsepol: dump non-mls validatetrans rules as such
cgzones May 12, 2023
45a4fc7
libsepol: validate some object contexts
cgzones May 12, 2023
4cf3760
libsepol: validate old style range trans classes
cgzones May 12, 2023
ac015a3
libsepol: validate: check low category is not bigger than high
cgzones May 12, 2023
4ba8f7c
libsepol: validate: reject XEN policy with xperm rules
cgzones May 12, 2023
cae65d9
libsepol: expand: skip invalid cat
cgzones May 12, 2023
808a43a
libsepol: drop message for uncommon error cases
cgzones Jun 2, 2023
b041ecc
libsepol: drop duplicate newline in sepol_log_err() calls
cgzones Jun 2, 2023
5c35a7b
libsepol: replace sepol_log_err() by ERR()
cgzones Jun 2, 2023
30fe0f1
libsepol: replace log_err() by ERR()
cgzones Jun 2, 2023
5045368
dismod: add --help option
masatake May 31, 2023
5b1a2f1
dismod: delete an unnecessary empty line
masatake May 31, 2023
d1a9cdd
dismod: handle EOF in user interaction
masatake May 31, 2023
df0b192
dismod: add --actions option for non-interactive use
masatake May 31, 2023
e867c95
policycoreutils: Add examples to man pages
vmojzis Jun 1, 2023
0b1cb09
python/sepolicy: Improve man pages
vmojzis Jun 1, 2023
535dc24
sandbox: Add examples to man pages
vmojzis Jun 1, 2023
966de0c
checkpolicy: Add examples to man pages
vmojzis Jun 1, 2023
d596efb
libselinux: Add examples to man pages
vmojzis Jun 1, 2023
6360af7
sepolicy: clarify manual page of sepolicy interface
topimiettinen Jun 4, 2023
f78eea5
dispol: add --help option
masatake Jun 8, 2023
eeb0a75
dispol: delete an unnecessary empty line
masatake Jun 8, 2023
f8a076f
dispol: handle EOF in user interaction
masatake Jun 8, 2023
666a7df
dispol: add --actions option for non-interactive use
masatake Jun 8, 2023
391cf12
python/sepolicy: Fix template for confined user policy modules
vmojzis Jun 1, 2023
48306c4
python/sepolicy: Add/remove user even when SELinux is disabled
vmojzis May 29, 2023
55b75a2
libsepol: stop translating deprecated intial SIDs to strings
WOnder93 Jun 12, 2023
02e471f
libsepol: add support for the new "init" initial SID
WOnder93 Jun 12, 2023
b87724c
checkpolicy: add option to skip checking neverallow rules
cgzones May 12, 2023
4c06922
checkpolicy/dismod: misc improvements
cgzones May 12, 2023
6e077ba
dismod: print the policy version only in interactive mode
masatake Jun 14, 2023
b3788b9
dismod, dispol: reduce the messages in batch mode
masatake Jun 14, 2023
d8edd36
libselinux: add check for calloc in check_booleans
Jun 18, 2023
1a29c28
python/sepolicy: Fix get_os_version except clause
jefferyto Jun 19, 2023
1a78f40
semodule_expand: update
cgzones May 12, 2023
f258445
semodule_link: update
cgzones May 12, 2023
84f786b
semodule_package: update
cgzones May 12, 2023
7d5efdc
semodule_unpackage: update
cgzones May 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
libselinux: performance optimization for duplicate detection
When semodule -i some.pp to install a module package, duplicate items are
detected for the module. The detection function is nodups_specs in
libselinux/src/label_file.c. The algorithm complexity of implementing
this function is O(M*(N^2)). M is a symbol related to the length of a string.
N indicates the number of data->nspec. In scenarios where N is very large, the
efficiency is very low.

To solve this problem, I propose to use the hash table to detect duplicates.
The algorithm complexity of new implementing is O(M*N). The execution
efficiency will be greatly improved.

Comparison between the execution time of the nodups_specs function.

Old double-layer loop implementation O(M*(N^2)):

semodule -i myapp1.pp
nodups_specs data->nspec: 5002
nodups_specs start: 11785.242s
nodups_specs end:   11785.588s
nodups_specs consumes:  0.346s

semodule -i myapp2.pp
nodups_specs data->nspec: 10002
nodups_specs start: 11804.280s
nodups_specs end:   11806.546s
nodups_specs consumes:  2.266s

semodule -i myapp3.pp
nodups_specs data->nspec: 20002
nodups_specs start: 11819.106s
nodups_specs end:   11830.892s
nodups_specs consumes: 11.786s

New hash table implementation O(M*N):

semodule -i myapp1.pp
nodups_specs data->nspec: 5002
nodups_specs start: 11785.588s
nodups_specs end:   11785.590s
nodups_specs consumes:  0.002s

semodule -i myapp2.pp
nodups_specs data->nspec: 10002
nodups_specs start: 11806.546s
nodups_specs end:   11806.552s
nodups_specs consumes:  0.006s

semodule -i myapp3.pp
nodups_specs data->nspec: 20002
nodups_specs start: 11830.892s
nodups_specs end:   11830.905s
nodups_specs consumes:  0.013s

Signed-off-by: wanghuizhao <[email protected]>
Acked-by: James Carter <[email protected]>
  • Loading branch information
wanghuizhao authored and jwcart2 committed Jun 5, 2023
commit 2c7b71db56895626cf2395da5f8c1a4090c29b6a
120 changes: 96 additions & 24 deletions libselinux/src/label_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@
#include <sys/types.h>
#include <sys/stat.h>

#include "hashtab.h"
#include "callbacks.h"
#include "label_internal.h"
#include "label_file.h"

/* controls the shrink multiple of the hashtab length */
#define SHRINK_MULTIS 1

struct chkdups_key {
char *regex;
unsigned int mode;
};

/*
* Internals, mostly moved over from matchpathcon.c
*/
Expand Down Expand Up @@ -56,41 +65,104 @@ static int find_stem_from_file(struct saved_data *data, const char *key)
return -1;
}

/*
* hash calculation and key comparison of hash table
*/

static unsigned int symhash(hashtab_t h, const_hashtab_key_t key)
{
const struct chkdups_key *k = (const struct chkdups_key *)key;
const char *p = NULL;
size_t size;
unsigned int val = 0;

size = strlen(k->regex);
for (p = k->regex; ((size_t) (p - k->regex)) < size; p++)
val =
((val << 4) | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val % h->size;
}

static int symcmp(hashtab_t h
__attribute__ ((unused)), const_hashtab_key_t key1,
const_hashtab_key_t key2)
{
const struct chkdups_key *a = (const struct chkdups_key *)key1;
const struct chkdups_key *b = (const struct chkdups_key *)key2;

return strcmp(a->regex, b->regex) || (a->mode && b->mode && a->mode != b->mode);
}

static int destroy_chkdups_key(hashtab_key_t key)
{
free(key);

return 0;
}

/*
* Warn about duplicate specifications.
*/
static int nodups_specs(struct saved_data *data, const char *path)
{
int rc = 0;
unsigned int ii, jj;
int rc = 0, ret = 0;
unsigned int ii;
struct spec *curr_spec, *spec_arr = data->spec_arr;
struct chkdups_key *new = NULL;
unsigned int hashtab_len = (data->nspec / SHRINK_MULTIS) ? data->nspec / SHRINK_MULTIS : 1;

hashtab_t hash_table = hashtab_create(symhash, symcmp, hashtab_len);
if (!hash_table) {
rc = -1;
COMPAT_LOG(SELINUX_ERROR, "%s: hashtab create failed.\n", path);
return rc;
}
for (ii = 0; ii < data->nspec; ii++) {
curr_spec = &spec_arr[ii];
for (jj = ii + 1; jj < data->nspec; jj++) {
if ((!strcmp(spec_arr[jj].regex_str,
curr_spec->regex_str))
&& (!spec_arr[jj].mode || !curr_spec->mode
|| spec_arr[jj].mode == curr_spec->mode)) {
rc = -1;
errno = EINVAL;
if (strcmp(spec_arr[jj].lr.ctx_raw,
curr_spec->lr.ctx_raw)) {
COMPAT_LOG
(SELINUX_ERROR,
"%s: Multiple different specifications for %s (%s and %s).\n",
path, curr_spec->regex_str,
spec_arr[jj].lr.ctx_raw,
curr_spec->lr.ctx_raw);
} else {
COMPAT_LOG
(SELINUX_ERROR,
"%s: Multiple same specifications for %s.\n",
path, curr_spec->regex_str);
}
new = (struct chkdups_key *)malloc(sizeof(struct chkdups_key));
if (!new) {
rc = -1;
hashtab_destroy_key(hash_table, destroy_chkdups_key);
COMPAT_LOG(SELINUX_ERROR, "%s: hashtab key create failed.\n", path);
return rc;
}
new->regex = spec_arr[ii].regex_str;
new->mode = spec_arr[ii].mode;
ret = hashtab_insert(hash_table, (hashtab_key_t)new, &spec_arr[ii]);
if (ret == HASHTAB_SUCCESS)
continue;
if (ret == HASHTAB_PRESENT) {
curr_spec =
(struct spec *)hashtab_search(hash_table, (hashtab_key_t)new);
rc = -1;
errno = EINVAL;
free(new);
if (strcmp(spec_arr[ii].lr.ctx_raw, curr_spec->lr.ctx_raw)) {
COMPAT_LOG
(SELINUX_ERROR,
"%s: Multiple different specifications for %s (%s and %s).\n",
path, curr_spec->regex_str,
spec_arr[ii].lr.ctx_raw,
curr_spec->lr.ctx_raw);
} else {
COMPAT_LOG
(SELINUX_ERROR,
"%s: Multiple same specifications for %s.\n",
path, curr_spec->regex_str);
}
}
if (ret == HASHTAB_OVERFLOW) {
rc = -1;
free(new);
COMPAT_LOG
(SELINUX_ERROR,
"%s: hashtab happen memory error.\n",
path);
break;
}
}

hashtab_destroy_key(hash_table, destroy_chkdups_key);

return rc;
}

Expand Down