blob: 97ffb1d30defcba629de3ec2b8d3e60939cdd0f5 [file] [log] [blame]
/*
* dd_common.h
*
* Created on: Oct 3, 2018
* Author: olic.moon
*/
#ifndef SECURITY_SDP_DD_COMMON_H_
#define SECURITY_SDP_DD_COMMON_H_
#include <sdp/dd.h>
#include <linux/jiffies.h>
#include <linux/ratelimit.h>
typedef enum {
DD_REQ_INIT = 0,
DD_REQ_PENDING,
DD_REQ_PROCESSING,
DD_REQ_SUBMITTED,
DD_REQ_FINISHING,
DD_REQ_UNALLOCATED,
DD_REQ_COUNT
}dd_req_state_t;
struct dd_benchmark_result {
unsigned long count;
struct ratelimit_state ratelimit_state;
long data[DD_REQ_COUNT];
spinlock_t lock;
};
struct dd_benchmark {
struct timeval stage[DD_REQ_COUNT];
};
struct dd_context {
char name[10]; // Informational name
/**
* Protects dd_context resources
* - req_ctr: req counter
* - procs: process list
* - dd_proc allocation and free
*/
spinlock_t lock;
spinlock_t ctr_lock; // lock for req counter
int req_ctr; // counter for request unique number
struct list_head procs; // Process list
struct dd_mmap_layout *layout;
struct mutex bio_alloc_lock;
struct bio_set *bio_set;
mempool_t *page_pool;
struct dd_benchmark_result bm_result;
};
struct dd_context *dd_get_global_context(void);
struct dd_proc {
/**
* Protect dd_proc attributes
* - pending/processing lists
*/
spinlock_t lock;
atomic_t reqcount; // free the object when this becomes 0
int abort;
wait_queue_head_t waitq;
pid_t pid;
pid_t tgid;
struct dd_context *context;
struct list_head proc_node; // list held in dd_context.procs
struct list_head pending; // pending requests
struct list_head processing; // processing requests
struct list_head submitted; // submitted requests
int num_control_page;
struct page *control_page[MAX_NUM_CONTROL_PAGE];
struct vm_area_struct *control_vma;
struct vm_area_struct *metadata_vma;
struct vm_area_struct *plaintext_vma;
struct vm_area_struct *ciphertext_vma;
};
#define CONFIG_DD_REQ_DEBUG 1
struct dd_req {
struct dd_context *context;
unsigned unique; // unique request id
dd_request_code_t code;
unsigned char dir;
struct list_head list;
int user_space_crypto;
int abort;
int need_xattr_flush;
dd_req_state_t state;
wait_queue_head_t waitq;
#if CONFIG_DD_REQ_DEBUG
struct list_head debug_list;
#endif
unsigned long timestamp;
struct dd_info *info;
unsigned long ino;
pid_t pid;
pid_t tgid;
union {
struct {
struct page *metadata;
}prepare;
struct {
dd_crypto_direction_t dir;
struct page *src_page;
struct page *dst_page;
}page;
struct {
struct bio *orig;
struct bio *clone;
}bio;
}u;
struct work_struct decryption_work;
struct work_struct delayed_free_work;
struct dd_benchmark bm;
};
#define usec(t) (t.tv_sec * 1000000 + t.tv_usec)
static inline void dd_req_state(struct dd_req *req, dd_req_state_t state) {
if (dd_debug_bit_test(DD_DEBUG_BENCHMARK)) {
if (state == DD_REQ_INIT)
memset((void *)&req->bm, 0, sizeof(struct dd_benchmark));
do_gettimeofday(&req->bm.stage[state]);
}
req->state = state;
}
static inline void dd_submit_benchmark(struct dd_benchmark *bm, struct dd_context *context) {
int i;
if (dd_debug_bit_test(DD_DEBUG_BENCHMARK)) {
spin_lock(&context->bm_result.lock);
for (i=1; i < DD_REQ_COUNT ; i++) {
long avg = context->bm_result.data[i];
long val = usec(bm->stage[i]) - usec(bm->stage[DD_REQ_INIT]);
long div = context->bm_result.count + 1;
context->bm_result.data[i] = avg + ((val - avg) / div);
}
context->bm_result.count++;
spin_unlock(&context->bm_result.lock);
}
}
static inline void dd_dump_benchmark(struct dd_benchmark_result *bm_result) {
if (dd_debug_bit_test(DD_DEBUG_BENCHMARK) &&
__ratelimit(&bm_result->ratelimit_state)) {
spin_lock(&bm_result->lock);
dd_info("benchmark req{pending:%ld processing:%ld submitted:%ld finishing:%ld freed:%ld} cnt:%ld\n",
bm_result->data[DD_REQ_PENDING],
bm_result->data[DD_REQ_PROCESSING],
bm_result->data[DD_REQ_SUBMITTED],
bm_result->data[DD_REQ_FINISHING],
bm_result->data[DD_REQ_UNALLOCATED],
bm_result->count);
spin_unlock(&bm_result->lock);
}
}
#define USE_KEYRING (0)
#if USE_KEYRING
#else
int dd_add_master_key(int userid, void *key, int len);
void dd_evict_master_key(int userid);
#ifdef CONFIG_SDP_KEY_DUMP
int dd_dump_key(int userid, int fd);
#endif
#endif
int get_dd_master_key(int userid, void *key);
int dd_sec_crypt_bio_pages(struct dd_info *info, struct bio *orig,
struct bio *clone, dd_crypto_direction_t rw);
int dd_sec_crypt_page(struct dd_info *info, dd_crypto_direction_t rw,
struct page *src_page, struct page *dst_page);
int dd_read_crypt_context(struct inode *inode, struct dd_crypt_context *crypt_context);
int dd_write_crypt_context(struct inode *inode, const struct dd_crypt_context *context, void *fs_data);
int dd_read_crypto_metadata(struct inode *inode, const char *name, void *buffer, size_t buffer_size);
int dd_write_crypto_metadata(struct inode *inode, const char *name, const void *buffer, size_t len);
void dd_hex_key_dump(const char* tag, uint8_t *data, size_t data_len);
#endif /* SECURITY_SDP_DD_COMMON_H_ */