<feed xmlns='http://www.w3.org/2005/Atom'>
<title>accel-ppp.git/accel-pppd/ipv6, branch master</title>
<subtitle>High performance PPTP/L2TP/SSTP/PPPoE/IPoE server for Linux (mirror of https://github.com/accel-ppp/accel-ppp.git)
</subtitle>
<id>https://git.amelek.net/accel-ppp/accel-ppp.git/atom?h=master</id>
<link rel='self' href='https://git.amelek.net/accel-ppp/accel-ppp.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/'/>
<updated>2026-09-07T19:08:04+00:00</updated>
<entry>
<title>dhcpv6: reject malformed options and bound relay replies</title>
<updated>2026-09-07T19:08:04+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-09-07T19:08:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=0648072b19b509fa4ca90664344371d1cfa01935'/>
<id>urn:sha1:0648072b19b509fa4ca90664344371d1cfa01935</id>
<content type='text'>
Reject duplicate Rapid-Commit/AFTR options, validate AFTR labels, and
limit relay nesting. Measure reply space from the allocation, propagate
allocation failure through reply builders, and encode relay lengths correctly.

Adapted from Ritika Chopra's accel-ppp-ng PR #40, T8473/T8474/T8475.
Upstream already has the status, AFTR-printing and inner relay bounds fixes.

Co-authored-by: Ritika Chopra &lt;r.chopra@vyos.io&gt;
</content>
</entry>
<entry>
<title>utils: centralize unaligned integer accessors</title>
<updated>2026-09-01T06:08:47+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-09-01T06:08:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=7d4f8524f57ba0ac77e47171bebfc0370df667b1'/>
<id>urn:sha1:7d4f8524f57ba0ac77e47171bebfc0370df667b1</id>
<content type='text'>
</content>
</entry>
<entry>
<title>dhcpv6: validate option and relay boundaries</title>
<updated>2026-09-01T05:55:54+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-09-01T05:47:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=94993558dab2b79107c1d67c5cdb081604dada71'/>
<id>urn:sha1:94993558dab2b79107c1d67c5cdb081604dada71</id>
<content type='text'>
Enforce fixed option prefixes centrally, bound nested relay messages to their declared payload, require one valid Relay-Message, and decode ORO and diagnostic fields without unaligned or oversized reads.
</content>
</entry>
<entry>
<title>Merge pull request #351 from nuclearcat/various-fixes-on-compiler-warnings</title>
<updated>2026-09-01T05:52:55+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-09-01T05:52:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=57ae56148c5519b9207ede623098d3cfad5211b8'/>
<id>urn:sha1:57ae56148c5519b9207ede623098d3cfad5211b8</id>
<content type='text'>
Various fixes on compiler warnings</content>
</entry>
<entry>
<title>ipv6: assign DNS servers per session from RADIUS</title>
<updated>2026-08-12T07:42:35+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-04T15:39:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=58ef850d1705d88f006d761d32c55bde5205a27d'/>
<id>urn:sha1:58ef850d1705d88f006d761d32c55bde5205a27d</id>
<content type='text'>
The ipv6_nd and ipv6_dhcp modules could only advertise the DNS servers
configured in [ipv6-dns], the same set for every subscriber. RFC 6911
defines DNS-Server-IPv6-Address (attribute 169) for exactly this, and
the attribute was already in the shipped dictionary and in attr_defs.h;
nothing read it.

Give struct ap_session an ipv6_dns list, filled by the radius module
from that attribute, and have both modules advertise it when the session
has one: in the RDNSS option of the router advertisements, and in the
DNS_SERVERS option of DHCPv6 replies. Sessions without a list of their
own keep getting the configured servers, so nothing changes for anyone
not sending the attribute.

The selection is a single ipv6_dns_get() shared by both modules rather
than a copy in each: they already duplicate the whole [ipv6-dns] parser,
and two copies of a precedence rule are two chances to drift. It caps
what it returns, so neither the RDNSS option length (one byte, in units
of 8) nor the router advertisement buffer can be pushed around by what a
RADIUS server sends. The radius module caps at the same 3 servers as
[ipv6-dns] accepts and warns once when a reply carries more.

An Access-Accept which carries the attribute replaces the whole
previously assigned list rather than appending to it, so a re-authorized
session ends up with the servers of the latest reply and not with a
concatenation. One which does not carry it leaves the current list
alone, which is how the IPv4 MS-Primary-DNS-Server attribute already
behaves.

ipv6_dns_test.c covers the selection: assigned wins over configured,
empty list means "nothing assigned" rather than "no DNS", the cap holds
for both sources, and a caller with no room gets nothing rather than a
stomped buffer. Wired into the ASAN/UBSAN workflow.

Inspired by the per-session IPv6 DNS support in accel-ppp-ng (commit
2df6eb99), reimplemented against mainline's ap_session and ipdb types.
</content>
</entry>
<entry>
<title>dhcpv6: read the elapsed time and preference options at their real width</title>
<updated>2026-08-10T06:43:09+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-10T06:43:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=7c98f320c3ef7e863a9c7d30bb81735bb4fec46d'/>
<id>urn:sha1:7c98f320c3ef7e863a9c7d30bb81735bb4fec46d</id>
<content type='text'>
print_time() read a 32 bit word out of the Elapsed Time option, which
RFC 8415 21.9 defines as exactly two octets, and clients include it in
almost every message they send. With verbose enabled that is a two byte
read past the option on every DHCPv6 transaction:

  ERROR: AddressSanitizer: heap-buffer-overflow
  READ of size 4 in print_time dhcpv6_packet.c:499

The value was not byte swapped either, so what got logged was not the
elapsed time. Read two octets, convert them, and copy them out rather
than dereferencing a pointer into the packet that need not be aligned.

print_uint8() has the same shape, so check the length there too before
reading the Preference octet.
</content>
</entry>
<entry>
<title>dhcpv6: fix end pointer of an encapsulated relay message</title>
<updated>2026-08-10T06:42:23+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-10T06:42:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=b0e7444cfea168b6b283ca89e00b57494e0bced2'/>
<id>urn:sha1:b0e7444cfea168b6b283ca89e00b57494e0bced2</id>
<content type='text'>
opth-&gt;data already points past the option header, so adding
sizeof(*opth) again counted it twice and left endptr four bytes beyond
the end of the Relay-Message option, and possibly beyond the received
packet.

The bounds check at the top of the option loop is written against that
endptr, so on the next pass it accepted an option header that lies
outside the buffer and read opth-&gt;len from it. ASan on a Relay-Forward
packet:

  ERROR: AddressSanitizer: heap-buffer-overflow
  READ of size 2 in dhcpv6_packet_parse dhcpv6_packet.c:158

The end of the relayed message is the option payload, nothing more.
</content>
</entry>
<entry>
<title>dhcpv6: bail out of the relay loop when it makes no progress</title>
<updated>2026-08-10T06:41:38+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-10T06:41:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=a9bfcdb86b2da91077c21c169e767975c029eabe'/>
<id>urn:sha1:a9bfcdb86b2da91077c21c169e767975c029eabe</id>
<content type='text'>
The relay decapsulation loop only advances pkt-&gt;hdr when it finds a
Relay-Message option inside the current relay header. A Relay-Forward
packet that carries no Relay-Message option leaves pkt-&gt;hdr pointing at
the same header, so the outer loop runs again on the same input and
allocates another struct dhcpv6_relay on every pass.

A 34 byte packet, a Relay-Forward header with no options at all, is
enough to allocate without limit. Instrumented with ASan it reaches
11.8 million allocations and over a gigabyte in a few seconds:

  ERROR: libFuzzer: out-of-memory (used: 1249Mb; limit: 512Mb)
  Live Heap Allocations: 781874575 bytes in 11834644 chunks
      #1 in dhcpv6_packet_parse dhcpv6_packet.c:142

The socket is per session, so this needs an established session, but the
packet is parsed before any DHCPv6 level validation and one client can
exhaust memory for the whole daemon.

Remember the header at the top of each pass and treat a pass that did
not move it as a malformed packet.
</content>
</entry>
<entry>
<title>dhcpv6: check option length before reading the status code</title>
<updated>2026-08-10T05:33:53+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-10T05:33:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=52a01730fd02c2579f474c01ebf72a312f737825'/>
<id>urn:sha1:52a01730fd02c2579f474c01ebf72a312f737825</id>
<content type='text'>
print_status() reads the 2-byte status code at offset 4 of the option,
but parse_option() only guarantees that the option header plus its
declared payload length are within the packet. A Status Code option with
a payload length below 2 as the last option in a packet therefore made
print_status() read past the end of the received buffer.

Skip the option if its payload is too short to hold the code.
</content>
</entry>
<entry>
<title>dhcpv6: fix status code name table and its bounds check</title>
<updated>2026-08-10T05:32:47+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-10T05:32:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=6019e1d14937731be7c88628fc7c1253aaa701e7'/>
<id>urn:sha1:6019e1d14937731be7c88628fc7c1253aaa701e7</id>
<content type='text'>
A missing comma made "UseMulticast" and "NoPrefixAvail" concatenate into
a single string literal, so the table held 6 entries instead of 7:
UseMulticast printed as "UseMulticastNoPrefixAvail" and NoPrefixAvail had
no entry at all.

The bounds check compared the status code against sizeof(status_name),
which is the size of the table in bytes (48), not its number of entries.
Codes 6..48 passed the check and indexed past the end of the table, so
print() was handed whatever pointer-sized garbage followed it. A client
can trigger this by sending a Status Code option with an out-of-range
code, which is printed verbatim when verbose is enabled.

Compare against the entry count instead, and drop the ntohs() &lt; 0 test,
which can never be true for an unsigned value.
</content>
</entry>
</feed>
