From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B47419C546; Wed, 18 Mar 2026 18:44:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773859482; cv=none; b=JNmRmU0xnUyNXVlcxFWHxjpAzhZS9Fh+PQAkZ1y5FOYRBHzHDtu8w4tJxYgRVby9cutXSE3ISTA3WJhbJKsUOSkeJb4c6Brt2HsvcaRELGUI+FlxLX/9dPLopWqIbcjwr6E5++XMiDKcpKofIohN+SDLxpM4ndSsGBaQJKYmjzs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773859482; c=relaxed/simple; bh=8wgexpQ+l6hsZh1Cp9+PA1dOETzb7+9N0+A6bgtIX2A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BDjnsk15ITlKl106xKqtHiNeWF36A/YSTV3hLY8yReUSiKFC93STkXQhI47kbLNrO9fn60dhmzQqf4OR2GQzy8QtOKMSA8WbEigL6v7ebjQL5rpJ6t+9ejxR8T1YEE3zCBtxoslqC5mkRc7zzROnPS6bxfGkvTjIDidG5XIxtZ4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TY2BQDIy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TY2BQDIy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F19DAC2BC9E; Wed, 18 Mar 2026 18:44:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773859482; bh=8wgexpQ+l6hsZh1Cp9+PA1dOETzb7+9N0+A6bgtIX2A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TY2BQDIyjGx7VDBG5FT63R3jWs1IkHMGAm61M0bkN3Jegz9OyyK34Bu6OBA00OdtT O0/fNS2hM9hom1SxLxSeKInI1ODQ5rObqeIFt4S2QbdIvu0wjyJxawemp8rTTYPyrm zU+/IOHAx6npT78KKw0Fa/R/jf+fkkwJWOFJfvV9uXfdFC/nEqkiw9YgH3456nJ+Jg RhnCfRLA/DaQM8CUu3nLSPhQCy0A3hLCE+ayTDce6VQxcUGSNVPlT6S1T3/Q06OBjM 6xiSc6Y39iNlcSKmyAB0mKk58LmRQVVynoWN8vWPAVPG/kVH3bHEYGqai9HleN4Vz7 5m6A0UC8bT6uw== From: Song Liu To: linux-security-module@vger.kernel.org, linux-fsdevel@vger.kernel.org, selinux@vger.kernel.org, apparmor@lists.ubuntu.com Cc: paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, john.johansen@canonical.com, stephen.smalley.work@gmail.com, omosnace@redhat.com, mic@digikod.net, gnoack@google.com, takedakn@nttdata.co.jp, penguin-kernel@I-love.SAKURA.ne.jp, herton@canonical.com, kernel-team@meta.com, Song Liu Subject: [PATCH 6/7] tomoyo: Convert from sb_mount to granular mount hooks Date: Wed, 18 Mar 2026 11:43:59 -0700 Message-ID: <20260318184400.3502908-7-song@kernel.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260318184400.3502908-1-song@kernel.org> References: <20260318184400.3502908-1-song@kernel.org> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Replace tomoyo_sb_mount() with granular mount hooks. Each hook reconstructs the MS_* flags expected by tomoyo_mount_permission() using the original flags parameter where available. Key changes: - mount_bind: passes the pre-resolved source path to tomoyo_mount_acl() via a new dev_path parameter, instead of re-resolving dev_name via kern_path(). This eliminates a TOCTOU vulnerability. - mount_new, mount_remount, mount_reconfigure: use the original mount(2) flags for policy matching. - mount_move: passes pre-resolved paths for both source and destination. - mount_change_type: passes raw ms_flags directly. Also removes the unused data_page parameter from tomoyo_mount_permission(). Code generated with the assistance of Claude, reviewed by human. Signed-off-by: Song Liu --- security/tomoyo/common.h | 2 +- security/tomoyo/mount.c | 31 +++++++++++++------- security/tomoyo/tomoyo.c | 63 ++++++++++++++++++++++++++++++---------- 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 4f1704c911ef..e40441844eab 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -1013,7 +1013,7 @@ int tomoyo_mkdev_perm(const u8 operation, const struct path *path, const unsigned int mode, unsigned int dev); int tomoyo_mount_permission(const char *dev_name, const struct path *path, const char *type, unsigned long flags, - void *data_page); + const struct path *dev_path); int tomoyo_open_control(const u8 type, struct file *file); int tomoyo_path2_perm(const u8 operation, const struct path *path1, const struct path *path2); diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 322dfd188ada..82ffe7d02814 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -70,6 +70,7 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, * @dir: Pointer to "struct path". * @type: Name of filesystem type. * @flags: Mount options. + * @dev_path: Pre-resolved device/source path. Maybe NULL. * * Returns 0 on success, negative value otherwise. * @@ -78,11 +79,11 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, static int tomoyo_mount_acl(struct tomoyo_request_info *r, const char *dev_name, const struct path *dir, const char *type, - unsigned long flags) + unsigned long flags, + const struct path *dev_path) __must_hold_shared(&tomoyo_ss) { struct tomoyo_obj_info obj = { }; - struct path path; struct file_system_type *fstype = NULL; const char *requested_type = NULL; const char *requested_dir_name = NULL; @@ -134,13 +135,23 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, need_dev = 1; } if (need_dev) { - /* Get mount point or device file. */ - if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) { + if (dev_path) { + /* Use pre-resolved path to avoid TOCTOU issues. */ + obj.path1 = *dev_path; + path_get(&obj.path1); + } else if (!dev_name) { error = -ENOENT; goto out; + } else { + struct path path; + + if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) { + error = -ENOENT; + goto out; + } + obj.path1 = path; } - obj.path1 = path; - requested_dev_name = tomoyo_realpath_from_path(&path); + requested_dev_name = tomoyo_realpath_from_path(&obj.path1); if (!requested_dev_name) { error = -ENOENT; goto out; @@ -173,7 +184,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, if (fstype) put_filesystem(fstype); kfree(requested_type); - /* Drop refcount obtained by kern_path(). */ + /* Drop refcount obtained by kern_path() or path_get(). */ if (obj.path1.dentry) path_put(&obj.path1); return error; @@ -186,13 +197,13 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, * @path: Pointer to "struct path". * @type: Name of filesystem type. Maybe NULL. * @flags: Mount options. - * @data_page: Optional data. Maybe NULL. + * @dev_path: Pre-resolved device/source path. Maybe NULL. * * Returns 0 on success, negative value otherwise. */ int tomoyo_mount_permission(const char *dev_name, const struct path *path, const char *type, unsigned long flags, - void *data_page) + const struct path *dev_path) { struct tomoyo_request_info r; int error; @@ -236,7 +247,7 @@ int tomoyo_mount_permission(const char *dev_name, const struct path *path, if (!type) type = ""; idx = tomoyo_read_lock(); - error = tomoyo_mount_acl(&r, dev_name, path, type, flags); + error = tomoyo_mount_acl(&r, dev_name, path, type, flags, dev_path); tomoyo_read_unlock(idx); return error; } diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index c66e02ed8ee3..ac84e1f03d5e 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -6,6 +6,8 @@ */ #include +#include +#include #include #include "common.h" @@ -398,21 +400,47 @@ static int tomoyo_path_chroot(const struct path *path) return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); } -/** - * tomoyo_sb_mount - Target for security_sb_mount(). - * - * @dev_name: Name of device file. Maybe NULL. - * @path: Pointer to "struct path". - * @type: Name of filesystem type. Maybe NULL. - * @flags: Mount options. - * @data: Optional data. Maybe NULL. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_mount(const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data) +static int tomoyo_mount_bind(const struct path *from, const struct path *to, + bool recurse) +{ + unsigned long flags = MS_BIND | (recurse ? MS_REC : 0); + + return tomoyo_mount_permission(NULL, to, NULL, flags, from); +} + +static int tomoyo_mount_new(struct fs_context *fc, const struct path *mp, + int mnt_flags, unsigned long flags, void *data) +{ + /* Use original MS_* flags for policy matching */ + return tomoyo_mount_permission(fc->source, mp, fc->fs_type->name, + flags, NULL); +} + +static int tomoyo_mount_remount(struct fs_context *fc, const struct path *mp, + int mnt_flags, unsigned long flags, void *data) +{ + /* Use original MS_* flags for policy matching */ + return tomoyo_mount_permission(NULL, mp, NULL, flags, NULL); +} + +static int tomoyo_mount_reconfigure(const struct path *mp, + unsigned int mnt_flags, + unsigned long flags) +{ + /* Use original MS_* flags for policy matching */ + return tomoyo_mount_permission(NULL, mp, NULL, flags, NULL); +} + +static int tomoyo_mount_change_type(const struct path *mp, int ms_flags) +{ + return tomoyo_mount_permission(NULL, mp, NULL, ms_flags, NULL); +} + +static int tomoyo_move_mount(const struct path *from_path, + const struct path *to_path) { - return tomoyo_mount_permission(dev_name, path, type, flags, data); + return tomoyo_mount_permission(NULL, to_path, NULL, MS_MOVE, + from_path); } /** @@ -576,7 +604,12 @@ static struct security_hook_list tomoyo_hooks[] __ro_after_init = { LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod), LSM_HOOK_INIT(path_chown, tomoyo_path_chown), LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot), - LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount), + LSM_HOOK_INIT(mount_bind, tomoyo_mount_bind), + LSM_HOOK_INIT(mount_new, tomoyo_mount_new), + LSM_HOOK_INIT(mount_remount, tomoyo_mount_remount), + LSM_HOOK_INIT(mount_reconfigure, tomoyo_mount_reconfigure), + LSM_HOOK_INIT(mount_change_type, tomoyo_mount_change_type), + LSM_HOOK_INIT(mount_move, tomoyo_move_mount), LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount), LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot), LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind), -- 2.52.0