コード例 #1
0
ファイル: file.c プロジェクト: CPonty/ext3301-fs
/*
 * ext3301 read: wrapper for the standard file read function.
 *  modifications: handling encryption and immediate files.
 *  original: do_sync_read
 */
ssize_t ext3301_read(struct file * filp, char __user * buf, size_t len,
                     loff_t * ppos) {
    struct inode * i = FILP_INODE(filp);
    ssize_t ret = 0;

    dbg(KERN_DEBUG "Read: '%s'\n", FILP_NAME(filp));

    //Check if the file is immediate (requires special read behaviour)
    if (I_ISIM(i)) {
        dbg_im(KERN_DEBUG "- Read-immediate\n");
        ret = ext3301_read_immediate(filp, buf, len, ppos);

    } else {
        dbg_im(KERN_DEBUG "- Read-regular\n");
        ret = do_sync_read(filp, buf, len, ppos);
    }

    //Check if the file is in the encryption tree
    if (ext3301_isencrypted(filp->f_path.dentry)) {
        //Decrypt the data which was read
        dbg_cr(KERN_DEBUG "- Encrypting data (%d bytes)\n", (int)len);
        if (ext3301_cryptbuf(buf, len) < 0)
            return -EIO;
    }

    return ret;
}
コード例 #2
0
ファイル: debug.c プロジェクト: Schiiiiins/lcu1
void dbg_prompt(int i)
{
	msg_print(MSG_PROMPT);
	msg_print(i);
	dbg_cr();
}
コード例 #3
0
ファイル: debug.c プロジェクト: Schiiiiins/lcu1
void dbg_print_cr(char * s)
{
	dbg_print(s);
	dbg_cr();
}
コード例 #4
0
ファイル: debug.c プロジェクト: Schiiiiins/lcu1
void dbg_printnum_cr(char * s, unsigned long no)
{
	dbg_printnum(s, no);
	dbg_cr();
}
コード例 #5
0
ファイル: namei.c プロジェクト: CPonty/ext3301-fs
/*
 * ext3301: modified to encrypt/decrypt files moving to/from
 * 	an encrypted folder.
 * Rename still succeeds if an encrypt/decrypt operation fails.
 */
static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
	struct inode * new_dir,	struct dentry * new_dentry )
{
	struct inode * old_inode = old_dentry->d_inode;
	struct inode * new_inode = new_dentry->d_inode;
	struct page * dir_page = NULL;
	struct ext2_dir_entry_2 * dir_de = NULL;
	struct page * old_page;
	struct ext2_dir_entry_2 * old_de;
	int err = -ENOENT;

	bool is_encryptable, src_encrypt, dest_encrypt;
	int i;
	struct file * fcrypt;
	ssize_t nchunk, nread, nwritten;
	loff_t fpos, fseekpos;
	unsigned int fsize, fremaining;
	char * buf, * strbuf1, * strbuf2, * path_src, * path_dest;
	size_t blocksize = INODE_BLKSIZE(old_inode);

	//

	dquot_initialize(old_dir);
	dquot_initialize(new_dir);

	old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page);
	if (!old_de)
		goto out;

	if (S_ISDIR(old_inode->i_mode)) {
		err = -EIO;
		dir_de = ext2_dotdot(old_inode, &dir_page);
		if (!dir_de)
			goto out_old;
	}

	if (new_inode) {
		struct page *new_page;
		struct ext2_dir_entry_2 *new_de;

		err = -ENOTEMPTY;
		if (dir_de && !ext2_empty_dir (new_inode))
			goto out_dir;

		err = -ENOENT;
		new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page);
		if (!new_de)
			goto out_dir;
		ext2_set_link(new_dir, new_de, new_page, old_inode, 1);
		new_inode->i_ctime = CURRENT_TIME_SEC;
		if (dir_de)
			drop_nlink(new_inode);
		inode_dec_link_count(new_inode);
	} else {
		err = ext2_add_link(new_dentry, old_inode);
		if (err)
			goto out_dir;
		if (dir_de)
			inode_inc_link_count(new_dir);
	}

	// allocate buffers
	strbuf1 = kmalloc((size_t)512, GFP_KERNEL);
	strbuf2 = kmalloc((size_t)512, GFP_KERNEL);
	buf = kmalloc(blocksize, GFP_KERNEL);
	if (!buf || !strbuf1 || !strbuf2)
		return -ENOMEM;

	// check if the source XOR destination lie under /encrypt,
	// 	and both entries are regular or immediate files
	is_encryptable = (I_ISIM(old_inode) || I_ISREG(old_inode));
	src_encrypt = ext3301_isencrypted(old_dentry);
	dest_encrypt = ext3301_isencrypted(new_dentry);
	path_src  = ext3301_getpath(old_dentry, strbuf1, blocksize);
	path_dest = ext3301_getpath(new_dentry, strbuf2, blocksize);

	// decide whether to encrypt
	dbg(KERN_DEBUG "rename (%s --> %s)\n", path_src, path_dest);
	if (is_encryptable) {
		dbg_cr(KERN_DEBUG "- File encryptable type (regular/immediate)\n");
		if (src_encrypt && dest_encrypt) {
			dbg_cr(KERN_DEBUG "- File moving inside /encrypt (no change))\n");
		} else if (src_encrypt) {
			dbg_cr(KERN_DEBUG "- File moving out of /encrypt. Decrypting..\n");
			goto cryptstart;
		} else if (dest_encrypt) {
			dbg_cr(KERN_DEBUG "- File moving into /encrypt. Encrypting..\n");
			goto cryptstart;
		} else {
			dbg_cr(KERN_DEBUG "- Src/dest directories not encryptable\n");
		}
	} else {
		dbg_cr(KERN_DEBUG "- File not an encryptable type\n");
	}
	goto cryptdone;

/* encrypt/decrypt file */
cryptstart: 
	// open file
	if (!path_src)
		goto cryptfail;
	fcrypt = kfile_open(path_src, O_RDWR);
	if (!fcrypt)
		goto cryptfail;
	fsize = FILP_FSIZE(fcrypt);
	fremaining = fsize;
	fpos = 0;
	fseekpos = 0;
	dbg_cr(KERN_DEBUG " - Opened %s (Fsize: %d)\n", 
		FILP_NAME(fcrypt), fsize);
	// special case: nothing to encrypt
	if (fsize==0) 
		goto cryptclose;
	// loop: read, encrypt, write
	while (fremaining > 0) {
		// choose a chunk size
		nchunk = (fremaining > blocksize ? blocksize : (ssize_t)fremaining);
		dbg_cr(KERN_DEBUG " - Starting a %d-byte chunk at pos %u.\n", 
			(int)nchunk, (unsigned int)fpos);
		// read a chunk; make sure we read all bytes requested.
		fpos = fseekpos;
		nread = kfile_read(fcrypt, buf, (size_t)nchunk, &fpos);
		//	this inequality covers error conditions (nread<0) and 
		//	partial reads (0<=nread<=nchunk && nread != nchunk)
		if (nread != nchunk) {
			kfile_close(fcrypt);
			goto cryptfail;
		}
		// encrypt the buffer
		for (i=0; i<nchunk; i++)
			buf[i] ^= crypter_key;
		// write the chunk back
		fpos = fseekpos;
		nwritten = kfile_write(fcrypt, buf, (size_t)nchunk, &fpos);
		if (nwritten != nchunk) {
			kfile_close(fcrypt);
			goto cryptfail;
		}
		// move the file marker forward, decrease the #bytes remaining
		fseekpos += nchunk;
		fremaining -= nchunk;
	}
	// sync the read/write operations to disk. Very important!
	kfile_sync(fcrypt);

cryptclose:
	kfile_close(fcrypt);
	goto cryptdone;

cryptfail:
	// encrypt/decrypt failed
	if (dest_encrypt)
		printk(KERN_WARNING "Crypting file entering /%s failed: ino %lu\n",
				crypter_dir, INODE_INO(old_inode));
	else if (src_encrypt)
		printk(KERN_WARNING "Decrypting file leaving /%s failed: ino %lu\n",
				crypter_dir, INODE_INO(old_inode));
	goto cryptdone;

cryptdone:
	/*
	 * Like most other Unix systems, set the ctime for inodes on a
 	 * rename.
	 */
	old_inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(old_inode);

	ext2_delete_entry (old_de, old_page);

	if (dir_de) {
		if (old_dir != new_dir)
			ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0);
		else {
			kunmap(dir_page);
			page_cache_release(dir_page);
		}
		inode_dec_link_count(old_dir);
	}
	goto out_free;

out_dir:
	if (dir_de) {
		kunmap(dir_page);
		page_cache_release(dir_page);
	}
out_old:
	kunmap(old_page);
	page_cache_release(old_page);
out:
	return err;
out_free:
	// free buffers
	kfree(strbuf1);
	kfree(strbuf2);
	kfree(buf);
	return 0;
}
コード例 #6
0
ファイル: file.c プロジェクト: CPonty/ext3301-fs
/*
 * ext3301 write: wrapper for the standard file write function.
 *  modifications: handling encryption and immediate files.
 *  original: do_sync_write
 */
ssize_t ext3301_write(struct file * filp, char __user * buf, size_t len,
                      loff_t * ppos) {
    ssize_t ret, written;
    struct inode * i = FILP_INODE(filp);

    dbg_im(KERN_DEBUG "Write: '%s'\n", FILP_NAME(filp));

    //Encryption: Check if the file is in the encryption tree
    if (ext3301_isencrypted(filp->f_path.dentry)) {
        //Encrypt the data being written
        dbg_cr(KERN_DEBUG "- Encrypting data (%d bytes)\n", (int)len);
        if (ext3301_cryptbuf(buf, len) < 0)
            return -EIO;
    }

    //Immediate file only: walk ppos forward manually for Append mode
    if (I_ISIM(i) && (FILP_FLAGS(filp) & O_APPEND)) {
        dbg_im(KERN_DEBUG "O_APPEND: walking ppos to EoF\n");
        *ppos += INODE_ISIZE(i);
    }

    //Immediate file only: Check if it needs to grow into a regular file
    if (I_ISIM(i) && (*ppos+len > EXT3301_IM_SIZE(i))) {
        dbg_im(KERN_DEBUG "- IM-->REG conversion\n");
        ret = ext3301_im2reg(filp);
        if (ret < 0) {
            printk(KERN_DEBUG "IM-->REG conversion fail: ino %lu, err %d\n",
                   INODE_INO(i), (int)ret);
            return ret;
        }
        //Append mode: undo the ppos offset. We are now writing to a
        //regular file, and the default methods already handle this.
        if (FILP_FLAGS(filp) & O_APPEND) {
            dbg_im(KERN_DEBUG "O_APPEND: walking ppos back (REG)\n");
            *ppos -= INODE_ISIZE(i);
        }
    }

    //Write to file (immediate and regular files have different methods)
    if (I_ISIM(i)) {
        dbg_im(KERN_DEBUG "- Write-immediate\n");
        written = ext3301_write_immediate(filp, buf, len, ppos);

    } else {
        dbg_im(KERN_DEBUG "- Write-regular\n");
        written = do_sync_write(filp, buf, len, ppos);
    }

    //Regular file only: Check if it's small enough to convert to immediate
    if (INODE_TYPE(i)==DT_REG && (INODE_ISIZE(i)<=EXT3301_IM_SIZE(i))) {
        dbg_im(KERN_DEBUG "- REG-->IM conversion\n");
        ret = ext3301_reg2im(filp);
        if (ret < 0) {
            printk(KERN_DEBUG "REG-->IM file conversion failed: ino %lu\n",
                   INODE_INO(i));
            return ret;
        }
    }

    return written;
}