/** * ecryptfs_interpose * @lower_dentry: Existing dentry in the lower filesystem * @dentry: ecryptfs' dentry * @sb: ecryptfs's super_block * * Interposes upper and lower dentries. * * Returns zero on success; non-zero otherwise */ static int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, struct super_block *sb) { struct inode *inode = ecryptfs_get_inode(lower_dentry->d_inode, sb); if (IS_ERR(inode)) return PTR_ERR(inode); d_instantiate(dentry, inode); if(d_unhashed(dentry)) d_rehash(dentry); #ifdef CONFIG_SDP if(S_ISDIR(inode->i_mode) && dentry) { if(IS_UNDER_ROOT(dentry)) { struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; int engineid; printk("Creating a directoy under root directory of current partition.\n"); if(is_chamber_directory(mount_crypt_stat, dentry->d_name.name, &engineid)) { printk("This is a chamber directory engine[%d]\n", engineid); set_chamber_flag(engineid, inode); } } else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) { /* * When parent directory is sensitive */ struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; struct ecryptfs_crypt_stat *parent_crypt_stat = &ecryptfs_inode_to_private(dentry->d_parent->d_inode)->crypt_stat; //TODO : remove this log DEK_LOGE("Parent %s[id:%d] is sensitive. so this directory is sensitive too\n", dentry->d_parent->d_name.name, parent_crypt_stat->engine_id); crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE; crypt_stat->engine_id = parent_crypt_stat->engine_id; } } #endif return 0; }
/** * ecryptfs_interpose * @lower_dentry: Existing dentry in the lower filesystem * @dentry: ecryptfs' dentry * @sb: ecryptfs's super_block * * Interposes upper and lower dentries. * * Returns zero on success; non-zero otherwise */ static int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, struct super_block *sb) { struct inode *inode = ecryptfs_get_inode(lower_dentry->d_inode, sb); if (IS_ERR(inode)) return PTR_ERR(inode); d_instantiate(dentry, inode); #ifdef CONFIG_SDP if(S_ISDIR(inode->i_mode) && dentry) { if(IS_UNDER_ROOT(dentry)) { struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; printk("Creating a directoy under root directory of current partition.\n"); if(is_chamber_directory(mount_crypt_stat, (char *)dentry->d_name.name)) { printk("This is a chamber directory\n"); set_chamber_flag(inode); } } else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) { /* * When parent directory is sensitive */ struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; printk("Parent %s is sensitive. so this directory is sensitive too\n", dentry->d_parent->d_name.name); crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE; } } #endif return 0; }
/** * ecryptfs_lookup_interpose - Dentry interposition for a lookup */ static int ecryptfs_lookup_interpose(struct dentry *dentry, struct dentry *lower_dentry, struct inode *dir_inode) { struct inode *inode, *lower_inode = lower_dentry->d_inode; struct ecryptfs_dentry_info *dentry_info; struct vfsmount *lower_mnt; int rc = 0; dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); if (!dentry_info) { printk(KERN_ERR "%s: Out of memory whilst attempting " "to allocate ecryptfs_dentry_info struct\n", __func__); dput(lower_dentry); return -ENOMEM; } lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode); BUG_ON(!lower_dentry->d_count); ecryptfs_set_dentry_private(dentry, dentry_info); ecryptfs_set_dentry_lower(dentry, lower_dentry); ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt); if (!lower_dentry->d_inode) { /* We want to add because we couldn't find in lower */ d_add(dentry, NULL); return 0; } inode = __ecryptfs_get_inode(lower_inode, dir_inode->i_sb); if (IS_ERR(inode)) { printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", __func__, PTR_ERR(inode)); return PTR_ERR(inode); } if (S_ISREG(inode->i_mode)) { rc = ecryptfs_i_size_read(dentry, inode); if (rc) { make_bad_inode(inode); return rc; } } #ifdef CONFIG_SDP if (S_ISDIR(inode->i_mode) && dentry) { if(IS_UNDER_ROOT(dentry)) { struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; printk("Lookup a directoy under root directory of current partition.\n"); if(is_chamber_directory(mount_crypt_stat, (char *)dentry->d_name.name)) { /* * When this directory is under ROOT directory and the name is registered * as Chamber. */ printk("This is a chamber directory\n"); set_chamber_flag(inode); } } else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) { /* * When parent directory is sensitive */ struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; printk("Parent %s is sensitive. so this directory is sensitive too\n", dentry->d_parent->d_name.name); crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE; } } #endif if (inode->i_state & I_NEW) unlock_new_inode(inode); d_add(dentry, inode); return rc; }
static int ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { int rc; struct dentry *lower_old_dentry; struct dentry *lower_new_dentry; struct dentry *lower_old_dir_dentry; struct dentry *lower_new_dir_dentry; struct dentry *trap = NULL; struct inode *target_inode; #ifdef CONFIG_DLP sdp_fs_command_t *cmd1 = NULL; unsigned long old_inode = old_dentry->d_inode->i_ino; #endif #ifdef CONFIG_SDP sdp_fs_command_t *cmd = NULL; int rename_event = 0x00; struct ecryptfs_crypt_stat *crypt_stat = &(ecryptfs_inode_to_private(old_dentry->d_inode)->crypt_stat); struct ecryptfs_crypt_stat *parent_crypt_stat = &(ecryptfs_inode_to_private(old_dentry->d_parent->d_inode)->crypt_stat); struct ecryptfs_crypt_stat *new_parent_crypt_stat = &(ecryptfs_inode_to_private(new_dentry->d_parent->d_inode)->crypt_stat); struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private(old_dentry->d_sb)->mount_crypt_stat; #if ECRYPTFS_SDP_RENAME_DEBUG printk("You're renaming %s to %s\n", old_dentry->d_name.name, new_dentry->d_name.name); printk("old_dentry[%p] : %s [parent %s : %s] inode:%p\n", old_dentry, old_dentry->d_name.name, old_dentry->d_parent->d_name.name, IS_SENSITIVE_DENTRY(old_dentry->d_parent) ? "sensitive" : "protected", old_dentry->d_inode); printk("new_dentry[%p] : %s [parent %s : %s] inode:%p\n", new_dentry, new_dentry->d_name.name, new_dentry->d_parent->d_name.name, IS_SENSITIVE_DENTRY(new_dentry->d_parent) ? "sensitive" : "protected", new_dentry->d_inode); #endif if(IS_CHAMBER_DENTRY(old_dentry)) { printk("Rename trial on chamber : failed\n"); return -EIO; } #if 0 // kernel panic. new_crypt_stat->engine_id if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) && IS_SENSITIVE_DENTRY(new_dentry->d_parent)) { if(crypt_stat->engine_id != new_crypt_stat->engine_id) { printk("Rename chamber file to another chamber : failed\n"); return -EIO; } } #endif if(IS_SENSITIVE_DENTRY(old_dentry->d_parent)) { if(ecryptfs_is_sdp_locked(parent_crypt_stat->engine_id)) { printk("Rename/move trial in locked state\n"); return -EIO; } } if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) && IS_SENSITIVE_DENTRY(new_dentry->d_parent)) { if(parent_crypt_stat->engine_id != new_parent_crypt_stat->engine_id) { printk("Can't move between chambers\n"); return -EIO; } } if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) && !IS_SENSITIVE_DENTRY(new_dentry->d_parent)) rename_event |= ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER; if(!IS_SENSITIVE_DENTRY(old_dentry->d_parent) && IS_SENSITIVE_DENTRY(new_dentry->d_parent)) rename_event |= ECRYPTFS_EVT_RENAME_TO_CHAMBER; #endif lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); dget(lower_old_dentry); dget(lower_new_dentry); lower_old_dir_dentry = dget_parent(lower_old_dentry); lower_new_dir_dentry = dget_parent(lower_new_dentry); target_inode = new_dentry->d_inode; trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); /* source should not be ancestor of target */ if (trap == lower_old_dentry) { rc = -EINVAL; goto out_lock; } /* target should not be ancestor of source */ if (trap == lower_new_dentry) { rc = -ENOTEMPTY; goto out_lock; } rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, lower_new_dir_dentry->d_inode, lower_new_dentry); if (rc) goto out_lock; if (target_inode) fsstack_copy_attr_all(target_inode, ecryptfs_inode_to_lower(target_inode)); fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); if (new_dir != old_dir) fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); #ifdef CONFIG_SDP if(!rc) { crypt_stat = &(ecryptfs_inode_to_private(old_dentry->d_inode)->crypt_stat); if(rename_event > 0) { switch(rename_event) { case ECRYPTFS_EVT_RENAME_TO_CHAMBER: cmd = sdp_fs_command_alloc(FSOP_SDP_SET_SENSITIVE, current->pid, mount_crypt_stat->userid, mount_crypt_stat->partition_id, old_dentry->d_inode->i_ino, GFP_NOFS); break; case ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER: cmd = sdp_fs_command_alloc(FSOP_SDP_SET_PROTECTED, current->pid, mount_crypt_stat->userid, mount_crypt_stat->partition_id, old_dentry->d_inode->i_ino, GFP_NOFS); break; default: cmd = NULL; break; } } #if ECRYPTFS_SDP_RENAME_DEBUG printk("[end of rename] old_dentry[%p] : %s [parent %s : %s] inode:%p\n", old_dentry, old_dentry->d_name.name, old_dentry->d_parent->d_name.name, IS_SENSITIVE_DENTRY(old_dentry->d_parent) ? "sensitive" : "protected", old_dentry->d_inode); printk("[end of rename] new_dentry[%p] : %s [parent %s : %s] inode:%p\n", new_dentry, new_dentry->d_name.name, new_dentry->d_parent->d_name.name, IS_SENSITIVE_DENTRY(new_dentry->d_parent) ? "sensitive" : "protected", new_dentry->d_inode); #endif } #endif out_lock: unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); dput(lower_new_dir_dentry); dput(lower_old_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); #ifdef CONFIG_SDP if(!rc && cmd != NULL) { sdp_fs_request(cmd, ecryptfs_fs_request_callback); sdp_fs_command_free(cmd); } #endif #ifdef CONFIG_DLP //create new init command and send--Handle transient case MS-Apps if(crypt_stat->flags & ECRYPTFS_DLP_ENABLED) { if(!rc && (in_egroup_p(AID_KNOX_DLP) || in_egroup_p(AID_KNOX_DLP_RESTRICTED))){ cmd1 = sdp_fs_command_alloc(FSOP_DLP_FILE_RENAME, current->tgid, mount_crypt_stat->userid, mount_crypt_stat->partition_id, old_inode, GFP_KERNEL); //send cmd if(cmd1) { sdp_fs_request(cmd1, NULL); sdp_fs_command_free(cmd1); } } } //end- Handle transient case MS-Apps #endif return rc; }