static int dek_on_device_locked(dek_arg_on_device_locked *evt) { int userid = evt->userid; int key_arr_idx; if (!dek_is_persona(userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, userid); return -EFAULT; } key_arr_idx = PERSONA_KEY_ARR_IDX(userid); dek_aes_key_free(sdp_tfm[key_arr_idx]); sdp_tfm[key_arr_idx] = NULL; zero_out((char *)&SDPK_sym[key_arr_idx], sizeof(kek_t)); zero_out((char *)&SDPK_Rpri[key_arr_idx], sizeof(kek_t)); zero_out((char *)&SDPK_Dpri[key_arr_idx], sizeof(kek_t)); zero_out((char *)&SDPK_EDpri[key_arr_idx], sizeof(kek_t)); ecryptfs_mm_drop_cache(userid); #ifdef CONFIG_SDP_KEY_DUMP if(get_sdp_sysfs_key_dump()) { dump_all_keys(key_arr_idx); } #endif return 0; }
static int ecryptfs_release(struct inode *inode, struct file *file) { #ifdef CONFIG_SDP struct ecryptfs_crypt_stat *crypt_stat; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; if(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) { #if 0 #ifdef SYNC_ONLY_CURRENT_SB struct super_block *sb = inode->i_sb; sync_inodes_sb(sb); writeback_inodes_sb(sb, WB_REASON_SYNC); #else sys_sync(); #endif DEK_LOGD("%s() sensitive inode being closed. [ino:%lu, state:%lu ref_count:%d efs_flag:0x%0.8x]\n", __func__, inode->i_ino, inode->i_state, atomic_read(&inode->i_count), crypt_stat->flags); spin_lock(&inode->i_lock); if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || (inode->i_mapping->nrpages == 0)) { spin_unlock(&inode->i_lock); } else { printk("freeing sensitive inode\n"); invalidate_mapping_pages(inode->i_mapping, 0, -1); } spin_unlock(&inode->i_lock); #else DEK_LOGD("%s() sensitive inode being closed. [ino:%lu, state:%lu ref_count:%d]\n", __func__, inode->i_ino, inode->i_state, atomic_read(&inode->i_count)); ecryptfs_clean_sdp_dek(crypt_stat); if(ecryptfs_is_persona_locked(crypt_stat->userid)) ecryptfs_mm_drop_cache(crypt_stat->userid); } #endif #endif ecryptfs_put_lower_file(inode); kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); return 0; }
static long dek_do_ioctl_evt(unsigned int minor, unsigned int cmd, unsigned long arg) { long ret = 0; void __user *ubuf = (void __user *)arg; void *cleanup = NULL; unsigned int size; switch (cmd) { /* * Event while booting. * * This event comes per persona, the driver is responsible to * verify things good whether it's compromised. */ case DEK_ON_BOOT: { dek_arg_on_boot *evt = kzalloc(sizeof(dek_arg_on_boot), GFP_KERNEL); DEK_LOGD("DEK_ON_BOOT\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_boot); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_boot(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Boot failed"); goto err; } dek_add_to_log(evt->userid, "Booted"); break; } /* * Event when device is locked. * * Nullify private key which prevents decryption. */ case DEK_ON_DEVICE_LOCKED: { dek_arg_on_device_locked *evt = kzalloc(sizeof(dek_arg_on_device_locked), GFP_KERNEL); DEK_LOGD("DEK_ON_DEVICE_LOCKED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_device_locked); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_device_locked(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Lock failed"); goto err; } dek_add_to_log(evt->userid, "Locked"); break; } /* * Event when device unlocked. * * Read private key and decrypt with user password. */ case DEK_ON_DEVICE_UNLOCKED: { dek_arg_on_device_unlocked *evt = kzalloc(sizeof(dek_arg_on_device_unlocked), GFP_KERNEL); DEK_LOGD("DEK_ON_DEVICE_UNLOCKED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_device_unlocked); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_device_unlocked(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Unlock failed"); goto err; } dek_add_to_log(evt->userid, "Unlocked"); break; } /* * Event when new user(persona) added. * * Generate RSA public key and encrypt private key with given * password. Also pub-key and encryped priv-key have to be stored * in a file system. */ case DEK_ON_USER_ADDED: { dek_arg_on_user_added *evt = kzalloc(sizeof(dek_arg_on_user_added), GFP_KERNEL); DEK_LOGD("DEK_ON_USER_ADDED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_user_added); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_user_added(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Add user failed"); goto err; } dek_add_to_log(evt->userid, "Added user"); break; } /* * Event when user is removed. * * Remove pub-key file & encrypted priv-key file. */ case DEK_ON_USER_REMOVED: { dek_arg_on_user_removed *evt = kzalloc(sizeof(dek_arg_on_user_removed), GFP_KERNEL); DEK_LOGD("DEK_ON_USER_REMOVED\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_user_removed); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } ret = dek_on_user_removed(evt); if (ret < 0) { dek_add_to_log(evt->userid, "Remove user failed"); goto err; } dek_add_to_log(evt->userid, "Removed user"); break; } /* * Event when password changed. * * Encrypt SDPK_Rpri with new password and store it. */ case DEK_ON_CHANGE_PASSWORD: { DEK_LOGD("DEK_ON_CHANGE_PASSWORD << deprecated. SKIP\n"); ret = 0; dek_add_to_log(0, "Changed password << deprecated"); break; } case DEK_DISK_CACHE_CLEANUP: { dek_arg_disk_cache_cleanup *evt = kzalloc(sizeof(dek_arg_disk_cache_cleanup), GFP_KERNEL); DEK_LOGD("DEK_DISK_CACHE_CLEANUP\n"); if (evt == NULL) { ret = -ENOMEM; goto err; } cleanup = evt; size = sizeof(dek_arg_on_user_removed); if(copy_from_user(evt, ubuf, size)) { DEK_LOGE("can't copy from user evt\n"); ret = -EFAULT; goto err; } if (!dek_is_persona(evt->userid)) { DEK_LOGE("%s invalid userid %d\n", __func__, evt->userid); ret = -EFAULT; goto err; } ecryptfs_mm_drop_cache(evt->userid); ret = 0; dek_add_to_log(evt->userid, "Disk cache clean up"); break; } default: DEK_LOGE("%s case default\n", __func__); ret = -EINVAL; break; } err: if (cleanup) { zero_out((char *)cleanup, size); kfree(cleanup); } return ret; }