ppp: update to 2.5.3

Update to 2.5.3 and use the official tarball.

Changelog: https://github.com/ppp-project/ppp/releases/tag/v2.5.3

Removed upstreamed:
- 000-pppd-session-fixed-building-with-gcc-15.patch
- 001-pppdump-fixed-building-with-gcc-15.patch
- 501-fix-memcpy-fortify.patch
- 502-remove_mru.patch

Manually rebased:
- 500-add-pptp-plugin.patch

Add a pending patch to relax the check to avoid breaking existing
configurations.

Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23540
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
This commit is contained in:
Qingfang Deng
2026-05-26 17:17:21 +08:00
committed by Jonas Jelonek
parent db533a6235
commit b25d90b7e4
15 changed files with 791 additions and 209 deletions
+5 -7
View File
@@ -9,14 +9,12 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=ppp
PKG_VERSION:=2.5.2
PKG_RELEASE:=3
PKG_VERSION:=2.5.3
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/ppp-project/ppp
PKG_MIRROR_HASH:=381668ce1547afeaf599f08ae37935bfd3d5841747c62bca5a870c11e3e9bedb
PKG_SOURCE_DATE:=2024-12-31
PKG_SOURCE_VERSION:=9f612dc02c34509f062ed63b60bcc7e937e25178
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://download.samba.org/pub/ppp
PKG_HASH:=ddda28dec8aca99a403ab6070d94ffd2b17d63e9a4c5509158e99e148f572d4f
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=BSD-4-Clause
@@ -1,30 +0,0 @@
From 5edcb01f1d8d521c819d45df1f1bb87697252130 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Mon, 17 Mar 2025 14:38:26 -0700
Subject: [PATCH] pppd/session: Fixed building with GCC 15
Fixed building with GCC 15 which defaults to C23
and find conflicting declration of getspnam() here
with the one provided by shadow.h (extern struct spwd *getspnam (const char *__name);)
Fixes
../../ppp-2.5.2/pppd/session.c: In function 'session_start':
../../ppp-2.5.2/pppd/session.c:185:18: error: conflicting types for 'getspnam'; have 'struct spwd *(void)'
185 | struct spwd *getspnam();
| ^~~~~~~~
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
pppd/session.c | 1 -
1 file changed, 1 deletion(-)
--- a/pppd/session.c
+++ b/pppd/session.c
@@ -182,7 +182,6 @@ session_start(const int flags, const cha
char *cbuf;
#ifdef HAVE_SHADOW_H
struct spwd *spwd;
- struct spwd *getspnam();
long now = 0;
#endif /* #ifdef HAVE_SHADOW_H */
#endif /* #ifdef PPP_WITH_PAM */
@@ -1,70 +0,0 @@
From c6c84c77c16878745be4955f2f5baac1f2280c96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
Date: Thu, 27 Feb 2025 11:44:08 +0100
Subject: [PATCH] Fixed building with GCC 15
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
GCC 15 defaults to C23 which does not allow K&R declarations.
Credit Yaakov Selkowitz in:
https://src.fedoraproject.org/rpms/ppp/pull-request/12
Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
---
pppdump/pppdump.c | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
--- a/pppdump/pppdump.c
+++ b/pppdump/pppdump.c
@@ -42,14 +42,12 @@ int tot_sent, tot_rcvd;
extern int optind;
extern char *optarg;
-void dumplog();
-void dumpppp();
-void show_time();
+void dumplog(FILE *);
+void dumpppp(FILE *);
+void show_time(FILE *, int);
int
-main(ac, av)
- int ac;
- char **av;
+main(int ac, char **av)
{
int i;
char *p;
@@ -97,8 +95,7 @@ main(ac, av)
}
void
-dumplog(f)
- FILE *f;
+dumplog(FILE *f)
{
int c, n, k, col;
int nb, c2;
@@ -241,8 +238,7 @@ struct pkt {
unsigned char dbuf[8192];
void
-dumpppp(f)
- FILE *f;
+dumpppp(FILE *f)
{
int c, n, k;
int nb, nl, dn, proto, rv;
@@ -375,9 +371,7 @@ dumpppp(f)
}
void
-show_time(f, c)
- FILE *f;
- int c;
+show_time(FILE *f, int c)
{
time_t t;
int n;
@@ -137,7 +137,7 @@
} else {
--- a/pppd/ipcp.c
+++ b/pppd/ipcp.c
@@ -1915,7 +1915,7 @@ ipcp_up(fsm *f)
@@ -1930,7 +1930,7 @@ ipcp_up(fsm *f)
proxy_arp_set[f->unit] = 1;
}
@@ -148,7 +148,7 @@
} else {
--- a/pppd/ipv6cp.c
+++ b/pppd/ipv6cp.c
@@ -1338,7 +1338,7 @@ ipv6cp_up(fsm *f)
@@ -1344,7 +1344,7 @@ ipv6cp_up(fsm *f)
if (sif6defaultroute(f->unit, go->ourid, ho->hisid))
default_route_set[f->unit] = 1;
}
@@ -159,7 +159,7 @@
} else {
--- a/pppd/pppd-private.h
+++ b/pppd/pppd-private.h
@@ -370,7 +370,7 @@ void demand_conf(void); /* config interf
@@ -375,7 +375,7 @@ void demand_conf(void); /* config interf
void demand_block(void); /* set all NPs to queue up packets */
void demand_unblock(void); /* set all NPs to pass packets */
void demand_discard(void); /* set all NPs to discard packets */
@@ -12,7 +12,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
--- a/pppd/main.c
+++ b/pppd/main.c
@@ -1150,7 +1150,8 @@ get_input(void)
@@ -1159,7 +1159,8 @@ get_input(void)
}
notice("Modem hangup");
hungup = 1;
@@ -23,7 +23,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
#
# SunOS provides a version of libpcap that would work, but SunOS has no support for activity filter
AM_CONDITIONAL([PPP_WITH_FILTER], [ test "x${with_pcap}" = "xyes" && test "x${build_sunos}" != "xyes" ])
@@ -348,6 +351,7 @@ $PACKAGE_NAME version $PACKAGE_VERSION
@@ -349,6 +352,7 @@ $PACKAGE_NAME version $PACKAGE_VERSION
With libatm..........: ${with_atm:-no}
With libpam..........: ${with_pam:-no}
With libpcap.........: ${with_pcap:-no}
@@ -56,7 +56,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
/*
* There have been 3 or 4 different names for this in libpcap CVS, but
* this seems to be what they have settled on...
@@ -182,6 +183,13 @@ static int setlogfile(char **);
@@ -186,6 +187,13 @@ static int setlogfile(char **);
static int loadplugin(char **);
#endif
@@ -70,7 +70,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
#ifdef PPP_WITH_FILTER
static int setpassfilter(char **);
static int setactivefilter(char **);
@@ -391,6 +399,14 @@ struct option general_options[] = {
@@ -404,6 +412,14 @@ struct option general_options[] = {
"set filter for active pkts", OPT_PRIO },
#endif
@@ -85,7 +85,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ "maxoctets", o_int, &maxoctets,
"Set connection traffic limit",
OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
@@ -1666,6 +1682,27 @@ callfile(char **argv)
@@ -1690,6 +1706,27 @@ callfile(char **argv)
return ok;
}
@@ -119,7 +119,7 @@ Signed-off-by: George Kashperko <george@znau.edu.ua>
&& memcmp(vd.dptr, key.dptr, vd.dsize) == 0;
--- a/pppd/sys-linux.c
+++ b/pppd/sys-linux.c
@@ -980,6 +980,16 @@ void cfg_bundle(int mrru, int mtru, int
@@ -1111,6 +1111,16 @@ void cfg_bundle(int mrru, int mtru, int
add_fd(ppp_dev_fd);
}
@@ -136,7 +136,7 @@ Signed-off-by: George Kashperko <george@znau.edu.ua>
/*
* make_new_bundle - create a new PPP unit (i.e. a bundle)
* and connect our channel to it. This should only get called
@@ -998,6 +1008,8 @@ void make_new_bundle(int mrru, int mtru,
@@ -1129,6 +1139,8 @@ void make_new_bundle(int mrru, int mtru,
/* set the mrru and flags */
cfg_bundle(mrru, mtru, rssn, tssn);
@@ -13,7 +13,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
--- a/pppd/sys-linux.c
+++ b/pppd/sys-linux.c
@@ -2247,6 +2247,9 @@ int sifdefaultroute (int unit, u_int32_t
@@ -2374,6 +2374,9 @@ int sifdefaultroute (int unit, u_int32_t
memset (&rt, 0, sizeof (rt));
SET_SA_FAMILY (rt.rt_dst, AF_INET);
@@ -23,7 +23,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
rt.rt_dev = ifname;
rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
@@ -2255,7 +2258,7 @@ int sifdefaultroute (int unit, u_int32_t
@@ -2382,7 +2385,7 @@ int sifdefaultroute (int unit, u_int32_t
SIN_ADDR(rt.rt_genmask) = 0L;
}
@@ -10,8 +10,8 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
--- a/pppd/sys-linux.c
+++ b/pppd/sys-linux.c
@@ -220,14 +220,10 @@ static fd_set in_fds; /* set of fds tha
static int max_in_fd; /* highest fd set in in_fds */
@@ -218,14 +218,10 @@ static int chindex; /* channel index (n
static unsigned routing_table_id = RT_TABLE_MAIN;
static int has_proxy_arp = 0;
-static int driver_version = 0;
@@ -26,7 +26,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
static char loop_name[20];
static unsigned char inbuf[512]; /* buffer for chars read from loopback */
@@ -245,9 +241,8 @@ static int dynaddr_set; /* 1 if ip_dyna
@@ -241,9 +237,8 @@ static int dynaddr_set; /* 1 if ip_dyna
static int looped; /* 1 if using loop */
static int link_mtu; /* mtu for the link (not bundle) */
@@ -37,7 +37,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
#define MAX_IFS 100
@@ -1966,11 +1961,12 @@ int ccp_fatal_error (int unit)
@@ -2067,11 +2062,12 @@ int ccp_fatal_error (int unit)
*
* path_to_procfs - find the path to the proc file system mount point
*/
@@ -52,7 +52,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
struct mntent *mntent;
FILE *fp;
@@ -1992,6 +1988,7 @@ static char *path_to_procfs(const char *
@@ -2093,6 +2089,7 @@ static char *path_to_procfs(const char *
fclose (fp);
}
}
@@ -60,7 +60,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
strlcpy(proc_path + proc_path_len, tail,
sizeof(proc_path) - proc_path_len);
@@ -2883,6 +2880,8 @@ ppp_registered(void)
@@ -2874,6 +2871,8 @@ ppp_registered(void)
int ppp_check_kernel_support(void)
{
@@ -69,7 +69,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
int s, ok, fd;
struct ifreq ifr;
int size;
@@ -3010,6 +3009,7 @@ int ppp_check_kernel_support(void)
@@ -3001,6 +3000,7 @@ int ppp_check_kernel_support(void)
}
close(s);
return ok;
@@ -77,7 +77,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
}
#ifndef HAVE_LOGWTMP
@@ -3571,6 +3571,7 @@ get_pty(int *master_fdp, int *slave_fdp,
@@ -3562,6 +3562,7 @@ get_pty(int *master_fdp, int *slave_fdp,
}
#endif /* TIOCGPTN */
@@ -85,7 +85,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
if (sfd < 0) {
/* the old way - scan through the pty name space */
for (i = 0; i < 64; ++i) {
@@ -3595,6 +3596,7 @@ get_pty(int *master_fdp, int *slave_fdp,
@@ -3586,6 +3587,7 @@ get_pty(int *master_fdp, int *slave_fdp,
}
}
}
@@ -93,7 +93,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
if (sfd < 0)
return 0;
@@ -3710,6 +3712,7 @@ get_host_seed(void)
@@ -3701,6 +3703,7 @@ get_host_seed(void)
int
sys_check_options(void)
{
@@ -101,7 +101,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
if (demand && driver_is_old) {
ppp_option_error("demand dialling is not supported by kernel driver "
"version %d.%d.%d", driver_version, driver_modification,
@@ -3720,6 +3723,7 @@ sys_check_options(void)
@@ -3711,6 +3714,7 @@ sys_check_options(void)
warn("Warning: multilink is not supported by the kernel driver");
multilink = 0;
}
@@ -147,7 +147,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
info("PPPoE plugin from pppd %s", PPPD_VERSION);
--- a/pppd/plugins/pppol2tp/pppol2tp.c
+++ b/pppd/plugins/pppol2tp/pppol2tp.c
@@ -501,10 +501,6 @@ static void pppol2tp_cleanup(void)
@@ -502,10 +502,6 @@ static void pppol2tp_cleanup(void)
void plugin_init(void)
{
#if defined(__linux__)
@@ -7,7 +7,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
--- a/pppd/main.c
+++ b/pppd/main.c
@@ -982,14 +982,17 @@ struct protocol_list {
@@ -991,14 +991,17 @@ struct protocol_list {
const char *name;
} protocol_list[] = {
{ 0x21, "IP" },
@@ -25,7 +25,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x33, "Stream Protocol ST-II" },
{ 0x35, "Banyan Vines" },
{ 0x39, "AppleTalk EDDP" },
@@ -1003,8 +1006,11 @@ struct protocol_list {
@@ -1012,8 +1015,11 @@ struct protocol_list {
{ 0x49, "Serial Data Transport Protocol (PPP-SDTP)" },
{ 0x4b, "SNA over 802.2" },
{ 0x4d, "SNA" },
@@ -37,7 +37,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x53, "Encryption" },
{ 0x55, "Individual Link Encryption" },
{ 0x57, "IPv6" },
@@ -1015,12 +1021,15 @@ struct protocol_list {
@@ -1024,12 +1030,15 @@ struct protocol_list {
{ 0x65, "RTP IPHC Compressed non-TCP" },
{ 0x67, "RTP IPHC Compressed UDP 8" },
{ 0x69, "RTP IPHC Compressed RTP 8" },
@@ -53,7 +53,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x0203, "IBM Source Routing BPDU" },
{ 0x0205, "DEC LANBridge100 Spanning Tree" },
{ 0x0207, "Cisco Discovery Protocol" },
@@ -1032,15 +1041,19 @@ struct protocol_list {
@@ -1041,15 +1050,19 @@ struct protocol_list {
{ 0x0231, "Luxcom" },
{ 0x0233, "Sigma Network Systems" },
{ 0x0235, "Apple Client Server Protocol" },
@@ -73,7 +73,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x4001, "Cray Communications Control Protocol" },
{ 0x4003, "CDPD Mobile Network Registration Protocol" },
{ 0x4005, "Expand accelerator protocol" },
@@ -1051,8 +1064,10 @@ struct protocol_list {
@@ -1060,8 +1073,10 @@ struct protocol_list {
{ 0x4023, "RefTek Protocol" },
{ 0x4025, "Fibre Channel" },
{ 0x4027, "EMIT Protocols" },
@@ -84,7 +84,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x8023, "OSI Network Layer Control Protocol" },
{ 0x8025, "Xerox NS IDP Control Protocol" },
{ 0x8027, "DECnet Phase IV Control Protocol" },
@@ -1061,7 +1076,9 @@ struct protocol_list {
@@ -1070,7 +1085,9 @@ struct protocol_list {
{ 0x8031, "Bridging NCP" },
{ 0x8033, "Stream Protocol Control Protocol" },
{ 0x8035, "Banyan Vines Control Protocol" },
@@ -94,7 +94,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x803f, "NETBIOS Framing Control Protocol" },
{ 0x8041, "Cisco Systems Control Protocol" },
{ 0x8043, "Ascom Timeplex" },
@@ -1070,18 +1087,24 @@ struct protocol_list {
@@ -1079,18 +1096,24 @@ struct protocol_list {
{ 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
{ 0x804b, "SNA over 802.2 Control Protocol" },
{ 0x804d, "SNA Control Protocol" },
@@ -119,7 +119,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
{ 0x8207, "Cisco Discovery Protocol Control" },
{ 0x8209, "Netcs Twin Routing" },
{ 0x820b, "STP - Control Protocol" },
@@ -1090,24 +1113,29 @@ struct protocol_list {
@@ -1099,24 +1122,29 @@ struct protocol_list {
{ 0x8281, "MPLSCP" },
{ 0x8285, "IEEE p1284.4 standard - Protocol Control" },
{ 0x8287, "ETSI TETRA TNP1 Control Protocol" },
@@ -9,7 +9,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
--- a/pppd/options.c
+++ b/pppd/options.c
@@ -379,13 +379,14 @@ struct option general_options[] = {
@@ -392,13 +392,14 @@ struct option general_options[] = {
"Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },
{ "nomultilink", o_bool, &multilink,
"Disable multilink operation", OPT_PRIOSUB | 0 },
@@ -1,9 +1,9 @@
--- a/configure.ac
+++ b/configure.ac
@@ -333,6 +333,7 @@ AC_CONFIG_FILES([
pppd/plugins/pppoatm/Makefile
@@ -334,6 +334,7 @@ AC_CONFIG_FILES([
pppd/plugins/pppol2tp/Makefile
pppd/plugins/radius/Makefile
pppd/plugins/dhcpv6relay/Makefile
+ pppd/plugins/pptp/Makefile
pppdump/Makefile
pppstats/Makefile
@@ -14,8 +14,8 @@
winbind_la_SOURCES = winbind.c
if !SUNOS
-SUBDIRS = pppoe pppoatm pppol2tp radius
+SUBDIRS = pppoe pppoatm pppol2tp radius pptp
-SUBDIRS = pppoe pppoatm pppol2tp radius dhcpv6relay
+SUBDIRS = pppoe pppoatm pppol2tp radius dhcpv6relay pptp
endif
--- /dev/null
+++ b/pppd/plugins/pptp/Makefile.am
@@ -1,37 +0,0 @@
From f8d994052e3858848ce11318085e04fe7a1cfb28 Mon Sep 17 00:00:00 2001
From: LGA1150 <9155358+LGA1150@users.noreply.github.com>
Date: Thu, 5 Mar 2026 05:41:30 +0800
Subject: [PATCH] pppd: fix memcpy overlap (#579)
memcpy() with overlapping src and dest buffers is an undefined behavior
in C. In the current code, a ConfRej response is generated by copying
input data in-place, where the dest address is lower than the src.
This happens to work in practice because memcpy() forward-copies data,
matching the behavior of memmove() in this case.
However, if FORTIFY_SOURCE or Address Sanitizer is enabled, memcpy()
will detect the overlap at run time and abort the program.
Replace the memcpy() with memmove() to ensure a well-defined behavior.
Reported-by: Filippo Carletti <filippo.carletti@gmail.com>
Closes: #576
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
---
pppd/pppd-private.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pppd/pppd-private.h b/pppd/pppd-private.h
index 5f841824..29ea940c 100644
--- a/pppd/pppd-private.h
+++ b/pppd/pppd-private.h
@@ -525,7 +525,7 @@ int parse_dotted_ip(char *, u_int32_t *)
#define TIMEOUT(r, f, t) ppp_timeout((r), (f), (t), 0)
#define UNTIMEOUT(r, f) ppp_untimeout((r), (f))
-#define BCOPY(s, d, l) memcpy(d, s, l)
+#define BCOPY(s, d, l) memmove(d, s, l)
#define BZERO(s, n) memset(s, 0, n)
#define BCMP(s1, s2, l) memcmp(s1, s2, l)
@@ -0,0 +1,749 @@
From 71d3d3a6703fce993432151d363f405b51e7b75c Mon Sep 17 00:00:00 2001
From: Qingfang Deng <dqfext@gmail.com>
Date: Fri, 12 Jun 2026 10:52:39 +0800
Subject: [PATCH] pppd: relax and simplify permission check
The additional check added in v2.5.3 is intended to mitigate symlink
attacks, but it checks the permissions of every component of a path and
is too strict, breaking existing configurations. Relax and simplify the
check by only checking the opened file descriptor of a path, so the path
is resolved only once.
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
---
configure.ac | 2 +
pppd/auth.c | 146 +++++++++++++++++++++++++-------------------
pppd/main.c | 46 ++++++++++----
pppd/options.c | 56 +++++++++++++----
pppd/pppd-private.h | 2 +-
pppd/pppd.8 | 10 ---
pppd/pppd.h | 2 +-
pppd/utils.c | 84 ++++++-------------------
8 files changed, 184 insertions(+), 164 deletions(-)
--- a/configure.ac
+++ b/configure.ac
@@ -2,6 +2,7 @@ AC_PREREQ([2.69])
AC_INIT([ppp],
[2.5.3],
[https://github.com/ppp-project/ppp])
+AC_USE_SYSTEM_EXTENSIONS
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_CONFIG_MACRO_DIR([m4])
@@ -93,6 +94,7 @@ AC_CHECK_SIZEOF(unsigned short)
# Checks for library functions.
AC_CHECK_FUNCS([ \
+ fexecve \
mmap \
logwtmp \
strerror])
--- a/pppd/auth.c
+++ b/pppd/auth.c
@@ -307,7 +307,7 @@ static int setupapfile (char **);
static int privgroup (char **);
static int set_noauth_addr (char **);
static int set_permitted_number (char **);
-static void check_access (FILE *, char *);
+static void check_access (int, const char *);
static int wordlist_count (struct wordlist *);
static void check_maxoctets (void *);
@@ -532,7 +532,7 @@ setupapfile(char **argv)
free(fname);
return 0;
}
- check_access(ufile, fname);
+ check_access(fileno(ufile), fname);
uafname = fname;
/* get username */
@@ -1543,8 +1543,7 @@ check_passwd(int unit,
* Open the file of pap secrets and scan for a suitable secret
* for authenticating this user.
*/
- if (!ppp_check_access(path_upapfile, &filename, 0, 0))
- return UPAP_AUTHNAK;
+ filename = path_upapfile;
addrs = opts = NULL;
ret = UPAP_AUTHNAK;
f = fopen(filename, "r");
@@ -1552,7 +1551,13 @@ check_passwd(int unit,
error("Can't open PAP password file %s: %m", filename);
} else {
- check_access(f, filename);
+ int fd = fileno(f);
+
+ if (!ppp_check_access(fd, filename, 0)) {
+ fclose(f);
+ return UPAP_AUTHNAK;
+ }
+ check_access(fd, filename);
if (scan_authfile(f, user, our_name, secret, &addrs, &opts, filename, 0) < 0) {
warn("no PAP secret found for %s", user);
} else {
@@ -1586,7 +1591,6 @@ check_passwd(int unit,
}
fclose(f);
}
- free(filename);
if (ret == UPAP_AUTHNAK) {
if (**msg == 0)
@@ -1646,21 +1650,24 @@ null_login(int unit)
* Open the file of pap secrets and scan for a suitable secret.
*/
if (ret <= 0) {
- if (!ppp_check_access(path_upapfile, &filename, 0, 0))
- return 0;
+ int fd;
+
+ filename = path_upapfile;
addrs = NULL;
f = fopen(filename, "r");
- if (f == NULL) {
- free(filename);
+ if (f == NULL)
+ return 0;
+ fd = fileno(f);
+ if (!ppp_check_access(fd, filename, 0)) {
+ fclose(f);
return 0;
}
- check_access(f, filename);
+ check_access(fd, filename);
i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0);
ret = i >= 0 && secret[0] == 0;
BZERO(secret, sizeof(secret));
fclose(f);
- free(filename);
}
if (ret)
@@ -1701,7 +1708,7 @@ get_pap_passwd(char *passwd)
f = fopen(filename, "r");
if (f == NULL)
return 0;
- check_access(f, filename);
+ check_access(fileno(f), filename);
ret = scan_authfile(f, user,
(remote_name[0]? remote_name: NULL),
secret, NULL, NULL, filename, 0);
@@ -1734,18 +1741,18 @@ have_pap_secret(int *lacks_ipp)
return ret;
}
- if (!ppp_check_access(path_upapfile, &filename, 0, 0))
- return 0;
+ filename = path_upapfile;
f = fopen(filename, "r");
- if (f == NULL) {
- free(filename);
+ if (f == NULL)
return 0;
- }
+ if (!ppp_check_access(fileno(f), filename, 0)) {
+ fclose(f);
+ return 0;
+ }
ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name,
NULL, &addrs, NULL, filename, 0);
fclose(f);
- free(filename);
if (ret >= 0 && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
*lacks_ipp = 1;
@@ -1780,11 +1787,13 @@ have_chap_secret(char *client, char *ser
}
}
- if (!ppp_check_access(path_chapfile, &filename, 0, 0))
- return 0;
+ filename = path_chapfile;
f = fopen(filename, "r");
- if (f == NULL) {
- free(filename);
+ if (f == NULL)
+ return 0;
+
+ if (!ppp_check_access(fileno(f), filename, 0)) {
+ fclose(f);
return 0;
}
@@ -1795,7 +1804,6 @@ have_chap_secret(char *client, char *ser
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
fclose(f);
- free(filename);
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
*lacks_ipp = 1;
@@ -1822,11 +1830,13 @@ have_srp_secret(char *client, char *serv
char *filename;
struct wordlist *addrs;
- if (!ppp_check_access(PPP_PATH_SRPFILE, &filename, 0, 0))
- return 0;
+ filename = PPP_PATH_SRPFILE;
f = fopen(filename, "r");
- if (f == NULL) {
- free(filename);
+ if (f == NULL)
+ return 0;
+
+ if (!ppp_check_access(fileno(f), filename, 0)) {
+ fclose(f);
return 0;
}
@@ -1837,7 +1847,6 @@ have_srp_secret(char *client, char *serv
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
fclose(f);
- free(filename);
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
*lacks_ipp = 1;
@@ -1874,22 +1883,27 @@ get_secret(int unit, char *client, char
return 0;
}
} else {
- if (!ppp_check_access(path_chapfile, &filename, 0, 0))
- return 0;
+ int fd;
+
+ filename = path_chapfile;
addrs = NULL;
secbuf[0] = 0;
f = fopen(filename, "r");
if (f == NULL) {
error("Can't open chap secret file %s: %m", filename);
- free(filename);
return 0;
}
- check_access(f, filename);
+
+ fd = fileno(f);
+ if (!ppp_check_access(fd, filename, 0)) {
+ fclose(f);
+ return 0;
+ }
+ check_access(fd, filename);
ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0);
fclose(f);
- free(filename);
if (ret < 0)
return 0;
@@ -1931,23 +1945,27 @@ get_srp_secret(int unit, char *client, c
if (!am_server && passwd[0] != '\0') {
strlcpy(secret, passwd, MAXWORDLEN);
} else {
- if (!ppp_check_access(PPP_PATH_SRPFILE, &filename, 0, 0))
- return 0;
- addrs = NULL;
+ int fd;
+ filename = PPP_PATH_SRPFILE;
+ addrs = NULL;
fp = fopen(filename, "r");
if (fp == NULL) {
error("Can't open srp secret file %s: %m", filename);
- free(filename);
return 0;
}
- check_access(fp, filename);
+
+ fd = fileno(fp);
+ if (!ppp_check_access(fd, filename, 0)) {
+ fclose(fp);
+ return 0;
+ }
+ check_access(fd, filename);
secret[0] = '\0';
ret = scan_authfile(fp, client, server, secret, &addrs, &opts,
filename, am_server);
fclose(fp);
- free(filename);
if (ret < 0)
return 0;
@@ -2214,11 +2232,11 @@ auth_number(void)
* check_access - complain if a secret file has too-liberal permissions.
*/
static void
-check_access(FILE *f, char *filename)
+check_access(int fd, const char *filename)
{
struct stat sbuf;
- if (fstat(fileno(f), &sbuf) < 0) {
+ if (fstat(fd, &sbuf) < 0) {
warn("cannot stat secret file %s: %m", filename);
} else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
warn("Warning - secret file %s has world and/or group access",
@@ -2326,25 +2344,25 @@ scan_authfile(FILE *f, char *client, cha
* Special syntax: @/pathname means read secret from file.
*/
if (word[0] == '@' && word[1] == '/') {
- char *realname;
+ int fd;
strlcpy(atfile, word+1, sizeof(atfile));
- if (!ppp_check_access(atfile, &realname, 0, 0))
- continue;
- if ((sf = fopen(realname, "r")) == NULL) {
+ if ((sf = fopen(atfile, "r")) == NULL) {
warn("can't open indirect secret file %s", atfile);
- free(realname);
continue;
}
- check_access(sf, atfile);
+ fd = fileno(sf);
+ if (!ppp_check_access(fd, atfile, 0)) {
+ fclose(sf);
+ continue;
+ }
+ check_access(fd, atfile);
if (!getword(sf, word, &xxx, atfile)) {
warn("no secret in indirect secret file %s", atfile);
fclose(sf);
- free(realname);
continue;
}
fclose(sf);
- free(realname);
}
strlcpy(lsecret, word, sizeof(lsecret));
}
@@ -2503,14 +2521,15 @@ have_eaptls_secret_server(char *client,
char cacertfile[MAXWORDLEN];
char pkfile[MAXWORDLEN];
- if (!ppp_check_access(PPP_PATH_EAPTLSSERVFILE, &filename, 0, 0))
- return 0;
+ filename = PPP_PATH_EAPTLSSERVFILE;
f = fopen(filename, "r");
- if (f == NULL) {
- free(filename);
+ if (f == NULL)
return 0;
- }
+ if (!ppp_check_access(fileno(f), filename, 0)) {
+ fclose(f);
+ return 0;
+ }
if (client != NULL && client[0] == 0)
client = NULL;
else if (server != NULL && server[0] == 0)
@@ -2522,7 +2541,6 @@ have_eaptls_secret_server(char *client,
0);
fclose(f);
- free(filename);
/*
if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile,
@@ -2782,26 +2800,28 @@ get_eaptls_secret(int unit, char *client
}
else
{
+ int fd;
+
filename = (am_server ? PPP_PATH_EAPTLSSERVFILE : PPP_PATH_EAPTLSCLIFILE);
addrs = NULL;
- if (!ppp_check_access(filename, &filename, 0, 0))
- return 0;
fp = fopen(filename, "r");
- if (fp == NULL)
- {
+ if (fp == NULL) {
error("Can't open eap-tls secret file %s: %m", filename);
- free(filename);
return 0;
}
- check_access(fp, filename);
+ fd = fileno(fp);
+ if (!ppp_check_access(fd, filename, 0)) {
+ fclose(fp);
+ return 0;
+ }
+ check_access(fd, filename);
ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile,
cacertfile, pkfile, &addrs, &opts, filename, 0);
fclose(fp);
- free(filename);
if (ret < 0) return 0;
}
--- a/pppd/main.c
+++ b/pppd/main.c
@@ -1952,22 +1952,37 @@ update_script_environment(void)
pid_t
run_program(char *prog, char * const *args, int must_exist, void (*done)(void *), void *arg, int wait)
{
- int pid, status, ret;
- char *rpath;
+ int fd, pid, status, ret;
/*
* First check if the file exists and is executable by root,
* and couldn't have been modified by a non-root process.
*/
- if (!ppp_check_access(prog, &rpath, must_exist, 1))
+#if defined(O_PATH)
+ fd = open(prog, O_PATH);
+#elif defined(O_EXEC)
+ fd = open(prog, O_EXEC);
+#else
+ fd = open(prog, O_RDONLY);
+#endif
+ if (fd < 0) {
+ if (errno != ENOENT || must_exist)
+ error("Can't access %s: %m", prog);
+ return 0;
+ }
+ if (!ppp_check_access(fd, prog, 1)) {
+ close(fd);
return 0;
+ }
pid = ppp_safe_fork(fd_devnull, fd_devnull, fd_devnull);
if (pid == -1) {
error("Failed to create child process for %s: %m", prog);
+ close(fd);
return -1;
}
if (pid != 0) {
+ close(fd);
if (debug)
dbglog("Script %s started (pid %d)", prog, pid);
record_child(pid, prog, done, arg, 0);
@@ -1979,7 +1994,6 @@ run_program(char *prog, char * const *ar
}
forget_child(pid, status);
}
- free(rpath);
return pid;
}
@@ -2007,14 +2021,24 @@ run_program(char *prog, char * const *ar
/* run the program */
update_script_environment();
- execve(rpath, args, script_env);
- if (must_exist || errno != ENOENT) {
- /* have to reopen the log, there's nowhere else
- for the message to go. */
- reopen_log();
- syslog(LOG_ERR, "Can't execute %s: %m", rpath);
- closelog();
+#ifdef HAVE_FEXECVE
+ fexecve(fd, args, script_env);
+#else
+ {
+ char fdpath[32];
+
+ snprintf(fdpath, sizeof(fdpath), "/dev/fd/%d", fd);
+ execve(fdpath, args, script_env);
+ if (errno == ENOENT) {
+ snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd);
+ execve(fdpath, args, script_env);
+ }
}
+#endif
+ /* have to reopen the log, there's nowhere else for the message to go. */
+ reopen_log();
+ syslog(LOG_ERR, "Can't execute %s: %m", prog);
+ closelog();
_exit(99);
}
--- a/pppd/options.c
+++ b/pppd/options.c
@@ -210,6 +210,8 @@ static struct option *find_option(char *
static int process_option(struct option *, char *, char **);
static int n_arguments(struct option *);
static int number_option(char *, u_int32_t *, int);
+static int ppp_options_open(const char *, int, int, FILE **);
+static int ppp_options_from_fp(FILE *, const char *, int);
/*
* Structure to store extra lists of options.
@@ -588,14 +590,23 @@ int
ppp_options_from_file(char *filename, int must_exist, int check_prot, int priv)
{
FILE *f;
- int i, newline, ret, err;
- struct option *opt;
- int oldpriv, n;
- char *oldsource;
+
+ if (!ppp_options_open(filename, must_exist, check_prot, &f))
+ return 0;
+ if (f == NULL)
+ return 1;
+ return ppp_options_from_fp(f, filename, priv);
+}
+
+/*
+ * ppp_options_open - Open a file for options
+ */
+static int
+ppp_options_open(const char *filename, int must_exist, int check_prot, FILE **fp)
+{
uid_t euid;
- char *argv[MAXARGS];
- char args[MAXARGS][MAXWORDLEN];
- char cmd[MAXWORDLEN];
+ FILE *f;
+ int err;
euid = geteuid();
if (check_prot && seteuid(getuid()) == -1) {
@@ -606,6 +617,7 @@ ppp_options_from_file(char *filename, in
err = errno;
if (check_prot && seteuid(euid) == -1)
fatal("unable to regain privileges");
+ *fp = f;
if (f == NULL) {
errno = err;
if (!must_exist) {
@@ -616,6 +628,22 @@ ppp_options_from_file(char *filename, in
ppp_option_error("Can't open options file %s: %m", filename);
return 0;
}
+ return 1;
+}
+
+/*
+ * Parse options from an open FILE pointer.
+ */
+static int
+ppp_options_from_fp(FILE *f, const char *filename, int priv)
+{
+ int i, newline, ret;
+ struct option *opt;
+ int oldpriv, n;
+ char *oldsource;
+ char *argv[MAXARGS];
+ char args[MAXARGS][MAXWORDLEN];
+ char cmd[MAXWORDLEN];
oldpriv = privileged_option;
privileged_option = priv;
@@ -1371,7 +1399,7 @@ readable(int fd)
* \<newline> is ignored.
*/
int
-getword(FILE *f, char *word, int *newlinep, char *filename)
+getword(FILE *f, char *word, int *newlinep, const char *filename)
{
int c, len, escape;
int quoted, comment;
@@ -1666,7 +1694,7 @@ callfile(char **argv)
{
char *fname, *arg, *p;
int l, ok;
- char *realname;
+ FILE *f;
arg = *argv;
ok = 1;
@@ -1695,15 +1723,19 @@ callfile(char **argv)
slprintf(fname, l, "%s%s", PPP_PATH_PEERFILES, arg);
ppp_script_setenv("CALL_FILE", arg, 0);
- if (!ppp_check_access(fname, &realname, 1, 0)) {
+ if (!ppp_options_open(fname, 1, 1, &f)) {
+ free(fname);
+ return 0;
+ }
+ if (!ppp_check_access(fileno(f), fname, 0)) {
free(fname);
+ fclose(f);
return 0;
}
- ok = ppp_options_from_file(realname, 1, 1, 1);
+ ok = ppp_options_from_fp(f, fname, 1);
free(fname);
- free(realname);
return ok;
}
--- a/pppd/pppd-private.h
+++ b/pppd/pppd-private.h
@@ -470,7 +470,7 @@ int get_first_ether_hwaddr(unsigned cha
int setipaddr(char *, char **, int); /* Set local/remote ip addresses */
int parse_args(int argc, char **argv);
/* Parse options from arguments given */
-int getword(FILE *f, char *word, int *newlinep, char *filename);
+int getword(FILE *f, char *word, int *newlinep, const char *filename);
/* Read a word from a file */
int options_from_user(void); /* Parse options from user's .ppprc */
int options_for_tty(void); /* Parse options from /etc/ppp/options.tty */
--- a/pppd/pppd.8
+++ b/pppd/pppd.8
@@ -1334,16 +1334,6 @@ file under /etc/ppp/peers, the system ad
establish a ppp connection via a device which they would not normally
have permission to access. Otherwise pppd uses the invoking user's
real UID when opening the device.
-.PP
-To avoid the possibility of privileged options files, secrets files,
-and other files which contain sensitive information being compromised,
-\fIpppd\fR performs a path check on these files before opening them.
-This involves first translating the file path into a real absolute path
-containing no symlinks or ".." components. Then each component from
-the root down is checked to ensure that it is owned by root and that
-its permissions do not permit writing by group or other. Failure to
-conform to these requirements will cause \fIpppd\fR to exit with a
-suitable error message.
.SH AUTHENTICATION
Authentication is the process whereby one peer convinces the other of
its identity. This involves the first peer sending its name to the
--- a/pppd/pppd.h
+++ b/pppd/pppd.h
@@ -300,7 +300,7 @@ void pr_log(void *, char *, ...);
void end_pr_log(void);
/* Check that a file can safely be used */
-int ppp_check_access(const char *path, char **path_to_use, int must_exist, int exec);
+int ppp_check_access(int fd, const char *path, int exec);
/*
* Get the current exist status of pppd
--- a/pppd/utils.c
+++ b/pppd/utils.c
@@ -75,98 +75,50 @@ struct buffer_info {
};
/*
- * Check that a file is owned by root, not writable by group or other,
- * and that all the directories in the path leading to it is likewise
- * owned by root and not writable by group or other. The real path to
- * the file is returned in *path_to_use, which should be freed after
- * use (real meaning not containing any symlinks or ".." components).
+ * Check that a file descriptor is owned by root, not writable by group or
+ * other.
* If exec is true, check for execute permission, otherwise for read
* permission.
+ * Note: the path argument is only used for log messages.
* Returns 1 if OK; if not, prints an error message and returns 0.
*/
int
-ppp_check_access(const char *path, char **path_to_use, int must_exist, int exec)
+ppp_check_access(int fd, const char *path, int exec)
{
- char *rpath, *slash, *part;
struct stat sbuf;
int perm;
- /*
- * Resolve symlinks such that we eliminate a few potential ToCToU
- * attack avenues (eg, changing symlinks).
- */
- rpath = realpath(path, NULL);
- if (!rpath) {
- if (errno == ENOMEM)
- fatal("Insufficient memory for real path");
- if (must_exist || errno != ENOENT)
- error("Can't access %s: %m", path);
- return 0;
+ if (fstat(fd, &sbuf) != 0) {
+ error("Can't stat %v: %m", path);
+ goto err;
}
- /*
- * full check the entire path, must be root: owned, and NOT be writable
- * to group/other (which incorporates FACL bits somehow, so we can ignore
- * explicit FACL checks).
- */
- part = "/";
- slash = rpath;
- for (;;) {
- bool ok = false;
- const char *pname = (slash? part: "it");
-
- if (lstat(part, &sbuf) != 0) {
- if (must_exist || errno != ENOENT) {
- if (!slash) {
- error("Can't access %v: %m", rpath);
- } else {
- error("Can't use %v, because of error accessing", path);
- error("path component %v: %m");
- }
- }
- goto err;
- }
-
- if (sbuf.st_uid != 0) {
- error("Can't safely use %v because %v is not owned by root",
- path, pname);
- goto err;
- }
-
- if (0 != (sbuf.st_mode & (S_IWGRP | S_IWOTH))) {
- error("Can't safely use %v because %v is group or other writable",
- path, pname);
- goto err;
- }
-
- if (!slash)
- break;
-
- *slash = '/';
- part = rpath;
-
- slash = strchr(slash + 1, '/');
- if (slash)
- *slash = 0;
+ if (!S_ISREG(sbuf.st_mode)) {
+ error("Can't use %v: not a regular file", path);
+ goto err;
}
- if (!S_ISREG(sbuf.st_mode)) {
- error("Can't use %v: not a regular file", rpath);
+ if (sbuf.st_uid != 0) {
+ error("Can't safely use %v because it is not owned by root", path);
+ goto err;
+ }
+
+ if (0 != (sbuf.st_mode & (S_IWGRP | S_IWOTH))) {
+ error("Can't safely use %v because it is group or other writable",
+ path);
goto err;
}
perm = exec? S_IXUSR : S_IRUSR;
if ((sbuf.st_mode & perm) == 0) {
- error("Can't use %v: not %sable by root", rpath,
+ error("Can't use %v: not %sable by root", path,
exec? "execut": "read");
goto err;
}
- *path_to_use = rpath;
return 1;
err:
- free(rpath);
return 0;
}
@@ -1,28 +0,0 @@
From f691c224e12ee13a1b317a1838d150f1ffef14a1 Mon Sep 17 00:00:00 2001
From: Mateusz Poliwczak <mpoliwczak34@gmail.com>
Date: Wed, 11 Feb 2026 00:40:14 +0100
Subject: [PATCH] Remove MRU limit on PPPoE (#573)
Fixes #331
Signed-off-by: Mateusz Poliwczak <mpoliwczak34@gmail.com>
---
pppd/plugins/pppoe/plugin.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/pppd/plugins/pppoe/plugin.c b/pppd/plugins/pppoe/plugin.c
index b429a2fd..0f672166 100644
--- a/pppd/plugins/pppoe/plugin.c
+++ b/pppd/plugins/pppoe/plugin.c
@@ -446,11 +446,6 @@ void pppoe_check_options(void)
lcp_allowoptions[0].neg_pcompression = 0;
lcp_wantoptions[0].neg_pcompression = 0;
- if (lcp_allowoptions[0].mru > MAX_PPPOE_MTU)
- lcp_allowoptions[0].mru = MAX_PPPOE_MTU;
- if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU)
- lcp_wantoptions[0].mru = MAX_PPPOE_MTU;
-
/* Save configuration */
conn->storedmtu = lcp_allowoptions[0].mru;
conn->storedmru = lcp_wantoptions[0].mru;