diff --git a/0001-sys-linux-rework-get_first_ethernet.patch b/0001-sys-linux-rework-get_first_ethernet.patch new file mode 100644 index 0000000..b1a29d8 --- /dev/null +++ b/0001-sys-linux-rework-get_first_ethernet.patch @@ -0,0 +1,380 @@ +From 13bd7b8832720f404d7799bc58091a246b77d331 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 9 Apr 2014 09:18:24 +0200 +Subject: [PATCH] sys-linux: rework get_first_ethernet() + +We can't assume that host has ethernet NIC named "eth0". Rather than guessing we +better ask udev. We iterate over symlinks symlinks in /sys/class/net and +for each device we determine if it is ethernet device and additionally we query +udev database for sub-type of the device. If we find PCI or USB device which has +ethernet datalink type and appropriate sub-type we return its name. If we don't +succeed in determining more information about device we will return "good +enough" device which in turn is first device with ethernet datalink type. + +Note that we now have two copies of get_first_ethernet() in the source code. This +is bad and should be fixed in the future. + +This commit replaces ppp-2.4.5-eth.patch. + +Resolves: #682381 +--- + pppd/Makefile.linux | 2 +- + pppd/multilink.c | 4 +- + pppd/plugins/rp-pppoe/Makefile.linux | 2 +- + pppd/plugins/rp-pppoe/pppoe-discovery.c | 117 +++++++++++++++++++++++++++++++- + pppd/pppd.h | 2 +- + pppd/sys-linux.c | 115 +++++++++++++++++++++++++++++-- + 6 files changed, 229 insertions(+), 13 deletions(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index ac782f8..de36b4d 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -34,7 +34,7 @@ endif + CC = gcc + # + COPTS = -Wall $(RPM_OPT_FLAGS) -DLIBDIR=\""$(LIBDIR)"\" +-LIBS = -lutil ++LIBS = -lutil -ludev + + # Uncomment the next 2 lines to include support for Microsoft's + # MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux. +diff --git a/pppd/multilink.c b/pppd/multilink.c +index 135cab0..2f0ed50 100644 +--- a/pppd/multilink.c ++++ b/pppd/multilink.c +@@ -436,12 +436,12 @@ static int + get_default_epdisc(ep) + struct epdisc *ep; + { +- char *p; ++ char *p = NULL; + struct hostent *hp; + u_int32_t addr; + + /* First try for an ethernet MAC address */ +- p = get_first_ethernet(); ++ get_first_ethernet(&p); + if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { + ep->class = EPD_MAC; + ep->length = 6; +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index f5ef9a1..8fc7289 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -31,7 +31,7 @@ CFLAGS=$(COPTS) -I../../../include '-DRP_VERSION="$(RP_VERSION)"' -fPIE + all: rp-pppoe.so pppoe-discovery + + pppoe-discovery: pppoe-discovery.o debug.o +- $(CC) -z now -pie -o pppoe-discovery pppoe-discovery.o debug.o ++ $(CC) -z now -pie -o pppoe-discovery pppoe-discovery.o debug.o -ludev + + pppoe-discovery.o: pppoe-discovery.c + $(CC) $(CFLAGS) -c -o pppoe-discovery.o pppoe-discovery.c +diff --git a/pppd/plugins/rp-pppoe/pppoe-discovery.c b/pppd/plugins/rp-pppoe/pppoe-discovery.c +index 88805f6..21a7333 100644 +--- a/pppd/plugins/rp-pppoe/pppoe-discovery.c ++++ b/pppd/plugins/rp-pppoe/pppoe-discovery.c +@@ -47,8 +47,13 @@ + #include + #endif + ++#include ++#include ++#include ++ + char *xstrdup(const char *s); + void usage(void); ++int get_first_ethernet(char **_r); + + void die(int status) + { +@@ -685,8 +690,15 @@ int main(int argc, char *argv[]) + } + + /* default interface name */ +- if (!conn->ifName) +- conn->ifName = strdup("eth0"); ++ if (!conn->ifName) { ++ char *eth_dev; ++ if (get_first_ethernet(ð_dev) < 0) { ++ fprintf(stderr, "No ethernet device on the host.\n"); ++ exit(1); ++ } ++ conn->ifName = eth_dev; ++ } ++ + + conn->discoverySocket = -1; + conn->sessionSocket = -1; +@@ -726,3 +738,104 @@ void usage(void) + fprintf(stderr, "Usage: pppoe-discovery [options]\n"); + fprintf(stderr, "\nVersion " RP_VERSION "\n"); + } ++ ++/* ++ * get_first_ethernet - return the name of the first ethernet-style ++ * interface on this system. ++ */ ++int ++get_first_ethernet(char **_r) ++{ ++ int r = 0; ++ DIR *d = NULL; ++ struct dirent *entry = NULL; ++ struct udev *udev = NULL; ++ struct udev_device *dev = NULL; ++ char *eth_dev = NULL; ++ ++ d = opendir("/sys/class/net"); ++ if (!d) { ++ fprintf(stderr, "Failed to open dir /sys/class/net : %m\n"); ++ r = -errno; ++ goto fail; ++ } ++ ++ udev = udev_new(); ++ if (!udev) { ++ fprintf(stderr, "Failed to talk to systemd-udevd\n"); ++ r = -EIO; ++ goto fail; ++ } ++ ++ while ((entry = readdir(d)) != NULL) { ++ char syspath[PATH_MAX] = {}; ++ const char *type = NULL; ++ ++ if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) ++ continue; ++ ++ sprintf(syspath, "/sys/class/net/%s", entry->d_name); ++ ++ dev = udev_device_new_from_syspath(udev, syspath); ++ if (!dev) ++ continue; ++ ++ type = udev_device_get_sysattr_value(dev, "type"); ++ if (strcmp(type, "1") == 0) { ++ const char *pci_dev_subclass = NULL, *usb_dev_subclass = NULL; ++ ++ pci_dev_subclass = udev_device_get_property_value(dev, ++ "ID_PCI_SUBCLASS_FROM_DATABASE"); ++ usb_dev_subclass = udev_device_get_property_value(dev, ++ "ID_USB_SUBCLASS_FROM_DATABASE"); ++ ++ if ((pci_dev_subclass && strcmp(pci_dev_subclass, "Ethernet controller") == 0) || ++ (usb_dev_subclass && (strcmp(usb_dev_subclass, "Ethernet Networking") == 0 || ++ strcmp(usb_dev_subclass, "Ethernet Emulation") == 0))) { ++ char *d = NULL; ++ ++ d = strdup(entry->d_name); ++ if (!d) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ free(eth_dev); ++ eth_dev = d; ++ break; ++ } else if (!eth_dev) { ++ eth_dev = strdup(entry->d_name); ++ if (!eth_dev) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ } ++ } ++ ++ udev_device_unref(dev); ++ dev = NULL; ++ } ++ ++ if (dev) ++ udev_device_unref(dev); ++ udev_unref(udev); ++ closedir(d); ++ ++ *_r = eth_dev; ++ ++ return 0; ++ ++fail: ++ if (dev) ++ udev_device_unref(dev); ++ ++ if (udev) ++ udev_unref(udev); ++ ++ if (d) ++ closedir(d); ++ ++ free(eth_dev); ++ ++ return r; ++} +diff --git a/pppd/pppd.h b/pppd/pppd.h +index bbff4c0..7c2eb8f 100644 +--- a/pppd/pppd.h ++++ b/pppd/pppd.h +@@ -676,7 +676,7 @@ int sipxfaddr __P((int, unsigned long, unsigned char *)); + int cipxfaddr __P((int)); + #endif + int get_if_hwaddr __P((u_char *addr, char *name)); +-char *get_first_ethernet __P((void)); ++int get_first_ethernet __P((char **_r)); + + /* Procedures exported from options.c */ + int setipaddr __P((char *, char **, int)); /* Set local/remote ip addresses */ +diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c +index 90ba900..15ec442 100644 +--- a/pppd/sys-linux.c ++++ b/pppd/sys-linux.c +@@ -92,6 +92,9 @@ + #include + #include + #include ++#include ++ ++#include + + /* This is in netdevice.h. However, this compile will fail miserably if + you attempt to include netdevice.h because it has so many references +@@ -1873,10 +1876,101 @@ get_if_hwaddr(u_char *addr, char *name) + * get_first_ethernet - return the name of the first ethernet-style + * interface on this system. + */ +-char * +-get_first_ethernet() +-{ +- return "eth0"; ++int ++get_first_ethernet(char **_r) ++{ ++ int r = 0; ++ DIR *d = NULL; ++ struct dirent *entry = NULL; ++ struct udev *udev = NULL; ++ struct udev_device *dev = NULL; ++ char *eth_dev = NULL; ++ ++ d = opendir("/sys/class/net"); ++ if (!d) { ++ fprintf(stderr, "Failed to open dir /sys/class/net : %m\n"); ++ r = -errno; ++ goto fail; ++ } ++ ++ udev = udev_new(); ++ if (!udev) { ++ fprintf(stderr, "Failed to talk to systemd-udevd\n"); ++ r = -EIO; ++ goto fail; ++ } ++ ++ while ((entry = readdir(d)) != NULL) { ++ char syspath[PATH_MAX] = {}; ++ const char *type = NULL; ++ ++ if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) ++ continue; ++ ++ sprintf(syspath, "/sys/class/net/%s", entry->d_name); ++ ++ dev = udev_device_new_from_syspath(udev, syspath); ++ if (!dev) ++ continue; ++ ++ type = udev_device_get_sysattr_value(dev, "type"); ++ if (strcmp(type, "1") == 0) { ++ const char *pci_dev_subclass = NULL, *usb_dev_subclass = NULL; ++ ++ pci_dev_subclass = udev_device_get_property_value(dev, ++ "ID_PCI_SUBCLASS_FROM_DATABASE"); ++ usb_dev_subclass = udev_device_get_property_value(dev, ++ "ID_USB_SUBCLASS_FROM_DATABASE"); ++ ++ if ((pci_dev_subclass && strcmp(pci_dev_subclass, "Ethernet controller") == 0) || ++ (usb_dev_subclass && (strcmp(usb_dev_subclass, "Ethernet Networking") == 0 || ++ strcmp(usb_dev_subclass, "Ethernet Emulation") == 0))) { ++ char *d = NULL; ++ ++ d = strdup(entry->d_name); ++ if (!d) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ free(eth_dev); ++ eth_dev = d; ++ break; ++ } else if (!eth_dev) { ++ eth_dev = strdup(entry->d_name); ++ if (!eth_dev) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ } ++ } ++ ++ udev_device_unref(dev); ++ dev = NULL; ++ } ++ ++ if (dev) ++ udev_device_unref(dev); ++ udev_unref(udev); ++ closedir(d); ++ ++ *_r = eth_dev; ++ ++ return 0; ++ ++fail: ++ if (dev) ++ udev_device_unref(dev); ++ ++ if (udev) ++ udev_unref(udev); ++ ++ if (d) ++ closedir(d); ++ ++ free(eth_dev); ++ ++ return r; + } + + /******************************************************************** +@@ -2783,6 +2877,7 @@ ether_to_eui64(eui64_t *p_eui64) + struct ifreq ifr; + int skfd; + const unsigned char *ptr; ++ char *eth_dev = NULL; + + skfd = socket_fd(PF_INET6, SOCK_DGRAM, 0); + if(skfd == -1) +@@ -2791,11 +2886,19 @@ ether_to_eui64(eui64_t *p_eui64) + return 0; + } + +- strcpy(ifr.ifr_name, "eth0"); ++ if (get_first_ethernet(ð_dev) < 0) ++ { ++ warn("no ethernet device present on the host"); ++ return 0; ++ } ++ ++ strcpy(ifr.ifr_name, eth_dev); ++ free(eth_dev); ++ + if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) + { + close(skfd); +- warn("could not obtain hardware address for eth0"); ++ warn("could not obtain hardware address for %s", ifr.ifr_name); + return 0; + } + close(skfd); +-- +1.8.3.1 + diff --git a/ppp.spec b/ppp.spec index 1662a9f..bc771e9 100644 --- a/ppp.spec +++ b/ppp.spec @@ -3,7 +3,7 @@ Summary: The Point-to-Point Protocol daemon Name: ppp Version: 2.4.5 -Release: 34%{?dist} +Release: 35%{?dist} License: BSD and LGPLv2+ and GPLv2+ and Public Domain Group: System Environment/Daemons URL: http://www.samba.org/ppp @@ -32,13 +32,13 @@ Patch26: ppp-2.4.5-manpg.patch Patch27: ppp-2.4.5-eaptls-mppe-0.99.patch Patch28: ppp-2.4.5-ppp_resolv.patch Patch29: ppp-2.4.5-man.patch -Patch30: ppp-2.4.5-eth.patch Patch31: ppp-2.4.5-lock.patch Patch32: ppp-2.4.5-l2tp-multilink.patch Patch33: ppp-2.4.5-radius-config.patch Patch34: ppp-2.4.5-crypt.patch Patch35: ppp-2.4.5-hardened.patch Patch36: 0001-pppd-Eliminate-potential-integer-overflow-in-option-.patch +Patch37: 0001-sys-linux-rework-get_first_ethernet.patch BuildRequires: pam-devel, libpcap-devel, openssl-devel, systemd Requires: glibc >= 2.0.6, /etc/pam.d/system-auth, libpcap >= 14:0.8.3-6, systemd @@ -84,8 +84,6 @@ This package contains the header files for building plugins for ppp. %patch27 -p1 -b .eaptls %patch28 -p1 -b .ppp_resolv %patch29 -p1 -b .man -# fixes bz#682381 - hardcodes eth0 -%patch30 -p1 -b .eth # fixes bz#708260 - SELinux is preventing access on the file LCK..ttyUSB3 %patch31 -p1 -b .lock %patch32 -p1 -b .l2tp-multilink @@ -93,6 +91,8 @@ This package contains the header files for building plugins for ppp. %patch34 -p1 -b .crypt %patch35 -p1 -b .hardened %patch36 -p1 -b .cve-2014-3158 +# rewritten fix for bz#682381 - hardcodes eth0 +%patch37 -p1 -b .eth rm -f scripts/*.local rm -f scripts/*.change_resolv_conf @@ -173,6 +173,9 @@ mkdir -p %{_localstatedir}/lock/ppp 2>&1 >/dev/null || : %doc PLUGINS %changelog +* Tue Dec 09 2014 Michal Sekletar - 2.4.5-35 +- replace patch implementing get_first_ethernet with F21 version (#1062419) + * Tue Aug 12 2014 Michal Sekletar - 2.4.5-34 - Fix for CVE-2014-3158