Ejemplo n.º 1
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
	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;
}
Ejemplo n.º 2
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
	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;
}
Ejemplo n.º 3
0
static int wrapfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
	int err;
	struct file *file, *lower_file;
	const struct vm_operations_struct *lower_vm_ops;
	struct vm_area_struct lower_vma;

	/*printk(KERN_ALERT "In wrapfs_fault()\n");	*/

	memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
	file = lower_vma.vm_file;
	lower_vm_ops = WRAPFS_F(file)->lower_vm_ops;
	BUG_ON(!lower_vm_ops);

	lower_file = wrapfs_lower_file(file);
	/*
	 * XXX: vm_ops->fault may be called in parallel.  Because we have to
	 * resort to temporarily changing the vma->vm_file to point to the
	 * lower file, a concurrent invocation of wrapfs_fault could see a
	 * different value.  In this workaround, we keep a different copy of
	 * the vma structure in our stack, so we never expose a different
	 * value of the vma->vm_file called to us, even temporarily.  A
	 * better fix would be to change the calling semantics of ->fault to
	 * take an explicit file pointer.
	 */
	lower_vma.vm_file = lower_file;
	err = lower_vm_ops->fault(&lower_vma, vmf);
	return err;
}
Ejemplo n.º 4
0
static int wrapfs_open(struct inode *inode, struct file *file)
{

	int err = 0;
	struct dentry *dentry = file->f_path.dentry;
	struct dentry *parent = NULL;
	int size;
	/* don't open unhashed/deleted files */
	if (d_unhashed(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;
	}

	atomic_set(&WRAPFS_F(file)->generation,
			atomic_read(&WRAPFS_I(inode)->generation));

	size = sizeof(struct file *) * 2;
	WRAPFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
	if (unlikely(!WRAPFS_F(file)->lower_files)) {
		err = -ENOMEM;
		goto out_err;
	}
	parent = dget_parent(dentry);
	if (S_ISDIR(inode->i_mode))
		err = __open_dir(inode, file, parent);
	else
		err = __open_file(inode, file, parent);
/*	if(!err)
		fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode));
*/
out_err:
	dput(parent);
	return err;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
static int wrapfs_mmap(struct file *file, struct vm_area_struct *vma)
{
	int err = 0;
	bool willwrite;
	struct file *lower_file;
	const struct vm_operations_struct *saved_vm_ops = NULL;
#ifdef DEBUG_SUPPORT
	if(debug_support(wrapfs_lower_file(file)->f_dentry->d_sb,"file"))
		UDBG;
#endif
	/* this might be deferred to mmap's writepage */
	willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);

	/*
	 * File systems which do not implement ->writepage may use
	 * generic_file_readonly_mmap as their ->mmap op.  If you call
	 * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
	 * But we cannot call the lower ->mmap op, so we can't tell that
	 * writeable mappings won't work.  Therefore, our only choice is to
	 * check if the lower file system supports the ->writepage, and if
	 * not, return EINVAL (the same error that
	 * generic_file_readonly_mmap returns in that case).
	 */
	lower_file = wrapfs_lower_file(file);
	if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
		err = -EINVAL;
		printk(KERN_ERR "wrapfs: lower file system does not "
		       "support writeable mmap\n");
		goto out;
	}

	/*
	 * find and save lower vm_ops.
	 *
	 * XXX: the VFS should have a cleaner way of finding the lower vm_ops
	 */
	if (!WRAPFS_F(file)->lower_vm_ops) {
		err = lower_file->f_op->mmap(lower_file, vma);
		if (err) {
			printk(KERN_ERR "wrapfs: lower mmap failed %d\n", err);
			goto out;
		}
		saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */
		err = do_munmap(current->mm, vma->vm_start,
				vma->vm_end - vma->vm_start);
		if (err) {
			printk(KERN_ERR "wrapfs: do_munmap failed %d\n", err);
			goto out;
		}
	}

	/*
	 * Next 3 lines are all I need from generic_file_mmap.  I definitely
	 * don't want its test for ->readpage which returns -ENOEXEC.
	 */
	file_accessed(file);
	vma->vm_ops = &wrapfs_vm_ops;
	vma->vm_flags |= VM_CAN_NONLINEAR;

	file->f_mapping->a_ops = &wrapfs_aops; /* set our aops */
	if (!WRAPFS_F(file)->lower_vm_ops) /* save for our ->fault */
		WRAPFS_F(file)->lower_vm_ops = saved_vm_ops;

out:
#ifdef DEBUG_SUPPORT
	if(debug_support(lower_file->f_dentry->d_sb,"file"))
		UDBGE(err);
#endif
	return err;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
/* Readpage expects a locked page, and must unlock it */
static int wrapfs_readpage(struct file *file, struct page *page)
{
    int err = 0;
    int count = 0;
    struct file *lower_file;
    struct inode *inode;
    mm_segment_t old_fs;
    char *page_data = NULL;
    mode_t orig_mode;
    
#ifdef WRAPFS_CRYPTO         
    /* for decryption, use a temp page(cipher_page) to store what we
       vfs_read from lower_file, then decrypt it and store the result
       in upper page
     */
    struct page *cipher_page;
    void *cipher;
    if (MMAP_FLAG == 0) {
	err = -EPERM;
	goto out_page;
    }
    /* init temp page here */
    cipher_page = alloc_page(GFP_KERNEL);
    if (IS_ERR(cipher_page)){
	err = PTR_ERR(cipher_page);
	goto out_page;
    }
    cipher = kmap(cipher_page);

#endif
    if (!WRAPFS_F(file)) {
	err = -ENOENT;
	goto out;
    }
    lower_file = wrapfs_lower_file(file);
    /* FIXME: is this assertion right here? */
    BUG_ON(lower_file == NULL);
    
    inode = file->f_path.dentry->d_inode;
    
    page_data = (char *) kmap(page);
    /*
     * Use vfs_read because some lower file systems don't have a
     * readpage method, and some file systems (esp. distributed ones)
     * don't like their pages to be accessed directly.  Using vfs_read
     * may be a little slower, but a lot safer, as the VFS does a lot of
     * the necessary magic for us.
     */
    lower_file->f_pos = page_offset(page);
    old_fs = get_fs();
    set_fs(KERNEL_DS);
    /*
     * generic_file_splice_write may call us on a file not opened for
     * reading, so temporarily allow reading.
     */
    orig_mode = lower_file->f_mode;
    lower_file->f_mode |= FMODE_READ;
#ifdef WRAPFS_CRYPTO
    count = vfs_read(lower_file, cipher, PAGE_CACHE_SIZE,
		   &lower_file->f_pos);
#else
    count = vfs_read(lower_file, page_data, PAGE_CACHE_SIZE,
		     &lower_file->f_pos);
#endif
    lower_file->f_mode = orig_mode;
    
    set_fs(old_fs);
#ifdef WRAPFS_CRYPTO
    /* do decryption here */
    if (count >= 0) 
	err = wrapfs_decrypt(WRAPFS_SB(inode->i_sb)->key,page_data, cipher, count);
    if (err < 0)
	goto out;
#endif
    if (count >= 0 && count < PAGE_CACHE_SIZE)
	memset(page_data + count, 0, PAGE_CACHE_SIZE - count);
    
    /* if vfs_read succeeded above, sync up our times */
    wrapfs_copy_attr_times(inode);
    kunmap(page);
    flush_dcache_page(page);
    /*
     * we have to unlock our page, b/c we _might_ have gotten a locked
     * page.  but we no longer have to wakeup on our page here, b/c
     * UnlockPage does it
     */
out:
#ifdef WRAPFS_CRYPTO
    kunmap(cipher_page);
    __free_page(cipher_page);
out_page:
#endif
    if (err == 0)
	SetPageUptodate(page);
    else
	ClearPageUptodate(page);
    
    unlock_page(page);    
    return err;
}