From patchwork Mon Jun 24 15:49:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709760 Received: from mail-yw1-f170.google.com (mail-yw1-f170.google.com [209.85.128.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5713954276 for ; Mon, 24 Jun 2024 15:50:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244242; cv=none; b=MdEHe/8C5EdYLCBO7axrFUY3jBtrxu4HjcuNb7DuL3FtOTNfdFyx+CHEQhzSDlGTleoGAv97UR9jvYl+5eYweffQtZYrgbRvUv/Ir7n5u7VInLWsHMEALDfVrEvwJlf4hGQFqoHSrAizG2GLRL8dhKJYwTNvGj38U+TriSjHam8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244242; c=relaxed/simple; bh=NKlVLeAlB/O4BqR1dTzw3WF3hpAo8lWj2ebWanDhls4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aZ44vmffCfr/nmBf1S3knA0urdX1d7lvj65eVlC4UGd4+pqT3ocbXZnlLuKcfAD5FOsfoXpAyGUsqeaSw0FLIRJK0RFnspH782GSIghh59DhcbTGzbBQOC5RXVzn0q0N9rfSbIy6EHgYr1eNJIVU4jOdD/5TGUoRoiartfqN950= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=bIpyUH9u; arc=none smtp.client-ip=209.85.128.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="bIpyUH9u" Received: by mail-yw1-f170.google.com with SMTP id 00721157ae682-63bd10df78dso41713647b3.2 for ; Mon, 24 Jun 2024 08:50:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244240; x=1719849040; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=qkm1rXAti7t12K0xpdW01teSJVvN4Hn65SQw4TAqa5U=; b=bIpyUH9urYxtJVtLhGRxI63reAH4p8RRgk4Razn4lcF1VefXL+oAmWoofsA9i8bkBX QCUsGGRrorzk3+wUtTQTZxSlPmy2kfskGqEoci3TgkgcaD5xgXf1btYGQfzEajLpQNvj ny3AJ09a74ahjkt7eFzaUiHfBhUoEgXJl3VfUzDu0fW1fht7in2q0SCjA52b/rduC4jE 6dNSn+X95CLws+Ty7fGdI+Mz3Y176biRAAhxGblvY2hjnJe0XPm3v/V3ljR2c0RRfc7d oG+2VRxu+IHqFVv7wvKjAKZobNSP7frTQtENm3mqsltNJY9Ak/SOBVDjT7+phMVpis+h SWKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244240; x=1719849040; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qkm1rXAti7t12K0xpdW01teSJVvN4Hn65SQw4TAqa5U=; b=TrD8JLWYoejFuYtVBhplercRjdM9bro12eJZYlUcLWbFbb/eR34An2PBu1yVjF9UA4 N3eTS6OVuQ0+PAP2IuFso/StNxtvEzdtxd82pM8pweiZqrGt/LfBgx6jkPNMbdXhTFKc BeC2s4RrjQF/xaSMrL6SCWFQgVBhnNpL6nPcj1tOKmhCj41vbzvn6lVWr1YlDzZnrA2u sHSeAy2JMO3zHoPvBOTR2n7sHfvxk7tJcy6sl3pdOV3sf7iNMOI0hLMu8x2RzRwm3t0S SsVrZq+y+7m4PtILtiym7XTGocHxZC5vQxRhd4gdoxSv4zd1FkM0Nxuxvfk1TjRu8o7a tm7A== X-Gm-Message-State: AOJu0Yw+vEM+2LuERoQOnzeKP1BhPeWSNJhzt3L9BqaD5NB8WZ/8fq5F CRnr15AgdWI3mnGggjqRR4Qgy8Ht8x0VC7ehHaEPBovN9jCPBhOfwg1NcPGraQsGwy8ScJ3aig8 D X-Google-Smtp-Source: AGHT+IGl01cxu0A+BNMzJ7rD+/DpNgA2kt0JVSdstEnb1cOoFJhIiX3z9uZSWjq7GjFfQ7nZ6q0U/w== X-Received: by 2002:a81:ad26:0:b0:645:25d:b741 with SMTP id 00721157ae682-645026cf997mr27543967b3.11.1719244240220; Mon, 24 Jun 2024 08:50:40 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 00721157ae682-63f1192454fsm29770147b3.39.2024.06.24.08.50.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:39 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 1/8] fs: relax permissions for listmount() Date: Mon, 24 Jun 2024 11:49:44 -0400 Message-ID: <8adc0d3f4f7495faacc6a7c63095961f7f1637c7.1719243756.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christian Brauner It is sufficient to have capabilities in the owning user namespace of the mount namespace to list all mounts regardless of whether they are reachable or not. Signed-off-by: Christian Brauner --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 4238c886394d..253cd8087d4e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -5107,7 +5107,7 @@ static ssize_t do_listmount(u64 mnt_parent_id, u64 last_mnt_id, u64 *mnt_ids, * mounts to show users. */ if (!is_path_reachable(real_mount(orig.mnt), orig.dentry, &root) && - !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) + !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) return -EPERM; ret = security_sb_statfs(orig.dentry); From patchwork Mon Jun 24 15:49:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709761 Received: from mail-qk1-f182.google.com (mail-qk1-f182.google.com [209.85.222.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3BE119D09C for ; Mon, 24 Jun 2024 15:50:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244244; cv=none; b=S2w7FngF3y464iqznEdet7EaXF/Wc4DJgslCzCohWq3UMTI5pNA6z4mj+31POM4oPERORH3z9NWqFDw8pBxb/P0MVAq73Ac9xcy0DNzp/IAe44QLggMR+OQASVAEznSSlV1De6VZnUNzXpSaqblRsRi4sgFLThifI8Ti/8U8rFg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244244; c=relaxed/simple; bh=K+A2IEqmBZeJw1GjB89iMPUcRsnzPu0hHoAFUAYhBvw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MpeSHTtjXP9Cp9/rC4CqlFko2/GZ8HU0anXbW8zmyoG666DZHaw/TmNmchwbLDif+Py3r6hit+tv8ohSG6hmiS0OSsTMiKwyriGSERW6yJB6utKOpdnFP91ph+ih52VnQfnk4Kh5H/N+xorZE8c7f/FLuejtbolHqLAZWBwYQwk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=Pt4hFpqq; arc=none smtp.client-ip=209.85.222.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="Pt4hFpqq" Received: by mail-qk1-f182.google.com with SMTP id af79cd13be357-797f2d8b408so301008985a.1 for ; Mon, 24 Jun 2024 08:50:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244241; x=1719849041; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=6flFxXVVqJLCrwleRzZ+Be3V8Fb6aljcx7RgVVG27BY=; b=Pt4hFpqqtQFv2cCkoJ+umBpGX8X2V1UZTg4vCpNFvzXnlSnZbRkSuTrI/vkFR0YS4l fvn6x/ojHBGw+0EpBUwR3LSwEvhbNpCYQE3md1ezW+4Cvy4hvLiMQWDzMuN+etuTMxbo ufjPYWS+GujpL2+nujdjJ5rIVt3f/Zt7u/5sk/3SukZrg+wyqEc6NKDWrC6IpQpS7vAK CbWF/1/3D0eJ9+jMG9xC9ChJOHzXwfXI+k03iofL0GAkRN+aDjBp2l3cBLKsULVgrFHb A7mFG4hWvUA+2PPI+NDPL0N/RAoMO6TjlaJGopOej2MvDHbsALtPEITzVddUhNSQys2x megQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244241; x=1719849041; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6flFxXVVqJLCrwleRzZ+Be3V8Fb6aljcx7RgVVG27BY=; b=eA3Yx7lLS+ad6DvUiPhKxrvHjKZssqeflX+7LzGkkN+QuQ+YPVz8R32ZcNbzGuELl8 N58GipJHaMCvRwQiNls6KWtQImVPU0ICjRxX1rDFOeSeXOpYj7TT0nt6XI/BI+CVTYN2 Bdf70/zvVwPdef7lcHREDVzXntS5h3zMBG97sbRWpauFjNTXwIMPyRfjzxv8+M3Y+CDF 7lrJDYm4BmLa36R7NKkxS3Eww+FO2MqzMqzpahoG7UOp4bq6TlCE7oeXdX5kL79zCUFl NTd+TWxqCw8ZyrlJMUEilJ0pTl0DuWa9iIIODQKxRYX2VfMMFJu6kWnjqo1mQi/bc0Cw SNdA== X-Gm-Message-State: AOJu0YxcAIG4kLAMciv73F5Q73vFmWnuhXQXXTdeBuDpCMDPoFyYwPdP FehIzOKnWlgy4gHwLAUPfyRJs5KjL0Qt0wtA/vRuAKJWjYP0g/1yFwg7JfniE4XIO93lpThlF52 Z X-Google-Smtp-Source: AGHT+IEaqtS08rspOq71bml1N+L7TsL4csT1IcVHvWCuQ4XJlL3xpw9EKFakg6+JBoecluoS6QcRVQ== X-Received: by 2002:a05:620a:318a:b0:795:573d:6192 with SMTP id af79cd13be357-79be702b585mr654482685a.77.1719244241335; Mon, 24 Jun 2024 08:50:41 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id af79cd13be357-79bce91d8bdsm323771985a.76.2024.06.24.08.50.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:41 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 2/8] fs: relax permissions for statmount() Date: Mon, 24 Jun 2024 11:49:45 -0400 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christian Brauner It is sufficient to have capabilities in the owning user namespace of the mount namespace to stat a mount regardless of whether it's reachable or not. Signed-off-by: Christian Brauner --- fs/namespace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 253cd8087d4e..45df82f2a059 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4933,6 +4933,7 @@ static int copy_statmount_to_user(struct kstatmount *s) static int do_statmount(struct kstatmount *s) { struct mount *m = real_mount(s->mnt); + struct mnt_namespace *ns = m->mnt_ns; int err; /* @@ -4940,7 +4941,7 @@ static int do_statmount(struct kstatmount *s) * mounts to show users. */ if (!is_path_reachable(m, m->mnt.mnt_root, &s->root) && - !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) + !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) return -EPERM; err = security_sb_statfs(s->mnt->mnt_root); From patchwork Mon Jun 24 15:49:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709762 Received: from mail-yw1-f177.google.com (mail-yw1-f177.google.com [209.85.128.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A6DF19D885 for ; Mon, 24 Jun 2024 15:50:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244245; cv=none; b=RbIJoDp6NKeXZraT7c738SfYTgY0j6dcFquzPCrEOrDyQgTECsehtudljIftwQj4BCorTViOWy5mSI94ZBcRksH2T2o09Y9V+eoj3u2DmVi3ccAhI30sTkUosJOpAXdmVBtPicbG4yG3iyZWITChCBaGdR8XRaixZZlh4EvYR0Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244245; c=relaxed/simple; bh=zTg9qQu1Q9PfFTRVh7ZIBSS+v7sQuQTOSzFfZLxIEzw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Mj/uvbPckOG5OrI5xkEVCQ/dLqerV5GJdxvGXBuMThsGBPU+oHFPy24OZfILdslrwWbNM7oN/KaFFeZYLRYW/IeSRv0ZwtBeT6uzOxvBTV+5u/sZHIP/ysZrPsGlNGNzrj6QRopF/g4n8M52l3tQPXheaVRyWmwjB54zw1sAl6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=ywMPHRLN; arc=none smtp.client-ip=209.85.128.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="ywMPHRLN" Received: by mail-yw1-f177.google.com with SMTP id 00721157ae682-63bc513ade5so35495737b3.3 for ; Mon, 24 Jun 2024 08:50:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244242; x=1719849042; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=aGXgHLDoX3hzupbKihgZmrg0zvt9l8kNFstnfMyRs4I=; b=ywMPHRLNc5hNVJV1pVLjiDz1gaP8jqM1eeZxl/iITPqYWHvGAcfz/E0n0+MCccGdVT 6Ndsi2r028Cc8stXXTnpdmJU3Jxb4KjejuduKsHcpSyJ5tgUPbcQUOI6KoTqi403eUHj GNfy3oXghWxRGvw42L1aHFgHbXP2AyLtKMuitvcGoNw1h7X8b7xFMajQUZwuBtsdK8Zk 169GZwjKYxfjctjUKMuRxJaftwbjh128uCfKqeTm3QaPgnSZ3Vngsf1ilUTgEuRSiQ6w 0u+HdisaRgAPazAgGtOFR0OjezI4RuzF47lhAhIeBJQMCod8qZA9tp7PDbAcTxgLM7jY 5WmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244242; x=1719849042; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aGXgHLDoX3hzupbKihgZmrg0zvt9l8kNFstnfMyRs4I=; b=Ile9a/dJXrBCkDpA9KBSeADfj4JxwLWqi8sDdYhcGE5iJQNKVadVlIrNm8XXIiaaJE tKUIel0+1IQVmfuT1NBmplQWfMvJs6WEzv3MW1ku2gQ4YQ0ZtmhFWmPyif/jxmj45f+N iEYGnj3q8oUu32Te7zc/sE45NYcJOgcxNrlI9G7tN4YwhA1wFv/DmSKYx/FISQpSusAs mYcI6XiEvmSefjSboOsgSsI6jKvXW1HLRPrdKlZaZpPkHp0xkR+XKG/p2T7u2xK/63fX 7WM+1ZTdH9NiACd8IkE+pS5NLrTsVTjFEJQqVRaS+/FYWKRjiOWsc+BWrZC1u8DaV1Ve w9Pw== X-Gm-Message-State: AOJu0YyBSqmYnPg4O5MPp/o7Cxenrd3GhpgYaAG0fuEWzwkjRdVN8ZjZ sfMrZa5GCPboDBmGrF0p43iwgMKCwfxZQRLQNe5niOXp9MfBEv6JWtrj9ofL4gH1M03R3NJGhME R X-Google-Smtp-Source: AGHT+IG2EDUM3icEp6NwDWZ4vGDXcxUbczZAi0r6lPd/6j9tfFhMZQODGPxohoQzz5SSg3x0e1vYxA== X-Received: by 2002:a81:b65b:0:b0:632:a329:921b with SMTP id 00721157ae682-643aa5a2029mr46523947b3.1.1719244242457; Mon, 24 Jun 2024 08:50:42 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 00721157ae682-63f14a3caa9sm29236307b3.86.2024.06.24.08.50.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:42 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 3/8] fs: keep an index of current mount namespaces Date: Mon, 24 Jun 2024 11:49:46 -0400 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to allow for listmount() to be used on different namespaces we need a way to lookup a mount ns by its id. Keep a rbtree of the current !anonymous mount name spaces indexed by ID that we can use to look up the namespace. Co-developed-by: Christian Brauner Signed-off-by: Josef Bacik Signed-off-by: Christian Brauner --- fs/mount.h | 2 + fs/namespace.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/fs/mount.h b/fs/mount.h index 4adce73211ae..ad4b1ddebb54 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -16,6 +16,8 @@ struct mnt_namespace { u64 event; unsigned int nr_mounts; /* # of mounts in the namespace */ unsigned int pending_mounts; + struct rb_node mnt_ns_tree_node; /* node in the mnt_ns_tree */ + refcount_t passive; /* number references not pinning @mounts */ } __randomize_layout; struct mnt_pcp { diff --git a/fs/namespace.c b/fs/namespace.c index 45df82f2a059..babdebdb0a9c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -78,6 +78,8 @@ static struct kmem_cache *mnt_cache __ro_after_init; static DECLARE_RWSEM(namespace_sem); static HLIST_HEAD(unmounted); /* protected by namespace_sem */ static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */ +static DEFINE_RWLOCK(mnt_ns_tree_lock); +static struct rb_root mnt_ns_tree = RB_ROOT; /* protected by namespace_sem */ struct mount_kattr { unsigned int attr_set; @@ -103,6 +105,109 @@ EXPORT_SYMBOL_GPL(fs_kobj); */ __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock); +static int mnt_ns_cmp(u64 seq, const struct mnt_namespace *ns) +{ + u64 seq_b = ns->seq; + + if (seq < seq_b) + return -1; + if (seq > seq_b) + return 1; + return 0; +} + +static inline struct mnt_namespace *node_to_mnt_ns(const struct rb_node *node) +{ + if (!node) + return NULL; + return rb_entry(node, struct mnt_namespace, mnt_ns_tree_node); +} + +static bool mnt_ns_less(struct rb_node *a, const struct rb_node *b) +{ + struct mnt_namespace *ns_a = node_to_mnt_ns(a); + struct mnt_namespace *ns_b = node_to_mnt_ns(b); + u64 seq_a = ns_a->seq; + + return mnt_ns_cmp(seq_a, ns_b) < 0; +} + +static void mnt_ns_tree_add(struct mnt_namespace *ns) +{ + guard(write_lock)(&mnt_ns_tree_lock); + rb_add(&ns->mnt_ns_tree_node, &mnt_ns_tree, mnt_ns_less); +} + +static void mnt_ns_release(struct mnt_namespace *ns) +{ + lockdep_assert_not_held(&mnt_ns_tree_lock); + + /* keep alive for {list,stat}mount() */ + if (refcount_dec_and_test(&ns->passive)) { + put_user_ns(ns->user_ns); + kfree(ns); + } +} +DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, if (_T) mnt_ns_release(_T)) + +static void mnt_ns_tree_remove(struct mnt_namespace *ns) +{ + /* remove from global mount namespace list */ + if (!is_anon_ns(ns)) { + guard(write_lock)(&mnt_ns_tree_lock); + rb_erase(&ns->mnt_ns_tree_node, &mnt_ns_tree); + } + + mnt_ns_release(ns); +} + +/* + * Returns the mount namespace which either has the specified id, or has the + * next smallest id afer the specified one. + */ +static struct mnt_namespace *mnt_ns_find_id_at(u64 mnt_ns_id) +{ + struct rb_node *node = mnt_ns_tree.rb_node; + struct mnt_namespace *ret = NULL; + + lockdep_assert_held(&mnt_ns_tree_lock); + + while (node) { + struct mnt_namespace *n = node_to_mnt_ns(node); + + if (mnt_ns_id <= n->seq) { + ret = node_to_mnt_ns(node); + if (mnt_ns_id == n->seq) + break; + node = node->rb_left; + } else { + node = node->rb_right; + } + } + return ret; +} + +/* + * Lookup a mount namespace by id and take a passive reference count. Taking a + * passive reference means the mount namespace can be emptied if e.g., the last + * task holding an active reference exits. To access the mounts of the + * namespace the @namespace_sem must first be acquired. If the namespace has + * already shut down before acquiring @namespace_sem, {list,stat}mount() will + * see that the mount rbtree of the namespace is empty. + */ +static struct mnt_namespace *lookup_mnt_ns(u64 mnt_ns_id) +{ + struct mnt_namespace *ns; + + guard(read_lock)(&mnt_ns_tree_lock); + ns = mnt_ns_find_id_at(mnt_ns_id); + if (!ns || ns->seq != mnt_ns_id) + return NULL; + + refcount_inc(&ns->passive); + return ns; +} + static inline void lock_mount_hash(void) { write_seqlock(&mount_lock); @@ -3736,8 +3841,7 @@ static void free_mnt_ns(struct mnt_namespace *ns) if (!is_anon_ns(ns)) ns_free_inum(&ns->ns); dec_mnt_namespaces(ns->ucounts); - put_user_ns(ns->user_ns); - kfree(ns); + mnt_ns_tree_remove(ns); } /* @@ -3776,7 +3880,9 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool a if (!anon) new_ns->seq = atomic64_add_return(1, &mnt_ns_seq); refcount_set(&new_ns->ns.count, 1); + refcount_set(&new_ns->passive, 1); new_ns->mounts = RB_ROOT; + RB_CLEAR_NODE(&new_ns->mnt_ns_tree_node); init_waitqueue_head(&new_ns->poll); new_ns->user_ns = get_user_ns(user_ns); new_ns->ucounts = ucounts; @@ -3853,6 +3959,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, while (p->mnt.mnt_root != q->mnt.mnt_root) p = next_mnt(skip_mnt_tree(p), old); } + mnt_ns_tree_add(new_ns); namespace_unlock(); if (rootmnt) @@ -5208,6 +5315,8 @@ static void __init init_mount_tree(void) set_fs_pwd(current->fs, &root); set_fs_root(current->fs, &root); + + mnt_ns_tree_add(ns); } void __init mnt_init(void) From patchwork Mon Jun 24 15:49:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709763 Received: from mail-yb1-f180.google.com (mail-yb1-f180.google.com [209.85.219.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB22119D899 for ; Mon, 24 Jun 2024 15:50:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244246; cv=none; b=oL+YrXuPm/P1htFoK5whDCxzFGukliS5nBZz9+f9GPP0vs/QvaDEeEMh8an+WcdWvU0fIG2+uHnipBRtJpQ2EMakX6VuuK9P7ahyjMfMdzd4g+TmIrUu85wM96jaKuRjcWXoip2OnKQHhaowPABp8baKtOXOPkFFIadwgMQr5OM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244246; c=relaxed/simple; bh=cDqLNf/uHwQJgBA4MP4M3lkhBs6hll14MGN6bLjx9EU=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YUTSAGhk3QT9jY0shHMEN0aDmPLhXF/a9Bf9napJ+snCAW9ExL4B8hI1SXwQ26Gqg6vwC2e7tnYPKEjJe8fGx6OlhpC9lGNF0B+/XNkINtzB/z488vjC+S1zBAYmrfszDo4+84R7ipAugieQ5iIf1GSzpBo3nGDiph5um6wplxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=WKfL22pB; arc=none smtp.client-ip=209.85.219.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="WKfL22pB" Received: by mail-yb1-f180.google.com with SMTP id 3f1490d57ef6-dfb05bcc50dso3898758276.0 for ; Mon, 24 Jun 2024 08:50:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244244; x=1719849044; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=uonl2vdPq4IuhaBPRJ328Klo99SK+IsfHoHDMlx1/Ho=; b=WKfL22pBSs8xbQDSNthirpZlTrjWNToTYrmVXBnc38Zcq3/kSsp2/pGKSe6b2T7TvT b9+YE0JXnNykH91pzkhi904r114efcZE3yxxZGnjDv1n2XVXULGRncbC5rcWEkL/RDnA nlDaZw1bLoCJgsngu2i8gPHgNYtnXBTC8tqj5Z3abvlkSVnASdbfZg8ScMDSyhVcyu8G cU2SFhnvL8343/9rIIiS+dScDzypMNfj8cSMK228HgF8563GJvm3zjKanVyfl6O7PZAj nBKRRhf8KYiHPPgqXRxXH2dJh/2zGoOKrez2OJs48TVMtXhVBmDhu20gvJTU9QYVDYKP X4Vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244244; x=1719849044; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uonl2vdPq4IuhaBPRJ328Klo99SK+IsfHoHDMlx1/Ho=; b=JhZXOy0hBsuKlYDecbYMUN23QZ1zs4vio+QCORZH/N9BaXbJmUPJBGaMe5Eyzh/pRo BsW5eKbeWPnw9MW5YcavOSwVEUlDHcAdXS8FT6BY4UluFYRIKinekX+R59F5bDamAJyR 8eEGIyP/tAxor+f0+RkTVwtcWilRiIIPr0LNe2bIMxWacJuynZpbXF2JE3ttDSXi6lYr EdUFjlinOf29Gxb3CM3QtFUbYa1FdHL4uXrlisVIpDrlptCN+BSk1vGTpqxgxyGXib8v r5q35D2TylotUojCpUsNZh00/EylVDExBrTzsI5mLlLCPlSUFPU2enY+J5xpyU0c+hzr snHA== X-Gm-Message-State: AOJu0YyIGBui5DD+vrtlKBs/wfjmQFkQsIT6TlrkThSlhBCtVzYEuz/V SOCGADQyxaArJoy9nblDS9k6V81l453cRXXc9V+RBuAyqCqm1ycMl0W7fMMvUHaELEnhQTvEftz E X-Google-Smtp-Source: AGHT+IGJliiVscHdOz5cUJ+TuarqpY8oEcuNMKbogxpMbrY4+abQd3RFGImTeUQypg2UvTYm8/NxwA== X-Received: by 2002:a25:dc84:0:b0:dfb:bf0:59db with SMTP id 3f1490d57ef6-e0303fc13acmr4825303276.41.1719244243635; Mon, 24 Jun 2024 08:50:43 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-e02e623f0f2sm3394395276.25.2024.06.24.08.50.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:43 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 4/8] fs: export the mount ns id via statmount Date: Mon, 24 Jun 2024 11:49:47 -0400 Message-ID: <6dabf437331fb7415d886f7c64b21cb2a50b1c66.1719243756.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to allow users to iterate through children mount namespaces via listmount we need a way for them to know what the ns id for the mount. Add a new field to statmount called mnt_ns_id which will carry the ns id for the given mount entry. Co-developed-by: Christian Brauner Signed-off-by: Josef Bacik Signed-off-by: Christian Brauner --- fs/namespace.c | 11 +++++++++++ include/uapi/linux/mount.h | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index babdebdb0a9c..3c6711fec3cd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4977,6 +4977,14 @@ static int statmount_fs_type(struct kstatmount *s, struct seq_file *seq) return 0; } +static void statmount_mnt_ns_id(struct kstatmount *s) +{ + struct mnt_namespace *ns = current->nsproxy->mnt_ns; + + s->sm.mask |= STATMOUNT_MNT_NS_ID; + s->sm.mnt_ns_id = ns->seq; +} + static int statmount_string(struct kstatmount *s, u64 flag) { int ret; @@ -5073,6 +5081,9 @@ static int do_statmount(struct kstatmount *s) if (!err && s->mask & STATMOUNT_MNT_POINT) err = statmount_string(s, STATMOUNT_MNT_POINT); + if (!err && s->mask & STATMOUNT_MNT_NS_ID) + statmount_mnt_ns_id(s); + if (err) return err; diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index 88d78de1519f..a07508aee518 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -172,7 +172,8 @@ struct statmount { __u64 propagate_from; /* Propagation from in current namespace */ __u32 mnt_root; /* [str] Root of mount relative to root of fs */ __u32 mnt_point; /* [str] Mountpoint relative to current root */ - __u64 __spare2[50]; + __u64 mnt_ns_id; /* ID of the mount namespace */ + __u64 __spare2[49]; char str[]; /* Variable size part containing strings */ }; @@ -202,6 +203,7 @@ struct mnt_id_req { #define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */ #define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */ #define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */ +#define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */ /* * Special @mnt_id values that can be passed to listmount From patchwork Mon Jun 24 15:49:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709764 Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DF90119D8A5 for ; Mon, 24 Jun 2024 15:50:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244247; cv=none; b=DYif1p8FrdK7qbGHsUyYVMtCb9HGu7K2LBc5IuY9BFM/U4TnPeqYgUJgxfCP9qURGhR2SbX2lPwa8UnLXAUrlyQlAfr6OqpIXshgr/NB+LauH2/MlgIhH6UPMM2qhVO0SODir7/l9rVUnkuReosGFUBgBC+Ls8PuzWDAWqPPqVE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244247; c=relaxed/simple; bh=38LHEfgALOYC66sa1e+K/n/lc4uBFNnqfHrvdHUL1oU=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lkjjJxGgn6sAPvBPPMgatKX3OITrl482mD37H2tRH9uuYQsMB65aNhOXbx1pLF6hRfu1bIrFmPmg5e42+ZcjTCcz7vpFgebOoX3rOTVIByzPuYS8NJS25sG8T6sxuZiO7/R9h+6amqjo65Pk1Tic07L5RfFuw/EZ/7tk1pqlhMU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=lSxD/iBK; arc=none smtp.client-ip=209.85.222.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="lSxD/iBK" Received: by mail-qk1-f181.google.com with SMTP id af79cd13be357-797dcb558ebso279233785a.2 for ; Mon, 24 Jun 2024 08:50:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244245; x=1719849045; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=SByAZNLq5sTtspyyUJQCXuY/e1cubv1bllAaHfOCEUA=; b=lSxD/iBKe+NmS+9vps4LiDo0GFFxDJ8d0mv4CWV/RWglVoEDujC+pBKKhtvGdpVG64 v1rhAzsPA7iRv9EinqSY9+Sd9nV+kal8e00OLfbWAxrL0po1oQ4mYTS6KmG1pamnGE9S nshuY6hMuVrka1jGw1JTHdXgHsG5BvhnSCV9DOBEWOLk1vTUsjGGUXkJ/kFAAdtOzTnh MD0Ap/I1dATd83uwI7sygHEUt+trHYQ2VtQAFotlaLjTXfDZvz974fNQF13ZrJycnXaZ DPwbwmPh+XGt9ykMH6kVGDHrkuG9KanDTocSnV1vCcLCDlOzkl4NOsgJ5mqJoUWtdSsa 1PNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244245; x=1719849045; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SByAZNLq5sTtspyyUJQCXuY/e1cubv1bllAaHfOCEUA=; b=kx+g3D3JZ6VZFkhXz/VYs/amnGhAtLP6kIpFZuRzfzn/IIjFbvC2n2FDCpS4y38Dmz d/SP6gzmMEjzdryVhibV2pTmA4u1PxnVGe7Za/sAZuyYoWlz1lWyFWkODYz/bObi/gkf WYix9RNGuTtt9RTNq1QMWS48A0meLm2vEMuMLYJP0kOkW61ISL3JShqP6c4d95waLW4N K/o4A57ie0s6sItJm39Lj8/qS7CwDWALgCGBq09GXQLE0XIn3LGlTTAcpKzl/LDa0A4v yrqxzDC6nViPu00x0urT/vqA7jFg4L46PGyrsknibgou2RsjUfZx+I7CdfHJgBzkxeMB AbUA== X-Gm-Message-State: AOJu0YxFPFLyXNKk6WEu4VNvUMGlTHUAUAllSOLb8kfmES3qgPq1lLV6 hJVNYSO6iLiNZmaRqoRV3Am6G+q4sXbILdwCuVbjw+B2kyi2B4o641v4VlTYF9dVT3d0SLJnDql P X-Google-Smtp-Source: AGHT+IHFJvs5Y62A4s2+4NyD91rMTfDMUQMyM96uSFMGWMijNiyZvoyZ2a3OpABQ3ov2M0eFA1Aicw== X-Received: by 2002:a05:622a:114:b0:440:c5bc:db7e with SMTP id d75a77b69052e-444d932b0b7mr44519051cf.66.1719244244738; Mon, 24 Jun 2024 08:50:44 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-444c2c3d97esm43764861cf.62.2024.06.24.08.50.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:44 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 5/8] fs: Allow listmount() in foreign mount namespace Date: Mon, 24 Jun 2024 11:49:48 -0400 Message-ID: <49930bdce29a8367a213eb14c1e68e7e49284f86.1719243756.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christian Brauner Expand struct mnt_id_req to add an optional mnt_ns_id field. When this field is populated, listmount() will be performed on the specified mount namespace, provided the currently application has CAP_SYS_ADMIN in its user namespace and the mount namespace is a child of the current namespace. Co-developed-by: Josef Bacik Signed-off-by: Christian Brauner Signed-off-by: Josef Bacik --- fs/namespace.c | 88 ++++++++++++++++++++++++++++++-------- include/uapi/linux/mount.h | 2 + 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 3c6711fec3cd..1b422fd5f267 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -5125,7 +5125,7 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req, int ret; size_t usize; - BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER0); + BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER1); ret = get_user(usize, &req->size); if (ret) @@ -5143,6 +5143,58 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req, return 0; } +static struct mount *listmnt_next(struct mount *curr, bool reverse) +{ + struct rb_node *node; + + if (reverse) + node = rb_prev(&curr->mnt_node); + else + node = rb_next(&curr->mnt_node); + + return node_to_mount(node); +} + +static int grab_requested_root(struct mnt_namespace *ns, struct path *root) +{ + struct mount *first; + + rwsem_assert_held(&namespace_sem); + + /* We're looking at our own ns, just use get_fs_root. */ + if (ns == current->nsproxy->mnt_ns) { + get_fs_root(current->fs, root); + return 0; + } + + /* + * We have to find the first mount in our ns and use that, however it + * may not exist, so handle that properly. + */ + if (RB_EMPTY_ROOT(&ns->mounts)) + return -ENOENT; + + first = listmnt_next(ns->root, false); + if (!first) + return -ENOENT; + root->mnt = mntget(&first->mnt); + root->dentry = dget(root->mnt->mnt_root); + return 0; +} + +/* + * If the user requested a specific mount namespace id, look that up and return + * that, or if not simply grab a passive reference on our mount namespace and + * return that. + */ +static struct mnt_namespace *grab_requested_mnt_ns(u64 mnt_ns_id) +{ + if (mnt_ns_id) + return lookup_mnt_ns(mnt_ns_id); + refcount_inc(¤t->nsproxy->mnt_ns->passive); + return current->nsproxy->mnt_ns; +} + SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, struct statmount __user *, buf, size_t, bufsize, unsigned int, flags) @@ -5188,30 +5240,21 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, return ret; } -static struct mount *listmnt_next(struct mount *curr, bool reverse) -{ - struct rb_node *node; - - if (reverse) - node = rb_prev(&curr->mnt_node); - else - node = rb_next(&curr->mnt_node); - - return node_to_mount(node); -} - -static ssize_t do_listmount(u64 mnt_parent_id, u64 last_mnt_id, u64 *mnt_ids, - size_t nr_mnt_ids, bool reverse) +static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id, + u64 last_mnt_id, u64 *mnt_ids, size_t nr_mnt_ids, + bool reverse) { struct path root __free(path_put) = {}; - struct mnt_namespace *ns = current->nsproxy->mnt_ns; struct path orig; struct mount *r, *first; ssize_t ret; rwsem_assert_held(&namespace_sem); - get_fs_root(current->fs, &root); + ret = grab_requested_root(ns, &root); + if (ret) + return ret; + if (mnt_parent_id == LSMT_ROOT) { orig = root; } else { @@ -5263,6 +5306,7 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, { u64 *kmnt_ids __free(kvfree) = NULL; const size_t maxcount = 1000000; + struct mnt_namespace *ns __free(mnt_ns_release) = NULL; struct mnt_id_req kreq; ssize_t ret; @@ -5289,8 +5333,16 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, if (!kmnt_ids) return -ENOMEM; + ns = grab_requested_mnt_ns(kreq.mnt_ns_id); + if (!ns) + return -ENOENT; + + if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) && + !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) + return -ENOENT; + scoped_guard(rwsem_read, &namespace_sem) - ret = do_listmount(kreq.mnt_id, kreq.param, kmnt_ids, + ret = do_listmount(ns, kreq.mnt_id, kreq.param, kmnt_ids, nr_mnt_ids, (flags & LISTMOUNT_REVERSE)); if (copy_to_user(mnt_ids, kmnt_ids, ret * sizeof(*mnt_ids))) diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index a07508aee518..ee1559cd6764 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -189,10 +189,12 @@ struct mnt_id_req { __u32 spare; __u64 mnt_id; __u64 param; + __u64 mnt_ns_id; }; /* List of all mnt_id_req versions. */ #define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */ +#define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */ /* * @mask bits for statmount(2) From patchwork Mon Jun 24 15:49:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709765 Received: from mail-yw1-f175.google.com (mail-yw1-f175.google.com [209.85.128.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A0E319D8AF for ; Mon, 24 Jun 2024 15:50:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244248; cv=none; b=M0vfazNok6Oph2QebsUEfaV6Ezp+T/ggoYTL7flM9X8AOqxBIwbQA69gTFYtOpCjRVfj7NU+e+PG4D4k97fgXef3F6JXtFPo89anxkiCpKP+4Trg53SAti3H27zFPAlh7h9/DG6c5vmMmguMHheFaUrFS+zXwAJDQvEUkjehUmk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244248; c=relaxed/simple; bh=GWwnakjkuG1wF7ZPqr9VZkWVkliKt//yimgDB+eDC6k=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RD6WVTsCchhtI06Ruz2cxJRhs8EN7CMo9UlAL4IbuyQpSdnpLIvprOvTTsAlbmzw0HHB0rDzwMyP8JZo9+S94BROvwKIfAbR48SHE2q/f0OullIMnbZPmwyPfC/QW49xzRzaOblXl6nB1m4Q66yGeFAtr18P5AkW3RA996cciWg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=lHYtiONw; arc=none smtp.client-ip=209.85.128.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="lHYtiONw" Received: by mail-yw1-f175.google.com with SMTP id 00721157ae682-62fe76c0a61so41325917b3.0 for ; Mon, 24 Jun 2024 08:50:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244246; x=1719849046; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=1aP/ldgWbu2+XT8YO2t/nVvVclNabe2RrR4wVmboSZo=; b=lHYtiONwpU4ln2GDhFHbWE9FozR14XnOrwxaG6THcb3oA10UOKu7g0F0m27pM5v8Hm Ul3wLSCQaqc66mOAN7yTGiw9NJxWyUZKSNUNSx4CHx2pNQmZ+g1dYhEuzOw9pazn0yND UoFIsrvMlIChLWBGcQh6mLJDIc5Foglb1W5a6pBsqDQ8yBF0/mxZoienHCV6maAU1t+s oQVKu5BQJuIg+FmMIO2+fgXYXuXGhZhyrDkPoEzkz6hkKRJ+LvAodRoRSkhLATss7bYs d2raTCN1ygOaOMozLJlIMih1DzMHQtSl/lrlMJeIEbPb4rnhVcCt57ydtjE7Tr3GfMfi 1gvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244246; x=1719849046; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1aP/ldgWbu2+XT8YO2t/nVvVclNabe2RrR4wVmboSZo=; b=ZX19M7vOEOZBsKnxphfH9D80iki0IgFDs5eLVdUzWgr/6WAV7IcD+C4Rc87wkbkxl+ LdrU0vrRETSBfXR2IRmjjJMRifL1buC7xNqXYsokgR+gV1GN9rhUpbOHnk3PikAxpsz6 Y4uE4I5uBprvV0icgAYntBaJLiy4ugwKirHG8TRvCJDXXY0+mgYHthNW/MBtEcoySUML sSRIHW9KohyDdxh3UQUyRiU2crPDswoCq11AT3kfY6Ob0QR6i6qLoU6NzNKqFAw3enVH RBz9ScosmvOX5VK/X+d/hbXaJ9TOHtuqrXUiL0Fnig04DbgJRQ7jnsjq5hNPELQaCuZM vaLg== X-Gm-Message-State: AOJu0Yx2xqFDdXvPGf6FpIPreqSvA2/V30NZ8jAUUI2yiBfVteP5OxEf ox8hDq4UhxGW/lzU+4L8d3TmIs+NtwOt5ttFal1qomdLJLIOUseJIXZXPmBetXGe1un98cQ/9DM Q X-Google-Smtp-Source: AGHT+IFcs18Fh0C+uER0RjZHd4S0uGPnIGPl54a1zVQndbkivmVpaqrO120CPd6ku5cvS0ILPXvI9Q== X-Received: by 2002:a81:848f:0:b0:622:c892:6ae7 with SMTP id 00721157ae682-643af6ebd94mr24990347b3.12.1719244245856; Mon, 24 Jun 2024 08:50:45 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 00721157ae682-63f14a3cd92sm29354037b3.102.2024.06.24.08.50.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:45 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 6/8] fs: Allow statmount() in foreign mount namespace Date: Mon, 24 Jun 2024 11:49:49 -0400 Message-ID: <52a2e17e50ba7aa420bc8bae1d9e88ff593395c1.1719243756.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Christian Brauner This patch makes use of the new mnt_ns_id field in struct mnt_id_req to allow users to stat mount entries not in their mount namespace. The rules are the same as listmount(), the user must have CAP_SYS_ADMIN in their user namespace and the target mount namespace must be a child of the current namespace. Co-developed-by: Josef Bacik Signed-off-by: Christian Brauner Signed-off-by: Josef Bacik --- fs/namespace.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 1b422fd5f267..6d44537fd78c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4977,10 +4977,8 @@ static int statmount_fs_type(struct kstatmount *s, struct seq_file *seq) return 0; } -static void statmount_mnt_ns_id(struct kstatmount *s) +static void statmount_mnt_ns_id(struct kstatmount *s, struct mnt_namespace *ns) { - struct mnt_namespace *ns = current->nsproxy->mnt_ns; - s->sm.mask |= STATMOUNT_MNT_NS_ID; s->sm.mnt_ns_id = ns->seq; } @@ -5082,7 +5080,7 @@ static int do_statmount(struct kstatmount *s) err = statmount_string(s, STATMOUNT_MNT_POINT); if (!err && s->mask & STATMOUNT_MNT_NS_ID) - statmount_mnt_ns_id(s); + statmount_mnt_ns_id(s, ns); if (err) return err; @@ -5199,6 +5197,7 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, struct statmount __user *, buf, size_t, bufsize, unsigned int, flags) { + struct mnt_namespace *ns __free(mnt_ns_release) = NULL; struct vfsmount *mnt; struct mnt_id_req kreq; struct kstatmount ks; @@ -5213,13 +5212,28 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, if (ret) return ret; + ns = grab_requested_mnt_ns(kreq.mnt_ns_id); + if (!ns) + return -ENOENT; + + if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) && + !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) + return -ENOENT; + retry: ret = prepare_kstatmount(&ks, &kreq, buf, bufsize, seq_size); if (ret) return ret; down_read(&namespace_sem); - mnt = lookup_mnt_in_ns(kreq.mnt_id, current->nsproxy->mnt_ns); + /* Has the namespace already been emptied? */ + if (kreq.mnt_ns_id && RB_EMPTY_ROOT(&ns->mounts)) { + up_read(&namespace_sem); + kvfree(ks.seq.buf); + return -ENOENT; + } + + mnt = lookup_mnt_in_ns(kreq.mnt_id, ns); if (!mnt) { up_read(&namespace_sem); kvfree(ks.seq.buf); @@ -5227,7 +5241,12 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, } ks.mnt = mnt; - get_fs_root(current->fs, &ks.root); + ret = grab_requested_root(ns, &ks.root); + if (ret) { + up_read(&namespace_sem); + kvfree(ks.seq.buf); + return ret; + } ret = do_statmount(&ks); path_put(&ks.root); up_read(&namespace_sem); From patchwork Mon Jun 24 15:49:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709766 Received: from mail-yb1-f173.google.com (mail-yb1-f173.google.com [209.85.219.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 539A719D8BC for ; Mon, 24 Jun 2024 15:50:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244249; cv=none; b=PZq1eZxS0Mc1R+BZi+L8JjAiKp/tav5gt/g/ZBwiRt49b4fqI9wo6KRfd7y2S3B4GzP8ah/hrmSUdnNdZ8CSfWU9w14dLfZhYYsJ3xWBenImoqx6O+Shpu9wTcb9HpWLodSFwgectgsf0PvnLcdm72GXH+6uGe7pI5bMWpt41o4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244249; c=relaxed/simple; bh=UNoAuN2n5KhnVagp3Pwrk7e62KXgFGLdI/OS8bbvPnI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PRXULM2oLhcspsoOp5KFjjETCV6jrKMMnTDAEXZi53+6ecVAIMmfOFqCahj4vvQDVfwZsAHgWimPjXm32kYjC3LrH7NEXtgMVQ2CGPc4ZoexGogM7xUDFmnCP1unJbABygdvVaA4Fu/fsaO6qRNMRHJ1DsArBXeQFpjsxiwkROM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=Lmd6tAnv; arc=none smtp.client-ip=209.85.219.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="Lmd6tAnv" Received: by mail-yb1-f173.google.com with SMTP id 3f1490d57ef6-dff1ccdc17bso4652349276.0 for ; Mon, 24 Jun 2024 08:50:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244247; x=1719849047; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=X08K0+5ubUz+4Dtb/n6m51W7n5tM+ufs3byELYmxH1A=; b=Lmd6tAnvQlSaaLdSThQi2sSlJc+tf2rVtZOzGLfyRHlt9BZzOqWVQacK7TMqTQ6AYv OfHAS+dxn3r8RzlBlmAfaz1cZNjVcM3pJe6rnjpdPQhXBq6af9CscArkY8v868sVxpOk Uq1MeZHipxTr6SQtpjjhnXrgumg6NEqQfzQaPTfNRvP/50P7P9aPdxVoLVsH89s5cpt7 SG8ZxtVCRlNby6MjrKhwRcoApcekihgusHOXICKuHNLVyyn2VjpJAJGk+JVhynmGydeB jh7wPqLtqBiZWAG/BQvUlBGxqkKU6v7whyimHeLbZlDi8sUalZ+jdT3LN5L9l+4cqpJT igmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244247; x=1719849047; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=X08K0+5ubUz+4Dtb/n6m51W7n5tM+ufs3byELYmxH1A=; b=etgDPBstJf46dTC1JKvfs31dtFgYLvA9pLLw/yBU7FLnalf8Qi/gezxsUME2OUdR2n yi2+lMy3EcsAeMU6Qhyh6Hzv550eZU+SXFQ7RwiQ8ZbZUdRKu6CyAOFXLkmEGzIHG460 0LhptfdWo36BnqOc3zEaOauRnxG190CNI6bC2LlIvkhE2YWKUIH7XWllbIvCgTe3NOLk lpiF6JQsGXi4I0X2fuf63N25Ydhbq0RF12tUyE6ftyujy/VH446s6kKI1SXmEK9Gz9e5 WgGnNo5UGz5Q1aIeYxFEid01+1LgL87ce2eKV027p7EfKiK4+6o4z9EOTM/MmW9dSpoz LvVA== X-Gm-Message-State: AOJu0YzFmMYLOULBW0gD4nmHpe+htKpZUiH6u+DFmTZsJZ3mLoVCBg8x muigCU+YG6PB7mUEilP+d7dMAA0s1sPW4TM+57I9w0ReB1t4HtC+dQ6W+6dp5dgKCRxHuFj86T2 R X-Google-Smtp-Source: AGHT+IGGDpNMWAqjctL7iQDQzsUjtxHg2UtzjpHu2kOO+8ymSyyqZQkqGrzwLsMAmWrMYfFWvbwPmA== X-Received: by 2002:a25:a503:0:b0:dfe:73d8:4593 with SMTP id 3f1490d57ef6-e02fc34f307mr5325972276.48.1719244247035; Mon, 24 Jun 2024 08:50:47 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-e02e6116e09sm3291522276.11.2024.06.24.08.50.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:46 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 7/8] fs: add an ioctl to get the mnt ns id from nsfs Date: Mon, 24 Jun 2024 11:49:50 -0400 Message-ID: <180449959d5a756af7306d6bda55f41b9d53e3cb.1719243756.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to utilize the listmount() and statmount() extensions that allow us to call them on different namespaces we need a way to get the mnt namespace id from user space. Add an ioctl to nsfs that will allow us to extract the mnt namespace id in order to make these new extensions usable. Signed-off-by: Josef Bacik --- fs/nsfs.c | 14 ++++++++++++++ include/uapi/linux/nsfs.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/fs/nsfs.c b/fs/nsfs.c index 07e22a15ef02..af352dadffe1 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -12,6 +12,7 @@ #include #include +#include "mount.h" #include "internal.h" static struct vfsmount *nsfs_mnt; @@ -143,6 +144,19 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl, argp = (uid_t __user *) arg; uid = from_kuid_munged(current_user_ns(), user_ns->owner); return put_user(uid, argp); + case NS_GET_MNTNS_ID: { + struct mnt_namespace *mnt_ns; + __u64 __user *idp; + __u64 id; + + if (ns->ops->type != CLONE_NEWNS) + return -EINVAL; + + mnt_ns = container_of(ns, struct mnt_namespace, ns); + idp = (__u64 __user *)arg; + id = mnt_ns->seq; + return put_user(id, idp); + } default: return -ENOTTY; } diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h index a0c8552b64ee..56e8b1639b98 100644 --- a/include/uapi/linux/nsfs.h +++ b/include/uapi/linux/nsfs.h @@ -15,5 +15,7 @@ #define NS_GET_NSTYPE _IO(NSIO, 0x3) /* Get owner UID (in the caller's user namespace) for a user namespace */ #define NS_GET_OWNER_UID _IO(NSIO, 0x4) +/* Get the id for a mount namespace */ +#define NS_GET_MNTNS_ID _IO(NSIO, 0x5) #endif /* __LINUX_NSFS_H */ From patchwork Mon Jun 24 15:49:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13709767 Received: from mail-yw1-f169.google.com (mail-yw1-f169.google.com [209.85.128.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43C4019DF47 for ; Mon, 24 Jun 2024 15:50:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244252; cv=none; b=u/kyq9hO63zUtyYpK95P/FsthawdsuPDU7T2/GXCuTVIvgrKSuFRcPdxGxKwGBKhqPK4/KEJ194XrvqZcFHen3gOBNK7cWgwSZUJtEei9IgT3msadrLqYPWeIfBThZVKAtoq1rBfUaMz4JooDDDOcE1Y62J3qGBkVSnxXSAGCrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719244252; c=relaxed/simple; bh=ROqeQc9ShPHVDAu6oiFpoYSzcQGVC5xaqHMOVM0ZNws=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WfOdXu+ohm0b+zCNZ9ZSFyzdPU/AiW5gVVb+0JrHufZiXHZmybnFiJ/dJMDFEFOfeKRPV9oYffOUKaEBLoLdJObNdpdr9mevC40j2z4zCc/ii2clF9D6jsdJTHYk/sja+iFUx4m1w9srpC6hQ9WoO9eSXILd6nzdHQRti5BiJ1g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com; spf=none smtp.mailfrom=toxicpanda.com; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b=I38biAzu; arc=none smtp.client-ip=209.85.128.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="I38biAzu" Received: by mail-yw1-f169.google.com with SMTP id 00721157ae682-63036fa87dbso35772697b3.1 for ; Mon, 24 Jun 2024 08:50:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1719244249; x=1719849049; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=06G3CQSYHYfgnl56rs4TSRzD4DsDReFJeEA6YjJT7uc=; b=I38biAzug67pCXw10OycHVpvhyZq330pDiWja7hcARwPKnlwk4QYi+2SYJVHoTxRIP q6SPOUbWF1F+Y0D4eKSrNDemHqasp6UesBYRIhrjPF6CBw+4EU7GOYauMIySnHdGGyhT 6f80WFdnX5fF/NSnJoPu+Cf2TMq8yrqB5srYzFdBj0K/RcRLUcVn5lo5twnRaSv/ZmyC 7CMcuOsh1utPewgTyuM5gRRJczbhMf5saIVpp7+LDZnoBR5tZzuWJJFk8HKPz1J9nCFC YYeZ23Fqz9ycNRdIskFz3oCuTigf1E8HJZr2ZstnvotnzEalOhDYZSq9Le+j0pJVH3Xy 8OQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719244249; x=1719849049; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=06G3CQSYHYfgnl56rs4TSRzD4DsDReFJeEA6YjJT7uc=; b=I7kHR55wpbSGUhlX011Q1ajnpATXCtY7th2zWnhjyCApbcAtvXb8lm/iyUtQSgEriS wAuUoyCARboSbM0o1AGcJqa/6aBr6PXT8PXpDt0Do3arB5uhZuJ8DzHFjkYIg77UYVUb IMPgEGTMGQGV/xQsYSrENqmk5i+u2r1ML73CPnXFKUvYc6t7KEgHxbHY6L4PEv2wWwZQ +ANwKoh2GaHKlp8x1PzhuF4eoYxz+4L5vKb0bgx6GET3ZHvBbyNDuJhYYfiukYFc6EUu v8z1cyYpr7Jbc3MrUYkr39of+elEkb+8uFOu+T/jHpoZFCJL2hiWN9Q7DBL/P2FJo8sI sS0Q== X-Gm-Message-State: AOJu0Yyx3DBKjvChgu05fp9sOGkVQeHrx/Qv5yVPvG3InIxA/QUdb4gC /1Rwnqxk7NKhkqDFIxxJj99fJ7hsgxKI/q8oaV4YeLVDKgMvie5kmXvAy5vscnLBrm69xLx1xO0 B X-Google-Smtp-Source: AGHT+IEU4eMODYn+sarM5XuvZfrUV6l7c/+yqzJNafKiGru23qlClHOvsInEVq+9O19brwPis+7i9g== X-Received: by 2002:a81:4322:0:b0:622:c70b:ab2b with SMTP id 00721157ae682-6424821b6e8mr34106557b3.2.1719244248086; Mon, 24 Jun 2024 08:50:48 -0700 (PDT) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 00721157ae682-63f11268c35sm29133947b3.24.2024.06.24.08.50.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 08:50:47 -0700 (PDT) From: Josef Bacik To: linux-fsdevel@vger.kernel.org, brauner@kernel.org, kernel-team@fb.com Subject: [PATCH 8/8] selftests: add a test for the foreign mnt ns extensions Date: Mon, 24 Jun 2024 11:49:51 -0400 Message-ID: <2d1a35bc9ab94b4656c056c420f25e429e7eb0b1.1719243756.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This tests both statmount and listmount to make sure they work with the extensions that allow us to specify a mount ns to enter in order to find the mount entries. Signed-off-by: Josef Bacik --- .../selftests/filesystems/statmount/Makefile | 2 +- .../filesystems/statmount/statmount.h | 46 +++ .../filesystems/statmount/statmount_test.c | 53 +-- .../filesystems/statmount/statmount_test_ns.c | 360 ++++++++++++++++++ 4 files changed, 420 insertions(+), 41 deletions(-) create mode 100644 tools/testing/selftests/filesystems/statmount/statmount.h create mode 100644 tools/testing/selftests/filesystems/statmount/statmount_test_ns.c diff --git a/tools/testing/selftests/filesystems/statmount/Makefile b/tools/testing/selftests/filesystems/statmount/Makefile index 07a0d5b545ca..3af3136e35a4 100644 --- a/tools/testing/selftests/filesystems/statmount/Makefile +++ b/tools/testing/selftests/filesystems/statmount/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) -TEST_GEN_PROGS := statmount_test +TEST_GEN_PROGS := statmount_test statmount_test_ns include ../../lib.mk diff --git a/tools/testing/selftests/filesystems/statmount/statmount.h b/tools/testing/selftests/filesystems/statmount/statmount.h new file mode 100644 index 000000000000..f4294bab9d73 --- /dev/null +++ b/tools/testing/selftests/filesystems/statmount/statmount.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __STATMOUNT_H +#define __STATMOUNT_H + +#include +#include +#include + +static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint64_t mask, + struct statmount *buf, size_t bufsize, + unsigned int flags) +{ + struct mnt_id_req req = { + .size = MNT_ID_REQ_SIZE_VER0, + .mnt_id = mnt_id, + .param = mask, + }; + + if (mnt_ns_id) { + req.size = MNT_ID_REQ_SIZE_VER1; + req.mnt_ns_id = mnt_ns_id; + } + + return syscall(__NR_statmount, &req, buf, bufsize, flags); +} + +static ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id, + uint64_t last_mnt_id, uint64_t list[], size_t num, + unsigned int flags) +{ + struct mnt_id_req req = { + .size = MNT_ID_REQ_SIZE_VER0, + .mnt_id = mnt_id, + .param = last_mnt_id, + }; + + if (mnt_ns_id) { + req.size = MNT_ID_REQ_SIZE_VER1; + req.mnt_ns_id = mnt_ns_id; + } + + return syscall(__NR_listmount, &req, list, num, flags); +} + +#endif /* __STATMOUNT_H */ diff --git a/tools/testing/selftests/filesystems/statmount/statmount_test.c b/tools/testing/selftests/filesystems/statmount/statmount_test.c index e6d7c4f1c85b..4f7023c2de77 100644 --- a/tools/testing/selftests/filesystems/statmount/statmount_test.c +++ b/tools/testing/selftests/filesystems/statmount/statmount_test.c @@ -4,17 +4,15 @@ #include #include -#include #include #include #include #include #include #include -#include #include -#include +#include "statmount.h" #include "../../kselftest.h" static const char *const known_fs[] = { @@ -36,18 +34,6 @@ static const char *const known_fs[] = { "ufs", "v7", "vboxsf", "vfat", "virtiofs", "vxfs", "xenfs", "xfs", "zonefs", NULL }; -static int statmount(uint64_t mnt_id, uint64_t mask, struct statmount *buf, - size_t bufsize, unsigned int flags) -{ - struct mnt_id_req req = { - .size = MNT_ID_REQ_SIZE_VER0, - .mnt_id = mnt_id, - .param = mask, - }; - - return syscall(__NR_statmount, &req, buf, bufsize, flags); -} - static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigned int flags) { size_t bufsize = 1 << 15; @@ -56,7 +42,7 @@ static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigne int ret; for (;;) { - ret = statmount(mnt_id, mask, tmp, bufsize, flags); + ret = statmount(mnt_id, 0, mask, tmp, bufsize, flags); if (ret != -1) break; if (tofree) @@ -122,7 +108,6 @@ static int orig_root; static uint64_t root_id, parent_id; static uint32_t old_root_id, old_parent_id; - static void cleanup_namespace(void) { fchdir(orig_root); @@ -138,7 +123,7 @@ static void setup_namespace(void) uid_t uid = getuid(); gid_t gid = getgid(); - ret = unshare(CLONE_NEWNS|CLONE_NEWUSER); + ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID); if (ret == -1) ksft_exit_fail_msg("unsharing mountns and userns: %s\n", strerror(errno)); @@ -208,25 +193,13 @@ static int setup_mount_tree(int log2_num) return 0; } -static ssize_t listmount(uint64_t mnt_id, uint64_t last_mnt_id, - uint64_t list[], size_t num, unsigned int flags) -{ - struct mnt_id_req req = { - .size = MNT_ID_REQ_SIZE_VER0, - .mnt_id = mnt_id, - .param = last_mnt_id, - }; - - return syscall(__NR_listmount, &req, list, num, flags); -} - static void test_listmount_empty_root(void) { ssize_t res; const unsigned int size = 32; uint64_t list[size]; - res = listmount(LSMT_ROOT, 0, list, size, 0); + res = listmount(LSMT_ROOT, 0, 0, list, size, 0); if (res == -1) { ksft_test_result_fail("listmount: %s\n", strerror(errno)); return; @@ -251,7 +224,7 @@ static void test_statmount_zero_mask(void) struct statmount sm; int ret; - ret = statmount(root_id, 0, &sm, sizeof(sm), 0); + ret = statmount(root_id, 0, 0, &sm, sizeof(sm), 0); if (ret == -1) { ksft_test_result_fail("statmount zero mask: %s\n", strerror(errno)); @@ -277,7 +250,7 @@ static void test_statmount_mnt_basic(void) int ret; uint64_t mask = STATMOUNT_MNT_BASIC; - ret = statmount(root_id, mask, &sm, sizeof(sm), 0); + ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0); if (ret == -1) { ksft_test_result_fail("statmount mnt basic: %s\n", strerror(errno)); @@ -337,7 +310,7 @@ static void test_statmount_sb_basic(void) struct statx sx; struct statfs sf; - ret = statmount(root_id, mask, &sm, sizeof(sm), 0); + ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0); if (ret == -1) { ksft_test_result_fail("statmount sb basic: %s\n", strerror(errno)); @@ -498,14 +471,14 @@ static void test_statmount_string(uint64_t mask, size_t off, const char *name) exactsize = sm->size; shortsize = sizeof(*sm) + i; - ret = statmount(root_id, mask, sm, exactsize, 0); + ret = statmount(root_id, 0, mask, sm, exactsize, 0); if (ret == -1) { ksft_test_result_fail("statmount exact size: %s\n", strerror(errno)); goto out; } errno = 0; - ret = statmount(root_id, mask, sm, shortsize, 0); + ret = statmount(root_id, 0, mask, sm, shortsize, 0); if (ret != -1 || errno != EOVERFLOW) { ksft_test_result_fail("should have failed with EOVERFLOW: %s\n", strerror(errno)); @@ -533,7 +506,7 @@ static void test_listmount_tree(void) if (res == -1) return; - num = res = listmount(LSMT_ROOT, 0, list, size, 0); + num = res = listmount(LSMT_ROOT, 0, 0, list, size, 0); if (res == -1) { ksft_test_result_fail("listmount: %s\n", strerror(errno)); return; @@ -545,7 +518,7 @@ static void test_listmount_tree(void) } for (i = 0; i < size - step;) { - res = listmount(LSMT_ROOT, i ? list2[i - 1] : 0, list2 + i, step, 0); + res = listmount(LSMT_ROOT, 0, i ? list2[i - 1] : 0, list2 + i, step, 0); if (res == -1) ksft_test_result_fail("short listmount: %s\n", strerror(errno)); @@ -577,11 +550,11 @@ int main(void) int ret; uint64_t all_mask = STATMOUNT_SB_BASIC | STATMOUNT_MNT_BASIC | STATMOUNT_PROPAGATE_FROM | STATMOUNT_MNT_ROOT | - STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE; + STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE | STATMOUNT_MNT_NS_ID; ksft_print_header(); - ret = statmount(0, 0, NULL, 0, 0); + ret = statmount(0, 0, 0, NULL, 0, 0); assert(ret == -1); if (errno == ENOSYS) ksft_exit_skip("statmount() syscall not supported\n"); diff --git a/tools/testing/selftests/filesystems/statmount/statmount_test_ns.c b/tools/testing/selftests/filesystems/statmount/statmount_test_ns.c new file mode 100644 index 000000000000..145ecb5f3fb2 --- /dev/null +++ b/tools/testing/selftests/filesystems/statmount/statmount_test_ns.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "statmount.h" +#include "../../kselftest.h" + +#define NSID_PASS 0 +#define NSID_FAIL 1 +#define NSID_SKIP 2 +#define NSID_ERROR 3 + +static void handle_result(int ret, const char *testname) +{ + if (ret == NSID_PASS) + ksft_test_result_pass(testname); + else if (ret == NSID_FAIL) + ksft_test_result_fail(testname); + else if (ret == NSID_ERROR) + ksft_exit_fail_msg(testname); + else + ksft_test_result_skip(testname); +} + +static inline int wait_for_pid(pid_t pid) +{ + int status, ret; + +again: + ret = waitpid(pid, &status, 0); + if (ret == -1) { + if (errno == EINTR) + goto again; + + ksft_print_msg("waitpid returned -1, errno=%d\n", errno); + return -1; + } + + if (!WIFEXITED(status)) { + ksft_print_msg( + "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n", + WIFSIGNALED(status), WTERMSIG(status)); + return -1; + } + + ret = WEXITSTATUS(status); + return ret; +} + +static int get_mnt_ns_id(const char *mnt_ns, uint64_t *mnt_ns_id) +{ + int fd = open(mnt_ns, O_RDONLY); + + if (fd < 0) { + ksft_print_msg("failed to open for ns %s: %s\n", + mnt_ns, strerror(errno)); + sleep(60); + return NSID_ERROR; + } + + if (ioctl(fd, NS_GET_MNTNS_ID, mnt_ns_id) < 0) { + ksft_print_msg("failed to get the nsid for ns %s: %s\n", + mnt_ns, strerror(errno)); + return NSID_ERROR; + } + close(fd); + return NSID_PASS; +} + +static int get_mnt_id(const char *path, uint64_t *mnt_id) +{ + struct statx sx; + int ret; + + ret = statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx); + if (ret == -1) { + ksft_print_msg("retrieving unique mount ID for %s: %s\n", path, + strerror(errno)); + return NSID_ERROR; + } + + if (!(sx.stx_mask & STATX_MNT_ID_UNIQUE)) { + ksft_print_msg("no unique mount ID available for %s\n", path); + return NSID_ERROR; + } + + *mnt_id = sx.stx_mnt_id; + return NSID_PASS; +} + +static int write_file(const char *path, const char *val) +{ + int fd = open(path, O_WRONLY); + size_t len = strlen(val); + int ret; + + if (fd == -1) { + ksft_print_msg("opening %s for write: %s\n", path, strerror(errno)); + return NSID_ERROR; + } + + ret = write(fd, val, len); + if (ret == -1) { + ksft_print_msg("writing to %s: %s\n", path, strerror(errno)); + return NSID_ERROR; + } + if (ret != len) { + ksft_print_msg("short write to %s\n", path); + return NSID_ERROR; + } + + ret = close(fd); + if (ret == -1) { + ksft_print_msg("closing %s\n", path); + return NSID_ERROR; + } + + return NSID_PASS; +} + +static int setup_namespace(void) +{ + int ret; + char buf[32]; + uid_t uid = getuid(); + gid_t gid = getgid(); + + ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID); + if (ret == -1) + ksft_exit_fail_msg("unsharing mountns and userns: %s\n", + strerror(errno)); + + sprintf(buf, "0 %d 1", uid); + ret = write_file("/proc/self/uid_map", buf); + if (ret != NSID_PASS) + return ret; + ret = write_file("/proc/self/setgroups", "deny"); + if (ret != NSID_PASS) + return ret; + sprintf(buf, "0 %d 1", gid); + ret = write_file("/proc/self/gid_map", buf); + if (ret != NSID_PASS) + return ret; + + ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL); + if (ret == -1) { + ksft_print_msg("making mount tree private: %s\n", + strerror(errno)); + return NSID_ERROR; + } + + return NSID_PASS; +} + +static int _test_statmount_mnt_ns_id(void) +{ + struct statmount sm; + uint64_t mnt_ns_id; + uint64_t root_id; + int ret; + + ret = get_mnt_ns_id("/proc/self/ns/mnt", &mnt_ns_id); + if (ret != NSID_PASS) + return ret; + + ret = get_mnt_id("/", &root_id); + if (ret != NSID_PASS) + return ret; + + ret = statmount(root_id, 0, STATMOUNT_MNT_NS_ID, &sm, sizeof(sm), 0); + if (ret == -1) { + ksft_print_msg("statmount mnt ns id: %s\n", strerror(errno)); + return NSID_ERROR; + } + + if (sm.size != sizeof(sm)) { + ksft_print_msg("unexpected size: %u != %u\n", sm.size, + (uint32_t)sizeof(sm)); + return NSID_FAIL; + } + if (sm.mask != STATMOUNT_MNT_NS_ID) { + ksft_print_msg("statmount mnt ns id unavailable\n"); + return NSID_SKIP; + } + + if (sm.mnt_ns_id != mnt_ns_id) { + ksft_print_msg("unexpected mnt ns ID: 0x%llx != 0x%llx\n", + (unsigned long long)sm.mnt_ns_id, + (unsigned long long)mnt_ns_id); + return NSID_FAIL; + } + + return NSID_PASS; +} + +static void test_statmount_mnt_ns_id(void) +{ + pid_t pid; + int ret; + + pid = fork(); + if (pid < 0) + ksft_exit_fail_msg("failed to fork: %s\n", strerror(errno)); + + /* We're the original pid, wait for the result. */ + if (pid != 0) { + ret = wait_for_pid(pid); + handle_result(ret, "test statmount ns id\n"); + return; + } + + ret = setup_namespace(); + if (ret != NSID_PASS) + exit(ret); + ret = _test_statmount_mnt_ns_id(); + exit(ret); +} + +static int validate_external_listmount(pid_t pid, uint64_t child_nr_mounts) +{ + uint64_t list[256]; + uint64_t mnt_ns_id; + uint64_t nr_mounts; + char buf[256]; + int ret; + + /* Get the mount ns id for our child. */ + snprintf(buf, sizeof(buf), "/proc/%lu/ns/mnt", (unsigned long)pid); + ret = get_mnt_ns_id(buf, &mnt_ns_id); + + nr_mounts = listmount(LSMT_ROOT, mnt_ns_id, 0, list, 256, 0); + if (nr_mounts == (uint64_t)-1) { + ksft_print_msg("listmount: %s\n", strerror(errno)); + return NSID_ERROR; + } + + if (nr_mounts != child_nr_mounts) { + ksft_print_msg("listmount results is %zi != %zi\n", nr_mounts, + child_nr_mounts); + return NSID_FAIL; + } + + /* Validate that all of our entries match our mnt_ns_id. */ + for (int i = 0; i < nr_mounts; i++) { + struct statmount sm; + + ret = statmount(list[i], mnt_ns_id, STATMOUNT_MNT_NS_ID, &sm, + sizeof(sm), 0); + if (ret < 0) { + ksft_print_msg("statmount mnt ns id: %s\n", strerror(errno)); + return NSID_ERROR; + } + + if (sm.mask != STATMOUNT_MNT_NS_ID) { + ksft_print_msg("statmount mnt ns id unavailable\n"); + return NSID_SKIP; + } + + if (sm.mnt_ns_id != mnt_ns_id) { + ksft_print_msg("listmount gave us the wrong ns id: 0x%llx != 0x%llx\n", + (unsigned long long)sm.mnt_ns_id, + (unsigned long long)mnt_ns_id); + return NSID_FAIL; + } + } + + return NSID_PASS; +} + +static void test_listmount_ns(void) +{ + uint64_t nr_mounts; + char pval; + int child_ready_pipe[2]; + int parent_ready_pipe[2]; + pid_t pid; + int ret, child_ret; + + if (pipe(child_ready_pipe) < 0) + ksft_exit_fail_msg("failed to create the child pipe: %s\n", + strerror(errno)); + if (pipe(parent_ready_pipe) < 0) + ksft_exit_fail_msg("failed to create the parent pipe: %s\n", + strerror(errno)); + + pid = fork(); + if (pid < 0) + ksft_exit_fail_msg("failed to fork: %s\n", strerror(errno)); + + if (pid == 0) { + char cval; + uint64_t list[256]; + + close(child_ready_pipe[0]); + close(parent_ready_pipe[1]); + + ret = setup_namespace(); + if (ret != NSID_PASS) + exit(ret); + + nr_mounts = listmount(LSMT_ROOT, 0, 0, list, 256, 0); + if (nr_mounts == (uint64_t)-1) { + ksft_print_msg("listmount: %s\n", strerror(errno)); + exit(NSID_FAIL); + } + + /* + * Tell our parent how many mounts we have, and then wait for it + * to tell us we're done. + */ + write(child_ready_pipe[1], &nr_mounts, sizeof(nr_mounts)); + read(parent_ready_pipe[0], &cval, sizeof(cval)); + exit(NSID_PASS); + } + + close(child_ready_pipe[1]); + close(parent_ready_pipe[0]); + + /* Wait until the child has created everything. */ + read(child_ready_pipe[0], &nr_mounts, sizeof(nr_mounts)); + + ret = validate_external_listmount(pid, nr_mounts); + + write(parent_ready_pipe[1], &pval, sizeof(pval)); + child_ret = wait_for_pid(pid); + if (child_ret != NSID_PASS) + ret = child_ret; + handle_result(ret, "test listmount ns id\n"); +} + +int main(void) +{ + int ret; + + ksft_print_header(); + ret = statmount(0, 0, 0, NULL, 0, 0); + assert(ret == -1); + if (errno == ENOSYS) + ksft_exit_skip("statmount() syscall not supported\n"); + + ksft_set_plan(2); + test_statmount_mnt_ns_id(); + test_listmount_ns(); + + if (ksft_get_fail_cnt() + ksft_get_error_cnt() > 0) + ksft_exit_fail(); + else + ksft_exit_pass(); +}