From 9e6dfa05580777a728ec42f2bf4bfaf9994e776a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 12 Aug 2017 15:06:19 +0200 Subject: lib/tun.c: Proper cleanup during tun_new() error paths Change-Id: I285be20df76774ac7258b6edb3d4f2d28703757d --- lib/tun.c | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/lib/tun.c b/lib/tun.c index c4b7d10..6ca9be7 100644 --- a/lib/tun.c +++ b/lib/tun.c @@ -748,7 +748,7 @@ int tun_new(struct tun_t **tun) /* Open the actual tun device */ if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "open() failed"); - return -1; + goto err_free; } /* Set device flags. For some weird reason this is also the method @@ -757,8 +757,7 @@ int tun_new(struct tun_t **tun) ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */ if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "ioctl() failed"); - close((*tun)->fd); - return -1; + goto err_close; } strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ); @@ -780,7 +779,7 @@ int tun_new(struct tun_t **tun) if ((*tun)->fd < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't find tunnel device"); - return -1; + goto err_free; } snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum); @@ -798,7 +797,7 @@ int tun_new(struct tun_t **tun) /* Create a channel to the NET kernel. */ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed"); - return -1; + goto err_close; } /* Delete any IP addresses until SIOCDIFADDR fails */ @@ -812,45 +811,53 @@ int tun_new(struct tun_t **tun) if ((ip_fd = open("/dev/udp", O_RDWR, 0)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't open /dev/udp"); - return -1; + goto err_free; } if (((*tun)->fd = open("/dev/tun", O_RDWR, 0)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't open /dev/tun"); - return -1; + close(ip_fd); + goto err_free; } /* Assign a new PPA and get its unit number. */ if ((ppa = ioctl((*tun)->fd, TUNNEWPPA, -1)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't assign new interface"); - return -1; + goto sun_close_ip; } if ((if_fd = open("/dev/tun", O_RDWR, 0)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't open /dev/tun (2)"); - return -1; + goto sun_close_ip; } if (ioctl(if_fd, I_PUSH, "ip") < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't push IP module"); - return -1; + goto sun_close_if; } /* Assign ppa according to the unit number returned by tun device */ if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't set PPA %d", ppa); - return -1; + goto sun_close_if; } /* Link the two streams */ if ((muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0) { SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't link TUN device to IP"); - return -1; + goto sun_close_if; + } + + /* Link the two streams */ + if ((muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0) { + SYS_ERR(DTUN, LOGL_ERROR, errno, + "Can't link TUN device to IP"); + goto sun_close_if; } close(if_fd); @@ -866,7 +873,7 @@ int tun_new(struct tun_t **tun) ioctl(ip_fd, I_PUNLINK, muxid); SYS_ERR(DTUN, LOGL_ERROR, errno, "Can't set multiplexor id"); - return -1; + goto sun_close_ip; } /* if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) @@ -874,10 +881,22 @@ int tun_new(struct tun_t **tun) return 0; +sun_close_if: + close(if_fd); +sun_close_ip: + close(ip_fd); + goto err_close; + #else #error "Unknown platform!" #endif +err_close: + close((*tun)->fd); +err_free: + free(*tun); + *tun = NULL; + return -1; } int tun_free(struct tun_t *tun) -- cgit v1.2.3