SELinux userspace 3.4 release
Resolves: rhbz#2079283
This commit is contained in:
		
							parent
							
								
									80c6e6516d
								
							
						
					
					
						commit
						f6f4dc5d0b
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -221,3 +221,4 @@ libselinux-2.0.96.tgz | |||||||
| /libselinux-3.3-rc2.tar.gz | /libselinux-3.3-rc2.tar.gz | ||||||
| /libselinux-3.3-rc3.tar.gz | /libselinux-3.3-rc3.tar.gz | ||||||
| /libselinux-3.3.tar.gz | /libselinux-3.3.tar.gz | ||||||
|  | /libselinux-3.4.tar.gz | ||||||
|  | |||||||
| @ -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> | From: Petr Lautrbach <plautrba@redhat.com> | ||||||
| Date: Fri, 30 Jul 2021 14:14:37 +0200 | Date: Fri, 30 Jul 2021 14:14:37 +0200 | ||||||
| Subject: [PATCH] Use SHA-2 instead of SHA-1 | Subject: [PATCH] Use SHA-2 instead of SHA-1 | ||||||
|  | Content-type: text/plain | ||||||
| 
 | 
 | ||||||
| The use of SHA-1 in RHEL9 is deprecated | 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/Makefile                       |   2 +- | ||||||
|  libselinux/src/label_file.c                   |  40 +-- |  libselinux/src/label_file.c                   |  40 +-- | ||||||
|  libselinux/src/label_internal.h               |  10 +- |  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/selinux_restorecon.c           |  24 +- | ||||||
|  libselinux/src/sha1.c                         | 220 ------------- |  libselinux/src/sha1.c                         | 220 ------------- | ||||||
|  libselinux/src/sha1.h                         |  85 ----- |  libselinux/src/sha1.h                         |  85 ----- | ||||||
| @ -22,7 +23,7 @@ The use of SHA-1 in RHEL9 is deprecated | |||||||
|  libselinux/src/sha256.h                       |  89 ++++++ |  libselinux/src/sha256.h                       |  89 ++++++ | ||||||
|  libselinux/utils/selabel_digest.c             |  26 +- |  libselinux/utils/selabel_digest.c             |  26 +- | ||||||
|  .../selabel_get_digests_all_partial_matches.c |  28 +- |  .../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.c | ||||||
|  delete mode 100644 libselinux/src/sha1.h |  delete mode 100644 libselinux/src/sha1.h | ||||||
|  create mode 100644 libselinux/src/sha256.c |  create mode 100644 libselinux/src/sha256.c | ||||||
| @ -50,10 +51,10 @@ index e8983606d93b..a35d84d63b0a 100644 | |||||||
|   * @num_specfiles: number of specfiles in the list. |   * @num_specfiles: number of specfiles in the list. | ||||||
|   * |   * | ||||||
| diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h
 | 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
 | --- a/libselinux/include/selinux/restorecon.h
 | ||||||
| +++ b/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 |   * restorecon_flags options | ||||||
|   */ |   */ | ||||||
|  /* |  /* | ||||||
| @ -83,7 +84,7 @@ index 56a008f00df0..5f7c42533d0e 100644 | |||||||
|  with the number of entries in |  with the number of entries in | ||||||
|  .IR num_specfiles . |  .IR num_specfiles . | ||||||
| diff --git a/libselinux/man/man3/selabel_open.3 b/libselinux/man/man3/selabel_open.3
 | 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
 | --- a/libselinux/man/man3/selabel_open.3
 | ||||||
| +++ b/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
 | @@ -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) |  .BR selabel_digest (3) | ||||||
|  . |  . | ||||||
| diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.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
 | --- a/libselinux/man/man3/selinux_restorecon.3
 | ||||||
| +++ b/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 |  .B SELINUX_RESTORECON_RECURSE | ||||||
|  has been set (for descending through directories), then |  has been set (for descending through directories), then | ||||||
|  .BR selinux_restorecon () |  .BR selinux_restorecon () | ||||||
| @ -108,7 +109,7 @@ index ad637406a30d..c4576fe79ff6 100644 | |||||||
|  .BR selabel_get_digests_all_partial_matches (3) |  .BR selabel_get_digests_all_partial_matches (3) | ||||||
|  to an extended attribute of |  to an extended attribute of | ||||||
|  .IR security.sehash |  .IR security.sehash | ||||||
| @@ -47,7 +47,7 @@ will take place.
 | @@ -55,7 +55,7 @@ will take place.
 | ||||||
|  .br |  .br | ||||||
|  The |  The | ||||||
|  .IR restorecon_flags |  .IR restorecon_flags | ||||||
| @ -117,7 +118,7 @@ index ad637406a30d..c4576fe79ff6 100644 | |||||||
|  .RS |  .RS | ||||||
|  .B SELINUX_RESTORECON_SKIP_DIGEST |  .B SELINUX_RESTORECON_SKIP_DIGEST | ||||||
|  .br |  .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. |  entries. | ||||||
|  .sp |  .sp | ||||||
|  .B SELINUX_RESTORECON_IGNORE_DIGEST |  .B SELINUX_RESTORECON_IGNORE_DIGEST | ||||||
| @ -128,7 +129,7 @@ index ad637406a30d..c4576fe79ff6 100644 | |||||||
|  .IR security.sehash |  .IR security.sehash | ||||||
|  extended attribute once relabeling has been completed successfully provided the |  extended attribute once relabeling has been completed successfully provided the | ||||||
|  .B SELINUX_RESTORECON_NOCHANGE |  .B SELINUX_RESTORECON_NOCHANGE | ||||||
| @@ -84,7 +84,7 @@ default specfile context.
 | @@ -95,7 +95,7 @@ default specfile context.
 | ||||||
|  .sp |  .sp | ||||||
|  .B SELINUX_RESTORECON_RECURSE |  .B SELINUX_RESTORECON_RECURSE | ||||||
|  change file and directory labels recursively (descend directories) |  change file and directory labels recursively (descend directories) | ||||||
| @ -137,8 +138,8 @@ index ad637406a30d..c4576fe79ff6 100644 | |||||||
|  extended attribute as described in the |  extended attribute as described in the | ||||||
|  .B NOTES |  .B NOTES | ||||||
|  section. |  section. | ||||||
| @@ -158,7 +158,7 @@ to treat conflicting specifications, such as where two hardlinks for the
 | @@ -184,7 +184,7 @@ walk, the specfile entries SHA1 digest will not have been written to the
 | ||||||
|  same inode have different contexts, as errors. |  extended attribute. | ||||||
|  .RE |  .RE | ||||||
|  .sp |  .sp | ||||||
| -The behavior regarding the checking and updating of the SHA1 digest described
 | -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 |  above is the default behavior. It is possible to change this by first calling | ||||||
|  .BR selabel_open (3) |  .BR selabel_open (3) | ||||||
|  and not enabling the |  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 |  .B SELINUX_RESTORECON_RECURSE | ||||||
|  flag is set) |  flag is set) | ||||||
|  .BR selinux_restorecon () |  .BR selinux_restorecon () | ||||||
| @ -155,7 +156,7 @@ index ad637406a30d..c4576fe79ff6 100644 | |||||||
|  .BR selabel_get_digests_all_partial_matches (3) |  .BR selabel_get_digests_all_partial_matches (3) | ||||||
|  to an extended attribute named |  to an extended attribute named | ||||||
|  .IR security.sehash |  .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 () |  .BR selinux_restorecon () | ||||||
|  is run again with the |  is run again with the | ||||||
|  .B SELINUX_RESTORECON_RECURSE |  .B SELINUX_RESTORECON_RECURSE | ||||||
| @ -178,10 +179,10 @@ index c56326814b94..098c840fc59b 100644 | |||||||
|  .BR selabel_open (3) |  .BR selabel_open (3) | ||||||
|  must be called specifying the required |  must be called specifying the required | ||||||
| diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
 | diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
 | ||||||
| index 52c40f018f51..674a5ed3a6f8 100644
 | index 04bf4f240168..222c3fa2d7c3 100644
 | ||||||
| --- a/libselinux/src/Makefile
 | --- a/libselinux/src/Makefile
 | ||||||
| +++ b/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 |  	-DBUILD_HOST | ||||||
|  SRCS= callbacks.c freecon.c label.c label_file.c \ |  SRCS= callbacks.c freecon.c label.c label_file.c \ | ||||||
|  	label_backends_android.c regex.c label_support.c \ |  	label_backends_android.c regex.c label_support.c \ | ||||||
| @ -191,10 +192,10 @@ index 52c40f018f51..674a5ed3a6f8 100644 | |||||||
|  LABEL_BACKEND_ANDROID=y |  LABEL_BACKEND_ANDROID=y | ||||||
|  endif |  endif | ||||||
| diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
 | 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
 | --- a/libselinux/src/label_file.c
 | ||||||
| +++ b/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 |   * 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. |   * digest will always be returned. The caller must free any returned digests. | ||||||
|   */ |   */ | ||||||
|  static bool get_digests_all_partial_matches(struct selabel_handle *rec, |  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, |  					    uint8_t **xattr_digest, | ||||||
|  					    size_t *digest_len) |  					    size_t *digest_len) | ||||||
|  { |  { | ||||||
| @ -254,7 +255,7 @@ index 2e28d0474d73..c1306c9979e7 100644 | |||||||
|  		return true; |  		return true; | ||||||
|   |   | ||||||
|  	return false; |  	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; |  		return false; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @ -327,31 +328,44 @@ index 782c6aa8cc0c..304e8d96490a 100644 | |||||||
|  }; |  }; | ||||||
|   |   | ||||||
| diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c
 | 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
 | --- a/libselinux/src/label_support.c
 | ||||||
| +++ b/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. */ |  /* Once all the specfiles are in the hash_buf, generate the hash. */ | ||||||
|  void  digest_gen_hash(struct selabel_digest *digest) |  void  digest_gen_hash(struct selabel_digest *digest) | ||||||
|  { |  { | ||||||
| -	Sha1Context context;
 | -	Sha1Context context;
 | ||||||
| +	Sha256Context 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) |  	if (!digest) | ||||||
|  		return; |  		return; | ||||||
|   |   | ||||||
| -	Sha1Initialise(&context);
 | -	Sha1Initialise(&context);
 | ||||||
| -	Sha1Update(&context, digest->hashbuf, digest->hashbuf_size);
 |  | ||||||
| -	Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
 |  | ||||||
| +	Sha256Initialise(&context);
 | +	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);
 | +	Sha256Finalise(&context, (SHA256_HASH *)digest->digest);
 | ||||||
|  	free(digest->hashbuf); |  	free(digest->hashbuf); | ||||||
|  	digest->hashbuf = NULL; |  	digest->hashbuf = NULL; | ||||||
|  	return; |  	return; | ||||||
| diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
 | 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
 | --- a/libselinux/src/selinux_restorecon.c
 | ||||||
| +++ b/libselinux/src/selinux_restorecon.c
 | +++ b/libselinux/src/selinux_restorecon.c
 | ||||||
| @@ -37,7 +37,7 @@
 | @@ -37,7 +37,7 @@
 | ||||||
| @ -363,16 +377,16 @@ index 04d956504952..100c77108a27 100644 | |||||||
|   |   | ||||||
|  #define STAR_COUNT 1024 |  #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, |  static int add_xattr_entry(const char *directory, bool delete_nonmatch, | ||||||
|  			   bool delete_all) |  			   bool delete_all) | ||||||
|  { |  { | ||||||
| -	char *sha1_buf = NULL;
 | -	char *sha1_buf = NULL;
 | ||||||
| +	char *sha256_buf = NULL;
 | +	char *sha256_buf = NULL;
 | ||||||
|  	size_t i, digest_len = 0; |  	size_t i, digest_len = 0; | ||||||
|  	int rc, digest_result; |  	int rc; | ||||||
|  	bool match; |  	enum digest_result digest_result; | ||||||
| @@ -316,15 +316,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 | @@ -329,15 +329,15 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
 | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
|  	/* Convert entry to a hex encoded string. */ |  	/* Convert entry to a hex encoded string. */ | ||||||
| @ -391,7 +405,7 @@ index 04d956504952..100c77108a27 100644 | |||||||
|   |   | ||||||
|  	digest_result = match ? MATCH : NOMATCH; |  	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. */ |  	/* Now add entries to link list. */ | ||||||
|  	new_entry = malloc(sizeof(struct dir_xattr)); |  	new_entry = malloc(sizeof(struct dir_xattr)); | ||||||
|  	if (!new_entry) { |  	if (!new_entry) { | ||||||
| @ -400,7 +414,7 @@ index 04d956504952..100c77108a27 100644 | |||||||
|  		goto oom; |  		goto oom; | ||||||
|  	} |  	} | ||||||
|  	new_entry->next = NULL; |  	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); |  	new_entry->directory = strdup(directory); | ||||||
|  	if (!new_entry->directory) { |  	if (!new_entry->directory) { | ||||||
|  		free(new_entry); |  		free(new_entry); | ||||||
| @ -419,7 +433,7 @@ index 04d956504952..100c77108a27 100644 | |||||||
|  		goto oom; |  		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; |  		dir_xattr_last = new_entry; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @ -428,7 +442,7 @@ index 04d956504952..100c77108a27 100644 | |||||||
|  	return 0; |  	return 0; | ||||||
|   |   | ||||||
|  oom: |  oom: | ||||||
| @@ -741,7 +741,7 @@ err:
 | @@ -781,7 +781,7 @@ err:
 | ||||||
|   |   | ||||||
|  struct dir_hash_node { |  struct dir_hash_node { | ||||||
|  	char *path; |  	char *path; | ||||||
| @ -437,7 +451,7 @@ index 04d956504952..100c77108a27 100644 | |||||||
|  	struct dir_hash_node *next; |  	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, |  			if (setxattr(current->path, | ||||||
|  			    RESTORECON_PARTIAL_MATCH_DIGEST, |  			    RESTORECON_PARTIAL_MATCH_DIGEST, | ||||||
|  			    current->digest, |  			    current->digest, | ||||||
| @ -1159,7 +1173,7 @@ index 000000000000..406ed869cd82 | |||||||
| +        SHA256_HASH*        Digest          // [in]
 | +        SHA256_HASH*        Digest          // [in]
 | ||||||
| +    );
 | +    );
 | ||||||
| diff --git a/libselinux/utils/selabel_digest.c b/libselinux/utils/selabel_digest.c
 | 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
 | --- a/libselinux/utils/selabel_digest.c
 | ||||||
| +++ b/libselinux/utils/selabel_digest.c
 | +++ b/libselinux/utils/selabel_digest.c
 | ||||||
| @@ -15,8 +15,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
 | @@ -15,8 +15,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
 | ||||||
| @ -1240,7 +1254,7 @@ index 49408a0ba8d8..67befadd23c5 100644 | |||||||
|  	selabel_close(hnd); |  	selabel_close(hnd); | ||||||
|  	return rc; |  	return rc; | ||||||
| diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c
 | 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
 | --- a/libselinux/utils/selabel_get_digests_all_partial_matches.c
 | ||||||
| +++ b/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)
 | @@ -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 selabel_handle *hnd; | ||||||
|  	struct selinux_opt selabel_option[] = { |  	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, |  							 &xattr_digest, | ||||||
|  							 &digest_len); |  							 &digest_len); | ||||||
|   |   | ||||||
| @ -1297,7 +1311,7 @@ index e28833d2ce97..900f018c0091 100644 | |||||||
|  					       ftsent->fts_path); |  					       ftsent->fts_path); | ||||||
|  					printf("as file_context entry is \"<<none>>\"\n"); |  					printf("as file_context entry is \"<<none>>\"\n"); | ||||||
|  					goto cleanup; |  					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); |  				       ftsent->fts_path); | ||||||
|   |   | ||||||
|  				for (i = 0; i < digest_len; i++) |  				for (i = 0; i < digest_len; i++) | ||||||
| @ -1329,5 +1343,5 @@ index e28833d2ce97..900f018c0091 100644 | |||||||
|  		} |  		} | ||||||
|  		default: |  		default: | ||||||
| -- 
 | -- 
 | ||||||
| 2.32.0 | 2.36.1 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -1,30 +1,22 @@ | |||||||
| %define ruby_inc %(pkg-config --cflags ruby) | %define ruby_inc %(pkg-config --cflags ruby) | ||||||
| %define libsepolver 3.3-1 | %define libsepolver 3.4-1 | ||||||
| 
 | 
 | ||||||
| Summary: SELinux library and simple utilities | Summary: SELinux library and simple utilities | ||||||
| Name: libselinux | Name: libselinux | ||||||
| Version: 3.3 | Version: 3.4 | ||||||
| Release: 2%{?dist} | Release: 1%{?dist} | ||||||
| License: Public Domain | License: Public Domain | ||||||
| # https://github.com/SELinuxProject/selinux/wiki/Releases | # 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 | Source1: selinuxconlist.8 | ||||||
| Source2: selinuxdefcon.8 | Source2: selinuxdefcon.8 | ||||||
| Url: https://github.com/SELinuxProject/selinux/wiki | Url: https://github.com/SELinuxProject/selinux/wiki | ||||||
| # $ git clone https://github.com/fedora-selinux/selinux.git | # $ git clone https://github.com/fedora-selinux/selinux.git | ||||||
| # $ cd selinux | # $ 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 | # $ i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done | ||||||
| # Patch list start | # Patch list start | ||||||
| Patch0001: 0001-Use-SHA-2-instead-of-SHA-1.patch | 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 | # Patch list end | ||||||
| BuildRequires: gcc make | BuildRequires: gcc make | ||||||
| BuildRequires: ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre2-devel xz-devel | 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 | %{ruby_vendorarchdir}/selinux.so | ||||||
| 
 | 
 | ||||||
| %changelog | %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 | * Mon Nov 29 2021 Petr Lautrbach <plautrba@redhat.com> - 3.3-2 | ||||||
| - Introduce selinux_restorecon_parallel(3) | - Introduce selinux_restorecon_parallel(3) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sources
									
									
									
									
									
								
							| @ -1 +1 @@ | |||||||
| SHA512 (libselinux-3.3.tar.gz) = 9a89c05ea4b17453168a985ece93ba6d6c4127916e657c46d4135eb59a1f6408faa0802cc2e49187defbde5247d659037beee089877affbab3eab6af3433696c | SHA512 (libselinux-3.4.tar.gz) = 7ffa6d2159d2333d836bde3f75dfc78a278283b66ae1e441c178371adb6f463aa6f2d62439079e2068d1135c39dd2b367b001d917c0bdc6871a73630919ef81e | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user