[PATCH 2/2] libselinux: fix infinite loop and missing errno in partial <<none>> lookup

Petr Matyas <[email protected]> Wed, 29 Jul 2026 15:14:13 +0200
Newsgroups org.kernel.vger.selinux
Message-ID <[email protected]>
lookup_check_node() has a do-while loop that iterates over matching
literal specs. When partial=true and a matching spec has <<none>>
context the loop body used `continue` to skip to the next entry.
In a do-while, `continue` jumps to the condition rather than the
loop increment, so `literal_idx` was never advanced and the loop
spun forever.

Fix by explicitly incrementing literal_idx before the continue so
the loop moves to the next literal spec as intended.

Additionally, set errno = ENOENT before continuing so that callers
which test errno after a NULL return (such as the selabel_file_text
fuzzer) see a valid error code. Without this, lookup_all() returned
NULL with errno still 0, violating the expected contract that a NULL
result is always accompanied by a non-zero errno.

Signed-off-by: Petr Matyas <[email protected]>
---
 libselinux/src/label_file.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 63066228..d716e0f1 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -1936,10 +1936,12 @@ lookup_check_node(struct spec_node *node, const char *key, uint8_t file_kind,
 
 						if (strcmp(lspec->lr.ctx_raw,
 							   "<<none>>") == 0) {
-							if (partial)
+							errno = ENOENT;
+							if (partial) {
+								literal_idx++;
 								continue;
+							}
 
-							errno = ENOENT;
 							goto fail;
 						}
 
@@ -2025,10 +2027,10 @@ lookup_check_node(struct spec_node *node, const char *key, uint8_t file_kind,
 
 				if (strcmp(rspec->lr.ctx_raw, "<<none>>") ==
 				    0) {
+					errno = ENOENT;
 					if (partial)
 						continue;
 
-					errno = ENOENT;
 					goto fail;
 				}
 
-- 
2.55.0