From patchwork Mon Nov 2 09:38:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 5541 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:6022:3119:b0:118:2077:975e with SMTP id e25csp5177235laa; Mon, 2 Nov 2026 01:38:47 -0800 (PST) X-Forwarded-Encrypted: i=2; AKwUvBxj2yD7mqIkRwbCne5P55hVJ8xGSA/0iz2J0xPosf58uXu7IRF1yfCovvE3/OW7gTwU1Zm7EKYEfBw=@openvpn.net X-Received: by 2002:a05:7300:c00f:10b0:36a:1470:da0e with SMTP id 5a478bee46e88-36a423bececmr17800450eec.29.1793612326984; Mon, 02 Nov 2026 01:38:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1793612326; cv=none; d=google.com; s=arc-20260327; b=dkUXbkOioc9p8TApntBzLgXRB60X8PBO8z7hf1zNOSdk0g7XZvVeaMOvx/vfrah9mt 0Wmju2CUSwu4se3s9+SdueuHKOM9ZgPfFP4eEd3L5IYK/7cVL5/32tTk3Gh7KMfaJ+VC BrfyQimFyxMM0o9vpcOaoLtmfkuCwwLkhiJZyMlODCKjCM2ZrRfVZkulmxL1vCrce367 F47WRd8kIj8u5dhX0AmPIxntFvq2XwNtboJbP5Ru8/wPD/0SjCwIMufFasmWCf1O0ib/ HSvdH4U2FWfeamWQ9is4qzJOH+Z2jjCmLKapTYIUB9tfjSR0P5g0xxkLmY6Oo8EQdjuU s9xg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=GszPiThRf1VLygdPXtXKhLdyQeVmLQSiJm9YXOTTA1c=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=jV+NpB1Gs2SBWU8zJT66rfwWy2iZaBfMJDfCjZA+zzphCjEvHYzJaQ2W7sADbsUkLg b0k+fi6AuJb6crNjxliTAymQv9e6nVzwyf0UlOcf8ThLRwZ++mW9WanyNvSW/eENv3xe KoHCQHneuXeCWPKi+FEaXfYSRzu0+wxJSjgAwpZB3y1FM30/kiXtCVaAkUin8IXpfthC svZ8bJ66k1tba6v6ftOIRtM1R6GiM4x8yCeve1fUvoZbuMoeyqsmpaXqj4EJk0qFVcge peEtZA01SnqSZ8tBd7kKabY6AWZANzYLL3Mr2s/l59x82ufbHvBGgcRbyrYvycz92pno a55w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=VFq22ExL; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=QczHMH0l; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=OOrvTFsv; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 5a478bee46e88-36a42a91169si29948027eec.22.2026.11.02.01.38.46 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 02 Nov 2026 01:38:46 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=VFq22ExL; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=QczHMH0l; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=OOrvTFsv; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Unsubscribe-Post: List-Owner; bh=GszPiThRf1VLygdPXtXKhLdyQeVmLQSiJm9YXOTTA1c=; b=VFq22ExLQxRysL JfD8jqz+v5crlg9VX7SV8DnXQDRutQOBoVR3wdqhFN8oODmmvFD+ZldQki7cNEPfylPWnMYsA7HIR eNa38RLbvTyD4yqgKJyNwqgnmwXpePOO4ytZq8Z3oRH2gsOEvKk/U9wueNXsYnd8CP7CmjVcgmaJj qMY=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.100.1) (envelope-from ) id 1xNoV2-000000003Jn-3O6j; Mon, 02 Nov 2026 09:38:44 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.100.1) (envelope-from ) id 1xNoV1-000000003Jb-35Nk for openvpn-devel@lists.sourceforge.net; Mon, 02 Nov 2026 09:38:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Unsubscribe-Post:List-Subscribe:List-Post:List-Owner:List-Archive; bh=wVZ+EO9P5rwvuVAunrt9Pxc2PIDO4rh1VFjHzsQ4viA=; b=QczHMH0lFmSMwv2DpbtC3Cqkp4 3uFPkzSggb3ErEvhZy/hrxgoXEr4ta5u/pPKFdx3ltfMGkORmk3R7qhZmi+wKvH/zfvEIDN+6iCiN uhYeNAOrT7PlkAeptNHDYYwj5BOZJdTHjzDWN32mJgfvwU+gxQffR4hVJnpLH4TWDhZM=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Unsubscribe-Post: List-Subscribe:List-Post:List-Owner:List-Archive; bh=wVZ+EO9P5rwvuVAunrt9Pxc2PIDO4rh1VFjHzsQ4viA=; b=OOrvTFsvTZPToGhHLNvKbeEL8M f6AvkmMbufYzLLdeUEvAAVOW68v86zGSPzGs9xgp/t2Pjctrywx/eDT8i0QdZwoT4R2IGUjATeaFi oiZ4C7gQ1jaAD2cLEnT+VqiOcfTahiPT0HiwzoxXz8jy1WWnwfIBGLq6V8V/Hc/PK7is=; Received: from [193.149.48.129] (helo=blue.greenie.muc.de) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.100.1) id 1xNoV0-000000002Ic-0BIQ for openvpn-devel@lists.sourceforge.net; Mon, 02 Nov 2026 09:38:43 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 6A29cZZv029625 for ; Mon, 2 Nov 2026 10:38:35 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.2/8.18.1/Submit) id 6A29cZVg029624 for openvpn-devel@lists.sourceforge.net; Mon, 2 Nov 2026 10:38:35 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Mon, 2 Nov 2026 10:38:27 +0100 Message-ID: <20261102093834.29593-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Naveed Khan journal_add() creates / with O_CREAT | O_TRUNC and writes the remote client's address into it. The name is predictable (the proxy connection's ephemeral local port) and the [...] Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1xNoV0-000000002Ic-0BIQ Subject: [Openvpn-devel] [PATCH v2] port-share: do not write journal file through symlinks or hardlinks X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1880738839840391027 X-GMAIL-MSGID: 1880738839840391027 From: Naveed Khan journal_add() creates / with O_CREAT | O_TRUNC and writes the remote client's address into it. The name is predictable (the proxy connection's ephemeral local port) and the write is triggered by any TCP client sending non-OpenVPN data to the shared port. Anyone who can create entries in the journal directory can therefore plant symlinks or hardlinks and have the port-share process, which runs as root unless --user is used, truncate and overwrite an arbitrary file with the client address. Create the journal file with O_EXCL | O_NOFOLLOW instead. Entries are removed as soon as the proxied connection is closed, so an existing entry is either a leftover from a proxy process that exited without cleaning up, or something planted. Unlink it and retry the exclusive create once, which keeps the old behavior of replacing stale entries. Also document that the journal directory must not be writable by other users. Github: closes OpenVPN/openvpn#1124 Change-Id: I70ebdadd660e41b40ed53f4238be6885f0a7bb8b Signed-off-by: Naveed Khan Acked-by: Razvan Cojocaru Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2074 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2074 This mail reflects revision 2 of this Change. Acked-by according to Gerrit (reflected above): Razvan Cojocaru diff --git a/doc/man-sections/server-options.rst b/doc/man-sections/server-options.rst index 9dfa6bd..7a09809 100644 --- a/doc/man-sections/server-options.rst +++ b/doc/man-sections/server-options.rst @@ -489,6 +489,10 @@ the origin of the connection. Each generated file will be automatically deleted when the proxied connection is torn down. + The files in ``dir`` are created and removed with the privileges of the + OpenVPN process, so ``dir`` must not be writable by any user other than + the one OpenVPN runs as. + Not implemented on Windows. --push option diff --git a/src/openvpn/ps.c b/src/openvpn/ps.c index 03c6f48..f8cfe1c5 100644 --- a/src/openvpn/ps.c +++ b/src/openvpn/ps.c @@ -341,7 +341,15 @@ check_malloc_return(jfn); snprintf(jfn, fnlen, "%s/%s", journal_dir, t); dmsg(D_PS_PROXY_DEBUG, "PORT SHARE PROXY: client origin %s -> %s", jfn, f); - int fd = platform_open(jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP); + /* never write through a pre-existing symlink or hardlink */ + const int flags = O_CREAT | O_EXCL | O_WRONLY | O_NOFOLLOW; + int fd = platform_open(jfn, flags, S_IRUSR | S_IWUSR | S_IRGRP); + if (fd == -1 && errno == EEXIST) + { + /* stale entry, e.g. left behind by a killed proxy process */ + unlink(jfn); + fd = platform_open(jfn, flags, S_IRUSR | S_IWUSR | S_IRGRP); + } if (fd != -1) { ssize_t write_len = strlen(f);