<feed xmlns='http://www.w3.org/2005/Atom'>
<title>accel-ppp.git/accel-pppd/ctrl/l2tp/packet.c, branch 1.15.0</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=1.15.0</id>
<link rel='self' href='https://git.amelek.net/accel-ppp/accel-ppp.git/atom?h=1.15.0'/>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/'/>
<updated>2026-09-01T06:08:47+00:00</updated>
<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>l2tp: validate the deciphered length of hidden AVPs</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-04T14:40:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=9554ce05e13fdb8c55a54e259b4154c9aeaca58d'/>
<id>urn:sha1:9554ce05e13fdb8c55a54e259b4154c9aeaca58d</id>
<content type='text'>
decode_avp() only checked the 2 bytes length prefix of the Hidden AVP
Subformat when the ciphered attribute spanned more than one MD5 block.
For an attribute of at most 16 bytes it deciphered the single block and
returned straight away, leaving l2tp_recv() to take the prefix at face
value:

	orig_avp_len = ntohs(*(uint16_t *)avp-&gt;val) + sizeof(*avp);
	...
	attr-&gt;length = orig_avp_len - sizeof(*avp);

That prefix is an output of the cipher, so a peer which does not know
the secret (i.e. anyone able to reach the L2TP socket, no handshake
needed beyond a preceding Random-Vector AVP) turns it into 16 random
bits. Worse than an over-read: orig_avp_len is a uint16_t, so a prefix
of 0xffff wraps to 5, attr-&gt;length becomes -1, and the ATTR_TYPE_STRING
and ATTR_TYPE_OCTETS cases then run

	attr-&gt;val.string = _malloc(attr-&gt;length + 1);	/* _malloc(0) */
	memcpy(attr-&gt;val.string, orig_avp_val, attr-&gt;length);	/* SIZE_MAX */

that is an unbounded memcpy() into a zero sized allocation. Remotely
triggerable heap corruption on any tunnel with a secret configured. The
accel-ppp encoder always pads hidden AVPs by at least 16 bytes, so it
never produces an attribute short enough to reach this path; only a
crafted packet does.

Fix it at the source rather than at the call site: decode_avp() now
returns the deciphered length through an output parameter, and the
length is bounded against the room actually available in the received
AVP on every path out of the function, single block included. Callers
can no longer re-derive it from the AVP body and get it wrong, and the
existing multi-block check keeps guarding the deciphering loop itself.

Add packet_test.c, a standalone test which drives the real parser
through a real UDP socket: hand-crafted packets cover the length prefix
checks (including the boundaries of what fits and the single block path
the encoder cannot produce), and l2tp_packet_send()/l2tp_recv() round
trips cover the multi-block cipher and the unaligned AVP accessors. It
reproduces the corruption above under ASan on unpatched code. Wire it,
and the so far unused bitpool_test.c, into the ASAN/UBSAN workflow.

Inspired by the equivalent hardening in accel-ppp-ng (commit a8ca0f3f),
which bounds the length at the call site; the fix here is placed inside
decode_avp() and covered by a regression test.
</content>
</entry>
<entry>
<title>l2tp: read and write AVP values through unaligned-safe accessors</title>
<updated>2026-08-12T07:42:12+00:00</updated>
<author>
<name>Denys Fedoryshchenko</name>
<email>denys.f@collabora.com</email>
</author>
<published>2026-08-04T14:38:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=36c440758fc9fd606fbdfe342a4b3fd842d05c4e'/>
<id>urn:sha1:36c440758fc9fd606fbdfe342a4b3fd842d05c4e</id>
<content type='text'>
AVPs are packed back to back in the receive buffer, so the offset of any
given AVP is the sum of the lengths of all the AVPs before it, i.e. a
value the peer picks. Casting avp-&gt;val to uint16_t/uint32_t/uint64_t
therefore dereferences a pointer with an arbitrary alignment, which is
undefined behaviour, is caught by -fsanitize=alignment, and is only
harmless on x86 by accident. The same applies to the send path, where
the AVPs being built are laid out the same way.

Introduce unaligned_{ntohs,ntohl,be64toh}() and their store
counterparts, all memcpy() based, and use them for every multi-byte
field read out of or written into an AVP body. Accesses to the members
of struct l2tp_avp_t itself are fine as it is declared packed.

memxor() had the same problem, in a worse form: it cast both of its
uint8_t pointers to uintmax_t and walked them word by word. Since it is
only ever called on MD5 sized chunks, replace it with a plain byte loop
which compilers vectorize just as well, and which no longer breaks
strict aliasing either.

No functional change intended, this is a portability and UB fix; it also
removes a source of noise for the s390x (big endian) CI job.
</content>
</entry>
<entry>
<title>crypto: Removed internal tomcat crypto.</title>
<updated>2025-12-10T17:16:42+00:00</updated>
<author>
<name>Andrii Melnychenko</name>
<email>a.melnychenko@vyos.io</email>
</author>
<published>2025-09-29T16:14:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=c912d09018828745e3bcba268cd02a611e324d54'/>
<id>urn:sha1:c912d09018828745e3bcba268cd02a611e324d54</id>
<content type='text'>
Signed-off-by: Andrii Melnychenko &lt;a.melnychenko@vyos.io&gt;
</content>
</entry>
<entry>
<title>build: fix compile errors on GCC 14</title>
<updated>2024-08-27T22:41:58+00:00</updated>
<author>
<name>Sergey V. Lobanov</name>
<email>sergey@lobanov.in</email>
</author>
<published>2024-08-27T21:44:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=966c2bc8df039c67f4711ba9bb3f267fbd405c8d'/>
<id>urn:sha1:966c2bc8df039c67f4711ba9bb3f267fbd405c8d</id>
<content type='text'>
This patch fixes compile errors on GCC 14 like the following

/root/accel-ppp/accel-pppd/radius/packet.c: In function 'rad_packet_recv':
/root/accel-ppp/accel-pppd/radius/packet.c:142:72: error: passing argument 5 of 'recvfrom' from incompatible pointer type [-Wincompatible-pointer-types]
  142 |                         n = recvfrom(fd, pack-&gt;buf, REQ_LENGTH_MAX, 0, addr, &amp;addr_len);
      |                                                                        ^~~~
      |                                                                        |
      |                                                                        struct sockaddr_in *
In file included from /usr/include/netinet/in.h:10,
                 from /usr/include/arpa/inet.h:9,
                 from /root/accel-ppp/accel-pppd/radius/packet.c:10:
/usr/include/sys/socket.h:397:55: note: expected 'struct sockaddr * restrict' but argument is of type 'struct sockaddr_in *'

Reference: https://gcc.gnu.org/gcc-14/porting_to.html
</content>
</entry>
<entry>
<title>l2tp: fix RCE through buffer overflow &amp; fix LE/BE compatibility</title>
<updated>2020-09-05T21:38:35+00:00</updated>
<author>
<name>Vladislav Grishenko</name>
<email>themiron@mail.ru</email>
</author>
<published>2020-09-05T21:38:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=2324bcd5ba12cf28f47357a8f03cd41b7c04c52b'/>
<id>urn:sha1:2324bcd5ba12cf28f47357a8f03cd41b7c04c52b</id>
<content type='text'>
Unsufficent checks of valid l2tp header &amp; avp length cause possible
RCE through buffer overflow, reported by https://github.com/WinMin
swings &amp; leommxj, Chaitin Security Research Lab. Add missed header
length and avp length validation to fix the issue.

Order of struct bitfields is implementation-defined so current code
doesn't play well with big-endian arch. switch to explicit flag bit
checking/gathering to fix the issue.

RFC 2661 and 3931 requires that length, seqeuence flags must be set
and offset flag must not be set, so avp-premissive can't help in
this cases.
</content>
</entry>
<entry>
<title>l2tp: skip obsolete session data packets from logging</title>
<updated>2017-12-05T12:03:40+00:00</updated>
<author>
<name>Vladislav Grishenko</name>
<email>themiron@mail.ru</email>
</author>
<published>2017-01-27T22:02:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=faf5bf8a0f40119273b94d8c80bafaaabb3d185e'/>
<id>urn:sha1:faf5bf8a0f40119273b94d8c80bafaaabb3d185e</id>
<content type='text'>
 After session is freed on our end, kernel doesn't bother with possible
 incoming data packets and just passes them to userspace, in turn
 they are mistreated as short control packets with corresponding errors.
 Since there's no special data packet handling, just ignore them.
</content>
</entry>
<entry>
<title>remove trailing whitespaces</title>
<updated>2014-11-22T05:56:40+00:00</updated>
<author>
<name>Dmitry Kozlov</name>
<email>xeb@mail.ru</email>
</author>
<published>2014-11-22T05:56:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=81ca3923a29ea9b67f7291be23b210019546aa5f'/>
<id>urn:sha1:81ca3923a29ea9b67f7291be23b210019546aa5f</id>
<content type='text'>
</content>
</entry>
<entry>
<title>l2tp: introduce data packet sequencing and reorder timeout support</title>
<updated>2013-10-02T18:57:42+00:00</updated>
<author>
<name>Vladislav Grishenko</name>
<email>themiron@mail.ru</email>
</author>
<published>2013-09-27T07:56:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=21d36db2bad56b6389873b1c10e45f36938ed5fc'/>
<id>urn:sha1:21d36db2bad56b6389873b1c10e45f36938ed5fc</id>
<content type='text'>
Signed-off-by: Vladislav Grishenko &lt;themiron@mail.ru&gt;
</content>
</entry>
<entry>
<title>l2tp: Handle 64 bits attributes</title>
<updated>2013-04-17T05:06:35+00:00</updated>
<author>
<name>Guillaume Nault</name>
<email>g.nault@alphalink.fr</email>
</author>
<published>2013-04-09T19:43:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/accel-ppp/accel-ppp.git/commit/?id=d3ad0e29c57c74c93db97f165bfa43024e180db3'/>
<id>urn:sha1:d3ad0e29c57c74c93db97f165bfa43024e180db3</id>
<content type='text'>
Define l2tp_packet_add_int64() to create attributes of 64 bits long
integers.

Signed-off-by: Guillaume Nault &lt;g.nault@alphalink.fr&gt;
</content>
</entry>
</feed>
