Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2021 Google LLC
0004  *
0005  * sysfs support for blk-crypto.  This file contains the code which exports the
0006  * crypto capabilities of devices via /sys/block/$disk/queue/crypto/.
0007  */
0008 
0009 #include <linux/blk-crypto-profile.h>
0010 
0011 #include "blk-crypto-internal.h"
0012 
0013 struct blk_crypto_kobj {
0014     struct kobject kobj;
0015     struct blk_crypto_profile *profile;
0016 };
0017 
0018 struct blk_crypto_attr {
0019     struct attribute attr;
0020     ssize_t (*show)(struct blk_crypto_profile *profile,
0021             struct blk_crypto_attr *attr, char *page);
0022 };
0023 
0024 static struct blk_crypto_profile *kobj_to_crypto_profile(struct kobject *kobj)
0025 {
0026     return container_of(kobj, struct blk_crypto_kobj, kobj)->profile;
0027 }
0028 
0029 static struct blk_crypto_attr *attr_to_crypto_attr(struct attribute *attr)
0030 {
0031     return container_of(attr, struct blk_crypto_attr, attr);
0032 }
0033 
0034 static ssize_t max_dun_bits_show(struct blk_crypto_profile *profile,
0035                  struct blk_crypto_attr *attr, char *page)
0036 {
0037     return sysfs_emit(page, "%u\n", 8 * profile->max_dun_bytes_supported);
0038 }
0039 
0040 static ssize_t num_keyslots_show(struct blk_crypto_profile *profile,
0041                  struct blk_crypto_attr *attr, char *page)
0042 {
0043     return sysfs_emit(page, "%u\n", profile->num_slots);
0044 }
0045 
0046 #define BLK_CRYPTO_RO_ATTR(_name) \
0047     static struct blk_crypto_attr _name##_attr = __ATTR_RO(_name)
0048 
0049 BLK_CRYPTO_RO_ATTR(max_dun_bits);
0050 BLK_CRYPTO_RO_ATTR(num_keyslots);
0051 
0052 static struct attribute *blk_crypto_attrs[] = {
0053     &max_dun_bits_attr.attr,
0054     &num_keyslots_attr.attr,
0055     NULL,
0056 };
0057 
0058 static const struct attribute_group blk_crypto_attr_group = {
0059     .attrs = blk_crypto_attrs,
0060 };
0061 
0062 /*
0063  * The encryption mode attributes.  To avoid hard-coding the list of encryption
0064  * modes, these are initialized at boot time by blk_crypto_sysfs_init().
0065  */
0066 static struct blk_crypto_attr __blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX];
0067 static struct attribute *blk_crypto_mode_attrs[BLK_ENCRYPTION_MODE_MAX + 1];
0068 
0069 static umode_t blk_crypto_mode_is_visible(struct kobject *kobj,
0070                       struct attribute *attr, int n)
0071 {
0072     struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj);
0073     struct blk_crypto_attr *a = attr_to_crypto_attr(attr);
0074     int mode_num = a - __blk_crypto_mode_attrs;
0075 
0076     if (profile->modes_supported[mode_num])
0077         return 0444;
0078     return 0;
0079 }
0080 
0081 static ssize_t blk_crypto_mode_show(struct blk_crypto_profile *profile,
0082                     struct blk_crypto_attr *attr, char *page)
0083 {
0084     int mode_num = attr - __blk_crypto_mode_attrs;
0085 
0086     return sysfs_emit(page, "0x%x\n", profile->modes_supported[mode_num]);
0087 }
0088 
0089 static const struct attribute_group blk_crypto_modes_attr_group = {
0090     .name = "modes",
0091     .attrs = blk_crypto_mode_attrs,
0092     .is_visible = blk_crypto_mode_is_visible,
0093 };
0094 
0095 static const struct attribute_group *blk_crypto_attr_groups[] = {
0096     &blk_crypto_attr_group,
0097     &blk_crypto_modes_attr_group,
0098     NULL,
0099 };
0100 
0101 static ssize_t blk_crypto_attr_show(struct kobject *kobj,
0102                     struct attribute *attr, char *page)
0103 {
0104     struct blk_crypto_profile *profile = kobj_to_crypto_profile(kobj);
0105     struct blk_crypto_attr *a = attr_to_crypto_attr(attr);
0106 
0107     return a->show(profile, a, page);
0108 }
0109 
0110 static const struct sysfs_ops blk_crypto_attr_ops = {
0111     .show = blk_crypto_attr_show,
0112 };
0113 
0114 static void blk_crypto_release(struct kobject *kobj)
0115 {
0116     kfree(container_of(kobj, struct blk_crypto_kobj, kobj));
0117 }
0118 
0119 static struct kobj_type blk_crypto_ktype = {
0120     .default_groups = blk_crypto_attr_groups,
0121     .sysfs_ops  = &blk_crypto_attr_ops,
0122     .release    = blk_crypto_release,
0123 };
0124 
0125 /*
0126  * If the request_queue has a blk_crypto_profile, create the "crypto"
0127  * subdirectory in sysfs (/sys/block/$disk/queue/crypto/).
0128  */
0129 int blk_crypto_sysfs_register(struct request_queue *q)
0130 {
0131     struct blk_crypto_kobj *obj;
0132     int err;
0133 
0134     if (!q->crypto_profile)
0135         return 0;
0136 
0137     obj = kzalloc(sizeof(*obj), GFP_KERNEL);
0138     if (!obj)
0139         return -ENOMEM;
0140     obj->profile = q->crypto_profile;
0141 
0142     err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, &q->kobj,
0143                    "crypto");
0144     if (err) {
0145         kobject_put(&obj->kobj);
0146         return err;
0147     }
0148     q->crypto_kobject = &obj->kobj;
0149     return 0;
0150 }
0151 
0152 void blk_crypto_sysfs_unregister(struct request_queue *q)
0153 {
0154     kobject_put(q->crypto_kobject);
0155 }
0156 
0157 static int __init blk_crypto_sysfs_init(void)
0158 {
0159     int i;
0160 
0161     BUILD_BUG_ON(BLK_ENCRYPTION_MODE_INVALID != 0);
0162     for (i = 1; i < BLK_ENCRYPTION_MODE_MAX; i++) {
0163         struct blk_crypto_attr *attr = &__blk_crypto_mode_attrs[i];
0164 
0165         attr->attr.name = blk_crypto_modes[i].name;
0166         attr->attr.mode = 0444;
0167         attr->show = blk_crypto_mode_show;
0168         blk_crypto_mode_attrs[i - 1] = &attr->attr;
0169     }
0170     return 0;
0171 }
0172 subsys_initcall(blk_crypto_sysfs_init);