Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp9652303pxu; Tue, 29 Dec 2020 00:58:36 -0800 (PST) X-Google-Smtp-Source: ABdhPJxucdYSrdLLYGGUgEYxLI0YjB4iOFdeVUNz7E06StxU7UbcuijO5HYuTeKpCgVterSq16Ke X-Received: by 2002:a17:906:710b:: with SMTP id x11mr46776813ejj.433.1609232316286; Tue, 29 Dec 2020 00:58:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1609232316; cv=none; d=google.com; s=arc-20160816; b=VwzUi1BFmr10SH1tcZ3n1zPolG1J+rnlN/gxzjzxTwpZ4tc1HIiRI+5I0wfTT5m2Z7 NPphN2vAQ214iYJZH7bw/Ua+0leUNcNpHqK4gWw8DPAboczyigjjijAjVVy4JKC6DJlz QCL7ZVQbluBdrLBnHBcPy2ZSHf4AuOGiK8T0CVxjyuK2wAW8uHd0s1OGn4cbNOgBNsWP Jl6b4tmcWgAZe6p1fWHAax0TPvNEqqp3vzmoO7qlw5EWApK1eseim3pPgkH8RTAGhTaT FxpqkP49PaeXEQ4ZxnlETJAUH1lMKoV3T+uWkrZn7Mj9Ec5c/LtwO/tKr/plgCHKMB1b 3L5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:sender:dkim-signature; bh=AHsPHV5g9RiEHoBH6SgrbuZwM40nn1MQir4HViM7xto=; b=OY1UA51caWGQlXxPUtTHqX/loJSaoXDupnEQS0PrJLVXKbiYO8LfctLz8OLQ+HOhjG 4Q+DtRfvyCMU6+apQcfNHqhFrM7h1cJ4Rbl7XVzmP+9cAniNbegsDuzWqNmMcRGqEV+N 6jvJTT5W/Z43aoxmvhpCmsCmaAYlZOEMVKIRO40yL2Y0hLl/0m1aMkBx6RGTQGOOZZrO fOkvoJrAj21xbyny6PZyUP1ulbqqKCkIJ2mSvx0jlGrH73nyU0UThN6r92bJJOmwMltE 3tRwhFUCKr8XcRvXxJxPUoH2OORLEO0L+t7qMjPSKr2J35tFiDwyye4Q3teFROPjSjGo olDQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=MCfJiSBd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j23si20833036eje.581.2020.12.29.00.58.13; Tue, 29 Dec 2020 00:58:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=MCfJiSBd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726365AbgL2I4n (ORCPT + 99 others); Tue, 29 Dec 2020 03:56:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726337AbgL2I4m (ORCPT ); Tue, 29 Dec 2020 03:56:42 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD785C06179F for ; Tue, 29 Dec 2020 00:55:35 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id 203so22756886ybz.2 for ; Tue, 29 Dec 2020 00:55:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=AHsPHV5g9RiEHoBH6SgrbuZwM40nn1MQir4HViM7xto=; b=MCfJiSBd2EZKgC/S/1p8+aHytGwvZFZ6W+n4r13mqlO867CotMVZeChoW8nF1zidB7 3bGVdI5YxcZXoWuEwqAYXwiDUB9s9kCK2pUeaoDCp0MbEwwsVuSPbCfwtkC0gUG/HguW bUb2Im9l+9h5S0QL09SGUEt+h0PgNSKrO6l6w5FuKvhFXR3VUYWPDPulpBt9MjhOEicH JTOt63xSY0iQ0S5pwmpYyWv2uMJxggz2xQ77Db4FmZ3vlR5RP/YU/IrRd0ikxslwhSXX KlKrN6jIRBX/rcH5HGL5Dut+rg9QciYjxsgYCMkB2H2c0jqanznebgyp1CUMm5goILoa Spaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=AHsPHV5g9RiEHoBH6SgrbuZwM40nn1MQir4HViM7xto=; b=Ld3XxG6ABTfHRcuj/a74XNMhPvVkyHTih4Lojlpf+SBtIAHekWcjxDP7T2khSqM/Mi 6ADDz00+PeLiNkudx66BTNCsDd+4YodZ83bg8FZbSi35f3kgaPXK4A4F/XH1/KfY+Ou3 hLfqe5K8iH/ym/6SuhloV/ZGXRrjYbmHYRRHTRKBh4EH6dHo6u1HO2Fnm0afzEWa/Kyt PfHKU/Zt1hJUTVRExm/KANpJMEdqDWKphUPhivCu6ig5ugYv4xFlHEPqY4Fvx7gRiZoa qis/7qMm9T4FxVpPii7zTeSkGkC7J559BI2XygeI33Wlb5wU1jQKuJxEHHeCUDFPybJJ ufgQ== X-Gm-Message-State: AOAM531ElPzu6VwW8sFBh0ZbkffPZ9jgxT82k1zf5UrVm7BTP5QdPHyx w4OjE9EtwuR/2yWZ/d/sulVAunDdVL4= Sender: "satyat via sendgmr" X-Received: from satyaprateek.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:1092]) (user=satyat job=sendgmr) by 2002:a25:aea8:: with SMTP id b40mr71477368ybj.347.1609232134987; Tue, 29 Dec 2020 00:55:34 -0800 (PST) Date: Tue, 29 Dec 2020 08:55:21 +0000 In-Reply-To: <20201229085524.2795331-1-satyat@google.com> Message-Id: <20201229085524.2795331-4-satyat@google.com> Mime-Version: 1.0 References: <20201229085524.2795331-1-satyat@google.com> X-Mailer: git-send-email 2.29.2.729.g45daf8777d-goog Subject: [PATCH v3 3/6] dm: add support for passing through inline crypto support From: Satya Tangirala To: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, dm-devel@redhat.com Cc: Jens Axboe , Alasdair Kergon , Mike Snitzer , Eric Biggers , Satya Tangirala Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Update the device-mapper core to support exposing the inline crypto support of the underlying device(s) through the device-mapper device. This works by creating a "passthrough keyslot manager" for the dm device, which declares support for encryption settings which all underlying devices support. When a supported setting is used, the bio cloning code handles cloning the crypto context to the bios for all the underlying devices. When an unsupported setting is used, the blk-crypto fallback is used as usual. Crypto support on each underlying device is ignored unless the corresponding dm target opts into exposing it. This is needed because for inline crypto to semantically operate on the original bio, the data must not be transformed by the dm target. Thus, targets like dm-linear can expose crypto support of the underlying device, but targets like dm-crypt can't. (dm-crypt could use inline crypto itself, though.) A DM device's table can only be changed if the "new" inline encryption capabilities are a (*not* necessarily strict) superset of the "old" inline encryption capabilities. Attempts to make changes to the table that result in some inline encryption capability becoming no longer supported will be rejected. For the sake of clarity, key eviction from underlying devices will be handled in a future patch. Co-developed-by: Eric Biggers Signed-off-by: Eric Biggers Signed-off-by: Satya Tangirala --- drivers/md/dm.c | 164 +++++++++++++++++++++++++++++++- include/linux/device-mapper.h | 6 ++ include/linux/keyslot-manager.h | 8 ++ 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index b3c3c8b4cb42..13b9c8e2e21b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -28,6 +28,7 @@ #include #include #include +#include #define DM_MSG_PREFIX "core" @@ -1718,6 +1719,8 @@ static const struct dax_operations dm_dax_ops; static void dm_wq_work(struct work_struct *work); +static void dm_destroy_inline_encryption(struct request_queue *q); + static void cleanup_mapped_device(struct mapped_device *md) { if (md->wq) @@ -1739,8 +1742,10 @@ static void cleanup_mapped_device(struct mapped_device *md) put_disk(md->disk); } - if (md->queue) + if (md->queue) { + dm_destroy_inline_encryption(md->queue); blk_cleanup_queue(md->queue); + } cleanup_srcu_struct(&md->io_barrier); @@ -1937,6 +1942,150 @@ static void event_callback(void *context) dm_issue_global_event(); } +#ifdef CONFIG_BLK_INLINE_ENCRYPTION + +struct dm_keyslot_manager { + struct blk_keyslot_manager ksm; + struct mapped_device *md; +}; + +static int device_intersect_crypto_modes(struct dm_target *ti, + struct dm_dev *dev, sector_t start, + sector_t len, void *data) +{ + struct blk_keyslot_manager *parent = data; + struct blk_keyslot_manager *child = bdev_get_queue(dev->bdev)->ksm; + + blk_ksm_intersect_modes(parent, child); + return 0; +} + +static void dm_destroy_keyslot_manager(struct blk_keyslot_manager *ksm) +{ + struct dm_keyslot_manager *dksm = container_of(ksm, + struct dm_keyslot_manager, + ksm); + + if (!ksm) + return; + + blk_ksm_destroy(ksm); + kfree(dksm); +} + +/* + * Constructs and returns a keyslot manager that represents the crypto + * capabilities of the devices described by the dm_table. However, if the + * constructed keyslot manager does not support a superset of the crypto + * capabilities supported by the current keyslot manager of the mapped_device, + * it returns an error instead, since we don't support restricting crypto + * capabilities on table changes. Finally, if the constructed keyslot manager + * doesn't actually support any crypto modes at all, it just returns NULL. + */ +static struct blk_keyslot_manager * +dm_construct_keyslot_manager(struct mapped_device *md, struct dm_table *t) +{ + struct dm_keyslot_manager *dksm; + struct blk_keyslot_manager *ksm; + struct dm_target *ti; + unsigned int i; + bool ksm_is_empty = true; + + dksm = kmalloc(sizeof(*dksm), GFP_KERNEL); + if (!dksm) + return ERR_PTR(-ENOMEM); + dksm->md = md; + + ksm = &dksm->ksm; + blk_ksm_init_passthrough(ksm); + ksm->max_dun_bytes_supported = UINT_MAX; + memset(ksm->crypto_modes_supported, 0xFF, + sizeof(ksm->crypto_modes_supported)); + + for (i = 0; i < dm_table_get_num_targets(t); i++) { + ti = dm_table_get_target(t, i); + + if (!dm_target_passes_crypto(ti->type)) { + blk_ksm_intersect_modes(ksm, NULL); + break; + } + if (!ti->type->iterate_devices) + continue; + ti->type->iterate_devices(ti, device_intersect_crypto_modes, + ksm); + } + + if (!blk_ksm_is_superset(ksm, md->queue->ksm)) { + DMWARN("Inline encryption capabilities of new DM table were more restrictive than the old table's. This is not supported!"); + dm_destroy_keyslot_manager(ksm); + return ERR_PTR(-EINVAL); + } + + /* + * If the new KSM doesn't actually support any crypto modes, we may as + * well represent it with a NULL ksm. + */ + ksm_is_empty = true; + for (i = 0; i < ARRAY_SIZE(ksm->crypto_modes_supported); i++) { + if (ksm->crypto_modes_supported[i]) { + ksm_is_empty = false; + break; + } + } + + if (ksm_is_empty) { + dm_destroy_keyslot_manager(ksm); + ksm = NULL; + } + + return ksm; +} + +static void dm_update_keyslot_manager(struct request_queue *q, + struct blk_keyslot_manager *ksm) +{ + if (!ksm) + return; + + /* Make the ksm less restrictive */ + if (!q->ksm) { + blk_ksm_register(ksm, q); + } else { + blk_ksm_update_capabilities(q->ksm, ksm); + dm_destroy_keyslot_manager(ksm); + } +} + +static void dm_destroy_inline_encryption(struct request_queue *q) +{ + if (!q->ksm) + return; + dm_destroy_keyslot_manager(q->ksm); +} + +#else /* CONFIG_BLK_INLINE_ENCRYPTION */ + +static inline struct blk_keyslot_manager * +dm_construct_keyslot_manager(struct mapped_device *md, struct dm_table *t) +{ + return NULL; +} + +static void dm_update_keyslot_manager(struct request_queue *q, + struct blk_keyslot_manager *ksm) +{ +} + +static void dm_destroy_keyslot_manager(struct blk_keyslot_manager *ksm) +{ +} + +static inline void dm_destroy_inline_encryption(struct request_queue *q) +{ +} + +#endif /* !CONFIG_BLK_INLINE_ENCRYPTION */ + /* * Returns old map, which caller must destroy. */ @@ -2332,6 +2481,7 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) { struct dm_table *live_map = NULL, *map = ERR_PTR(-EINVAL); struct queue_limits limits; + struct blk_keyslot_manager *ksm; int r; mutex_lock(&md->suspend_lock); @@ -2361,7 +2511,19 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) } } + ksm = dm_construct_keyslot_manager(md, table); + if (IS_ERR(ksm)) { + map = ERR_CAST(ksm); + goto out; + } + map = __bind(md, table, &limits); + + if (IS_ERR(map)) + dm_destroy_keyslot_manager(ksm); + else + dm_update_keyslot_manager(md->queue, ksm); + dm_issue_global_event(); out: diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 61a66fb8ebb3..0d5794a0a89a 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -257,6 +257,12 @@ struct target_type { #define DM_TARGET_NOWAIT 0x00000080 #define dm_target_supports_nowait(type) ((type)->features & DM_TARGET_NOWAIT) +/* + * + */ +#define DM_TARGET_PASSES_CRYPTO 0x00000100 +#define dm_target_passes_crypto(type) ((type)->features & DM_TARGET_PASSES_CRYPTO) + struct dm_target { struct dm_table *table; struct target_type *type; diff --git a/include/linux/keyslot-manager.h b/include/linux/keyslot-manager.h index 164568f52be7..9164c1c72288 100644 --- a/include/linux/keyslot-manager.h +++ b/include/linux/keyslot-manager.h @@ -11,6 +11,8 @@ struct blk_keyslot_manager; +#ifdef CONFIG_BLK_INLINE_ENCRYPTION + /** * struct blk_ksm_ll_ops - functions to manage keyslots in hardware * @keyslot_program: Program the specified key into the specified slot in the @@ -114,4 +116,10 @@ bool blk_ksm_is_superset(struct blk_keyslot_manager *ksm_superset, void blk_ksm_update_capabilities(struct blk_keyslot_manager *target_ksm, struct blk_keyslot_manager *reference_ksm); +#else /* CONFIG_BLK_INLINE_ENCRYPTION */ + +static inline void blk_ksm_destroy(struct blk_keyslot_manager *ksm) { } + +#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ + #endif /* __LINUX_KEYSLOT_MANAGER_H */ -- 2.29.2.729.g45daf8777d-goog