From nobody Fri Dec 19 20:16:27 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A8E1E7D0AA for ; Thu, 21 Sep 2023 21:21:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231674AbjIUVVE (ORCPT ); Thu, 21 Sep 2023 17:21:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233066AbjIUVPP (ORCPT ); Thu, 21 Sep 2023 17:15:15 -0400 Received: from smtp-42a8.mail.infomaniak.ch (smtp-42a8.mail.infomaniak.ch [84.16.66.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B34CC2D221 for ; Thu, 21 Sep 2023 10:07:30 -0700 (PDT) Received: from smtp-2-0001.mail.infomaniak.ch (unknown [10.5.36.108]) by smtp-3-3000.mail.infomaniak.ch (Postfix) with ESMTPS id 4RrlYD10SYzMpp2X; Thu, 21 Sep 2023 06:17:04 +0000 (UTC) Received: from unknown by smtp-2-0001.mail.infomaniak.ch (Postfix) with ESMTPA id 4RrlYC4BjrzMppKR; Thu, 21 Sep 2023 08:17:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=digikod.net; s=20191114; t=1695277024; bh=aXxAzAZrVv/AQrM1hbU5eAstfAxS1hqSXWRkrvqIPdw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NIkVnGqhXST4ff8AXuEDBtYbO577M5gPCcl8ioUJLhFVZ/9MT+b5xSJWdc/Ejx95W 34dNrLXehRDfDf4p/H+ylzPrcZHOg03FmLJcrXkmVut5vV/xcwyn7vnt78ptkUEXtC 2pLnKDwNZSOXw6R9CHZ5lP7yTTxoAm0ndKQvkLGI= From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= To: Eric Paris , James Morris , Paul Moore , "Serge E . Hallyn" Cc: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Ben Scarlato , =?UTF-8?q?G=C3=BCnther=20Noack?= , Jeff Xu , Jorge Lucangeli Obes , Konstantin Meskhidze , Shervin Oloumi , audit@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Subject: [RFC PATCH v1 6/7] landlock: Log mount-related requests Date: Thu, 21 Sep 2023 08:16:40 +0200 Message-ID: <20230921061641.273654-7-mic@digikod.net> In-Reply-To: <20230921061641.273654-1-mic@digikod.net> References: <20230921061641.273654-1-mic@digikod.net> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Infomaniak-Routing: alpha Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add audit support for mount, move_mount, umount, remount, and pivot_root requests. Signed-off-by: Micka=C3=ABl Sala=C3=BCn --- security/landlock/audit.c | 26 ++++++++++++- security/landlock/audit.h | 13 ++++++- security/landlock/fs.c | 82 ++++++++++++++++++++++++++++++++++----- 3 files changed, 109 insertions(+), 12 deletions(-) diff --git a/security/landlock/audit.c b/security/landlock/audit.c index 148fc0fafef4..89bd701d124f 100644 --- a/security/landlock/audit.c +++ b/security/landlock/audit.c @@ -18,6 +18,11 @@ static const char *op_to_string(enum landlock_operation = operation) { const char *const desc[] =3D { [0] =3D "", + [LANDLOCK_OP_MOUNT] =3D "mount", + [LANDLOCK_OP_MOVE_MOUNT] =3D "move_mount", + [LANDLOCK_OP_UMOUNT] =3D "umount", + [LANDLOCK_OP_REMOUNT] =3D "remount", + [LANDLOCK_OP_PIVOT_ROOT] =3D "pivot_root", [LANDLOCK_OP_MKDIR] =3D "mkdir", [LANDLOCK_OP_MKNOD] =3D "mknod", [LANDLOCK_OP_SYMLINK] =3D "symlink", @@ -33,6 +38,20 @@ static const char *op_to_string(enum landlock_operation = operation) return desc[operation]; } =20 +static const char *perm_to_string(enum landlock_permission permission) +{ + const char *const desc[] =3D { + [0] =3D "", + [LANDLOCK_PERM_PTRACE] =3D "ptrace", + [LANDLOCK_PERM_FS_LAYOUT] =3D "fs_layout", + }; + + if (WARN_ON_ONCE(permission < 0 || permission > ARRAY_SIZE(desc))) + return "unknown"; + + return desc[permission]; +} + #define BIT_INDEX(bit) HWEIGHT(bit - 1) =20 static void log_accesses(struct audit_buffer *const ab, @@ -177,8 +196,11 @@ update_request(struct landlock_request *const request, WARN_ON_ONCE(request->youngest_domain); WARN_ON_ONCE(request->missing_access); =20 - if (WARN_ON_ONCE(!access_request)) + if (!access_request) { + /* No missing accesses. */ + request->youngest_domain =3D node->id; return; + } =20 if (WARN_ON_ONCE(!layer_masks)) return; @@ -240,6 +262,8 @@ log_request(const int error, struct landlock_request *c= onst request, request->youngest_domain, op_to_string(request->operation), -error); log_accesses(ab, request->missing_access); + audit_log_format(ab, " missing-permission=3D%s", + perm_to_string(request->missing_permission)); audit_log_lsm_data(ab, &request->audit); audit_log_end(ab); } diff --git a/security/landlock/audit.h b/security/landlock/audit.h index 8edc68b98fca..e559fb6a89dd 100644 --- a/security/landlock/audit.h +++ b/security/landlock/audit.h @@ -14,7 +14,12 @@ #include "ruleset.h" =20 enum landlock_operation { - LANDLOCK_OP_MKDIR =3D 1, + LANDLOCK_OP_MOUNT =3D 1, + LANDLOCK_OP_MOVE_MOUNT, + LANDLOCK_OP_UMOUNT, + LANDLOCK_OP_REMOUNT, + LANDLOCK_OP_PIVOT_ROOT, + LANDLOCK_OP_MKDIR, LANDLOCK_OP_MKNOD, LANDLOCK_OP_SYMLINK, LANDLOCK_OP_UNLINK, @@ -23,8 +28,14 @@ enum landlock_operation { LANDLOCK_OP_OPEN, }; =20 +enum landlock_permission { + LANDLOCK_PERM_PTRACE =3D 1, + LANDLOCK_PERM_FS_LAYOUT, +}; + struct landlock_request { const enum landlock_operation operation; + const enum landlock_permission missing_permission; access_mask_t missing_access; u64 youngest_domain; struct common_audit_data audit; diff --git a/security/landlock/fs.c b/security/landlock/fs.c index 104dfb2abc32..8600530e304c 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -1050,17 +1050,41 @@ static int hook_sb_mount(const char *const dev_name, const struct path *const path, const char *const type, const unsigned long flags, void *const data) { - if (!landlock_get_current_domain()) + const struct landlock_ruleset *const dom =3D + landlock_get_current_domain(); + struct landlock_request request =3D { + .operation =3D LANDLOCK_OP_MOUNT, + .missing_permission =3D LANDLOCK_PERM_FS_LAYOUT, + .audit =3D { + .type =3D LSM_AUDIT_DATA_PATH, + .u.path =3D *path, + }, + }; + + if (!dom) return 0; - return -EPERM; + + return landlock_log_request(-EPERM, &request, dom, 0, NULL); } =20 static int hook_move_mount(const struct path *const from_path, const struct path *const to_path) { - if (!landlock_get_current_domain()) + const struct landlock_ruleset *const dom =3D + landlock_get_current_domain(); + struct landlock_request request =3D { + .operation =3D LANDLOCK_OP_MOVE_MOUNT, + .missing_permission =3D LANDLOCK_PERM_FS_LAYOUT, + .audit =3D { + .type =3D LSM_AUDIT_DATA_PATH, + .u.path =3D *to_path, + }, + }; + + if (!dom) return 0; - return -EPERM; + + return landlock_log_request(-EPERM, &request, dom, 0, NULL); } =20 /* @@ -1069,16 +1093,42 @@ static int hook_move_mount(const struct path *const= from_path, */ static int hook_sb_umount(struct vfsmount *const mnt, const int flags) { - if (!landlock_get_current_domain()) + const struct landlock_ruleset *const dom =3D + landlock_get_current_domain(); + struct landlock_request request =3D { + .operation =3D LANDLOCK_OP_UMOUNT, + .missing_permission =3D LANDLOCK_PERM_FS_LAYOUT, + .audit =3D { + // TODO: try to print the mounted path + // cf. dentry_path() + .type =3D LSM_AUDIT_DATA_DENTRY, + .u.dentry =3D mnt->mnt_root, + }, + }; + + if (!dom) return 0; - return -EPERM; + + return landlock_log_request(-EPERM, &request, dom, 0, NULL); } =20 static int hook_sb_remount(struct super_block *const sb, void *const mnt_o= pts) { - if (!landlock_get_current_domain()) + const struct landlock_ruleset *const dom =3D + landlock_get_current_domain(); + struct landlock_request request =3D { + .operation =3D LANDLOCK_OP_REMOUNT, + .missing_permission =3D LANDLOCK_PERM_FS_LAYOUT, + .audit =3D { + .type =3D LSM_AUDIT_DATA_DENTRY, + .u.dentry =3D sb->s_root, + }, + }; + + if (!dom) return 0; - return -EPERM; + + return landlock_log_request(-EPERM, &request, dom, 0, NULL); } =20 /* @@ -1092,9 +1142,21 @@ static int hook_sb_remount(struct super_block *const= sb, void *const mnt_opts) static int hook_sb_pivotroot(const struct path *const old_path, const struct path *const new_path) { - if (!landlock_get_current_domain()) + const struct landlock_ruleset *const dom =3D + landlock_get_current_domain(); + struct landlock_request request =3D { + .operation =3D LANDLOCK_OP_PIVOT_ROOT, + .missing_permission =3D LANDLOCK_PERM_FS_LAYOUT, + .audit =3D { + .type =3D LSM_AUDIT_DATA_PATH, + .u.path =3D *new_path, + }, + }; + + if (!dom) return 0; - return -EPERM; + + return landlock_log_request(-EPERM, &request, dom, 0, NULL); } =20 /* Path hooks */ --=20 2.42.0