static int wrapfs_open(struct inode *inode, struct file *file) { int err = 0; struct file *lower_file = NULL; struct path lower_path; #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_MESG("Enter"); #endif /* don't open unhashed/deleted files */ if (d_unhashed(file->f_path.dentry)) { err = -ENOENT; goto out_err; } file->private_data = kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL); if (!WRAPFS_F(file)) { err = -ENOMEM; goto out_err; } /* open lower object and link wrapfs's file struct to lower's */ wrapfs_get_lower_path(file->f_path.dentry, &lower_path); lower_file = dentry_open(lower_path.dentry, lower_path.mnt, file->f_flags, current_cred()); if (IS_ERR(lower_file)) { err = PTR_ERR(lower_file); lower_file = wrapfs_lower_file(file); if (lower_file) { wrapfs_set_lower_file(file, NULL); fput(lower_file); /* fput calls dput for lower_dentry */ } } else { wrapfs_set_lower_file(file, lower_file); } if (err) kfree(WRAPFS_F(file)); else fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode)); out_err: #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_RETURN("Exit", err); #endif return err; }
/* release all lower object references & free the file info structure */ static int wrapfs_file_release(struct inode *inode, struct file *file) { struct file *lower_file; #ifdef EXTRA_CREDIT int CHKSUM_SIZE =0; char *algo = kmalloc(sizeof(char)*10,GFP_KERNEL); int *algo_len = kmalloc(sizeof(int)*1,GFP_KERNEL); char *getchkbuf = kmalloc(sizeof(char)*32,GFP_KERNEL); #else char *getchkbuf = kmalloc(sizeof(char)*CHKSUM_SIZE,GFP_KERNEL); #endif char *has_integrity = kmalloc(sizeof(char)*1,GFP_KERNEL); int rc; lower_file = wrapfs_lower_file(file); if (lower_file) { if(lower_file->f_mode == O_RDONLY) goto out_release; else if(!S_ISDIR(lower_file->f_path.dentry->d_inode->i_mode)&& wrapfs_get_write_dirty(inode) == WRITE_DIRTY_BIT) { #ifdef EXTRA_CREDIT CHKSUM_SIZE = get_default_chksum_size(lower_file->f_path.dentry,algo,algo_len); #endif if(!has_integrity || !getchkbuf) { rc = -ENOMEM; goto out_release; } spin_lock(&inode->i_lock); wrapfs_set_write_dirty(inode,READ_DIRTY_BIT); spin_unlock(&inode->i_lock); if(vfs_getxattr(lower_file->f_path.dentry,XATTR_HAS_INTEGRITY,has_integrity,1)>0) { if(!memcmp(has_integrity,"1",1)) { calculate_checksum(lower_file,getchkbuf,CHKSUM_SIZE); rc = vfs_setxattr(lower_file->f_path.dentry,XATTR_INTEGRITY_VAL,getchkbuf,CHKSUM_SIZE,XATTR_CREATE); if(rc == -EEXIST) rc = vfs_setxattr(lower_file->f_path.dentry,XATTR_INTEGRITY_VAL,getchkbuf,CHKSUM_SIZE,XATTR_REPLACE); } } } out_release: wrapfs_set_lower_file(file, NULL); fput(lower_file); } kfree(WRAPFS_F(file)); kfree(getchkbuf); kfree(has_integrity); #ifdef EXTRA_CREDIT kfree(algo); kfree(algo_len); #endif return 0; }
static int __open_file(struct inode *inode, struct file *file, struct dentry *parent) { struct dentry *lower_dentry; struct file *lower_file; struct vfsmount *lower_mnt; struct dentry *dentry = file->f_path.dentry; int lower_flags; int i = 0, idx = 0; for (i = 0; i <= 1; i++) { lower_dentry = wrapfs_lower_dentry_idx(dentry, i); if (!lower_dentry || !lower_dentry->d_inode) continue; lower_flags = file->f_flags; if (lower_dentry->d_inode && (i == 1)) { UDBG; if (lower_flags & O_TRUNC) { int size = 0; int err = -EROFS; UDBG; err = copyup_file(parent->d_inode, file, i, 0, size); if (!err) break; return err; } else lower_flags &= ~(OPEN_WRITE_FLAGS); } dget(lower_dentry); lower_mnt = mntget(wrapfs_lower_mnt_idx(dentry, i)); if (!lower_mnt) lower_mnt = mntget(wrapfs_lower_mnt_idx(parent, i)); lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags, current_cred()); if (IS_ERR(lower_file)) return PTR_ERR(lower_file); wrapfs_set_lower_file(file, lower_file); branchget(inode->i_sb, i); idx = i; goto out; } out: if (!wrapfs_lower_inode_idx(inode, idx)) fsstack_copy_attr_all(inode, wrapfs_lower_inode_idx(inode, idx)); return 0; }
/* release all lower object references & free the file info structure */ static int wrapfs_file_release(struct inode *inode, struct file *file) { struct file *lower_file; lower_file = wrapfs_lower_file(file); if (lower_file) { wrapfs_set_lower_file(file, NULL); fput(lower_file); } kfree(WRAPFS_F(file)); return 0; }
/* release all lower object references & free the file info structure */ static int wrapfs_file_release(struct inode *inode, struct file *file) { struct file *lower_file; #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_MESG("Enter"); #endif lower_file = wrapfs_lower_file(file); if (lower_file) { wrapfs_set_lower_file(file, NULL); fput(lower_file); } #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_MESG("Exit"); #endif kfree(WRAPFS_F(file)); return 0; }
static int wrapfs_open(struct inode *inode, struct file *file) { int err = 0; struct file *lower_file = NULL; struct path lower_path; #ifdef EXTRA_CREDIT int CHKSUM_SIZE =0; char *algo = kmalloc(sizeof(char)*10,GFP_KERNEL); int *algo_len = kmalloc(sizeof(char)*1,GFP_KERNEL); char *chkbuf = kmalloc(sizeof(char)*32,GFP_KERNEL); char *getchkbuf = kmalloc(sizeof(char)*32,GFP_KERNEL); #else char *chkbuf = kmalloc(sizeof(char)*CHKSUM_SIZE,GFP_KERNEL); char *getchkbuf = kmalloc(sizeof(char)*CHKSUM_SIZE,GFP_KERNEL); #endif char *has_integrity = kmalloc(sizeof(char)*1,GFP_KERNEL); int rc = 0; if(!chkbuf || !has_integrity || !getchkbuf) { err = -ENOMEM; goto out_err; } /* don't open unhashed/deleted files */ if (d_unhashed(file->f_path.dentry)) { err = -ENOENT; goto out_err; } file->private_data = kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL); if (!WRAPFS_F(file)) { err = -ENOMEM; goto out_err; } /* open lower object and link wrapfs's file struct to lower's */ wrapfs_get_lower_path(file->f_path.dentry, &lower_path); lower_file = dentry_open(lower_path.dentry, lower_path.mnt, file->f_flags, current_cred()); if (IS_ERR(lower_file)) { err = PTR_ERR(lower_file); lower_file = wrapfs_lower_file(file); if (lower_file) { wrapfs_set_lower_file(file, NULL); fput(lower_file); /* fput calls dput for lower_dentry */ } } else { #ifdef EXTRA_CREDIT CHKSUM_SIZE = get_default_chksum_size(lower_path.dentry,algo,algo_len); #endif rc = vfs_getxattr(lower_path.dentry,XATTR_HAS_INTEGRITY,has_integrity,1); if(rc > 0 && !S_ISDIR(lower_path.dentry->d_inode->i_mode)) { wrapfs_set_lower_file(file,lower_file); if(lower_file->f_mode == O_TRUNC) wrapfs_set_write_dirty(inode,WRITE_DIRTY_BIT); if(!memcmp(has_integrity,"1",1) && wrapfs_get_write_dirty(inode)!=WRITE_DIRTY_BIT && rc ==1) { if(vfs_getxattr(lower_path.dentry,XATTR_INTEGRITY_VAL,chkbuf,CHKSUM_SIZE)>0) { //mutex_lock(&lower_path.dentry->d_inode->i_mutex); calculate_checksum(lower_file,getchkbuf,CHKSUM_SIZE); if(memcmp(chkbuf,getchkbuf,CHKSUM_SIZE)) { printk("Integrity mismatch\n"); err = -EPERM; wrapfs_set_lower_file(file,NULL); fput(lower_file); } //mutex_unlock(&lower_path.dentry->d_inode->i_mutex); } } else if(!memcmp(has_integrity,"0",1) && rc ==1) { if(vfs_getxattr(lower_path.dentry,XATTR_INTEGRITY_VAL,chkbuf,CHKSUM_SIZE)>0) { err = -EIO; wrapfs_set_lower_file(file,NULL); fput(lower_file); } else wrapfs_set_lower_file(file,lower_file); } else { printk("File corrupted.Unexpected value for has_integrity attribute\n"); err = -EPERM; wrapfs_set_lower_file(file,NULL); fput(lower_file); } } else if(vfs_getxattr(lower_path.dentry,XATTR_HAS_INTEGRITY,has_integrity,1)<=0 && vfs_getxattr(lower_path.dentry,XATTR_INTEGRITY_VAL,chkbuf,CHKSUM_SIZE)>0) { err = -EIO; wrapfs_set_lower_file(file,NULL); fput(lower_file); } else { wrapfs_set_lower_file(file, lower_file); } } if (err) kfree(WRAPFS_F(file)); else fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode)); out_err: kfree(chkbuf); kfree(getchkbuf); kfree(has_integrity); #ifdef EXTRA_CREDIT kfree(algo); kfree(algo_len); #endif return err; }