Received: by 2002:a05:7412:e794:b0:fa:551:50a7 with SMTP id o20csp2839045rdd; Sat, 13 Jan 2024 04:17:26 -0800 (PST) X-Google-Smtp-Source: AGHT+IFP7Jz7OQdiPLMDk4O/qxnOk+CXrRDeI0Ycet38kYiHqgUTxAUpeGf+JFcZEKwGivJRkntW X-Received: by 2002:a05:6a20:2d2a:b0:19a:c05d:bdb2 with SMTP id g42-20020a056a202d2a00b0019ac05dbdb2mr463951pzl.32.1705148246385; Sat, 13 Jan 2024 04:17:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1705148246; cv=none; d=google.com; s=arc-20160816; b=hUOIv/cbC2quS5oPG0mpQng67xgYqb5QQyJEMj62GvVglxsP199yy/MEHOG4MIlgiy /Vs/jYWRTyOOxJ1Gz7UJyRbCIqrJ59kquYS8fVa0UsuN06Diz5XLHpoftYpTY9AKUOkP ur6mZR1Hk/Mbs6SWD293/URK6gA3ja0pkZ0cYuFPSr5jeGyhUbpS7q+khWI3esQyYyuE NEt/0hEaMkH0WVQisBdvgEwBAkj5WorbgAWwhU6GUnyf/neyIVqwEZ0mrsm3ijzghK27 oqh3kTPlzNPotDMdVfH6twACIu6fKsjZ3xDY6Yd25HotLYLpPjvfKjqOnIxpHzyQl97r xrng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature:dkim-filter; bh=UXsO+FATYJuTPtjVESRdxfPqcMfgJ+Z5TRk9Ig/cU7s=; fh=Rd6HdvXkAQOeO9wzvJ4xPYhZ10H20VMbGiok+pAFBP0=; b=rW7mngrucQYonhuJNpm7cSHs279Bob6Yn7spXW7OPSiMf941VeVrUrTXFtXN1oIXkW yf09rXkmQV74ztta860YGmlN9JjvU6mq+unOzmnJJh/FnM6KDJeIbr5yS4UhjKO5pq59 lDLcv/TpiEqnN5mxVsXcBitVriYShdmfnm9ZKYRxN2j0D9b/AFKkiJiBG8L5WjAebnnS UH6N9PeRXlTH8KfHgUChVrsWfXkWEv8++mKV1+IOlNCFIb0E3LpIyJBRXh/BGi6fMuTl RN4IN5DUmGERE1DNAkLnWMif8jabGX58QUnTGtdJR1SkzPcfaX6MZaXXhbIuYRvYBZV3 mItw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ispras.ru header.s=default header.b=rBdODkxM; spf=pass (google.com: domain of linux-kernel+bounces-25283-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-25283-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ispras.ru Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id z14-20020a056a001d8e00b006d9a170f053si5148088pfw.201.2024.01.13.04.17.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 13 Jan 2024 04:17:26 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-25283-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@ispras.ru header.s=default header.b=rBdODkxM; spf=pass (google.com: domain of linux-kernel+bounces-25283-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-25283-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ispras.ru Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id C4DB3B224C2 for ; Sat, 13 Jan 2024 12:17:01 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6B8FF21363; Sat, 13 Jan 2024 12:16:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ispras.ru header.i=@ispras.ru header.b="rBdODkxM" Received: from mail.ispras.ru (mail.ispras.ru [83.149.199.84]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0DE3220DF7; Sat, 13 Jan 2024 12:16:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ispras.ru Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ispras.ru Received: from localhost.ispras.ru (unknown [10.10.165.8]) by mail.ispras.ru (Postfix) with ESMTPSA id E84F740762E4; Sat, 13 Jan 2024 12:16:14 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.ispras.ru E84F740762E4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ispras.ru; s=default; t=1705148175; bh=UXsO+FATYJuTPtjVESRdxfPqcMfgJ+Z5TRk9Ig/cU7s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rBdODkxMg1L5H2zTmGYLSPw2S0CURDXH1HU32selNRUiQC7bDtQiED74SYYfHrq+G 6qL+D97qMSSKzxcWDtVNeZCWKugYZ+eB4jMUvCaDc3TjBixl3RikLhIYO4YlSvIZt6 weSxaEwRWSQ3XwZdgAJK0FCQ2VOZhkjGb8zdm3yA= From: Fedor Pchelkin To: John Johansen Cc: Fedor Pchelkin , Paul Moore , James Morris , "Serge E. Hallyn" , apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Alexey Khoroshilov , lvc-project@linuxtesting.org Subject: [PATCH 2/2] apparmor: fix namespace check in serialized stream headers from the same policy load Date: Sat, 13 Jan 2024 15:15:52 +0300 Message-ID: <20240113121556.12948-3-pchelkin@ispras.ru> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240113121556.12948-1-pchelkin@ispras.ru> References: <20240113121556.12948-1-pchelkin@ispras.ru> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Per commit 04dc715e24d0 ("apparmor: audit policy ns specified in policy load"), profiles in a single load must specify the same namespace. It is supposed to be detected inside aa_replace_profiles() and verify_header(), but seems not to be implemented correctly in the second function. Consider we have the following profile load profile :ns1:profile1 ... {} profile :ns2:profile2 ... {} The profiles specify different policy namespaces but if they are loaded as a single binary where the serialized stream headers contain different namespace values, it eventually leads to the profiles specified with different namespaces be included into the same one without any specific indication to user. *ns is assigned NULL in verify_header(), and the branch indicating an "invalid ns change" message is a dead code. Moreover, some of *ns strings is leaked as they are allocated every time verify_header() reads a namespace string. Actually, *ns is already assigned NULL in aa_unpack(), before the multiple profiles unpacking loop. So make verify_header() check if every new unpacked namespace declaration differs from the previous one in the same load. Note that similar to the namespace check in aa_replace_profiles(), if one profile in the load specifies some namespace declaration in the header and the other one doesn't specify any namespace in the header - it is also considered invalid, e.g. the following multiple profiles load will fail after this patch profile profile1 ... {} profile :ns:profile2 ... {} Found by Linux Verification Center (linuxtesting.org). Fixes: dd51c8485763 ("apparmor: provide base for multiple profiles to be replaced at once") Signed-off-by: Fedor Pchelkin --- security/apparmor/policy_unpack.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 54f7b4346506..5bd8ab7f1c88 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -1120,7 +1120,6 @@ static int verify_header(struct aa_ext *e, int start, const char **ns) { int error = -EPROTONOSUPPORT; const char *name = NULL; - *ns = NULL; /* get the interface version */ if (!aa_unpack_u32(e, &e->version, "version")) { @@ -1142,20 +1141,35 @@ static int verify_header(struct aa_ext *e, int start, const char **ns) return error; } - /* read the namespace if present */ + /* read the namespace if present and check it against policy load + * namespace specified in the data start header + */ if (aa_unpack_str(e, &name, "namespace")) { if (*name == '\0') { audit_iface(NULL, NULL, NULL, "invalid namespace name", e, error); return error; } + + /* don't allow different namespaces be specified in the same + * policy load set + */ + error = -EACCES; if (*ns && strcmp(*ns, name)) { - audit_iface(NULL, NULL, NULL, "invalid ns change", e, + audit_iface(NULL, NULL, NULL, + "policy load has mixed namespaces", e, error); - } else if (!*ns) { + return error; + } else if (!*ns && start) { + /* fill current policy load namespace at data start */ *ns = kstrdup(name, GFP_KERNEL); if (!*ns) return -ENOMEM; + } else if (!*ns) { + audit_iface(NULL, NULL, NULL, + "policy load has mixed namespaces", e, + error); + return error; } } -- 2.43.0