SELinux userspace 3.4 release

Resolves: rhbz#2079283
This commit is contained in:
Petr Lautrbach 2022-05-19 18:16:40 +02:00
parent 80c6e6516d
commit f6f4dc5d0b
40 changed files with 66 additions and 2616 deletions

1
.gitignore vendored
View File

@ -221,3 +221,4 @@ libselinux-2.0.96.tgz
/libselinux-3.3-rc2.tar.gz
/libselinux-3.3-rc3.tar.gz
/libselinux-3.3.tar.gz
/libselinux-3.4.tar.gz

View File

@ -1,7 +1,8 @@
From ec1b147076345478636de763ce5d4e8daa69afd6 Mon Sep 17 00:00:00 2001
From ff417d9a70e6d6ee40176b184ea7b67ee3f2355b Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Fri, 30 Jul 2021 14:14:37 +0200
Subject: [PATCH] Use SHA-2 instead of SHA-1
Content-type: text/plain
The use of SHA-1 in RHEL9 is deprecated
---
@ -14,7 +15,7 @@ The use of SHA-1 in RHEL9 is deprecated
libselinux/src/Makefile | 2 +-
libselinux/src/label_file.c | 40 +--
libselinux/src/label_internal.h | 10 +-
libselinux/src/label_support.c | 8 +-
libselinux/src/label_support.c | 10 +-
libselinux/src/selinux_restorecon.c | 24 +-
libselinux/src/sha1.c | 220 -------------
libselinux/src/sha1.h | 85 -----
@ -22,7 +23,7 @@ The use of SHA-1 in RHEL9 is deprecated
libselinux/src/sha256.h | 89 ++++++
libselinux/utils/selabel_digest.c | 26 +-
.../selabel_get_digests_all_partial_matches.c | 28 +-
17 files changed, 469 insertions(+), 391 deletions(-)
17 files changed, 470 insertions(+), 392 deletions(-)
delete mode 100644 libselinux/src/sha1.c
delete mode 100644 libselinux/src/sha1.h
create mode 100644 libselinux/src/sha256.c
@ -50,10 +51,10 @@ index e8983606d93b..a35d84d63b0a 100644
* @num_specfiles: number of specfiles in the list.
*
diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h
index 466de39aac72..ca8ce768587a 100644
index b10fe684eff9..8df4744505b3 100644
--- a/libselinux/include/selinux/restorecon.h
+++ b/libselinux/include/selinux/restorecon.h
@@ -27,8 +27,8 @@ extern int selinux_restorecon(const char *pathname,
@@ -41,8 +41,8 @@ extern int selinux_restorecon_parallel(const char *pathname,
* restorecon_flags options
*/
/*
@ -83,7 +84,7 @@ index 56a008f00df0..5f7c42533d0e 100644
with the number of entries in
.IR num_specfiles .
diff --git a/libselinux/man/man3/selabel_open.3 b/libselinux/man/man3/selabel_open.3
index 971ebc1acd41..2cf2eb8a1410 100644
index 0e03e1be111e..14ab888d2e03 100644
--- a/libselinux/man/man3/selabel_open.3
+++ b/libselinux/man/man3/selabel_open.3
@@ -69,7 +69,7 @@ is used; a custom validation function can be provided via
@ -96,10 +97,10 @@ index 971ebc1acd41..2cf2eb8a1410 100644
.BR selabel_digest (3)
.
diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.3
index ad637406a30d..c4576fe79ff6 100644
index 218aaf6d2ae5..c74189c0852d 100644
--- a/libselinux/man/man3/selinux_restorecon.3
+++ b/libselinux/man/man3/selinux_restorecon.3
@@ -28,7 +28,7 @@ If this is a directory and the
@@ -36,7 +36,7 @@ If this is a directory and the
.B SELINUX_RESTORECON_RECURSE
has been set (for descending through directories), then
.BR selinux_restorecon ()
@ -108,7 +109,7 @@ index ad637406a30d..c4576fe79ff6 100644
.BR selabel_get_digests_all_partial_matches (3)
to an extended attribute of
.IR security.sehash
@@ -47,7 +47,7 @@ will take place.
@@ -55,7 +55,7 @@ will take place.
.br
The
.IR restorecon_flags
@ -117,7 +118,7 @@ index ad637406a30d..c4576fe79ff6 100644
.RS
.B SELINUX_RESTORECON_SKIP_DIGEST
.br
@@ -65,8 +65,8 @@ Do not check or update any extended attribute
@@ -73,8 +73,8 @@ Do not check or update any extended attribute
entries.
.sp
.B SELINUX_RESTORECON_IGNORE_DIGEST
@ -128,7 +129,7 @@ index ad637406a30d..c4576fe79ff6 100644
.IR security.sehash
extended attribute once relabeling has been completed successfully provided the
.B SELINUX_RESTORECON_NOCHANGE
@@ -84,7 +84,7 @@ default specfile context.
@@ -95,7 +95,7 @@ default specfile context.
.sp
.B SELINUX_RESTORECON_RECURSE
change file and directory labels recursively (descend directories)
@ -137,8 +138,8 @@ index ad637406a30d..c4576fe79ff6 100644
extended attribute as described in the
.B NOTES
section.
@@ -158,7 +158,7 @@ to treat conflicting specifications, such as where two hardlinks for the
same inode have different contexts, as errors.
@@ -184,7 +184,7 @@ walk, the specfile entries SHA1 digest will not have been written to the
extended attribute.
.RE
.sp
-The behavior regarding the checking and updating of the SHA1 digest described
@ -146,7 +147,7 @@ index ad637406a30d..c4576fe79ff6 100644
above is the default behavior. It is possible to change this by first calling
.BR selabel_open (3)
and not enabling the
@@ -200,7 +200,7 @@ To improve performance when relabeling file systems recursively (e.g. the
@@ -247,7 +247,7 @@ To improve performance when relabeling file systems recursively (e.g. the
.B SELINUX_RESTORECON_RECURSE
flag is set)
.BR selinux_restorecon ()
@ -155,7 +156,7 @@ index ad637406a30d..c4576fe79ff6 100644
.BR selabel_get_digests_all_partial_matches (3)
to an extended attribute named
.IR security.sehash
@@ -222,7 +222,7 @@ Should any of the specfile entries have changed, then when
@@ -269,7 +269,7 @@ Should any of the specfile entries have changed, then when
.BR selinux_restorecon ()
is run again with the
.B SELINUX_RESTORECON_RECURSE
@ -178,10 +179,10 @@ index c56326814b94..098c840fc59b 100644
.BR selabel_open (3)
must be called specifying the required
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 52c40f018f51..674a5ed3a6f8 100644
index 04bf4f240168..222c3fa2d7c3 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -120,7 +120,7 @@ DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \
@@ -119,7 +119,7 @@ DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \
-DBUILD_HOST
SRCS= callbacks.c freecon.c label.c label_file.c \
label_backends_android.c regex.c label_support.c \
@ -191,10 +192,10 @@ index 52c40f018f51..674a5ed3a6f8 100644
LABEL_BACKEND_ANDROID=y
endif
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 2e28d0474d73..c1306c9979e7 100644
index 74ae9b9feb70..33d395e414f0 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -1005,7 +1005,7 @@ static struct spec *lookup_common(struct selabel_handle *rec,
@@ -1010,7 +1010,7 @@ static struct spec *lookup_common(struct selabel_handle *rec,
/*
* Returns true if the digest of all partial matched contexts is the same as
@ -203,7 +204,7 @@ index 2e28d0474d73..c1306c9979e7 100644
* digest will always be returned. The caller must free any returned digests.
*/
static bool get_digests_all_partial_matches(struct selabel_handle *rec,
@@ -1014,39 +1014,39 @@ static bool get_digests_all_partial_matches(struct selabel_handle *rec,
@@ -1019,39 +1019,39 @@ static bool get_digests_all_partial_matches(struct selabel_handle *rec,
uint8_t **xattr_digest,
size_t *digest_len)
{
@ -254,7 +255,7 @@ index 2e28d0474d73..c1306c9979e7 100644
return true;
return false;
@@ -1066,22 +1066,22 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key
@@ -1071,22 +1071,22 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key
return false;
}
@ -327,31 +328,44 @@ index 782c6aa8cc0c..304e8d96490a 100644
};
diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c
index 94ed6e4273cb..f53d73b609ab 100644
index 54fd49a5b7b9..4003eb8dc7af 100644
--- a/libselinux/src/label_support.c
+++ b/libselinux/src/label_support.c
@@ -115,15 +115,15 @@ int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
@@ -115,7 +115,7 @@ int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
/* Once all the specfiles are in the hash_buf, generate the hash. */
void digest_gen_hash(struct selabel_digest *digest)
{
- Sha1Context context;
+ Sha256Context context;
size_t remaining_size;
const unsigned char *ptr;
/* If SELABEL_OPT_DIGEST not set then just return */
@@ -123,19 +123,19 @@ void digest_gen_hash(struct selabel_digest *digest)
if (!digest)
return;
- Sha1Initialise(&context);
- Sha1Update(&context, digest->hashbuf, digest->hashbuf_size);
- Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
+ Sha256Initialise(&context);
+ Sha256Update(&context, digest->hashbuf, digest->hashbuf_size);
/* Process in blocks of UINT32_MAX bytes */
remaining_size = digest->hashbuf_size;
ptr = digest->hashbuf;
while (remaining_size > UINT32_MAX) {
- Sha1Update(&context, ptr, UINT32_MAX);
+ Sha256Update(&context, ptr, UINT32_MAX);
remaining_size -= UINT32_MAX;
ptr += UINT32_MAX;
}
- Sha1Update(&context, ptr, remaining_size);
+ Sha256Update(&context, ptr, remaining_size);
- Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
+ Sha256Finalise(&context, (SHA256_HASH *)digest->digest);
free(digest->hashbuf);
digest->hashbuf = NULL;
return;
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 04d956504952..100c77108a27 100644
index 9dd6be817832..dc222b425c95 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -37,7 +37,7 @@
@ -363,16 +377,16 @@ index 04d956504952..100c77108a27 100644
#define STAR_COUNT 1024
@@ -293,7 +293,7 @@ static int exclude_non_seclabel_mounts(void)
@@ -305,7 +305,7 @@ static uint64_t exclude_non_seclabel_mounts(void)
static int add_xattr_entry(const char *directory, bool delete_nonmatch,
bool delete_all)
{
- char *sha1_buf = NULL;
+ char *sha256_buf = NULL;
size_t i, digest_len = 0;
int rc, digest_result;
bool match;
@@ -316,15 +316,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
int rc;
enum digest_result digest_result;
@@ -329,15 +329,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
}
/* Convert entry to a hex encoded string. */
@ -391,7 +405,7 @@ index 04d956504952..100c77108a27 100644
digest_result = match ? MATCH : NOMATCH;
@@ -344,7 +344,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
@@ -357,7 +357,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
/* Now add entries to link list. */
new_entry = malloc(sizeof(struct dir_xattr));
if (!new_entry) {
@ -400,7 +414,7 @@ index 04d956504952..100c77108a27 100644
goto oom;
}
new_entry->next = NULL;
@@ -352,15 +352,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
@@ -365,15 +365,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
new_entry->directory = strdup(directory);
if (!new_entry->directory) {
free(new_entry);
@ -419,7 +433,7 @@ index 04d956504952..100c77108a27 100644
goto oom;
}
@@ -374,7 +374,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
@@ -387,7 +387,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
dir_xattr_last = new_entry;
}
@ -428,7 +442,7 @@ index 04d956504952..100c77108a27 100644
return 0;
oom:
@@ -741,7 +741,7 @@ err:
@@ -781,7 +781,7 @@ err:
struct dir_hash_node {
char *path;
@ -437,7 +451,7 @@ index 04d956504952..100c77108a27 100644
struct dir_hash_node *next;
};
/*
@@ -1091,7 +1091,7 @@ int selinux_restorecon(const char *pathname_orig,
@@ -1270,7 +1270,7 @@ static int selinux_restorecon_common(const char *pathname_orig,
if (setxattr(current->path,
RESTORECON_PARTIAL_MATCH_DIGEST,
current->digest,
@ -1159,7 +1173,7 @@ index 000000000000..406ed869cd82
+ SHA256_HASH* Digest // [in]
+ );
diff --git a/libselinux/utils/selabel_digest.c b/libselinux/utils/selabel_digest.c
index 49408a0ba8d8..67befadd23c5 100644
index 6a8313a2c88d..a69331f1c6b5 100644
--- a/libselinux/utils/selabel_digest.c
+++ b/libselinux/utils/selabel_digest.c
@@ -15,8 +15,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
@ -1240,7 +1254,7 @@ index 49408a0ba8d8..67befadd23c5 100644
selabel_close(hnd);
return rc;
diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c
index e28833d2ce97..900f018c0091 100644
index c4e0f836b260..80723f714264 100644
--- a/libselinux/utils/selabel_get_digests_all_partial_matches.c
+++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c
@@ -18,8 +18,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
@ -1263,7 +1277,7 @@ index e28833d2ce97..900f018c0091 100644
struct selabel_handle *hnd;
struct selinux_opt selabel_option[] = {
@@ -105,27 +105,27 @@ int main(int argc, char **argv)
@@ -106,27 +106,27 @@ int main(int argc, char **argv)
&xattr_digest,
&digest_len);
@ -1297,7 +1311,7 @@ index e28833d2ce97..900f018c0091 100644
ftsent->fts_path);
printf("as file_context entry is \"<<none>>\"\n");
goto cleanup;
@@ -135,25 +135,25 @@ int main(int argc, char **argv)
@@ -136,25 +136,25 @@ int main(int argc, char **argv)
ftsent->fts_path);
for (i = 0; i < digest_len; i++)
@ -1329,5 +1343,5 @@ index e28833d2ce97..900f018c0091 100644
}
default:
--
2.32.0
2.36.1

View File

@ -1,45 +0,0 @@
From 651c1fdee084cbf9a25d5131ebe367d6d1473ca5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 10 May 2021 12:12:38 +0200
Subject: [PATCH] libselinux: selinux_check_passwd_access_internal(): respect
deny_unknown
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
`selinux_check_passwd_access_internal()`, and thereby
`checkPasswdAccess(3)` and `selinux_check_passwd_access(3)`, does not
respect the policy defined setting of `deny_unknown`, like
`selinux_check_access(3)` does.
This means in case the security class `passwd` is not defined, success
is returned instead of failure, i.e. permission denied.
Most policies should define the `passwd` class and the two affected
public functions are marked deprecated.
Align the behavior with `selinux_check_access(3)` and respect
the deny_unknown setting in case the security class is not defined.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/checkAccess.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libselinux/src/checkAccess.c b/libselinux/src/checkAccess.c
index b337ea64f977..022cd6b5ecab 100644
--- a/libselinux/src/checkAccess.c
+++ b/libselinux/src/checkAccess.c
@@ -78,7 +78,9 @@ static int selinux_check_passwd_access_internal(access_vector_t requested)
passwd_class = string_to_security_class("passwd");
if (passwd_class == 0) {
freecon(user_context);
- return 0;
+ if (security_deny_unknown() == 0)
+ return 0;
+ return -1;
}
retval = security_compute_av_raw(user_context,
--
2.32.0.rc1

View File

@ -1,73 +0,0 @@
From 5844f389429f26a0a62a65561fa3006feaaf6f3b Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:32 +0200
Subject: [PATCH] label_file: fix a data race
The 'matches' member of 'struct spec' may be written to by different
threads, so it needs to be accessed using the proper atomic constructs.
Since the actual count of matches doesn't matter and is not used,
convert this field to a bool and just atomically set/read it using GCC
__atomic builtins (which are already being used in another place).
If the compiler lacks support for __atomic builtins (which seem to have
been introduced in GCC 4.1), just fail the compilation. I don't think
it's worth tryin to invent a workaround to support a 15 years old
compiler.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
libselinux/src/label_file.c | 15 +++++++++++++--
libselinux/src/label_file.h | 2 +-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index c1306c9979e7..33d395e414f0 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -951,7 +951,12 @@ static struct spec **lookup_all(struct selabel_handle *rec,
rc = regex_match(spec->regex, key, partial);
if (rc == REGEX_MATCH || (partial && rc == REGEX_MATCH_PARTIAL)) {
if (rc == REGEX_MATCH) {
- spec->matches++;
+#ifdef __ATOMIC_RELAXED
+ __atomic_store_n(&spec->any_matches,
+ true, __ATOMIC_RELAXED);
+#else
+#error "Please use a compiler that supports __atomic builtins"
+#endif
}
if (strcmp(spec_arr[i].lr.ctx_raw, "<<none>>") == 0) {
@@ -1249,9 +1254,15 @@ static void stats(struct selabel_handle *rec)
struct saved_data *data = (struct saved_data *)rec->data;
unsigned int i, nspec = data->nspec;
struct spec *spec_arr = data->spec_arr;
+ bool any_matches;
for (i = 0; i < nspec; i++) {
- if (spec_arr[i].matches == 0) {
+#ifdef __ATOMIC_RELAXED
+ any_matches = __atomic_load_n(&spec_arr[i].any_matches, __ATOMIC_RELAXED);
+#else
+#error "Please use a compiler that supports __atomic builtins"
+#endif
+ if (!any_matches) {
if (spec_arr[i].type_str) {
COMPAT_LOG(SELINUX_WARNING,
"Warning! No matches for (%s, %s, %s)\n",
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 343ffc705e43..b453e13f8075 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -51,7 +51,7 @@ struct spec {
bool regex_compiled; /* bool to indicate if the regex is compiled */
pthread_mutex_t regex_lock; /* lock for lazy compilation of regex */
mode_t mode; /* mode format value */
- int matches; /* number of matching pathnames */
+ bool any_matches; /* did any pathname match? */
int stem_id; /* indicates which stem-compression item */
char hasMetaChars; /* regular expression has meta-chars */
char from_mmap; /* this spec is from an mmap of the data */
--
2.33.1

View File

@ -1,51 +0,0 @@
From 3bf8068d0854bbb4d7b5f63ab0c0137659d6d346 Mon Sep 17 00:00:00 2001
From: Nicolas Iooss <nicolas.iooss@m4x.org>
Date: Fri, 30 Apr 2021 21:37:02 +0200
Subject: [PATCH] libselinux: silence -Wstringop-overflow warning from gcc
10.3.1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When building libselinux on Fedora 33 with gcc 10.3.1, the compiler
reports:
label_file.c: In function lookup_all.isra:
label_file.c:940:4: error: strncpy specified bound depends on the
length of the source argument [-Werror=stringop-overflow=]
940 | strncpy(clean_key, key, len - 1);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label_file.c:927:8: note: length computed here
927 | len = strlen(key);
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
As clean_key is the result of malloc(len), there is no issue here. But
using strncpy can be considered as strange, because the size of the
string is already known and the NUL terminator is always added later, in
function lookup_all.isra.
Replace strncpy with memcpy to silence this gcc false-positive warning.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
---
libselinux/src/label_file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 726394ca4332..cfce23e0119e 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -909,7 +909,7 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
if (!clean_key)
goto finish;
- strncpy(clean_key, key, len - 1);
+ memcpy(clean_key, key, len - 1);
}
clean_key[len - 1] = '\0';
--
2.32.0.rc1

View File

@ -1,46 +0,0 @@
From c530a5f37bb2ebd0cca1eeb714d39c43bd514cd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:35 +0200
Subject: [PATCH] libselinux: sidtab_hash(): do not discard const qualifier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Do not discard the const qualifier of the function argument, and drop
the redundant local variable `keyp`.
avc_sidtab.c: In function sidtab_hash:
avc_sidtab.c:23:9: warning: cast discards const qualifier from pointer target type [-Wcast-qual]
23 | keyp = (char *)key;
| ^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/avc_sidtab.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c
index 9669264d651a..8dc875608762 100644
--- a/libselinux/src/avc_sidtab.c
+++ b/libselinux/src/avc_sidtab.c
@@ -15,14 +15,13 @@
static inline unsigned sidtab_hash(const char * key)
{
- char *p, *keyp;
+ const char *p;
unsigned int size;
unsigned int val;
val = 0;
- keyp = (char *)key;
- size = strlen(keyp);
- for (p = keyp; (unsigned int)(p - keyp) < size; p++)
+ size = strlen(key);
+ for (p = key; (unsigned int)(p - key) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (SIDTAB_SIZE - 1);
--
2.32.0.rc1

View File

@ -1,30 +0,0 @@
From 5dd3a11842c08a25a0f7ab798ce85710fe1e8f1f Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:33 +0200
Subject: [PATCH] selinux_restorecon: simplify fl_head allocation by using
calloc()
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
libselinux/src/selinux_restorecon.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 100c77108a27..e29a2c390182 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -425,10 +425,9 @@ static int filespec_add(ino_t ino, const char *con, const char *file,
struct stat64 sb;
if (!fl_head) {
- fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
+ fl_head = calloc(HASH_BUCKETS, sizeof(file_spec_t));
if (!fl_head)
goto oom;
- memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
}
h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
--
2.33.1

View File

@ -1,48 +0,0 @@
From 17ddb94f4014b715214268148447c84e7c037fcb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:40 +0200
Subject: [PATCH] libselinux: selinux_file_context_cmp(): do not discard const
qualifier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
matchpathcon.c: In function selinux_file_context_cmp:
matchpathcon.c:487:18: warning: cast discards const qualifier from pointer target type [-Wcast-qual]
487 | rest_a = strchr((char *)a, ':');
| ^
matchpathcon.c:488:18: warning: cast discards const qualifier from pointer target type [-Wcast-qual]
488 | rest_b = strchr((char *)b, ':');
| ^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/matchpathcon.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index 2ec66650cae0..9e1fab593266 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -477,15 +477,15 @@ void matchpathcon_checkmatches(char *str __attribute__((unused)))
int selinux_file_context_cmp(const char * a,
const char * b)
{
- char *rest_a, *rest_b; /* Rest of the context after the user */
+ const char *rest_a, *rest_b; /* Rest of the context after the user */
if (!a && !b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
- rest_a = strchr((char *)a, ':');
- rest_b = strchr((char *)b, ':');
+ rest_a = strchr(a, ':');
+ rest_b = strchr(b, ':');
if (!rest_a && !rest_b)
return 0;
if (!rest_a)
--
2.32.0.rc1

View File

@ -1,81 +0,0 @@
From 4598a46c5ed12248a3a6e1dbe1b5a3dca52bacac Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:34 +0200
Subject: [PATCH] selinux_restorecon: protect file_spec list with a mutex
Not very useful on its own, but will allow to implement a parallel
version of selinux_restorecon() in subsequent patches.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
libselinux/src/selinux_restorecon.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index e29a2c390182..43acbace309d 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -411,6 +411,7 @@ typedef struct file_spec {
} file_spec_t;
static file_spec_t *fl_head;
+static pthread_mutex_t fl_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Try to add an association between an inode and a context. If there is a
@@ -424,6 +425,8 @@ static int filespec_add(ino_t ino, const char *con, const char *file,
int h, ret;
struct stat64 sb;
+ __pthread_mutex_lock(&fl_mutex);
+
if (!fl_head) {
fl_head = calloc(HASH_BUCKETS, sizeof(file_spec_t));
if (!fl_head)
@@ -444,11 +447,11 @@ static int filespec_add(ino_t ino, const char *con, const char *file,
fl->con = strdup(con);
if (!fl->con)
goto oom;
- return 1;
+ goto unlock_1;
}
if (strcmp(fl->con, con) == 0)
- return 1;
+ goto unlock_1;
selinux_log(SELINUX_ERROR,
"conflicting specifications for %s and %s, using %s.\n",
@@ -457,6 +460,9 @@ static int filespec_add(ino_t ino, const char *con, const char *file,
fl->file = strdup(file);
if (!fl->file)
goto oom;
+
+ __pthread_mutex_unlock(&fl_mutex);
+
if (flags->conflicterror) {
selinux_log(SELINUX_ERROR,
"treating conflicting specifications as an error.\n");
@@ -481,13 +487,19 @@ static int filespec_add(ino_t ino, const char *con, const char *file,
goto oom_freefl;
fl->next = prevfl->next;
prevfl->next = fl;
+
+ __pthread_mutex_unlock(&fl_mutex);
return 0;
oom_freefl:
free(fl);
oom:
+ __pthread_mutex_unlock(&fl_mutex);
selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__);
return -1;
+unlock_1:
+ __pthread_mutex_unlock(&fl_mutex);
+ return 1;
}
/*
--
2.33.1

View File

@ -1,69 +0,0 @@
From 967d3d5d1b42b6483fc9135e7ac7d198fbd85212 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:42 +0200
Subject: [PATCH] libselinux: label_common(): do not discard const qualifier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
As the const qualifier is discarded in label_common(), do not return a
const qualified pointer pointer from the local function `lookup_all()`.
label_file.c: In function lookup_common:
label_file.c:994:24: warning: cast discards const qualifier from pointer target type [-Wcast-qual]
994 | struct spec *result = (struct spec*)matches[0];
| ^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_file.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index cfce23e0119e..b080fcf1305b 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -845,7 +845,7 @@ static void closef(struct selabel_handle *rec)
// Finds all the matches of |key| in the given context. Returns the result in
// the allocated array and updates the match count. If match_count is NULL,
// stops early once the 1st match is found.
-static const struct spec **lookup_all(struct selabel_handle *rec,
+static struct spec **lookup_all(struct selabel_handle *rec,
const char *key,
int type,
bool partial,
@@ -861,7 +861,7 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
unsigned int sofar = 0;
char *sub = NULL;
- const struct spec **result = NULL;
+ struct spec **result = NULL;
if (match_count) {
*match_count = 0;
result = calloc(data->nspec, sizeof(struct spec*));
@@ -987,11 +987,11 @@ static struct spec *lookup_common(struct selabel_handle *rec,
const char *key,
int type,
bool partial) {
- const struct spec **matches = lookup_all(rec, key, type, partial, NULL);
+ struct spec **matches = lookup_all(rec, key, type, partial, NULL);
if (!matches) {
return NULL;
}
- struct spec *result = (struct spec*)matches[0];
+ struct spec *result = matches[0];
free(matches);
return result;
}
@@ -1054,7 +1054,7 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key
assert(digest);
size_t total_matches;
- const struct spec **matches = lookup_all(rec, key, 0, true, &total_matches);
+ struct spec **matches = lookup_all(rec, key, 0, true, &total_matches);
if (!matches) {
return false;
}
--
2.32.0.rc1

View File

@ -1,88 +0,0 @@
From c2e4cf5b21e8c775c669f3933d25a0946774ec0d Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:35 +0200
Subject: [PATCH] libselinux: make selinux_log() thread-safe
Ensure that selinux_log() is thread-safe by guarding the call to the
underlying callback with a mutex.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
libselinux/src/callbacks.c | 8 +++++---
libselinux/src/callbacks.h | 13 ++++++++++++-
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c
index c18ccc54754a..469c4055f4d7 100644
--- a/libselinux/src/callbacks.c
+++ b/libselinux/src/callbacks.c
@@ -10,6 +10,8 @@
#include <selinux/selinux.h>
#include "callbacks.h"
+pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
+
/* default implementations */
static int __attribute__ ((format(printf, 2, 3)))
default_selinux_log(int type __attribute__((unused)), const char *fmt, ...)
@@ -56,7 +58,7 @@ default_selinux_policyload(int seqno __attribute__((unused)))
/* callback pointers */
int __attribute__ ((format(printf, 2, 3)))
-(*selinux_log)(int, const char *, ...) =
+(*selinux_log_direct)(int, const char *, ...) =
default_selinux_log;
int
@@ -81,7 +83,7 @@ selinux_set_callback(int type, union selinux_callback cb)
{
switch (type) {
case SELINUX_CB_LOG:
- selinux_log = cb.func_log;
+ selinux_log_direct = cb.func_log;
break;
case SELINUX_CB_AUDIT:
selinux_audit = cb.func_audit;
@@ -106,7 +108,7 @@ selinux_get_callback(int type)
switch (type) {
case SELINUX_CB_LOG:
- cb.func_log = selinux_log;
+ cb.func_log = selinux_log_direct;
break;
case SELINUX_CB_AUDIT:
cb.func_audit = selinux_audit;
diff --git a/libselinux/src/callbacks.h b/libselinux/src/callbacks.h
index 03d87f0cbdfe..f4dab15789f9 100644
--- a/libselinux/src/callbacks.h
+++ b/libselinux/src/callbacks.h
@@ -10,9 +10,11 @@
#include <string.h>
#include <selinux/selinux.h>
+#include "selinux_internal.h"
+
/* callback pointers */
extern int __attribute__ ((format(printf, 2, 3)))
-(*selinux_log) (int type, const char *, ...) ;
+(*selinux_log_direct) (int type, const char *, ...) ;
extern int
(*selinux_audit) (void *, security_class_t, char *, size_t) ;
@@ -26,4 +28,13 @@ extern int
extern int
(*selinux_netlink_policyload) (int seqno) ;
+/* Thread-safe selinux_log() function */
+extern pthread_mutex_t log_mutex;
+
+#define selinux_log(type, ...) do { \
+ __pthread_mutex_lock(&log_mutex); \
+ selinux_log_direct(type, __VA_ARGS__); \
+ __pthread_mutex_unlock(&log_mutex); \
+} while(0)
+
#endif /* _SELINUX_CALLBACKS_H_ */
--
2.33.1

View File

@ -1,85 +0,0 @@
From 35016346471698822834471ca2ddf9019ebd25d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:44 +0200
Subject: [PATCH] libselinux: Sha1Finalise(): do not discard const qualifier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Mark the argument `Buffer` of `Sha1Update()` const, since it is not
modified.
sha1.c: In function Sha1Finalise:
sha1.c:208:25: warning: cast discards const qualifier from pointer target type [-Wcast-qual]
208 | Sha1Update(Context, (uint8_t*)"\x80", 1);
| ^
sha1.c:211:29: warning: cast discards const qualifier from pointer target type [-Wcast-qual]
211 | Sha1Update(Context, (uint8_t*)"\0", 1);
| ^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/sha1.c | 10 +++++-----
libselinux/src/sha1.h | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c
index 9a8ce01dceda..664bbcf26eef 100644
--- a/libselinux/src/sha1.c
+++ b/libselinux/src/sha1.c
@@ -151,7 +151,7 @@ void
Sha1Update
(
Sha1Context* Context,
- void* Buffer,
+ const void* Buffer,
uint32_t BufferSize
)
{
@@ -172,7 +172,7 @@ void
TransformFunction(Context->State, Context->Buffer);
for (; i + 63 < BufferSize; i += 64)
{
- TransformFunction(Context->State, (uint8_t*)Buffer + i);
+ TransformFunction(Context->State, (const uint8_t*)Buffer + i);
}
j = 0;
}
@@ -181,7 +181,7 @@ void
i = 0;
}
- memcpy(&Context->Buffer[j], &((uint8_t*)Buffer)[i], BufferSize - i);
+ memcpy(&Context->Buffer[j], &((const uint8_t*)Buffer)[i], BufferSize - i);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -205,10 +205,10 @@ void
finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); // Endian independent
}
- Sha1Update(Context, (uint8_t*)"\x80", 1);
+ Sha1Update(Context, (const uint8_t*)"\x80", 1);
while ((Context->Count[0] & 504) != 448)
{
- Sha1Update(Context, (uint8_t*)"\0", 1);
+ Sha1Update(Context, (const uint8_t*)"\0", 1);
}
Sha1Update(Context, finalcount, 8); // Should cause a Sha1TransformFunction()
diff --git a/libselinux/src/sha1.h b/libselinux/src/sha1.h
index eac3c195351a..f83a6e7ed7ba 100644
--- a/libselinux/src/sha1.h
+++ b/libselinux/src/sha1.h
@@ -64,7 +64,7 @@ void
Sha1Update
(
Sha1Context* Context,
- void* Buffer,
+ const void* Buffer,
uint32_t BufferSize
);
--
2.32.0.rc1

View File

@ -1,81 +0,0 @@
From 9a8db9356c07d16a9337df416a3261c0527afeb7 Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:36 +0200
Subject: [PATCH] libselinux: make is_context_customizable() thread-safe
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use the __selinux_once() macro to ensure that threads don't race to
initialize the list of customizable types.
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Tested-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/is_customizable_type.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/libselinux/src/is_customizable_type.c b/libselinux/src/is_customizable_type.c
index 1b17860c3622..f83e1e83e944 100644
--- a/libselinux/src/is_customizable_type.c
+++ b/libselinux/src/is_customizable_type.c
@@ -9,7 +9,10 @@
#include "selinux_internal.h"
#include "context_internal.h"
-static int get_customizable_type_list(char *** retlist)
+static char **customizable_list = NULL;
+static pthread_once_t customizable_once = PTHREAD_ONCE_INIT;
+
+static void customizable_init(void)
{
FILE *fp;
char *buf;
@@ -18,12 +21,12 @@ static int get_customizable_type_list(char *** retlist)
fp = fopen(selinux_customizable_types_path(), "re");
if (!fp)
- return -1;
+ return;
buf = malloc(selinux_page_size);
if (!buf) {
fclose(fp);
- return -1;
+ return;
}
while (fgets_unlocked(buf, selinux_page_size, fp) && ctr < UINT_MAX) {
ctr++;
@@ -54,23 +57,19 @@ static int get_customizable_type_list(char *** retlist)
fclose(fp);
free(buf);
if (!list)
- return -1;
- *retlist = list;
- return 0;
+ return;
+ customizable_list = list;
}
-static char **customizable_list = NULL;
-
int is_context_customizable(const char * scontext)
{
int i;
const char *type;
context_t c;
- if (!customizable_list) {
- if (get_customizable_type_list(&customizable_list) != 0)
- return -1;
- }
+ __selinux_once(customizable_once, customizable_init);
+ if (!customizable_list)
+ return -1;
c = context_new(scontext);
if (!c)
--
2.33.1

View File

@ -1,31 +0,0 @@
From 0a14ec7348a5657fa29d58e03c51500d89cc9908 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:46 +0200
Subject: [PATCH] libselinux: sefcontext_compile: mark local variable static
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `policy_file` is only used in sefcontext_compile.c.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/utils/sefcontext_compile.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c
index dcb0085ad67e..6c32172d9944 100644
--- a/libselinux/utils/sefcontext_compile.c
+++ b/libselinux/utils/sefcontext_compile.c
@@ -14,7 +14,7 @@
#include "../src/label_file.h"
#include "../src/regex.h"
-const char *policy_file;
+static const char *policy_file;
static int ctx_err;
static int validate_context(char **ctxp)
--
2.32.0.rc1

View File

@ -1,45 +0,0 @@
From 73310c9694724b3ef54bbf3a3193dbb0a68ecc3b Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:37 +0200
Subject: [PATCH] selinux_restorecon: add a global mutex to synchronize
progress output
Another small incremental change to pave the way for a parallel
selinux_restorecon() function.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
libselinux/src/selinux_restorecon.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 43acbace309d..169dfe3ae232 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -60,6 +60,7 @@ static int exclude_count = 0;
static struct edir *exclude_lst = NULL;
static uint64_t fc_count = 0; /* Number of files processed so far */
static uint64_t efile_count; /* Estimated total number of files */
+static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Store information on directories with xattr's. */
static struct dir_xattr *dir_xattr_list;
@@ -647,6 +648,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
}
if (flags->progress) {
+ __pthread_mutex_lock(&progress_mutex);
fc_count++;
if (fc_count % STAR_COUNT == 0) {
if (flags->mass_relabel && efile_count > 0) {
@@ -658,6 +660,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
}
fflush(stdout);
}
+ __pthread_mutex_unlock(&progress_mutex);
}
if (flags->add_assoc) {
--
2.33.1

View File

@ -1,42 +0,0 @@
From c3f4742bb96b7688eb8abd6cc3a89f30aff55f06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:48 +0200
Subject: [PATCH] libselinux: avcstat: use standard length modifier for
unsigned long long
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The format width specifier `L` is only standardized for floating point
types. Use `ll` for fixed-width data types.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/utils/avcstat.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libselinux/utils/avcstat.c b/libselinux/utils/avcstat.c
index da2392870c51..cc9a48dd4c3a 100644
--- a/libselinux/utils/avcstat.c
+++ b/libselinux/utils/avcstat.c
@@ -205,7 +205,7 @@ int main(int argc, char **argv)
die("unable to parse \'%s\': no data", avcstatfile);
if (cumulative || !i)
- printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n",
+ printf("%10llu %10llu %10llu %10llu %10llu %10llu\n",
tot.lookups, tot.hits, tot.misses,
tot.allocations, tot.reclaims, tot.frees);
else {
@@ -215,7 +215,7 @@ int main(int argc, char **argv)
rel.allocations = tot.allocations - last.allocations;
rel.reclaims = tot.reclaims - last.reclaims;
rel.frees = tot.frees - last.frees;
- printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n",
+ printf("%10llu %10llu %10llu %10llu %10llu %10llu\n",
rel.lookups, rel.hits, rel.misses,
rel.allocations, rel.reclaims, rel.frees);
}
--
2.32.0.rc1

View File

@ -1,800 +0,0 @@
From 847282ce385a4fc03092eb10422b1878590e9bdd Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <omosnace@redhat.com>
Date: Tue, 26 Oct 2021 13:52:38 +0200
Subject: [PATCH] selinux_restorecon: introduce selinux_restorecon_parallel(3)
Refactor selinux_restorecon(3) to allow for distributing the relabeling
to multiple threads and add a new function
selinux_restorecon_parallel(3), which allows specifying the number of
threads to use. The existing selinux_restorecon(3) function maintains
the same interface and maintains the same behavior (i.e. relabeling is
done on a single thread).
The parallel implementation takes a simple approach of performing all
the directory tree traversal in a critical section and only letting the
relabeling of individual objects run in parallel. Thankfully, this
approach turns out to be efficient enough in practice, as shown by
restorecon benchmarks (detailed in a subsequent patch that switches
setfiles & restorecon to use selinux_restorecon_parallel(3)).
Note that to be able to use the parallelism, the calling application/
library must be explicitly linked to the libpthread library (statically
or dynamically). This is necessary to mantain the requirement that
libselinux shouldn't explicitly link with libpthread. (I don't know what
exactly was the reason behind this requirement as the commit logs are
fuzzy, but special care has been taken in the past to maintain it, so I
didn't want to break it...)
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
libselinux/include/selinux/restorecon.h | 14 +
libselinux/man/man3/selinux_restorecon.3 | 29 ++
.../man/man3/selinux_restorecon_parallel.3 | 1 +
libselinux/src/libselinux.map | 5 +
libselinux/src/selinux_internal.h | 16 +
libselinux/src/selinux_restorecon.c | 436 ++++++++++++------
libselinux/src/selinuxswig_python.i | 6 +-
libselinux/src/selinuxswig_python_exception.i | 8 +
8 files changed, 368 insertions(+), 147 deletions(-)
create mode 100644 libselinux/man/man3/selinux_restorecon_parallel.3
diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h
index ca8ce768587a..8f9a030cda98 100644
--- a/libselinux/include/selinux/restorecon.h
+++ b/libselinux/include/selinux/restorecon.h
@@ -2,6 +2,7 @@
#define _RESTORECON_H_
#include <sys/types.h>
+#include <stddef.h>
#include <stdarg.h>
#ifdef __cplusplus
@@ -23,6 +24,19 @@ extern "C" {
*/
extern int selinux_restorecon(const char *pathname,
unsigned int restorecon_flags);
+/**
+ * selinux_restorecon_parallel - Relabel files, optionally use more threads.
+ * @pathname: specifies file/directory to relabel.
+ * @restorecon_flags: specifies the actions to be performed when relabeling.
+ * @nthreads: specifies the number of threads to use (0 = use number of CPUs
+ * currently online)
+ *
+ * Same as selinux_restorecon(3), but allows to use multiple threads to do
+ * the work.
+ */
+extern int selinux_restorecon_parallel(const char *pathname,
+ unsigned int restorecon_flags,
+ size_t nthreads);
/*
* restorecon_flags options
*/
diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.3
index c4576fe79ff6..500845917fb8 100644
--- a/libselinux/man/man3/selinux_restorecon.3
+++ b/libselinux/man/man3/selinux_restorecon.3
@@ -11,6 +11,14 @@ selinux_restorecon \- restore file(s) default SELinux security contexts
.br
.BI "unsigned int " restorecon_flags ");"
.in
+.sp
+.BI "int selinux_restorecon_parallel(const char *" pathname ,
+.in +\w'int selinux_restorecon_parallel('u
+.br
+.BI "unsigned int " restorecon_flags ","
+.br
+.BI "size_t " nthreads ");"
+.in
.
.SH "DESCRIPTION"
.BR selinux_restorecon ()
@@ -187,6 +195,27 @@ unless the
.B SELINUX_RESTORECON_IGNORE_MOUNTS
flag has been set.
.RE
+.sp
+.BR selinux_restorecon_parallel()
+is similar to
+.BR selinux_restorecon (3),
+but accepts another parameter that allows to run relabeling over multiple
+threads:
+.sp
+.RS
+.IR nthreads
+specifies the number of threads to use during relabeling. When set to 1,
+the behavior is the same as calling
+.BR selinux_restorecon (3).
+When set to 0, the function will try to use as many threads as there are
+online CPU cores. When set to any other number, the function will try to use
+the given number of threads.
+.sp
+Note that to use the parallel relabeling capability, the calling process
+must be linked with the
+.B libpthread
+library (either at compile time or dynamically at run time). Otherwise the
+function will print a warning and fall back to the single threaded mode.
.
.SH "RETURN VALUE"
On success, zero is returned. On error, \-1 is returned and
diff --git a/libselinux/man/man3/selinux_restorecon_parallel.3 b/libselinux/man/man3/selinux_restorecon_parallel.3
new file mode 100644
index 000000000000..092d8412cc93
--- /dev/null
+++ b/libselinux/man/man3/selinux_restorecon_parallel.3
@@ -0,0 +1 @@
+.so man3/selinux_restorecon.3
diff --git a/libselinux/src/libselinux.map b/libselinux/src/libselinux.map
index 2a368e93f9fd..d138e951ef0d 100644
--- a/libselinux/src/libselinux.map
+++ b/libselinux/src/libselinux.map
@@ -240,3 +240,8 @@ LIBSELINUX_1.0 {
local:
*;
};
+
+LIBSELINUX_3.3 {
+ global:
+ selinux_restorecon_parallel;
+} LIBSELINUX_1.0;
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index 27e9ac532c3f..297dcf26dee3 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -69,6 +69,22 @@ extern int selinux_page_size ;
pthread_mutex_unlock(LOCK); \
} while (0)
+#pragma weak pthread_create
+#pragma weak pthread_join
+#pragma weak pthread_cond_init
+#pragma weak pthread_cond_signal
+#pragma weak pthread_cond_destroy
+#pragma weak pthread_cond_wait
+
+/* check if all functions needed to do parallel operations are available */
+#define __pthread_supported ( \
+ pthread_create && \
+ pthread_join && \
+ pthread_cond_init && \
+ pthread_cond_destroy && \
+ pthread_cond_signal && \
+ pthread_cond_wait \
+)
#define SELINUXDIR "/etc/selinux/"
#define SELINUXCONFIG SELINUXDIR "config"
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 169dfe3ae232..f7e84657d09d 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -610,7 +610,7 @@ out:
}
static int restorecon_sb(const char *pathname, const struct stat *sb,
- struct rest_flags *flags)
+ struct rest_flags *flags, bool first)
{
char *newcon = NULL;
char *curcon = NULL;
@@ -639,7 +639,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
sb->st_mode);
if (rc < 0) {
- if (errno == ENOENT && flags->warnonnomatch)
+ if (errno == ENOENT && flags->warnonnomatch && first)
selinux_log(SELINUX_INFO,
"Warning no default label for %s\n",
lookup_path);
@@ -814,66 +814,215 @@ oom:
goto free;
}
+struct rest_state {
+ struct rest_flags flags;
+ dev_t dev_num;
+ struct statfs sfsb;
+ bool ignore_digest;
+ bool setrestorecondigest;
+ bool parallel;
-/*
- * Public API
- */
+ FTS *fts;
+ FTSENT *ftsent_first;
+ struct dir_hash_node *head, *current;
+ bool abort;
+ int error;
+ int saved_errno;
+ pthread_mutex_t mutex;
+};
-/* selinux_restorecon(3) - Main function that is responsible for labeling */
-int selinux_restorecon(const char *pathname_orig,
- unsigned int restorecon_flags)
+static void *selinux_restorecon_thread(void *arg)
{
- struct rest_flags flags;
+ struct rest_state *state = arg;
+ FTS *fts = state->fts;
+ FTSENT *ftsent;
+ int error;
+ char ent_path[PATH_MAX];
+ struct stat ent_st;
+ bool first = false;
+
+ if (state->parallel)
+ pthread_mutex_lock(&state->mutex);
+
+ if (state->ftsent_first) {
+ ftsent = state->ftsent_first;
+ state->ftsent_first = NULL;
+ first = true;
+ goto loop_body;
+ }
+
+ while (((void)(errno = 0), ftsent = fts_read(fts)) != NULL) {
+loop_body:
+ /* If the FTS_XDEV flag is set and the device is different */
+ if (state->flags.set_xdev &&
+ ftsent->fts_statp->st_dev != state->dev_num)
+ continue;
+
+ switch (ftsent->fts_info) {
+ case FTS_DC:
+ selinux_log(SELINUX_ERROR,
+ "Directory cycle on %s.\n",
+ ftsent->fts_path);
+ errno = ELOOP;
+ state->error = -1;
+ state->abort = true;
+ goto finish;
+ case FTS_DP:
+ continue;
+ case FTS_DNR:
+ error = errno;
+ errno = ftsent->fts_errno;
+ selinux_log(SELINUX_ERROR,
+ "Could not read %s: %m.\n",
+ ftsent->fts_path);
+ errno = error;
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ case FTS_NS:
+ error = errno;
+ errno = ftsent->fts_errno;
+ selinux_log(SELINUX_ERROR,
+ "Could not stat %s: %m.\n",
+ ftsent->fts_path);
+ errno = error;
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ case FTS_ERR:
+ error = errno;
+ errno = ftsent->fts_errno;
+ selinux_log(SELINUX_ERROR,
+ "Error on %s: %m.\n",
+ ftsent->fts_path);
+ errno = error;
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ case FTS_D:
+ if (state->sfsb.f_type == SYSFS_MAGIC &&
+ !selabel_partial_match(fc_sehandle,
+ ftsent->fts_path)) {
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ }
+
+ if (check_excluded(ftsent->fts_path)) {
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ }
- flags.nochange = (restorecon_flags &
+ if (state->setrestorecondigest) {
+ struct dir_hash_node *new_node = NULL;
+
+ if (check_context_match_for_dir(ftsent->fts_path,
+ &new_node,
+ state->error) &&
+ !state->ignore_digest) {
+ selinux_log(SELINUX_INFO,
+ "Skipping restorecon on directory(%s)\n",
+ ftsent->fts_path);
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ }
+
+ if (new_node && !state->error) {
+ if (!state->current) {
+ state->current = new_node;
+ state->head = state->current;
+ } else {
+ state->current->next = new_node;
+ state->current = new_node;
+ }
+ }
+ }
+ /* fall through */
+ default:
+ strcpy(ent_path, ftsent->fts_path);
+ ent_st = *ftsent->fts_statp;
+ if (state->parallel)
+ pthread_mutex_unlock(&state->mutex);
+
+ error = restorecon_sb(ent_path, &ent_st, &state->flags,
+ first);
+
+ if (state->parallel) {
+ pthread_mutex_lock(&state->mutex);
+ if (state->abort)
+ goto unlock;
+ }
+
+ state->error |= error;
+ first = false;
+ if (error && state->flags.abort_on_error) {
+ state->abort = true;
+ goto finish;
+ }
+ break;
+ }
+ }
+
+finish:
+ if (!state->saved_errno)
+ state->saved_errno = errno;
+unlock:
+ if (state->parallel)
+ pthread_mutex_unlock(&state->mutex);
+ return NULL;
+}
+
+static int selinux_restorecon_common(const char *pathname_orig,
+ unsigned int restorecon_flags,
+ size_t nthreads)
+{
+ struct rest_state state;
+
+ state.flags.nochange = (restorecon_flags &
SELINUX_RESTORECON_NOCHANGE) ? true : false;
- flags.verbose = (restorecon_flags &
+ state.flags.verbose = (restorecon_flags &
SELINUX_RESTORECON_VERBOSE) ? true : false;
- flags.progress = (restorecon_flags &
+ state.flags.progress = (restorecon_flags &
SELINUX_RESTORECON_PROGRESS) ? true : false;
- flags.mass_relabel = (restorecon_flags &
+ state.flags.mass_relabel = (restorecon_flags &
SELINUX_RESTORECON_MASS_RELABEL) ? true : false;
- flags.recurse = (restorecon_flags &
+ state.flags.recurse = (restorecon_flags &
SELINUX_RESTORECON_RECURSE) ? true : false;
- flags.set_specctx = (restorecon_flags &
+ state.flags.set_specctx = (restorecon_flags &
SELINUX_RESTORECON_SET_SPECFILE_CTX) ? true : false;
- flags.userealpath = (restorecon_flags &
+ state.flags.userealpath = (restorecon_flags &
SELINUX_RESTORECON_REALPATH) ? true : false;
- flags.set_xdev = (restorecon_flags &
+ state.flags.set_xdev = (restorecon_flags &
SELINUX_RESTORECON_XDEV) ? true : false;
- flags.add_assoc = (restorecon_flags &
+ state.flags.add_assoc = (restorecon_flags &
SELINUX_RESTORECON_ADD_ASSOC) ? true : false;
- flags.abort_on_error = (restorecon_flags &
+ state.flags.abort_on_error = (restorecon_flags &
SELINUX_RESTORECON_ABORT_ON_ERROR) ? true : false;
- flags.syslog_changes = (restorecon_flags &
+ state.flags.syslog_changes = (restorecon_flags &
SELINUX_RESTORECON_SYSLOG_CHANGES) ? true : false;
- flags.log_matches = (restorecon_flags &
+ state.flags.log_matches = (restorecon_flags &
SELINUX_RESTORECON_LOG_MATCHES) ? true : false;
- flags.ignore_noent = (restorecon_flags &
+ state.flags.ignore_noent = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_NOENTRY) ? true : false;
- flags.warnonnomatch = true;
- flags.conflicterror = (restorecon_flags &
+ state.flags.warnonnomatch = true;
+ state.flags.conflicterror = (restorecon_flags &
SELINUX_RESTORECON_CONFLICT_ERROR) ? true : false;
ignore_mounts = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_MOUNTS) ? true : false;
- bool ignore_digest = (restorecon_flags &
+ state.ignore_digest = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_DIGEST) ? true : false;
- bool setrestorecondigest = true;
+ state.setrestorecondigest = true;
+
+ state.head = NULL;
+ state.current = NULL;
+ state.abort = false;
+ state.error = 0;
+ state.saved_errno = 0;
struct stat sb;
- struct statfs sfsb;
- FTS *fts;
- FTSENT *ftsent;
char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname;
char *paths[2] = { NULL, NULL };
int fts_flags, error, sverrno;
- dev_t dev_num = 0;
struct dir_hash_node *current = NULL;
- struct dir_hash_node *head = NULL;
- int errno_tmp;
- if (flags.verbose && flags.progress)
- flags.verbose = false;
+ if (state.flags.verbose && state.flags.progress)
+ state.flags.verbose = false;
__selinux_once(fc_once, restorecon_init);
@@ -886,13 +1035,31 @@ int selinux_restorecon(const char *pathname_orig,
*/
if (selabel_no_digest ||
(restorecon_flags & SELINUX_RESTORECON_SKIP_DIGEST))
- setrestorecondigest = false;
+ state.setrestorecondigest = false;
+
+ if (!__pthread_supported) {
+ if (nthreads != 1) {
+ nthreads = 1;
+ selinux_log(SELINUX_WARNING,
+ "Threading functionality not available, falling back to 1 thread.");
+ }
+ } else if (nthreads == 0) {
+ long nproc = sysconf(_SC_NPROCESSORS_ONLN);
+
+ if (nproc > 0) {
+ nthreads = nproc;
+ } else {
+ nthreads = 1;
+ selinux_log(SELINUX_WARNING,
+ "Unable to detect CPU count, falling back to 1 thread.");
+ }
+ }
/*
* Convert passed-in pathname to canonical pathname by resolving
* realpath of containing dir, then appending last component name.
*/
- if (flags.userealpath) {
+ if (state.flags.userealpath) {
char *basename_cpy = strdup(pathname_orig);
if (!basename_cpy)
goto realpatherr;
@@ -937,7 +1104,7 @@ int selinux_restorecon(const char *pathname_orig,
paths[0] = pathname;
if (lstat(pathname, &sb) < 0) {
- if (flags.ignore_noent && errno == ENOENT) {
+ if (state.flags.ignore_noent && errno == ENOENT) {
free(pathdnamer);
free(pathname);
return 0;
@@ -952,21 +1119,21 @@ int selinux_restorecon(const char *pathname_orig,
/* Skip digest if not a directory */
if (!S_ISDIR(sb.st_mode))
- setrestorecondigest = false;
+ state.setrestorecondigest = false;
- if (!flags.recurse) {
+ if (!state.flags.recurse) {
if (check_excluded(pathname)) {
error = 0;
goto cleanup;
}
- error = restorecon_sb(pathname, &sb, &flags);
+ error = restorecon_sb(pathname, &sb, &state.flags, true);
goto cleanup;
}
/* Obtain fs type */
- memset(&sfsb, 0, sizeof sfsb);
- if (!S_ISLNK(sb.st_mode) && statfs(pathname, &sfsb) < 0) {
+ memset(&state.sfsb, 0, sizeof(state.sfsb));
+ if (!S_ISLNK(sb.st_mode) && statfs(pathname, &state.sfsb) < 0) {
selinux_log(SELINUX_ERROR,
"statfs(%s) failed: %m\n",
pathname);
@@ -975,21 +1142,21 @@ int selinux_restorecon(const char *pathname_orig,
}
/* Skip digest on in-memory filesystems and /sys */
- if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC ||
- sfsb.f_type == SYSFS_MAGIC)
- setrestorecondigest = false;
+ if (state.sfsb.f_type == RAMFS_MAGIC || state.sfsb.f_type == TMPFS_MAGIC ||
+ state.sfsb.f_type == SYSFS_MAGIC)
+ state.setrestorecondigest = false;
- if (flags.set_xdev)
+ if (state.flags.set_xdev)
fts_flags = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV;
else
fts_flags = FTS_PHYSICAL | FTS_NOCHDIR;
- fts = fts_open(paths, fts_flags, NULL);
- if (!fts)
+ state.fts = fts_open(paths, fts_flags, NULL);
+ if (!state.fts)
goto fts_err;
- ftsent = fts_read(fts);
- if (!ftsent)
+ state.ftsent_first = fts_read(state.fts);
+ if (!state.ftsent_first)
goto fts_err;
/*
@@ -1001,106 +1168,66 @@ int selinux_restorecon(const char *pathname_orig,
* directories with a different device number when the FTS_XDEV flag
* is set (from http://marc.info/?l=selinux&m=124688830500777&w=2).
*/
- dev_num = ftsent->fts_statp->st_dev;
+ state.dev_num = state.ftsent_first->fts_statp->st_dev;
- error = 0;
- do {
- /* If the FTS_XDEV flag is set and the device is different */
- if (flags.set_xdev && ftsent->fts_statp->st_dev != dev_num)
- continue;
+ if (nthreads == 1) {
+ state.parallel = false;
+ selinux_restorecon_thread(&state);
+ } else {
+ size_t i;
+ pthread_t self = pthread_self();
+ pthread_t *threads = NULL;
- switch (ftsent->fts_info) {
- case FTS_DC:
- selinux_log(SELINUX_ERROR,
- "Directory cycle on %s.\n",
- ftsent->fts_path);
- errno = ELOOP;
- error = -1;
- goto out;
- case FTS_DP:
- continue;
- case FTS_DNR:
- errno_tmp = errno;
- errno = ftsent->fts_errno;
- selinux_log(SELINUX_ERROR,
- "Could not read %s: %m.\n",
- ftsent->fts_path);
- errno = errno_tmp;
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_NS:
- errno_tmp = errno;
- errno = ftsent->fts_errno;
- selinux_log(SELINUX_ERROR,
- "Could not stat %s: %m.\n",
- ftsent->fts_path);
- errno = errno_tmp;
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_ERR:
- errno_tmp = errno;
- errno = ftsent->fts_errno;
- selinux_log(SELINUX_ERROR,
- "Error on %s: %m.\n",
- ftsent->fts_path);
- errno = errno_tmp;
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_D:
- if (sfsb.f_type == SYSFS_MAGIC &&
- !selabel_partial_match(fc_sehandle,
- ftsent->fts_path)) {
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- }
+ pthread_mutex_init(&state.mutex, NULL);
- if (check_excluded(ftsent->fts_path)) {
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
+ threads = calloc(nthreads - 1, sizeof(*threads));
+ if (!threads)
+ goto oom;
+
+ state.parallel = true;
+ /*
+ * Start (nthreads - 1) threads - the main thread is going to
+ * take part, too.
+ */
+ for (i = 0; i < nthreads - 1; i++) {
+ if (pthread_create(&threads[i], NULL,
+ selinux_restorecon_thread, &state)) {
+ /*
+ * If any thread fails to be created, just mark
+ * it as such and let the successfully created
+ * threads do the job. In the worst case the
+ * main thread will do everything, but that's
+ * still better than to give up.
+ */
+ threads[i] = self;
}
+ }
- if (setrestorecondigest) {
- struct dir_hash_node *new_node = NULL;
+ /* Let's join in on the fun! */
+ selinux_restorecon_thread(&state);
- if (check_context_match_for_dir(ftsent->fts_path,
- &new_node,
- error) &&
- !ignore_digest) {
- selinux_log(SELINUX_INFO,
- "Skipping restorecon on directory(%s)\n",
- ftsent->fts_path);
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- }
-
- if (new_node && !error) {
- if (!current) {
- current = new_node;
- head = current;
- } else {
- current->next = new_node;
- current = current->next;
- }
- }
- }
- /* fall through */
- default:
- error |= restorecon_sb(ftsent->fts_path,
- ftsent->fts_statp, &flags);
- if (flags.warnonnomatch)
- flags.warnonnomatch = false;
- if (error && flags.abort_on_error)
- goto out;
- break;
+ /* Now wait for all threads to finish. */
+ for (i = 0; i < nthreads - 1; i++) {
+ /* Skip threads that failed to be created. */
+ if (pthread_equal(threads[i], self))
+ continue;
+ pthread_join(threads[i], NULL);
}
- } while ((ftsent = fts_read(fts)) != NULL);
+ free(threads);
+
+ pthread_mutex_destroy(&state.mutex);
+ }
+
+ error = state.error;
+ if (state.saved_errno)
+ goto out;
/*
* Labeling successful. Write partial match digests for subdirectories.
* TODO: Write digest upon FTS_DP if no error occurs in its descents.
*/
- if (setrestorecondigest && !flags.nochange && !error) {
- current = head;
+ if (state.setrestorecondigest && !state.flags.nochange && !error) {
+ current = state.head;
while (current != NULL) {
if (setxattr(current->path,
RESTORECON_PARTIAL_MATCH_DIGEST,
@@ -1115,22 +1242,21 @@ int selinux_restorecon(const char *pathname_orig,
}
out:
- if (flags.progress && flags.mass_relabel)
+ if (state.flags.progress && state.flags.mass_relabel)
fprintf(stdout, "\r%s 100.0%%\n", pathname);
- sverrno = errno;
- (void) fts_close(fts);
- errno = sverrno;
+ (void) fts_close(state.fts);
+ errno = state.saved_errno;
cleanup:
- if (flags.add_assoc) {
- if (flags.verbose)
+ if (state.flags.add_assoc) {
+ if (state.flags.verbose)
filespec_eval();
filespec_destroy();
}
free(pathdnamer);
free(pathname);
- current = head;
+ current = state.head;
while (current != NULL) {
struct dir_hash_node *next = current->next;
@@ -1164,6 +1290,26 @@ fts_err:
goto cleanup;
}
+
+/*
+ * Public API
+ */
+
+/* selinux_restorecon(3) - Main function that is responsible for labeling */
+int selinux_restorecon(const char *pathname_orig,
+ unsigned int restorecon_flags)
+{
+ return selinux_restorecon_common(pathname_orig, restorecon_flags, 1);
+}
+
+/* selinux_restorecon_parallel(3) - Parallel version of selinux_restorecon(3) */
+int selinux_restorecon_parallel(const char *pathname_orig,
+ unsigned int restorecon_flags,
+ size_t nthreads)
+{
+ return selinux_restorecon_common(pathname_orig, restorecon_flags, nthreads);
+}
+
/* selinux_restorecon_set_sehandle(3) is called to set the global fc handle */
void selinux_restorecon_set_sehandle(struct selabel_handle *hndl)
{
diff --git a/libselinux/src/selinuxswig_python.i b/libselinux/src/selinuxswig_python.i
index 4c73bf92df96..17e03b9e36a5 100644
--- a/libselinux/src/selinuxswig_python.i
+++ b/libselinux/src/selinuxswig_python.i
@@ -20,7 +20,7 @@ DISABLED = -1
PERMISSIVE = 0
ENFORCING = 1
-def restorecon(path, recursive=False, verbose=False, force=False):
+def restorecon(path, recursive=False, verbose=False, force=False, nthreads=1):
""" Restore SELinux context on a given path
Arguments:
@@ -32,6 +32,8 @@ def restorecon(path, recursive=False, verbose=False, force=False):
force -- Force reset of context to match file_context for customizable files,
and the default file context, changing the user, role, range portion as well
as the type (default False)
+ nthreads -- The number of threads to use during relabeling, or 0 to use as many
+ threads as there are online CPU cores (default 1)
"""
restorecon_flags = SELINUX_RESTORECON_IGNORE_DIGEST | SELINUX_RESTORECON_REALPATH
@@ -41,7 +43,7 @@ def restorecon(path, recursive=False, verbose=False, force=False):
restorecon_flags |= SELINUX_RESTORECON_VERBOSE
if force:
restorecon_flags |= SELINUX_RESTORECON_SET_SPECFILE_CTX
- selinux_restorecon(os.path.expanduser(path), restorecon_flags)
+ selinux_restorecon_parallel(os.path.expanduser(path), restorecon_flags, nthreads)
def chcon(path, context, recursive=False):
""" Set the SELinux context on a given path """
diff --git a/libselinux/src/selinuxswig_python_exception.i b/libselinux/src/selinuxswig_python_exception.i
index 237ea69ad5f5..a02f4923a1e7 100644
--- a/libselinux/src/selinuxswig_python_exception.i
+++ b/libselinux/src/selinuxswig_python_exception.i
@@ -1183,6 +1183,14 @@
}
}
+%exception selinux_restorecon_parallel {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
%exception selinux_restorecon_set_alt_rootpath {
$action
if (result < 0) {
--
2.33.1

View File

@ -1,29 +0,0 @@
From 9456297275987dedefe2e8ad508360be9d9f9e7f Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Tue, 23 Nov 2021 11:31:08 +0100
Subject: [PATCH] libselinux: Fix selinux_restorecon_parallel symbol version
selinux_restorecon_parallel was originally proposed before 3.3, but it
was merged after release so it will be introduced in version 3.4.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
libselinux/src/libselinux.map | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/src/libselinux.map b/libselinux/src/libselinux.map
index d138e951ef0d..4acf1caacb55 100644
--- a/libselinux/src/libselinux.map
+++ b/libselinux/src/libselinux.map
@@ -241,7 +241,7 @@ LIBSELINUX_1.0 {
*;
};
-LIBSELINUX_3.3 {
+LIBSELINUX_3.4 {
global:
selinux_restorecon_parallel;
} LIBSELINUX_1.0;
--
2.33.1

View File

@ -1,38 +0,0 @@
From b1a27a010e12a88eb93c507018d7cb0b5ad84951 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:51 +0200
Subject: [PATCH] libselinux: selinux_restorecon: mark local variable static
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `dir_xattr_list` is only used inside `selinux_restorecon.c`.
selinux_restorecon.c:65:19: warning: no previous extern declaration for non-static variable 'dir_xattr_list' [-Wmissing-variable-declarations]
struct dir_xattr *dir_xattr_list;
^
selinux_restorecon.c:65:1: note: declare 'static' if the variable is not intended to be used outside of this translation unit
struct dir_xattr *dir_xattr_list;
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/selinux_restorecon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 63fb8dc53c28..249c361fa988 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -62,7 +62,7 @@ static uint64_t fc_count = 0; /* Number of files processed so far */
static uint64_t efile_count; /* Estimated total number of files */
/* Store information on directories with xattr's. */
-struct dir_xattr *dir_xattr_list;
+static struct dir_xattr *dir_xattr_list;
static struct dir_xattr *dir_xattr_last;
/* restorecon_flags for passing to restorecon_sb() */
--
2.32.0.rc1

View File

@ -1,51 +0,0 @@
From b31e50f9d00c3dcd68a63228e206e1f6099570f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:53 +0200
Subject: [PATCH] libselinux: selabel_get_digests_all_partial_matches: free
memory after FTS_D block
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Free all memory from `selabel_get_digests_all_partial_matches()` in case
of success and failure.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
.../utils/selabel_get_digests_all_partial_matches.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c
index 0c2edc67771d..e28833d2ce97 100644
--- a/libselinux/utils/selabel_get_digests_all_partial_matches.c
+++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c
@@ -128,7 +128,7 @@ int main(int argc, char **argv)
printf("No SHA1 digest available for: %s\n",
ftsent->fts_path);
printf("as file_context entry is \"<<none>>\"\n");
- break;
+ goto cleanup;
}
printf("The file_context entries for: %s\n",
@@ -149,11 +149,11 @@ int main(int argc, char **argv)
xattr_digest[i]);
printf("%s\n", sha1_buf);
}
-
- free(xattr_digest);
- free(calculated_digest);
- free(sha1_buf);
}
+ cleanup:
+ free(xattr_digest);
+ free(calculated_digest);
+ free(sha1_buf);
break;
}
default:
--
2.32.0.rc1

View File

@ -1,34 +0,0 @@
From 809615a5b204e3e8426d363d62717785401618ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:55 +0200
Subject: [PATCH] libselinux: getconlist: free memory on multiple level
arguments
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Do not leak memory if the program argument `l` got passed more than
once.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/utils/getconlist.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libselinux/utils/getconlist.c b/libselinux/utils/getconlist.c
index 76654b75151a..0bb2846937ca 100644
--- a/libselinux/utils/getconlist.c
+++ b/libselinux/utils/getconlist.c
@@ -26,6 +26,7 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "l:")) > 0) {
switch (opt) {
case 'l':
+ free(level);
level = strdup(optarg);
if (!level) {
fprintf(stderr, "memory allocation failure: %d(%s)\n",
--
2.32.0.rc1

View File

@ -1,42 +0,0 @@
From b7e0f5dce75c4c7a1333f5231a61af58f225b725 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:57 +0200
Subject: [PATCH] libselinux: exclude_non_seclabel_mounts(): drop unused
variable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `num` is never read from.
Found by clang-analyer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/selinux_restorecon.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 249c361fa988..6fb9e1ff486d 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -230,7 +230,6 @@ static int exclude_non_seclabel_mounts(void)
struct utsname uts;
FILE *fp;
size_t len;
- ssize_t num;
int index = 0, found = 0, nfile = 0;
char *mount_info[4];
char *buf = NULL, *item;
@@ -245,7 +244,7 @@ static int exclude_non_seclabel_mounts(void)
if (!fp)
return 0;
- while ((num = getline(&buf, &len, fp)) != -1) {
+ while (getline(&buf, &len, fp) != -1) {
found = 0;
index = 0;
item = strtok(buf, " ");
--
2.32.0.rc1

View File

@ -1,34 +0,0 @@
From d924809116c2a6215d31c08a6a03e4c429f48fc0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:10:59 +0200
Subject: [PATCH] libselinux: context_new(): drop dead assignment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `i` is not used inside this loop, and it later
unconditionally set to 0.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/context.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/src/context.c b/libselinux/src/context.c
index ce4258806c53..b2144c7cf76c 100644
--- a/libselinux/src/context.c
+++ b/libselinux/src/context.c
@@ -37,7 +37,7 @@ context_t context_new(const char *str)
}
n->current_str = n->component[0] = n->component[1] = n->component[2] =
n->component[3] = 0;
- for (i = count = 0, p = str; *p; p++) {
+ for (count = 0, p = str; *p; p++) {
switch (*p) {
case ':':
count++;
--
2.32.0.rc1

View File

@ -1,33 +0,0 @@
From 36354ac7585d6e40873cbb74602f651d3d8a4d86 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:01 +0200
Subject: [PATCH] libselinux: label_x::init(): drop dead assignment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `lineno` is only used in the preceding loop and is always
set prior that to 0.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_x.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c
index 9674529931a7..e9fa063fafff 100644
--- a/libselinux/src/label_x.c
+++ b/libselinux/src/label_x.c
@@ -146,7 +146,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
if (process_line(path, line_buf, pass, ++lineno, rec))
goto finish;
}
- lineno = 0;
if (pass == 0) {
if (data->nspec == 0) {
--
2.32.0.rc1

View File

@ -1,33 +0,0 @@
From 0bceb02d526b73495d8ce0a85170aba46d2760bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:03 +0200
Subject: [PATCH] libselinux: label_media::init(): drop dead assignment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `lineno` is only used in the preceding loop and it always
set prior that to 0.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_media.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c
index d202e5d5ab83..eb27deaf510e 100644
--- a/libselinux/src/label_media.c
+++ b/libselinux/src/label_media.c
@@ -119,7 +119,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
if (process_line(path, line_buf, pass, ++lineno, rec))
goto finish;
}
- lineno = 0;
if (pass == 0) {
if (data->nspec == 0) {
--
2.32.0.rc1

View File

@ -1,33 +0,0 @@
From 39eb347b3c557b65085b007ce5fab93f1f32ddd1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:05 +0200
Subject: [PATCH] libselinux: setexecfilecon(): drop dead assignment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The variable `rc` is always unconditionally assigned by the next call of
`setexeccon()` and never read in between.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/setexecfilecon.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libselinux/src/setexecfilecon.c b/libselinux/src/setexecfilecon.c
index e72ba0d98880..2c6505a96a48 100644
--- a/libselinux/src/setexecfilecon.c
+++ b/libselinux/src/setexecfilecon.c
@@ -37,7 +37,6 @@ int setexecfilecon(const char *filename, const char *fallback_type)
newcon = strdup(context_str(con));
if (!newcon)
goto out;
- rc = 0;
}
rc = setexeccon(newcon);
--
2.32.0.rc1

View File

@ -1,51 +0,0 @@
From 4c3c1c070a5f4b80cfdd45e261e4517c76c19448 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:07 +0200
Subject: [PATCH] libselinux: getdefaultcon: free memory on multiple same
arguments
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Do not leak memory if program arguments get specified more than once.
Found by clang-anlyzer.
getdefaultcon.c:52:3: warning: Potential leak of memory pointed to by 'level' [unix.Malloc]
fprintf(stderr,
^~~~~~~~~~~~~~~
getdefaultcon.c:52:3: warning: Potential leak of memory pointed to by 'role' [unix.Malloc]
fprintf(stderr,
^~~~~~~~~~~~~~~
getdefaultcon.c:52:3: warning: Potential leak of memory pointed to by 'service' [unix.Malloc]
fprintf(stderr,
^~~~~~~~~~~~~~~
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/utils/getdefaultcon.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c
index 96a5a8c23656..957c1cb2e307 100644
--- a/libselinux/utils/getdefaultcon.c
+++ b/libselinux/utils/getdefaultcon.c
@@ -28,12 +28,15 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) {
switch (opt) {
case 'l':
+ free(level);
level = strdup(optarg);
break;
case 'r':
+ free(role);
role = strdup(optarg);
break;
case 's':
+ free(service);
service = strdup(optarg);
break;
case 'v':
--
2.32.0.rc1

View File

@ -1,62 +0,0 @@
From cc1db9c34d00faf0ee13c152194fcd4e675ab753 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:09 +0200
Subject: [PATCH] libselinux: store_stem(): do not free possible non-heap
object
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
GCC 11 complains:
In file included from label_file.c:24:
In function store_stem,
inlined from load_mmap at label_file.c:277:12,
inlined from process_file at label_file.c:551:5:
label_file.h:289:25: error: free called on pointer *mmap_area.next_addr with nonzero offset 4 [-Werror=free-nonheap-object]
289 | free(buf);
| ^~~~~~~~~
Free the pointer on failure at the caller instead of inside `store_stem()`.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_file.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index baed3341b6b3..9f6337012216 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -286,7 +286,6 @@ static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
tmp_arr = realloc(data->stem_arr,
sizeof(*tmp_arr) * alloc_stems);
if (!tmp_arr) {
- free(buf);
return -1;
}
data->alloc_stems = alloc_stems;
@@ -308,6 +307,7 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
int stem_len = get_stem_from_spec(buf);
int stemid;
char *stem;
+ int r;
if (!stem_len)
return -1;
@@ -321,7 +321,11 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
if (!stem)
return -1;
- return store_stem(data, stem, stem_len);
+ r = store_stem(data, stem, stem_len);
+ if (r < 0)
+ free(stem);
+
+ return r;
}
/* This will always check for buffer over-runs and either read the next entry
--
2.32.0.rc1

View File

@ -1,39 +0,0 @@
From 0732233fd29c20dd54450803d9113916d3b6e28d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:11 +0200
Subject: [PATCH] libselinux: matchmediacon(): close file on error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by Infer.
matchmediacon.c:25: error: Resource Leak
resource of type `_IO_FILE` acquired to `return` by call to `fopen()` at line 21, column 16 is not released after line 25, column 4.
23. while (!feof_unlocked(infile)) {
24. if (!fgets_unlocked(current_line, sizeof(current_line), infile)) {
25. return -1;
^
26. }
27. if (current_line[strlen(current_line) - 1])
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/matchmediacon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libselinux/src/matchmediacon.c b/libselinux/src/matchmediacon.c
index 23d01af476d2..d3d9504348e1 100644
--- a/libselinux/src/matchmediacon.c
+++ b/libselinux/src/matchmediacon.c
@@ -22,6 +22,7 @@ int matchmediacon(const char *media, char ** con)
return -1;
while (!feof_unlocked(infile)) {
if (!fgets_unlocked(current_line, sizeof(current_line), infile)) {
+ fclose(infile);
return -1;
}
if (current_line[strlen(current_line) - 1])
--
2.32.0.rc1

View File

@ -1,53 +0,0 @@
From 99bb0488069bc6ce8deb629b4f5e2cde73160e7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:13 +0200
Subject: [PATCH] libselinux: init_selinux_config(): free resources on error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by Infer.
selinux_config.c:181: error: Resource Leak
resource of type `_IO_FILE` acquired by call to `fopen()` at line 165, column 7 is not released after line 181, column 6.
179. type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
180. if (!type)
181. return;
^
182. end = type + strlen(type) - 1;
183. while ((end > type) &&
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/selinux_config.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index 6c5238953cb1..97f81a8b61ce 100644
--- a/libselinux/src/selinux_config.c
+++ b/libselinux/src/selinux_config.c
@@ -177,8 +177,11 @@ static void init_selinux_config(void)
if (!strncasecmp(buf_p, SELINUXTYPETAG,
sizeof(SELINUXTYPETAG) - 1)) {
type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
- if (!type)
+ if (!type) {
+ free(line_buf);
+ fclose(fp);
return;
+ }
end = type + strlen(type) - 1;
while ((end > type) &&
(isspace(*end) || iscntrl(*end))) {
@@ -187,6 +190,8 @@ static void init_selinux_config(void)
}
if (setpolicytype(type) != 0) {
free(type);
+ free(line_buf);
+ fclose(fp);
return;
}
free(type);
--
2.32.0.rc1

View File

@ -1,48 +0,0 @@
From 20feb894849305cdc4c786ced44f397804e308f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:15 +0200
Subject: [PATCH] libselinux: label_file::init(): do not pass NULL to strdup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If any of the build flags `BUILD_HOST` or `ANDROID` is set and the
caller did not pass an option of type `SELABEL_OPT_PATH`, the variable
`path` might be not set.
Add a check to avoid calling `strdup()` with a NULL pointer.
Found by cppcheck.
src/label_file.c:759:26: warning: Possible null pointer dereference: path [nullPointer]
rec->spec_file = strdup(path);
^
src/label_file.c:713:21: note: Assignment 'path=NULL', assigned value is 0
const char *path = NULL;
^
src/label_file.c:759:26: note: Null pointer dereference
rec->spec_file = strdup(path);
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_file.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index b080fcf1305b..4268b52c84cc 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -756,6 +756,10 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
}
#endif
+
+ if (!path)
+ goto finish;
+
rec->spec_file = strdup(path);
/*
--
2.32.0.rc1

View File

@ -1,80 +0,0 @@
From 640a5a732e3d836c3a0f6992d4085468a486b4b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:17 +0200
Subject: [PATCH] libselinux: matchpathcon: free memory on realloc failure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In case `realloc()` fails and returns NULL, free the passed array,
instead of just setting the size helper variables to 0.
Also free the string contents in `free_array_elts()` of the array
`con_array`, instead of just the array of pointers.
Found by cppcheck.
src/matchpathcon.c:86:4: error: Common realloc mistake: 'con_array' nulled but not freed upon failure [memleakOnRealloc]
con_array = (char **)realloc(con_array, sizeof(char*) *
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/matchpathcon.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index 9e1fab593266..075a3fb3ffcb 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -78,17 +78,30 @@ static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_key_t destructor_key;
static int destructor_key_initialized = 0;
+static void free_array_elts(void)
+{
+ int i;
+ for (i = 0; i < con_array_used; i++)
+ free(con_array[i]);
+ free(con_array);
+
+ con_array_size = con_array_used = 0;
+ con_array = NULL;
+}
+
static int add_array_elt(char *con)
{
+ char **tmp;
if (con_array_size) {
while (con_array_used >= con_array_size) {
con_array_size *= 2;
- con_array = (char **)realloc(con_array, sizeof(char*) *
+ tmp = (char **)realloc(con_array, sizeof(char*) *
con_array_size);
- if (!con_array) {
- con_array_size = con_array_used = 0;
+ if (!tmp) {
+ free_array_elts();
return -1;
}
+ con_array = tmp;
}
} else {
con_array_size = 1000;
@@ -105,13 +118,6 @@ static int add_array_elt(char *con)
return con_array_used++;
}
-static void free_array_elts(void)
-{
- con_array_size = con_array_used = 0;
- free(con_array);
- con_array = NULL;
-}
-
void set_matchpathcon_invalidcon(int (*f) (const char *p, unsigned l, char *c))
{
myinvalidcon = f;
--
2.32.0.rc1

View File

@ -1,36 +0,0 @@
From 370b39312430af8fc0426cc91a287def5d253771 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:19 +0200
Subject: [PATCH] libselinux: label_db::db_init(): open file with CLOEXEC mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Open the file stream with the `e` flag, so that the underlying file
descriptor gets closed on an exec in a potential sibling thread.
Also drop the flag `b`, since it is ignored on POSIX systems.
Found by clang-tidy.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_db.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c
index fba96c92299f..94c05c6d4397 100644
--- a/libselinux/src/label_db.c
+++ b/libselinux/src/label_db.c
@@ -277,7 +277,7 @@ db_init(const struct selinux_opt *opts, unsigned nopts,
if (!path)
path = selinux_sepgsql_context_path();
- if ((filp = fopen(path, "rb")) == NULL) {
+ if ((filp = fopen(path, "re")) == NULL) {
free(catalog);
return NULL;
}
--
2.32.0.rc1

View File

@ -1,73 +0,0 @@
From 2fb2a289325e63b603124741ba12a0dedad5fae0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:22 +0200
Subject: [PATCH] libselinux: drop redundant casts to the same type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by clang-tidy.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/audit2why.c | 2 +-
libselinux/src/avc_sidtab.c | 2 +-
libselinux/src/is_customizable_type.c | 2 +-
libselinux/src/selinux_restorecon.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
index d56b56eb2a1a..029f874f4702 100644
--- a/libselinux/src/audit2why.c
+++ b/libselinux/src/audit2why.c
@@ -275,7 +275,7 @@ static int __policy_init(const char *init_path)
}
sepol_bool_iterate(avc->handle, avc->policydb,
- load_booleans, (void *)NULL);
+ load_booleans, NULL);
/* Initialize the sidtab for subsequent use by sepol_context_to_sid
and sepol_compute_av_reason. */
diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c
index 8dc875608762..8c81cf65d2ef 100644
--- a/libselinux/src/avc_sidtab.c
+++ b/libselinux/src/avc_sidtab.c
@@ -56,7 +56,7 @@ int sidtab_insert(struct sidtab *s, const char * ctx)
rc = -1;
goto out;
}
- newctx = (char *) strdup(ctx);
+ newctx = strdup(ctx);
if (!newctx) {
rc = -1;
avc_free(newnode);
diff --git a/libselinux/src/is_customizable_type.c b/libselinux/src/is_customizable_type.c
index 92876f4d9371..1b17860c3622 100644
--- a/libselinux/src/is_customizable_type.c
+++ b/libselinux/src/is_customizable_type.c
@@ -38,7 +38,7 @@ static int get_customizable_type_list(char *** retlist)
while (fgets_unlocked(buf, selinux_page_size, fp)
&& i < ctr) {
buf[strlen(buf) - 1] = 0;
- list[i] = (char *) strdup(buf);
+ list[i] = strdup(buf);
if (!list[i]) {
unsigned int j;
for (j = 0; j < i; j++)
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 6fb9e1ff486d..999aa924ba32 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -1152,7 +1152,7 @@ void selinux_restorecon_set_sehandle(struct selabel_handle *hndl)
unsigned char *fc_digest;
size_t num_specfiles, fc_digest_len;
- fc_sehandle = (struct selabel_handle *) hndl;
+ fc_sehandle = hndl;
if (!fc_sehandle)
return;
--
2.32.0.rc1

View File

@ -1,60 +0,0 @@
From 215d83598c180055cddd3787bcb6e1abe8a416d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:24 +0200
Subject: [PATCH] libselinux: sidtab_sid_stats(): unify parameter name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by clang-tidy.
libselinux/src/avc_sidtab.h:32:6: warning: function 'sidtab_sid_stats' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]
void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) ;
^
libselinux/src/avc_sidtab.c:103:6: note: the definition seen here
void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
^
libselinux/src/avc_sidtab.h:32:6: note: differing parameters are named here: ('s'), in definition: ('h')
void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) ;
^ ~
h
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/avc_sidtab.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c
index 8c81cf65d2ef..f179d8558a45 100644
--- a/libselinux/src/avc_sidtab.c
+++ b/libselinux/src/avc_sidtab.c
@@ -100,7 +100,7 @@ sidtab_context_to_sid(struct sidtab *s,
return rc;
}
-void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
+void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen)
{
int i, chain_len, slots_used, max_chain_len;
struct sidtab_node *cur;
@@ -108,7 +108,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
slots_used = 0;
max_chain_len = 0;
for (i = 0; i < SIDTAB_SIZE; i++) {
- cur = h->htable[i];
+ cur = s->htable[i];
if (cur) {
slots_used++;
chain_len = 0;
@@ -124,7 +124,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
snprintf(buf, buflen,
"%s: %u SID entries and %d/%d buckets used, longest "
- "chain length %d\n", avc_prefix, h->nel, slots_used,
+ "chain length %d\n", avc_prefix, s->nel, slots_used,
SIDTAB_SIZE, max_chain_len);
}
--
2.32.0.rc1

View File

@ -1,42 +0,0 @@
From 027fa1706e3804577132e835b22965ceca761b31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:26 +0200
Subject: [PATCH] libselinux: regex: unify parameter names
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use the same parameter names as in the header `regex.h`.
Found by clang-tidy.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/regex.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c
index 770bc3ea1310..73987d9f1063 100644
--- a/libselinux/src/regex.c
+++ b/libselinux/src/regex.c
@@ -319,7 +319,7 @@ char const *regex_version(void)
}
int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex,
- int unused __attribute__((unused)), bool *regex_compiled)
+ int do_load_precompregex __attribute__((unused)), bool *regex_compiled)
{
int rc;
uint32_t entry_len;
@@ -387,7 +387,7 @@ static inline pcre_extra *get_pcre_extra(struct regex_data *regex)
}
int regex_writef(struct regex_data *regex, FILE *fp,
- int unused __attribute__((unused)))
+ int do_write_precompregex __attribute__((unused)))
{
int rc;
size_t len;
--
2.32.0.rc1

View File

@ -1,35 +0,0 @@
From 700c829317e44f194f69c785144423d10b14c21d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Mon, 3 May 2021 17:11:31 +0200
Subject: [PATCH] libselinux: label_file.c: fix indent
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by clang-tidy.
libselinux/src/label_file.c:374:4: warning: different indentation for 'if' and corresponding 'else' [readability-misleading-indentation]
else
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
libselinux/src/label_file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 4268b52c84cc..56f499faef97 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -371,7 +371,7 @@ end_arch_check:
if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
spec->stem_id = -1;
- else
+ else
spec->stem_id = stem_map[stem_id];
/* retrieve the hasMetaChars bit */
--
2.32.0.rc1

View File

@ -1,39 +0,0 @@
From 44760b7ef671b83eb7d1168b07d849d1d887b54f Mon Sep 17 00:00:00 2001
From: Petr Lautrbach <plautrba@redhat.com>
Date: Tue, 25 May 2021 14:55:02 +0200
Subject: [PATCH] libselinux/setexecfilecon: remove unnecessary if
Fixes:
Error: IDENTICAL_BRANCHES (CWE-398): [#def2]
libselinux/src/setexecfilecon.c:46: implicit_else: The code from the above if-then branch is identical to the code after the if statement.
libselinux/src/setexecfilecon.c:44: identical_branches: The same code is executed when the condition "rc < 0" is true or false, because the code in the if-then branch and after the if statement is identical. Should the if statement be removed?
# 42|
# 43| rc = setexeccon(newcon);
# 44|-> if (rc < 0)
# 45| goto out;
# 46| out:
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
libselinux/src/setexecfilecon.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/libselinux/src/setexecfilecon.c b/libselinux/src/setexecfilecon.c
index 2c6505a96a48..669d426065f6 100644
--- a/libselinux/src/setexecfilecon.c
+++ b/libselinux/src/setexecfilecon.c
@@ -40,9 +40,8 @@ int setexecfilecon(const char *filename, const char *fallback_type)
}
rc = setexeccon(newcon);
- if (rc < 0)
- goto out;
- out:
+
+ out:
if (rc < 0 && security_getenforce() == 0)
rc = 0;
--
2.32.0.rc1

View File

@ -1,30 +1,22 @@
%define ruby_inc %(pkg-config --cflags ruby)
%define libsepolver 3.3-1
%define libsepolver 3.4-1
Summary: SELinux library and simple utilities
Name: libselinux
Version: 3.3
Release: 2%{?dist}
Version: 3.4
Release: 1%{?dist}
License: Public Domain
# https://github.com/SELinuxProject/selinux/wiki/Releases
Source0: https://github.com/SELinuxProject/selinux/releases/download/3.3/libselinux-3.3.tar.gz
Source0: https://github.com/SELinuxProject/selinux/releases/download/3.4/libselinux-3.4.tar.gz
Source1: selinuxconlist.8
Source2: selinuxdefcon.8
Url: https://github.com/SELinuxProject/selinux/wiki
# $ git clone https://github.com/fedora-selinux/selinux.git
# $ cd selinux
# $ git format-patch -N 3.3 -- libselinux
# $ git format-patch -N 3.4 -- libselinux
# $ i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done
# Patch list start
Patch0001: 0001-Use-SHA-2-instead-of-SHA-1.patch
Patch0002: 0002-label_file-fix-a-data-race.patch
Patch0003: 0003-selinux_restorecon-simplify-fl_head-allocation-by-us.patch
Patch0004: 0004-selinux_restorecon-protect-file_spec-list-with-a-mut.patch
Patch0005: 0005-libselinux-make-selinux_log-thread-safe.patch
Patch0006: 0006-libselinux-make-is_context_customizable-thread-safe.patch
Patch0007: 0007-selinux_restorecon-add-a-global-mutex-to-synchronize.patch
Patch0008: 0008-selinux_restorecon-introduce-selinux_restorecon_para.patch
Patch0009: 0009-libselinux-Fix-selinux_restorecon_parallel-symbol-ve.patch
# Patch list end
BuildRequires: gcc make
BuildRequires: ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre2-devel xz-devel
@ -221,6 +213,9 @@ rm -f %{buildroot}%{_mandir}/man8/togglesebool*
%{ruby_vendorarchdir}/selinux.so
%changelog
* Thu May 19 2022 Petr Lautrbach <plautrba@redhat.com> - 3.4-1
- SELinux userspace 3.4 release
* Mon Nov 29 2021 Petr Lautrbach <plautrba@redhat.com> - 3.3-2
- Introduce selinux_restorecon_parallel(3)

View File

@ -1 +1 @@
SHA512 (libselinux-3.3.tar.gz) = 9a89c05ea4b17453168a985ece93ba6d6c4127916e657c46d4135eb59a1f6408faa0802cc2e49187defbde5247d659037beee089877affbab3eab6af3433696c
SHA512 (libselinux-3.4.tar.gz) = 7ffa6d2159d2333d836bde3f75dfc78a278283b66ae1e441c178371adb6f463aa6f2d62439079e2068d1135c39dd2b367b001d917c0bdc6871a73630919ef81e