/* * sdp_name.c * */ #include #include #include "../fscrypt_private.h" struct fscrypt_sdp_renament { struct inode *dir; struct dentry *dentry; struct inode *inode; }; static inline int fscrypt_is_sensitive_dentry(struct dentry *dentry) { struct ext_fscrypt_info *ext_ci = GET_EXT_CI(dentry->d_inode->i_crypt_info); if (ext_ci->ci_sdp_info && (ext_ci->ci_sdp_info->sdp_flags & SDP_DEK_IS_SENSITIVE)) { return 1; } return 0; } static inline int fscrypt_is_chamber_dentry(struct dentry *dentry) { struct ext_fscrypt_info *ext_ci = GET_EXT_CI(dentry->d_inode->i_crypt_info); if (ext_ci->ci_sdp_info && (ext_ci->ci_sdp_info->sdp_flags & SDP_IS_CHAMBER_DIR)) { return 1; } return 0; } int fscrypt_sdp_get_storage_type(struct dentry *target_dentry) { if (!target_dentry) return FSCRYPT_SDP_NAME_FUNC_ERROR; else { int p_type = FSCRYPT_SDP_NAME_FUNC_ERROR; struct dentry *t_dentry = target_dentry; while (strcasecmp(t_dentry->d_name.name, "/")) {// "/" means "/data" if (!strcasecmp(t_dentry->d_name.name, "user")) { p_type = FSCRYPT_STORAGE_TYPE_DATA_CE; } else if (!strcasecmp(t_dentry->d_name.name, "media")) { p_type = FSCRYPT_STORAGE_TYPE_MEDIA_CE; } else if (!strcasecmp(t_dentry->d_name.name, "system_ce")) { p_type = FSCRYPT_STORAGE_TYPE_SYSTEM_CE; } else if (!strcasecmp(t_dentry->d_name.name, "misc_ce")) { p_type = FSCRYPT_STORAGE_TYPE_MISC_CE; } else if (!strcasecmp(t_dentry->d_name.name, "user_de")) { p_type = FSCRYPT_STORAGE_TYPE_DATA_DE; } else if (!strcasecmp(t_dentry->d_name.name, "system_de")) { p_type = FSCRYPT_STORAGE_TYPE_SYSTEM_DE; } else if (!strcasecmp(t_dentry->d_name.name, "misc_de")) { p_type = FSCRYPT_STORAGE_TYPE_MISC_DE; } else if (!strcasecmp(t_dentry->d_name.name, "enc_user")) { p_type = FSCRYPT_STORAGE_TYPE_SDP_ENC_USER; } else if (!strcasecmp(t_dentry->d_name.name, "knox")) { p_type = FSCRYPT_STORAGE_TYPE_SDP_ENC_EMULATED; } else { p_type = FSCRYPT_SDP_NAME_FUNC_ERROR; } t_dentry = t_dentry->d_parent; } return p_type; } } EXPORT_SYMBOL(fscrypt_sdp_get_storage_type); void fscrypt_sdp_check_chamber_event(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct fscrypt_sdp_renament old = { .dir = old_dir, .dentry = old_dentry, .inode = d_inode(old_dentry), }; struct fscrypt_sdp_renament new = { .dir = new_dir, .dentry = new_dentry, .inode = d_inode(new_dentry), }; if (old_dir->i_crypt_info && new_dir->i_crypt_info) { sdp_fs_command_t *cmd = NULL; int rename_event = 0x00; if (fscrypt_is_sensitive_dentry(old.dentry->d_parent) && !fscrypt_is_sensitive_dentry(new.dentry->d_parent)) rename_event |= FSCRYPT_EVT_RENAME_OUT_OF_CHAMBER; if (!fscrypt_is_sensitive_dentry(old.dentry->d_parent) && fscrypt_is_sensitive_dentry(new.dentry->d_parent)) rename_event |= FSCRYPT_EVT_RENAME_TO_CHAMBER; if ((rename_event & FSCRYPT_EVT_RENAME_TO_CHAMBER) && !fscrypt_is_sensitive_dentry(old.dentry)) {//Protected dir to Sensitive area cmd = sdp_fs_command_alloc(FSOP_SDP_SET_SENSITIVE, current->pid, fscrypt_sdp_get_engine_id(new.dir), fscrypt_sdp_get_storage_type(new.dentry->d_parent), old.inode->i_ino, 0, GFP_NOFS); } else if (rename_event & FSCRYPT_EVT_RENAME_OUT_OF_CHAMBER) {//Sensitive dir to Protected area cmd = sdp_fs_command_alloc(FSOP_SDP_SET_PROTECTED, current->pid, fscrypt_sdp_get_engine_id(old.dir), fscrypt_sdp_get_storage_type(new.dentry->d_parent), old.inode->i_ino, 0, GFP_NOFS); } if (cmd != NULL) { sdp_fs_request(cmd, NULL); sdp_fs_command_free(cmd); } } } int fscrypt_sdp_check_rename_pre(struct dentry *old_dentry) { if (old_dentry->d_inode->i_crypt_info) { struct ext_fscrypt_info *ext_ci = GET_EXT_CI(old_dentry->d_inode->i_crypt_info); if (ext_ci->ci_sdp_info && fscrypt_is_chamber_dentry(old_dentry)) { printk_once(KERN_WARNING "Renaming Chamber directory, I/O error\n"); return -EIO; } } return 0; } void fscrypt_sdp_check_rename_post(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { if (IS_ENCRYPTED(d_inode(old_dentry))) fscrypt_sdp_check_chamber_event(old_dir, old_dentry, new_dir, new_dentry); } int fscrypt_sdp_check_rmdir(struct dentry *dentry) { if (dentry->d_inode->i_crypt_info) { struct ext_fscrypt_info *ext_ci = GET_EXT_CI(dentry->d_inode->i_crypt_info); if (ext_ci->ci_sdp_info && fscrypt_is_chamber_dentry(dentry)) { printk_once(KERN_WARNING "You're removing Chamber directory, I/O error\n"); return -EIO; } } return 0; }