/* * dd_common.h * * Created on: Oct 3, 2018 * Author: olic.moon */ #ifndef SECURITY_SDP_DD_COMMON_H_ #define SECURITY_SDP_DD_COMMON_H_ #include #include #include 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 timespec64 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 nsec(t) (t.tv_sec * 1000000000 + t.tv_nsec) 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)); ktime_get_real_ts64(&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 = nsec(bm->stage[i]) - nsec(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); void dd_hex_key_dump(const char *tag, uint8_t *data, unsigned int data_len); #endif /* SECURITY_SDP_DD_COMMON_H_ */