1*237fead6SMichael Halcrow /** 2*237fead6SMichael Halcrow * eCryptfs: Linux filesystem encryption layer 3*237fead6SMichael Halcrow * 4*237fead6SMichael Halcrow * Copyright (C) 1997-2004 Erez Zadok 5*237fead6SMichael Halcrow * Copyright (C) 2001-2004 Stony Brook University 6*237fead6SMichael Halcrow * Copyright (C) 2004-2006 International Business Machines Corp. 7*237fead6SMichael Halcrow * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> 8*237fead6SMichael Halcrow * Michael C. Thompson <mcthomps@us.ibm.com> 9*237fead6SMichael Halcrow * 10*237fead6SMichael Halcrow * This program is free software; you can redistribute it and/or 11*237fead6SMichael Halcrow * modify it under the terms of the GNU General Public License as 12*237fead6SMichael Halcrow * published by the Free Software Foundation; either version 2 of the 13*237fead6SMichael Halcrow * License, or (at your option) any later version. 14*237fead6SMichael Halcrow * 15*237fead6SMichael Halcrow * This program is distributed in the hope that it will be useful, but 16*237fead6SMichael Halcrow * WITHOUT ANY WARRANTY; without even the implied warranty of 17*237fead6SMichael Halcrow * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18*237fead6SMichael Halcrow * General Public License for more details. 19*237fead6SMichael Halcrow * 20*237fead6SMichael Halcrow * You should have received a copy of the GNU General Public License 21*237fead6SMichael Halcrow * along with this program; if not, write to the Free Software 22*237fead6SMichael Halcrow * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 23*237fead6SMichael Halcrow * 02111-1307, USA. 24*237fead6SMichael Halcrow */ 25*237fead6SMichael Halcrow 26*237fead6SMichael Halcrow #include <linux/file.h> 27*237fead6SMichael Halcrow #include <linux/poll.h> 28*237fead6SMichael Halcrow #include <linux/mount.h> 29*237fead6SMichael Halcrow #include <linux/pagemap.h> 30*237fead6SMichael Halcrow #include <linux/security.h> 31*237fead6SMichael Halcrow #include <linux/smp_lock.h> 32*237fead6SMichael Halcrow #include <linux/compat.h> 33*237fead6SMichael Halcrow #include "ecryptfs_kernel.h" 34*237fead6SMichael Halcrow 35*237fead6SMichael Halcrow /** 36*237fead6SMichael Halcrow * ecryptfs_llseek 37*237fead6SMichael Halcrow * @file: File we are seeking in 38*237fead6SMichael Halcrow * @offset: The offset to seek to 39*237fead6SMichael Halcrow * @origin: 2 - offset from i_size; 1 - offset from f_pos 40*237fead6SMichael Halcrow * 41*237fead6SMichael Halcrow * Returns the position we have seeked to, or negative on error 42*237fead6SMichael Halcrow */ 43*237fead6SMichael Halcrow static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin) 44*237fead6SMichael Halcrow { 45*237fead6SMichael Halcrow loff_t rv; 46*237fead6SMichael Halcrow loff_t new_end_pos; 47*237fead6SMichael Halcrow int rc; 48*237fead6SMichael Halcrow int expanding_file = 0; 49*237fead6SMichael Halcrow struct inode *inode = file->f_mapping->host; 50*237fead6SMichael Halcrow 51*237fead6SMichael Halcrow /* If our offset is past the end of our file, we're going to 52*237fead6SMichael Halcrow * need to grow it so we have a valid length of 0's */ 53*237fead6SMichael Halcrow new_end_pos = offset; 54*237fead6SMichael Halcrow switch (origin) { 55*237fead6SMichael Halcrow case 2: 56*237fead6SMichael Halcrow new_end_pos += i_size_read(inode); 57*237fead6SMichael Halcrow expanding_file = 1; 58*237fead6SMichael Halcrow break; 59*237fead6SMichael Halcrow case 1: 60*237fead6SMichael Halcrow new_end_pos += file->f_pos; 61*237fead6SMichael Halcrow if (new_end_pos > i_size_read(inode)) { 62*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) " 63*237fead6SMichael Halcrow "> i_size_read(inode)(=[0x%.16x])\n", 64*237fead6SMichael Halcrow new_end_pos, i_size_read(inode)); 65*237fead6SMichael Halcrow expanding_file = 1; 66*237fead6SMichael Halcrow } 67*237fead6SMichael Halcrow break; 68*237fead6SMichael Halcrow default: 69*237fead6SMichael Halcrow if (new_end_pos > i_size_read(inode)) { 70*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) " 71*237fead6SMichael Halcrow "> i_size_read(inode)(=[0x%.16x])\n", 72*237fead6SMichael Halcrow new_end_pos, i_size_read(inode)); 73*237fead6SMichael Halcrow expanding_file = 1; 74*237fead6SMichael Halcrow } 75*237fead6SMichael Halcrow } 76*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos); 77*237fead6SMichael Halcrow if (expanding_file) { 78*237fead6SMichael Halcrow rc = ecryptfs_truncate(file->f_dentry, new_end_pos); 79*237fead6SMichael Halcrow if (rc) { 80*237fead6SMichael Halcrow rv = rc; 81*237fead6SMichael Halcrow ecryptfs_printk(KERN_ERR, "Error on attempt to " 82*237fead6SMichael Halcrow "truncate to (higher) offset [0x%.16x];" 83*237fead6SMichael Halcrow " rc = [%d]\n", new_end_pos, rc); 84*237fead6SMichael Halcrow goto out; 85*237fead6SMichael Halcrow } 86*237fead6SMichael Halcrow } 87*237fead6SMichael Halcrow rv = generic_file_llseek(file, offset, origin); 88*237fead6SMichael Halcrow out: 89*237fead6SMichael Halcrow return rv; 90*237fead6SMichael Halcrow } 91*237fead6SMichael Halcrow 92*237fead6SMichael Halcrow /** 93*237fead6SMichael Halcrow * ecryptfs_read_update_atime 94*237fead6SMichael Halcrow * 95*237fead6SMichael Halcrow * generic_file_read updates the atime of upper layer inode. But, it 96*237fead6SMichael Halcrow * doesn't give us a chance to update the atime of the lower layer 97*237fead6SMichael Halcrow * inode. This function is a wrapper to generic_file_read. It 98*237fead6SMichael Halcrow * updates the atime of the lower level inode if generic_file_read 99*237fead6SMichael Halcrow * returns without any errors. This is to be used only for file reads. 100*237fead6SMichael Halcrow * The function to be used for directory reads is ecryptfs_read. 101*237fead6SMichael Halcrow */ 102*237fead6SMichael Halcrow static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, 103*237fead6SMichael Halcrow const struct iovec *iov, 104*237fead6SMichael Halcrow unsigned long nr_segs, loff_t pos) 105*237fead6SMichael Halcrow { 106*237fead6SMichael Halcrow int rc; 107*237fead6SMichael Halcrow struct dentry *lower_dentry; 108*237fead6SMichael Halcrow struct vfsmount *lower_vfsmount; 109*237fead6SMichael Halcrow struct file *file = iocb->ki_filp; 110*237fead6SMichael Halcrow 111*237fead6SMichael Halcrow rc = generic_file_aio_read(iocb, iov, nr_segs, pos); 112*237fead6SMichael Halcrow /* 113*237fead6SMichael Halcrow * Even though this is a async interface, we need to wait 114*237fead6SMichael Halcrow * for IO to finish to update atime 115*237fead6SMichael Halcrow */ 116*237fead6SMichael Halcrow if (-EIOCBQUEUED == rc) 117*237fead6SMichael Halcrow rc = wait_on_sync_kiocb(iocb); 118*237fead6SMichael Halcrow if (rc >= 0) { 119*237fead6SMichael Halcrow lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry); 120*237fead6SMichael Halcrow lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_dentry); 121*237fead6SMichael Halcrow touch_atime(lower_vfsmount, lower_dentry); 122*237fead6SMichael Halcrow } 123*237fead6SMichael Halcrow return rc; 124*237fead6SMichael Halcrow } 125*237fead6SMichael Halcrow 126*237fead6SMichael Halcrow struct ecryptfs_getdents_callback { 127*237fead6SMichael Halcrow void *dirent; 128*237fead6SMichael Halcrow struct dentry *dentry; 129*237fead6SMichael Halcrow filldir_t filldir; 130*237fead6SMichael Halcrow int err; 131*237fead6SMichael Halcrow int filldir_called; 132*237fead6SMichael Halcrow int entries_written; 133*237fead6SMichael Halcrow }; 134*237fead6SMichael Halcrow 135*237fead6SMichael Halcrow /* Inspired by generic filldir in fs/readir.c */ 136*237fead6SMichael Halcrow static int 137*237fead6SMichael Halcrow ecryptfs_filldir(void *dirent, const char *name, int namelen, loff_t offset, 138*237fead6SMichael Halcrow u64 ino, unsigned int d_type) 139*237fead6SMichael Halcrow { 140*237fead6SMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat; 141*237fead6SMichael Halcrow struct ecryptfs_getdents_callback *buf = 142*237fead6SMichael Halcrow (struct ecryptfs_getdents_callback *)dirent; 143*237fead6SMichael Halcrow int rc; 144*237fead6SMichael Halcrow int decoded_length; 145*237fead6SMichael Halcrow char *decoded_name; 146*237fead6SMichael Halcrow 147*237fead6SMichael Halcrow crypt_stat = ecryptfs_dentry_to_private(buf->dentry)->crypt_stat; 148*237fead6SMichael Halcrow buf->filldir_called++; 149*237fead6SMichael Halcrow decoded_length = ecryptfs_decode_filename(crypt_stat, name, namelen, 150*237fead6SMichael Halcrow &decoded_name); 151*237fead6SMichael Halcrow if (decoded_length < 0) { 152*237fead6SMichael Halcrow rc = decoded_length; 153*237fead6SMichael Halcrow goto out; 154*237fead6SMichael Halcrow } 155*237fead6SMichael Halcrow rc = buf->filldir(buf->dirent, decoded_name, decoded_length, offset, 156*237fead6SMichael Halcrow ino, d_type); 157*237fead6SMichael Halcrow kfree(decoded_name); 158*237fead6SMichael Halcrow if (rc >= 0) 159*237fead6SMichael Halcrow buf->entries_written++; 160*237fead6SMichael Halcrow out: 161*237fead6SMichael Halcrow return rc; 162*237fead6SMichael Halcrow } 163*237fead6SMichael Halcrow 164*237fead6SMichael Halcrow /** 165*237fead6SMichael Halcrow * ecryptfs_readdir 166*237fead6SMichael Halcrow * @file: The ecryptfs file struct 167*237fead6SMichael Halcrow * @dirent: Directory entry 168*237fead6SMichael Halcrow * @filldir: The filldir callback function 169*237fead6SMichael Halcrow */ 170*237fead6SMichael Halcrow static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) 171*237fead6SMichael Halcrow { 172*237fead6SMichael Halcrow int rc; 173*237fead6SMichael Halcrow struct file *lower_file; 174*237fead6SMichael Halcrow struct inode *inode; 175*237fead6SMichael Halcrow struct ecryptfs_getdents_callback buf; 176*237fead6SMichael Halcrow 177*237fead6SMichael Halcrow lower_file = ecryptfs_file_to_lower(file); 178*237fead6SMichael Halcrow lower_file->f_pos = file->f_pos; 179*237fead6SMichael Halcrow inode = file->f_dentry->d_inode; 180*237fead6SMichael Halcrow memset(&buf, 0, sizeof(buf)); 181*237fead6SMichael Halcrow buf.dirent = dirent; 182*237fead6SMichael Halcrow buf.dentry = file->f_dentry; 183*237fead6SMichael Halcrow buf.filldir = filldir; 184*237fead6SMichael Halcrow retry: 185*237fead6SMichael Halcrow buf.filldir_called = 0; 186*237fead6SMichael Halcrow buf.entries_written = 0; 187*237fead6SMichael Halcrow buf.err = 0; 188*237fead6SMichael Halcrow rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); 189*237fead6SMichael Halcrow if (buf.err) 190*237fead6SMichael Halcrow rc = buf.err; 191*237fead6SMichael Halcrow if (buf.filldir_called && !buf.entries_written) 192*237fead6SMichael Halcrow goto retry; 193*237fead6SMichael Halcrow file->f_pos = lower_file->f_pos; 194*237fead6SMichael Halcrow if (rc >= 0) 195*237fead6SMichael Halcrow ecryptfs_copy_attr_atime(inode, lower_file->f_dentry->d_inode); 196*237fead6SMichael Halcrow return rc; 197*237fead6SMichael Halcrow } 198*237fead6SMichael Halcrow 199*237fead6SMichael Halcrow struct kmem_cache *ecryptfs_file_info_cache; 200*237fead6SMichael Halcrow 201*237fead6SMichael Halcrow /** 202*237fead6SMichael Halcrow * ecryptfs_open 203*237fead6SMichael Halcrow * @inode: inode speciying file to open 204*237fead6SMichael Halcrow * @file: Structure to return filled in 205*237fead6SMichael Halcrow * 206*237fead6SMichael Halcrow * Opens the file specified by inode. 207*237fead6SMichael Halcrow * 208*237fead6SMichael Halcrow * Returns zero on success; non-zero otherwise 209*237fead6SMichael Halcrow */ 210*237fead6SMichael Halcrow static int ecryptfs_open(struct inode *inode, struct file *file) 211*237fead6SMichael Halcrow { 212*237fead6SMichael Halcrow int rc = 0; 213*237fead6SMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat = NULL; 214*237fead6SMichael Halcrow struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 215*237fead6SMichael Halcrow struct dentry *ecryptfs_dentry = file->f_dentry; 216*237fead6SMichael Halcrow /* Private value of ecryptfs_dentry allocated in 217*237fead6SMichael Halcrow * ecryptfs_lookup() */ 218*237fead6SMichael Halcrow struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 219*237fead6SMichael Halcrow struct inode *lower_inode = NULL; 220*237fead6SMichael Halcrow struct file *lower_file = NULL; 221*237fead6SMichael Halcrow struct vfsmount *lower_mnt; 222*237fead6SMichael Halcrow struct ecryptfs_file_info *file_info; 223*237fead6SMichael Halcrow int lower_flags; 224*237fead6SMichael Halcrow 225*237fead6SMichael Halcrow /* Released in ecryptfs_release or end of function if failure */ 226*237fead6SMichael Halcrow file_info = kmem_cache_alloc(ecryptfs_file_info_cache, SLAB_KERNEL); 227*237fead6SMichael Halcrow ecryptfs_set_file_private(file, file_info); 228*237fead6SMichael Halcrow if (!file_info) { 229*237fead6SMichael Halcrow ecryptfs_printk(KERN_ERR, 230*237fead6SMichael Halcrow "Error attempting to allocate memory\n"); 231*237fead6SMichael Halcrow rc = -ENOMEM; 232*237fead6SMichael Halcrow goto out; 233*237fead6SMichael Halcrow } 234*237fead6SMichael Halcrow memset(file_info, 0, sizeof(*file_info)); 235*237fead6SMichael Halcrow lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 236*237fead6SMichael Halcrow crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; 237*237fead6SMichael Halcrow mount_crypt_stat = &ecryptfs_superblock_to_private( 238*237fead6SMichael Halcrow ecryptfs_dentry->d_sb)->mount_crypt_stat; 239*237fead6SMichael Halcrow mutex_lock(&crypt_stat->cs_mutex); 240*237fead6SMichael Halcrow if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) { 241*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); 242*237fead6SMichael Halcrow /* Policy code enabled in future release */ 243*237fead6SMichael Halcrow ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED); 244*237fead6SMichael Halcrow ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); 245*237fead6SMichael Halcrow } 246*237fead6SMichael Halcrow mutex_unlock(&crypt_stat->cs_mutex); 247*237fead6SMichael Halcrow /* This mntget & dget is undone via fput when the file is released */ 248*237fead6SMichael Halcrow dget(lower_dentry); 249*237fead6SMichael Halcrow lower_flags = file->f_flags; 250*237fead6SMichael Halcrow if ((lower_flags & O_ACCMODE) == O_WRONLY) 251*237fead6SMichael Halcrow lower_flags = (lower_flags & O_ACCMODE) | O_RDWR; 252*237fead6SMichael Halcrow if (file->f_flags & O_APPEND) 253*237fead6SMichael Halcrow lower_flags &= ~O_APPEND; 254*237fead6SMichael Halcrow lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); 255*237fead6SMichael Halcrow mntget(lower_mnt); 256*237fead6SMichael Halcrow /* Corresponding fput() in ecryptfs_release() */ 257*237fead6SMichael Halcrow lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags); 258*237fead6SMichael Halcrow if (IS_ERR(lower_file)) { 259*237fead6SMichael Halcrow rc = PTR_ERR(lower_file); 260*237fead6SMichael Halcrow ecryptfs_printk(KERN_ERR, "Error opening lower file\n"); 261*237fead6SMichael Halcrow goto out_puts; 262*237fead6SMichael Halcrow } 263*237fead6SMichael Halcrow ecryptfs_set_file_lower(file, lower_file); 264*237fead6SMichael Halcrow /* Isn't this check the same as the one in lookup? */ 265*237fead6SMichael Halcrow lower_inode = lower_dentry->d_inode; 266*237fead6SMichael Halcrow if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { 267*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); 268*237fead6SMichael Halcrow ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); 269*237fead6SMichael Halcrow rc = 0; 270*237fead6SMichael Halcrow goto out; 271*237fead6SMichael Halcrow } 272*237fead6SMichael Halcrow mutex_lock(&crypt_stat->cs_mutex); 273*237fead6SMichael Halcrow if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { 274*237fead6SMichael Halcrow if (!(mount_crypt_stat->flags 275*237fead6SMichael Halcrow & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { 276*237fead6SMichael Halcrow rc = -EIO; 277*237fead6SMichael Halcrow printk(KERN_WARNING "Attempt to read file that is " 278*237fead6SMichael Halcrow "not in a valid eCryptfs format, and plaintext " 279*237fead6SMichael Halcrow "passthrough mode is not enabled; returning " 280*237fead6SMichael Halcrow "-EIO\n"); 281*237fead6SMichael Halcrow mutex_unlock(&crypt_stat->cs_mutex); 282*237fead6SMichael Halcrow goto out_puts; 283*237fead6SMichael Halcrow } 284*237fead6SMichael Halcrow crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 285*237fead6SMichael Halcrow rc = 0; 286*237fead6SMichael Halcrow mutex_unlock(&crypt_stat->cs_mutex); 287*237fead6SMichael Halcrow goto out; 288*237fead6SMichael Halcrow } else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, 289*237fead6SMichael Halcrow ECRYPTFS_POLICY_APPLIED) 290*237fead6SMichael Halcrow || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, 291*237fead6SMichael Halcrow ECRYPTFS_KEY_VALID)) { 292*237fead6SMichael Halcrow rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file); 293*237fead6SMichael Halcrow if (rc) { 294*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, 295*237fead6SMichael Halcrow "Valid headers not found\n"); 296*237fead6SMichael Halcrow if (!(mount_crypt_stat->flags 297*237fead6SMichael Halcrow & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { 298*237fead6SMichael Halcrow rc = -EIO; 299*237fead6SMichael Halcrow printk(KERN_WARNING "Attempt to read file that " 300*237fead6SMichael Halcrow "is not in a valid eCryptfs format, " 301*237fead6SMichael Halcrow "and plaintext passthrough mode is not " 302*237fead6SMichael Halcrow "enabled; returning -EIO\n"); 303*237fead6SMichael Halcrow mutex_unlock(&crypt_stat->cs_mutex); 304*237fead6SMichael Halcrow goto out_puts; 305*237fead6SMichael Halcrow } 306*237fead6SMichael Halcrow ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, 307*237fead6SMichael Halcrow ECRYPTFS_ENCRYPTED); 308*237fead6SMichael Halcrow rc = 0; 309*237fead6SMichael Halcrow mutex_unlock(&crypt_stat->cs_mutex); 310*237fead6SMichael Halcrow goto out; 311*237fead6SMichael Halcrow } 312*237fead6SMichael Halcrow } 313*237fead6SMichael Halcrow mutex_unlock(&crypt_stat->cs_mutex); 314*237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] " 315*237fead6SMichael Halcrow "size: [0x%.16x]\n", inode, inode->i_ino, 316*237fead6SMichael Halcrow i_size_read(inode)); 317*237fead6SMichael Halcrow ecryptfs_set_file_lower(file, lower_file); 318*237fead6SMichael Halcrow goto out; 319*237fead6SMichael Halcrow out_puts: 320*237fead6SMichael Halcrow mntput(lower_mnt); 321*237fead6SMichael Halcrow dput(lower_dentry); 322*237fead6SMichael Halcrow kmem_cache_free(ecryptfs_file_info_cache, 323*237fead6SMichael Halcrow ecryptfs_file_to_private(file)); 324*237fead6SMichael Halcrow out: 325*237fead6SMichael Halcrow return rc; 326*237fead6SMichael Halcrow } 327*237fead6SMichael Halcrow 328*237fead6SMichael Halcrow static int ecryptfs_flush(struct file *file, fl_owner_t td) 329*237fead6SMichael Halcrow { 330*237fead6SMichael Halcrow int rc = 0; 331*237fead6SMichael Halcrow struct file *lower_file = NULL; 332*237fead6SMichael Halcrow 333*237fead6SMichael Halcrow lower_file = ecryptfs_file_to_lower(file); 334*237fead6SMichael Halcrow if (lower_file->f_op && lower_file->f_op->flush) 335*237fead6SMichael Halcrow rc = lower_file->f_op->flush(lower_file, td); 336*237fead6SMichael Halcrow return rc; 337*237fead6SMichael Halcrow } 338*237fead6SMichael Halcrow 339*237fead6SMichael Halcrow static int ecryptfs_release(struct inode *inode, struct file *file) 340*237fead6SMichael Halcrow { 341*237fead6SMichael Halcrow struct file *lower_file = ecryptfs_file_to_lower(file); 342*237fead6SMichael Halcrow struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); 343*237fead6SMichael Halcrow struct inode *lower_inode = ecryptfs_inode_to_lower(inode); 344*237fead6SMichael Halcrow 345*237fead6SMichael Halcrow fput(lower_file); 346*237fead6SMichael Halcrow inode->i_blocks = lower_inode->i_blocks; 347*237fead6SMichael Halcrow kmem_cache_free(ecryptfs_file_info_cache, file_info); 348*237fead6SMichael Halcrow return 0; 349*237fead6SMichael Halcrow } 350*237fead6SMichael Halcrow 351*237fead6SMichael Halcrow static int 352*237fead6SMichael Halcrow ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync) 353*237fead6SMichael Halcrow { 354*237fead6SMichael Halcrow struct file *lower_file = ecryptfs_file_to_lower(file); 355*237fead6SMichael Halcrow struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 356*237fead6SMichael Halcrow struct inode *lower_inode = lower_dentry->d_inode; 357*237fead6SMichael Halcrow int rc = -EINVAL; 358*237fead6SMichael Halcrow 359*237fead6SMichael Halcrow if (lower_inode->i_fop->fsync) { 360*237fead6SMichael Halcrow mutex_lock(&lower_inode->i_mutex); 361*237fead6SMichael Halcrow rc = lower_inode->i_fop->fsync(lower_file, lower_dentry, 362*237fead6SMichael Halcrow datasync); 363*237fead6SMichael Halcrow mutex_unlock(&lower_inode->i_mutex); 364*237fead6SMichael Halcrow } 365*237fead6SMichael Halcrow return rc; 366*237fead6SMichael Halcrow } 367*237fead6SMichael Halcrow 368*237fead6SMichael Halcrow static int ecryptfs_fasync(int fd, struct file *file, int flag) 369*237fead6SMichael Halcrow { 370*237fead6SMichael Halcrow int rc = 0; 371*237fead6SMichael Halcrow struct file *lower_file = NULL; 372*237fead6SMichael Halcrow 373*237fead6SMichael Halcrow lower_file = ecryptfs_file_to_lower(file); 374*237fead6SMichael Halcrow if (lower_file->f_op && lower_file->f_op->fasync) 375*237fead6SMichael Halcrow rc = lower_file->f_op->fasync(fd, lower_file, flag); 376*237fead6SMichael Halcrow return rc; 377*237fead6SMichael Halcrow } 378*237fead6SMichael Halcrow 379*237fead6SMichael Halcrow static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos, 380*237fead6SMichael Halcrow size_t count, read_actor_t actor, void *target) 381*237fead6SMichael Halcrow { 382*237fead6SMichael Halcrow struct file *lower_file = NULL; 383*237fead6SMichael Halcrow int rc = -EINVAL; 384*237fead6SMichael Halcrow 385*237fead6SMichael Halcrow lower_file = ecryptfs_file_to_lower(file); 386*237fead6SMichael Halcrow if (lower_file->f_op && lower_file->f_op->sendfile) 387*237fead6SMichael Halcrow rc = lower_file->f_op->sendfile(lower_file, ppos, count, 388*237fead6SMichael Halcrow actor, target); 389*237fead6SMichael Halcrow 390*237fead6SMichael Halcrow return rc; 391*237fead6SMichael Halcrow } 392*237fead6SMichael Halcrow 393*237fead6SMichael Halcrow static int ecryptfs_ioctl(struct inode *inode, struct file *file, 394*237fead6SMichael Halcrow unsigned int cmd, unsigned long arg); 395*237fead6SMichael Halcrow 396*237fead6SMichael Halcrow const struct file_operations ecryptfs_dir_fops = { 397*237fead6SMichael Halcrow .readdir = ecryptfs_readdir, 398*237fead6SMichael Halcrow .ioctl = ecryptfs_ioctl, 399*237fead6SMichael Halcrow .mmap = generic_file_mmap, 400*237fead6SMichael Halcrow .open = ecryptfs_open, 401*237fead6SMichael Halcrow .flush = ecryptfs_flush, 402*237fead6SMichael Halcrow .release = ecryptfs_release, 403*237fead6SMichael Halcrow .fsync = ecryptfs_fsync, 404*237fead6SMichael Halcrow .fasync = ecryptfs_fasync, 405*237fead6SMichael Halcrow .sendfile = ecryptfs_sendfile, 406*237fead6SMichael Halcrow }; 407*237fead6SMichael Halcrow 408*237fead6SMichael Halcrow const struct file_operations ecryptfs_main_fops = { 409*237fead6SMichael Halcrow .llseek = ecryptfs_llseek, 410*237fead6SMichael Halcrow .read = do_sync_read, 411*237fead6SMichael Halcrow .aio_read = ecryptfs_read_update_atime, 412*237fead6SMichael Halcrow .write = do_sync_write, 413*237fead6SMichael Halcrow .aio_write = generic_file_aio_write, 414*237fead6SMichael Halcrow .readdir = ecryptfs_readdir, 415*237fead6SMichael Halcrow .ioctl = ecryptfs_ioctl, 416*237fead6SMichael Halcrow .mmap = generic_file_mmap, 417*237fead6SMichael Halcrow .open = ecryptfs_open, 418*237fead6SMichael Halcrow .flush = ecryptfs_flush, 419*237fead6SMichael Halcrow .release = ecryptfs_release, 420*237fead6SMichael Halcrow .fsync = ecryptfs_fsync, 421*237fead6SMichael Halcrow .fasync = ecryptfs_fasync, 422*237fead6SMichael Halcrow .sendfile = ecryptfs_sendfile, 423*237fead6SMichael Halcrow }; 424*237fead6SMichael Halcrow 425*237fead6SMichael Halcrow static int 426*237fead6SMichael Halcrow ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 427*237fead6SMichael Halcrow unsigned long arg) 428*237fead6SMichael Halcrow { 429*237fead6SMichael Halcrow int rc = 0; 430*237fead6SMichael Halcrow struct file *lower_file = NULL; 431*237fead6SMichael Halcrow 432*237fead6SMichael Halcrow if (ecryptfs_file_to_private(file)) 433*237fead6SMichael Halcrow lower_file = ecryptfs_file_to_lower(file); 434*237fead6SMichael Halcrow if (lower_file && lower_file->f_op && lower_file->f_op->ioctl) 435*237fead6SMichael Halcrow rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode), 436*237fead6SMichael Halcrow lower_file, cmd, arg); 437*237fead6SMichael Halcrow else 438*237fead6SMichael Halcrow rc = -ENOTTY; 439*237fead6SMichael Halcrow return rc; 440*237fead6SMichael Halcrow } 441