possible bug in structure-type attribute assignement in freeradius-4 alpha

Stacy stacy at bcc.com.uz
Tue Nov 11 08:48:05 UTC 2025


Hello freeradius dev team!

Recently, I've tried to use freeradius as a DHCPv6 server
because my previous experience with freeradius as a DHCPv4 server was quite good.
I know that DHCPv6 support is in alpha stage, but decided to try anyway.
I've used "radiusd - DEVELOPER BUILD - FreeRADIUS version 4.0.65535" release.

During my experiments I've hit a bug - radiusd crashes trying to reply to
the dhcpv6 relay-forward request. I've conducted some investigations and 
found approximate area where this bug may lurk. To the best of my guess -
something wrong happens when unlang tries to assign structure-type attribute 
in the "send Relay-Reply" section. Looks like it doesn't allocate or 
otherwise prepare memory for assigned structure. Then subsequent assignement 
to the structure's attributes causes sigsegv.

Namely, I'm talking about this piece of config:

-----8<--------------8<-----------------------------
send Relay-Reply {
         #
         #  All replies MUST include a Server-ID option
         #
         &reply.Server-ID.DUID += ::UUID
         &reply.Server-ID.DUID.UUID.Value := 0x00000000000000000000000000000000
}
-----8<--------------8<-----------------------------

Crashes sease if I comment out the "&reply.Server-ID.DUID.UUID.Value := 0x00000000000000000000000000000000" 
assignement, but reply packet gets malformed - the Server-ID attribute
is sent incompletely over the wire. This supports my guesses about incomplete allocation of
struct attributes.

Could you please clarify, where to look in the code to try to pinpoint this bug?
Or if this bug is already known to you, could you please suggest a patch?

Please find attached some of debugging info:
-----------------8<--------------------------------8<-------------------
Ready to process requests
proto_dhcpv6_udp - Received Relay-Forward XID 00002a07 length 169 dhcpv6_udp server <skipped> port 547 on interface eth0.10
Worker - Resetting cleanup timer to +30
(0)  dhcpv6 {
(0)    Received Relay-Forward XID 00002a07 from <skipped> to <skipped>:547 via eth0.10 
(0)      Packet-Type = Relay-Forward
(0)      Hop-Count = 0
(0)      Relay-Link-Address = <skipped>
(0)      Relay-Peer-Address = <skipped>
(0)      Relay-Message {
(0)        Packet-Type = Solicit
(0)        Transaction-ID = 0x1835ef
(0)        Client-ID {
(0)          DUID = UUID
(0)          DUID.UUID {
(0)            Value = <skipped>
(0)          }
(0)        }
(0)        IA-NA {
(0)          IAID = 4278191680
(0)          T1 = 0
(0)          T2 = 0
(0)        }
(0)        Option-Request = DNS-Servers
(0)        Option-Request = Domain-List
(0)        Option-Request = SNTP-Servers
(0)        Option-Request = Client-FQDN
(0)        Option-Request = SOL-Max-RT
(0)        Option-Request = INF-Max-RT
(0)        Elapsed-Time = 0
(0)        Rapid-Commit = yes
(0)        Client-FQDN {
(0)          Reserved = 0
(0)          No-Server-Update = no
(0)          Server-Override = no
(0)          Server-Update = yes
(0)          Domain-Name = "rei"
(0)        }
(0)      }
(0)      Client-Link-Layer {
(0)        Type = Ethernet
(0)        Type.Ethernet {
(0)          Address = <skipped>
(0)        }
(0)      }
(0)      Interface-ID = <skipped>
(0)      Relay-Agent-Remote-ID {
(0)        Vendor = 9
(0)        Value = <skipped>
(0)      }
(0)    recv Relay-Forward {
(0)      ok (ok)
(0)    } # recv Relay-Forward (ok)
(0)    dhcpv6 - send Relay-Reply {
(0)    dhcpv6 -   &reply.Server-ID.DUID += 4

Thread 1 "radiusd" received signal SIGSEGV, Segmentation fault.


0x00007ffff7db5fd1 in fr_dict_attr_cmp (a=0x7ffff604db10, b=0x8a91a0bdbdbdbd) at src/freeradius-devel/util/dict.h:419
419             if (a->flags.is_unknown | a->flags.is_raw | b->flags.is_unknown | b->flags.is_raw) {
(gdb) bt
#0  0x00007ffff7db5fd1 in fr_dict_attr_cmp (a=0x7ffff604db10, b=0x8a91a0bdbdbdbd) at src/freeradius-devel/util/dict.h:419
#1  0x00007ffff7db653e in _tmpl_cursor_child_next (list=0x12735b0, curr=0x0, uctx=0x126cf50) at src/lib/server/tmpl_dcursor.c:61
#2  0x00007ffff7f1cf67 in dcursor_next (cursor=0x126cf78, iter=0x7ffff7db64fa <_tmpl_cursor_child_next>, current=0x0) at src/freeradius-devel/util/dcursor.h:168
#3  0x00007ffff7f1d071 in fr_dcursor_next (cursor=0x126cf78) at src/freeradius-devel/util/dcursor.h:289
#4  0x00007ffff7f1d1ec in _fr_dcursor_init (cursor=0x126cf78, head=0x12735b0, iter=0x7ffff7db64fa <_tmpl_cursor_child_next>, peek=0x0, iter_uctx=0x126cf50,
     insert=0x7ffff7f1f915 <_pair_list_dcursor_insert>, remove=0x7ffff7f1f97b <_pair_list_dcursor_remove>, mod_uctx=0x12735a8, is_const=false)
     at src/freeradius-devel/util/dcursor.h:769
#5  0x00007ffff7f1fc46 in _fr_pair_dcursor_iter_init (cursor=0x126cf78, list=0x12735a8, iter=0x7ffff7db64fa <_tmpl_cursor_child_next>, uctx=0x126cf50, is_const=false)
     at src/lib/util/pair.c:1076
#6  0x00007ffff7db6abd in _tmpl_cursor_pair_init (cc=0x7fffffffdbd0, ar=0xf15970, list=0x12735a8, list_ctx=0x1273570) at src/lib/server/tmpl_dcursor.c:103
#7  _tmpl_cursor_next (list=0x126dd60, curr=0x1273570, uctx=0x7fffffffdbd0) at src/lib/server/tmpl_dcursor.c:231
#8  0x00007ffff7f1cf67 in dcursor_next (cursor=0x7fffffffdb80, iter=0x7ffff7db6569 <_tmpl_cursor_next>, current=0x0) at src/freeradius-devel/util/dcursor.h:168
#9  0x00007ffff7f1d071 in fr_dcursor_next (cursor=0x7fffffffdb80) at src/freeradius-devel/util/dcursor.h:289
#10 0x00007ffff7f1d1ec in _fr_dcursor_init (cursor=0x7fffffffdb80, head=0x126dd60, iter=0x7ffff7db6569 <_tmpl_cursor_next>, peek=0x0, iter_uctx=0x7fffffffdbd0,
     insert=0x7ffff7f1f915 <_pair_list_dcursor_insert>, remove=0x7ffff7f1f97b <_pair_list_dcursor_remove>, mod_uctx=0x126dd58, is_const=false)
     at src/freeradius-devel/util/dcursor.h:769
#11 0x00007ffff7f1fc46 in _fr_pair_dcursor_iter_init (cursor=0x7fffffffdb80, list=0x126dd58, iter=0x7ffff7db6569 <_tmpl_cursor_next>, uctx=0x7fffffffdbd0, is_const=false)
     at src/lib/util/pair.c:1076
#12 0x00007ffff7db7023 in tmpl_dcursor_init_relative (err=0x7fffffffdcac, ctx=0x126ca80, cc=0x7fffffffdbd0, cursor=0x7fffffffdb80, request=0x12693f0, list=0x126dd20,
     vpt=0xf15560, build=0x0, uctx=0x0) at src/lib/server/tmpl_dcursor.c:348
#13 0x00007ffff7db71c4 in _tmpl_dcursor_init (err=0x7fffffffdcac, ctx=0x126ca80, cc=0x7fffffffdbd0, cursor=0x7fffffffdb80, request=0x12693f0, vpt=0xf15560, build=0x0,
     uctx=0x0) at src/lib/server/tmpl_dcursor.c:413
#14 0x00007ffff7c8646c in check_rhs (request=0x12693f0, state=0x126ca80, current=0x126ca98) at src/lib/unlang/edit.c:878
#15 0x00007ffff7c86cd7 in expand_rhs (request=0x12693f0, state=0x126ca80, current=0x126ca98) at src/lib/unlang/edit.c:1067
#16 0x00007ffff7c885b5 in check_lhs (request=0x12693f0, state=0x126ca80, current=0x126ca98) at src/lib/unlang/edit.c:1290
#17 0x00007ffff7c88bf8 in expand_lhs (request=0x12693f0, state=0x126ca80, current=0x126ca98) at src/lib/unlang/edit.c:1460
#18 0x00007ffff7c88c60 in process_edit (p_result=0x12695dc, request=0x12693f0, frame=0x1269808) at src/lib/unlang/edit.c:1492
#19 0x00007ffff7c88fc5 in unlang_edit_state_init (p_result=0x12695dc, request=0x12693f0, frame=0x1269808) at src/lib/unlang/edit.c:1578
#20 0x00007ffff7c8e3d5 in frame_eval (priority=0x12695d8, result=0x12695dc, frame=0x1269808, request=0x12693f0) at src/lib/unlang/interpret.c:598
#21 unlang_interpret (request=0x12693f0) at src/lib/unlang/interpret.c:793
#22 0x00007ffff7c482c8 in worker_run_request (start=..., worker=0xff44e0) at src/lib/io/worker.c:1321
#23 fr_worker_post_event (el=0xff7a80, now=..., uctx=0xff44e0) at src/lib/io/worker.c:1555
#24 0x00007ffff7f0437b in fr_event_service (el=0xff7a80) at src/lib/util/event.c:2725
#25 0x00007ffff7f04465 in fr_event_loop (el=0xff7a80) at src/lib/util/event.c:2765
#26 0x00007ffff7d8bbd4 in main_loop_start () at src/lib/server/main_loop.c:214
#27 0x0000000000406997 in main (argc=2, argv=0x7fffffffe4f8) at src/bin/radiusd.c:986


(gdb) print *a
$1 = {dict = 0x8a91a0, name = 0x7ffff604db80 "UUID", name_len = 4, attr = 4, depth = 3, last_child_attr = 16777216, type = FR_TYPE_STRUCT, parent = 0x7ffff6037c00,
   next = 0x0, fixup = 0x0, flags = {is_root = 0, is_unknown = 0, is_raw = 0, is_alias = 0, internal = 0, array = 0, is_known_width = 0, has_value = 0, is_unsigned = 0,
     counter = 0, name_only = 0, secret = 0, extra = 0, local = 0, subtype = 0 '\000', length = 0 '\000', type_size = 0 '\000'}, ext = "\r\n\000\000\000\000\f"}
(gdb) print *b
Cannot access memory at address 0x8a91a0bdbdbdbd
(gdb)


----------------
And this is what happens if I comment out the 
"&reply.Server-ID.DUID.UUID.Value := 0x00000000000000000000000000000000" 
string:


------------8<--------------------------8<-----------------------------
Ready to process requests
proto_dhcpv6_udp - Received Relay-Forward XID 00002a07 length 169 dhcpv6_udp server <skipped>  port 547 on interface eth0.10
Worker - Resetting cleanup timer to +30
(0)  dhcpv6 {
(0)    Received Relay-Forward XID 00002a07 from <skipped>  to <skipped>  via eth0.10 
(0)      Packet-Type = Relay-Forward
(0)      Hop-Count = 0
(0)      Relay-Link-Address = <skipped> 
(0)      Relay-Peer-Address = <skipped> 
(0)      Relay-Message {
(0)        Packet-Type = Solicit
(0)        Transaction-ID = 0x03cc7c
(0)        Client-ID {
(0)          DUID = UUID
(0)          DUID.UUID {
(0)            Value = <skipped> 
(0)          }
(0)        }
(0)        IA-NA {
(0)          IAID = 4278191680
(0)          T1 = 0
(0)          T2 = 0
(0)        }
(0)        Option-Request = DNS-Servers
(0)        Option-Request = Domain-List
(0)        Option-Request = SNTP-Servers
(0)        Option-Request = Client-FQDN
(0)        Option-Request = SOL-Max-RT
(0)        Option-Request = INF-Max-RT
(0)        Elapsed-Time = 0
(0)        Rapid-Commit = yes
(0)        Client-FQDN {
(0)          Reserved = 0
(0)          No-Server-Update = no
(0)          Server-Override = no
(0)          Server-Update = yes
(0)          Domain-Name = "rei"
(0)        }
(0)      }
(0)      Client-Link-Layer {
(0)        Type = Ethernet
(0)        Type.Ethernet {
(0)          Address = <skipped> 
(0)        }
(0)      }
(0)      Interface-ID = <skipped> 
(0)      Relay-Agent-Remote-ID {
(0)        Vendor = 9
(0)        Value = <skipped> 
(0)      }
(0)    recv Relay-Forward {
(0)      ok (ok)
(0)    } # recv Relay-Forward (ok)
(0)    dhcpv6 - send Relay-Reply {
(0)    dhcpv6 -   &reply.Server-ID.DUID += 4
(0)    dhcpv6 - } # send Relay-Reply (noop)
(0)    dhcpv6 - Running 'send Relay-Reply' from file /opt/radius_ipv6-4.0_alpha1/etc/raddb/sites-enabled/dhcpv6
(0)    dhcpv6 - send Relay-Reply {
(0)    dhcpv6 -   &reply.Server-ID.DUID += 4
(0)    dhcpv6 - } # send Relay-Reply (noop)
(0)    Sending Relay-Reply XID 00002a07 from <skipped>  to <skipped>  via eth0.10 
(0)      Server-ID {     <---------------SEE - NO VALUE----------------
(0)        DUID = 8
(0)      }
(0)      Packet-Type = Relay-Reply
(0)      Hop-Count = 0
(0)      Relay-Link-Address = <skipped> 
(0)      Relay-Peer-Address = <skipped> 
(0)      Interface-ID = <skipped> 
(0)    dhcpv6 (noop)
(0)  } # dhcpv6 (noop)
(0)  Done request
(0)  Finished request
proto_dhcpv6_udp - cleaning up request in 5.000000s
------------8<-----------------------8<-----------------

The above reply is malformed - this can be seen looking into the wireshark 
analyze of replied packet:

Internet Protocol Version 6, Src: <skipped> , Dst: <skipped>
     0110 .... = Version: 6
     .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
         .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
         .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
     .... .... .... 0111 0000 0001 1010 0000 = Flow Label: 0x701a0
     Payload Length: 64
     Next Header: UDP (17)
     Hop Limit: 64
     Source: <skipped>
     Destination: <skipped> 
User Datagram Protocol, Src Port: 547, Dst Port: 547
     Source Port: 547
     Destination Port: 547
     Length: 64
     Checksum: 0x03eb [unverified]
     [Checksum Status: Unverified]
     [Stream index: 0]
DHCPv6
     Message type: Relay-reply (13)
     Hopcount: 0
     Link address: <skipped>
     Peer address: <skipped>
     Server Identifier
         Option: Server Identifier (2)
         Length: 2
         Value: 0004
         DUID: 0004
         DUID Type: Universally Unique IDentifier (UUID) (4)
         [Expert Info (Error/Malformed): DUID: malformed option]	<-------------MALFORMED!!!!
             [DUID: malformed option]
             [Severity level: Error]
             [Group: Malformed]
     Interface-Id
         Option: Interface-Id (18)
         Length: 12
         Value: <skipped>
         Interface-ID: <skipped>


----------------8<-----------------------8<-----------------------


With best regards,
Stacy.



More information about the Freeradius-Devel mailing list