Keyring instance in fscrypt_info structure was removed by commit "fscrypt: remove broken support for detecting keyring key revocation". However we still keep keyring reference for HIE design: HIE gets key from keyring instance. This will lead to failed I/O after keyring is revoked specifically because HIE did not check if keyring is revoked while referring to it. To fix this and not care about keyring revoking in HIE, re-design HIE flow to keep raw key in fscrypt_info instance instead, and also hook fscrypt_info to encrypted bios. Consequently underlying driver can get key from bios fscrypt_info reference. An important thing is, we shall promise enough fscrypt_infos life cycle by applying usage count to fscrypt_info because evicting inode process kills fscrypt_info but encrypted bios may not be finished before inodes are evicted. For example, unlinking an inode with bios submitted but not finished. Future work: Saving more memory by reducing number of fscrypt_info instances by cache mechanism because there are many fscrypt_info instances with exact the same contents, e.g., having the same key and crypto configurations. MTK-Commit-Id: 8a46b511231c3ff4ed49cde9a22a10371c220bae Change-Id: I314d6175a8836997224f1e48417e9f32e8d36b8d Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> CR-Id: ALPS04362512 Feature: Multi-Storage (cherry picked from commit 81b45b62c52f07e35b1e5f7321725f0beaf41bce)
189 lines
3.8 KiB
C
189 lines
3.8 KiB
C
/*
|
|
* Copyright (C) 2017 MediaTek Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef __HIE_H_
|
|
#define __HIE_H_
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/blk_types.h>
|
|
#include <linux/blkdev.h>
|
|
#include <keys/user-type.h>
|
|
|
|
#define HIE_MAX_KEY_SIZE 64
|
|
|
|
#define HIE_DBG_FS 0x02
|
|
#define HIE_DBG_BIO 0x04
|
|
#define HIE_DBG_KEY 0x08
|
|
#define HIE_DBG_HIE 0x10
|
|
#define HIE_DBG_DRV 0x20
|
|
#define HIE_DBG_CRY 0x40
|
|
|
|
struct hie_fs {
|
|
const char *name;
|
|
int (*key_payload)(struct bio_crypt_ctx *ctx,
|
|
const unsigned char **key);
|
|
int (*set_bio_context)(struct inode *inode,
|
|
struct bio *bio);
|
|
void *priv; /* fs specific data */
|
|
|
|
struct list_head list;
|
|
};
|
|
|
|
struct hie_dev {
|
|
const char *name;
|
|
unsigned int mode; /* encryption modes supported by the device */
|
|
int (*encrypt)(unsigned int mode, const char *key, int len,
|
|
struct request *req, void *priv);
|
|
int (*decrypt)(unsigned int mode, const char *key, int len,
|
|
struct request *req, void *priv);
|
|
void *priv; /* device specific data */
|
|
|
|
struct list_head list;
|
|
};
|
|
|
|
typedef int (*hie_act)(unsigned int, const char *, int,
|
|
struct request *, void *);
|
|
|
|
static inline bool hie_request_crypted(struct request *req)
|
|
{
|
|
return (req && req->bio) ?
|
|
(req->bio->bi_crypt_ctx.bc_flags & BC_CRYPT) : 0;
|
|
}
|
|
|
|
#ifdef CONFIG_HIE
|
|
bool hie_is_capable(const struct super_block *sb);
|
|
int hie_is_dummy(void);
|
|
int hie_is_nocrypt(void);
|
|
int hie_register_fs(struct hie_fs *fs);
|
|
int hie_register_device(struct hie_dev *dev);
|
|
int hie_decrypt(struct hie_dev *dev, struct request *req, void *priv);
|
|
int hie_encrypt(struct hie_dev *dev, struct request *req, void *priv);
|
|
bool hie_key_verify(struct bio *bio1, struct bio *bio2);
|
|
int hie_set_bio_crypt_context(struct inode *inode, struct bio *bio);
|
|
int hie_set_dio_crypt_context(struct inode *inode, struct bio *bio,
|
|
loff_t fs_offset);
|
|
u64 hie_get_iv(struct request *req);
|
|
|
|
int hie_debug(unsigned int mask);
|
|
int hie_debug_ino(unsigned long ino);
|
|
int hie_req_end_size(struct request *req, unsigned long bytes);
|
|
int hie_dump_req(struct request *req, const char *prefix);
|
|
#else
|
|
static inline
|
|
bool hie_is_capable(const struct super_block *sb)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline
|
|
int hie_is_dummy(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_is_nocrypt(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
bool hie_key_verify(struct bio *bio1, struct bio *bio2)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static inline
|
|
int hie_register_fs(struct hie_fs *fs)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_register_device(struct hie_dev *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_decrypt(struct hie_dev *dev, struct request *req, void *priv)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_encrypt(struct hie_dev *dev, struct request *req, void *priv)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_set_bio_crypt_context(struct inode *inode, struct bio *bio)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_set_dio_crypt_context(struct inode *inode, struct bio *bio,
|
|
loff_t fs_offset)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
u64 hie_get_iv(struct request *req)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_debug(unsigned int mask)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_debug_ino(unsigned long ino)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
int hie_req_end_size(struct request *req, unsigned long bytes)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline
|
|
void hie_dump_bio_file(struct bio *bio, const char *prefix,
|
|
const char *filename)
|
|
{
|
|
}
|
|
|
|
static inline
|
|
int hie_dump_req(struct request *req, const char *prefix)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
static inline
|
|
int hie_req_end(struct request *req)
|
|
{
|
|
return hie_req_end_size(req, 0);
|
|
}
|
|
|
|
#endif
|
|
|