xref: /linux/fs/ecryptfs/file.c (revision 237fead619984cc48818fe12ee0ceada3f55b012)
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