aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@us.ibm.com>2007-10-16 04:28:07 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:12 -0400
commitda0102a10aed2244d8fc34f289e81e502622b81e (patch)
treea3c939a25b12efb94c3fd36f98d65708ae09b964 /fs
parentcf81f89d9a85b1825d8c8cf1f8f0e2c98cc72823 (diff)
eCryptfs: read_write.c routines
Add a set of functions through which all I/O to lower files is consolidated. This patch adds a new inode_info reference to a persistent lower file for each eCryptfs inode; another patch later in this series will set that up. This persistent lower file is what the read_write.c functions use to call vfs_read() and vfs_write() on the lower filesystem, so even when reads and writes come in through aops->readpage and aops->writepage, we can satisfy them without resorting to direct access to the lower inode's address space. Several function declarations are going to be changing with this patchset. For now, in order to keep from breaking the build, I am putting dummy parameters in for those functions. Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ecryptfs/Makefile2
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h18
-rw-r--r--fs/ecryptfs/mmap.c2
-rw-r--r--fs/ecryptfs/read_write.c359
4 files changed, 379 insertions, 2 deletions
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index 1f1107237eab..768857015516 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
4 4
5obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o 5obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
6 6
7ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o 7ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index a618ab77642d..e6a68a87b5df 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -260,6 +260,8 @@ struct ecryptfs_crypt_stat {
260struct ecryptfs_inode_info { 260struct ecryptfs_inode_info {
261 struct inode vfs_inode; 261 struct inode vfs_inode;
262 struct inode *wii_inode; 262 struct inode *wii_inode;
263 struct file *lower_file;
264 struct mutex lower_file_mutex;
263 struct ecryptfs_crypt_stat crypt_stat; 265 struct ecryptfs_crypt_stat crypt_stat;
264}; 266};
265 267
@@ -653,5 +655,21 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
653 char *sig); 655 char *sig);
654int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, 656int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
655 int num_zeros); 657 int num_zeros);
658int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
659 loff_t offset, size_t size);
660int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
661 struct page *page_for_lower,
662 size_t offset_in_page, size_t size);
663int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
664 size_t size);
665int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
666 struct inode *ecryptfs_inode);
667int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
668 pgoff_t page_index,
669 size_t offset_in_page, size_t size,
670 struct inode *ecryptfs_inode);
671int ecryptfs_read(char *data, loff_t offset, size_t size,
672 struct file *ecryptfs_file);
673struct page *ecryptfs_get1page(struct file *file, loff_t index);
656 674
657#endif /* #ifndef ECRYPTFS_KERNEL_H */ 675#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 307f7ee77420..0c53320b9eb8 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -44,7 +44,7 @@ struct kmem_cache *ecryptfs_lower_page_cache;
44 * Returns unlocked and up-to-date page (if ok), with increased 44 * Returns unlocked and up-to-date page (if ok), with increased
45 * refcnt. 45 * refcnt.
46 */ 46 */
47static struct page *ecryptfs_get1page(struct file *file, int index) 47struct page *ecryptfs_get1page(struct file *file, loff_t index)
48{ 48{
49 struct dentry *dentry; 49 struct dentry *dentry;
50 struct inode *inode; 50 struct inode *inode;
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
new file mode 100644
index 000000000000..e59c94add127
--- /dev/null
+++ b/fs/ecryptfs/read_write.c
@@ -0,0 +1,359 @@
1/**
2 * eCryptfs: Linux filesystem encryption layer
3 *
4 * Copyright (C) 2007 International Business Machines Corp.
5 * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <linux/fs.h>
24#include <linux/pagemap.h>
25#include "ecryptfs_kernel.h"
26
27/**
28 * ecryptfs_write_lower
29 * @ecryptfs_inode: The eCryptfs inode
30 * @data: Data to write
31 * @offset: Byte offset in the lower file to which to write the data
32 * @size: Number of bytes from @data to write at @offset in the lower
33 * file
34 *
35 * Write data to the lower file.
36 *
37 * Returns zero on success; non-zero on error
38 */
39int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
40 loff_t offset, size_t size)
41{
42 struct ecryptfs_inode_info *inode_info;
43 ssize_t octets_written;
44 mm_segment_t fs_save;
45 int rc = 0;
46
47 inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
48 mutex_lock(&inode_info->lower_file_mutex);
49 BUG_ON(!inode_info->lower_file);
50 inode_info->lower_file->f_pos = offset;
51 fs_save = get_fs();
52 set_fs(get_ds());
53 octets_written = vfs_write(inode_info->lower_file, data, size,
54 &inode_info->lower_file->f_pos);
55 set_fs(fs_save);
56 if (octets_written < 0) {
57 printk(KERN_ERR "%s: octets_written = [%td]; "
58 "expected [%td]\n", __FUNCTION__, octets_written, size);
59 rc = -EINVAL;
60 }
61 mutex_unlock(&inode_info->lower_file_mutex);
62 mark_inode_dirty_sync(ecryptfs_inode);
63 return rc;
64}
65
66/**
67 * ecryptfs_write_lower_page_segment
68 * @ecryptfs_inode: The eCryptfs inode
69 * @page_for_lower: The page containing the data to be written to the
70 * lower file
71 * @offset_in_page: The offset in the @page_for_lower from which to
72 * start writing the data
73 * @size: The amount of data from @page_for_lower to write to the
74 * lower file
75 *
76 * Determines the byte offset in the file for the given page and
77 * offset within the page, maps the page, and makes the call to write
78 * the contents of @page_for_lower to the lower inode.
79 *
80 * Returns zero on success; non-zero otherwise
81 */
82int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
83 struct page *page_for_lower,
84 size_t offset_in_page, size_t size)
85{
86 char *virt;
87 loff_t offset;
88 int rc;
89
90 offset = (page_for_lower->index << PAGE_CACHE_SHIFT) + offset_in_page;
91 virt = kmap(page_for_lower);
92 rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
93 kunmap(page_for_lower);
94 return rc;
95}
96
97/**
98 * ecryptfs_write
99 * @ecryptfs_file: The eCryptfs file into which to write
100 * @data: Virtual address where data to write is located
101 * @offset: Offset in the eCryptfs file at which to begin writing the
102 * data from @data
103 * @size: The number of bytes to write from @data
104 *
105 * Write an arbitrary amount of data to an arbitrary location in the
106 * eCryptfs inode page cache. This is done on a page-by-page, and then
107 * by an extent-by-extent, basis; individual extents are encrypted and
108 * written to the lower page cache (via VFS writes). This function
109 * takes care of all the address translation to locations in the lower
110 * filesystem; it also handles truncate events, writing out zeros
111 * where necessary.
112 *
113 * Returns zero on success; non-zero otherwise
114 */
115int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
116 size_t size)
117{
118 struct page *ecryptfs_page;
119 char *ecryptfs_page_virt;
120 u64 ecryptfs_file_size = i_size_read(ecryptfs_file->f_dentry->d_inode);
121 loff_t data_offset = 0;
122 loff_t pos;
123 int rc = 0;
124
125 if (offset > ecryptfs_file_size)
126 pos = ecryptfs_file_size;
127 else
128 pos = offset;
129 while (pos < (offset + size)) {
130 pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
131 size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
132 size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
133 size_t total_remaining_bytes = ((offset + size) - pos);
134
135 if (num_bytes > total_remaining_bytes)
136 num_bytes = total_remaining_bytes;
137 if (pos < offset) {
138 size_t total_remaining_zeros = (offset - pos);
139
140 if (num_bytes > total_remaining_zeros)
141 num_bytes = total_remaining_zeros;
142 }
143 ecryptfs_page = ecryptfs_get1page(ecryptfs_file,
144 ecryptfs_page_idx);
145 if (IS_ERR(ecryptfs_page)) {
146 rc = PTR_ERR(ecryptfs_page);
147 printk(KERN_ERR "%s: Error getting page at "
148 "index [%ld] from eCryptfs inode "
149 "mapping; rc = [%d]\n", __FUNCTION__,
150 ecryptfs_page_idx, rc);
151 goto out;
152 }
153 if (start_offset_in_page) {
154 /* Read in the page from the lower
155 * into the eCryptfs inode page cache,
156 * decrypting */
157 if ((rc = ecryptfs_decrypt_page(NULL, /* placeholder for git-bisect */
158 ecryptfs_page))) {
159 printk(KERN_ERR "%s: Error decrypting "
160 "page; rc = [%d]\n",
161 __FUNCTION__, rc);
162 page_cache_release(ecryptfs_page);
163 goto out;
164 }
165 }
166 ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
167 if (pos >= offset) {
168 memcpy(((char *)ecryptfs_page_virt
169 + start_offset_in_page),
170 (data + data_offset), num_bytes);
171 data_offset += num_bytes;
172 } else {
173 /* We are extending past the previous end of the file.
174 * Fill in zero values up to the start of where we
175 * will be writing data. */
176 memset(((char *)ecryptfs_page_virt
177 + start_offset_in_page), 0, num_bytes);
178 }
179 kunmap_atomic(ecryptfs_page_virt, KM_USER0);
180 flush_dcache_page(ecryptfs_page);
181 rc = ecryptfs_encrypt_page(NULL /* placeholder for git-bisect */);
182 if (rc) {
183 printk(KERN_ERR "%s: Error encrypting "
184 "page; rc = [%d]\n", __FUNCTION__, rc);
185 page_cache_release(ecryptfs_page);
186 goto out;
187 }
188 page_cache_release(ecryptfs_page);
189 pos += num_bytes;
190 }
191 if ((offset + size) > ecryptfs_file_size) {
192 i_size_write(ecryptfs_file->f_dentry->d_inode, (offset + size));
193 rc = ecryptfs_write_inode_size_to_metadata(NULL, NULL, NULL,
194 NULL, 0); /* placeholders for git-bisect */
195 if (rc) {
196 printk(KERN_ERR "Problem with "
197 "ecryptfs_write_inode_size_to_metadata; "
198 "rc = [%d]\n", rc);
199 goto out;
200 }
201 }
202out:
203 return rc;
204}
205
206/**
207 * ecryptfs_read_lower
208 * @data: The read data is stored here by this function
209 * @offset: Byte offset in the lower file from which to read the data
210 * @size: Number of bytes to read from @offset of the lower file and
211 * store into @data
212 * @ecryptfs_inode: The eCryptfs inode
213 *
214 * Read @size bytes of data at byte offset @offset from the lower
215 * inode into memory location @data.
216 *
217 * Returns zero on success; non-zero on error
218 */
219int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
220 struct inode *ecryptfs_inode)
221{
222 struct ecryptfs_inode_info *inode_info =
223 ecryptfs_inode_to_private(ecryptfs_inode);
224 ssize_t octets_read;
225 mm_segment_t fs_save;
226 size_t i;
227 int rc = 0;
228
229 mutex_lock(&inode_info->lower_file_mutex);
230 BUG_ON(!inode_info->lower_file);
231 inode_info->lower_file->f_pos = offset;
232 fs_save = get_fs();
233 set_fs(get_ds());
234 octets_read = vfs_read(inode_info->lower_file, data, size,
235 &inode_info->lower_file->f_pos);
236 set_fs(fs_save);
237 if (octets_read < 0) {
238 printk(KERN_ERR "%s: octets_read = [%td]; "
239 "expected [%td]\n", __FUNCTION__, octets_read, size);
240 rc = -EINVAL;
241 }
242 mutex_unlock(&inode_info->lower_file_mutex);
243 for (i = 0; i < size; i += PAGE_CACHE_SIZE) {
244 struct page *data_page;
245
246 data_page = virt_to_page(data + i);
247 flush_dcache_page(data_page);
248 if (rc)
249 ClearPageUptodate(data_page);
250 else
251 SetPageUptodate(data_page);
252 }
253 return rc;
254}
255
256/**
257 * ecryptfs_read_lower_page_segment
258 * @page_for_ecryptfs: The page into which data for eCryptfs will be
259 * written
260 * @offset_in_page: Offset in @page_for_ecryptfs from which to start
261 * writing
262 * @size: The number of bytes to write into @page_for_ecryptfs
263 * @ecryptfs_inode: The eCryptfs inode
264 *
265 * Determines the byte offset in the file for the given page and
266 * offset within the page, maps the page, and makes the call to read
267 * the contents of @page_for_ecryptfs from the lower inode.
268 *
269 * Returns zero on success; non-zero otherwise
270 */
271int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
272 pgoff_t page_index,
273 size_t offset_in_page, size_t size,
274 struct inode *ecryptfs_inode)
275{
276 char *virt;
277 loff_t offset;
278 int rc;
279
280 offset = ((page_index << PAGE_CACHE_SHIFT) + offset_in_page);
281 virt = kmap(page_for_ecryptfs);
282 rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
283 kunmap(page_for_ecryptfs);
284 return rc;
285}
286
287/**
288 * ecryptfs_read
289 * @data: The virtual address into which to write the data read (and
290 * possibly decrypted) from the lower file
291 * @offset: The offset in the decrypted view of the file from which to
292 * read into @data
293 * @size: The number of bytes to read into @data
294 * @ecryptfs_file: The eCryptfs file from which to read
295 *
296 * Read an arbitrary amount of data from an arbitrary location in the
297 * eCryptfs page cache. This is done on an extent-by-extent basis;
298 * individual extents are decrypted and read from the lower page
299 * cache (via VFS reads). This function takes care of all the
300 * address translation to locations in the lower filesystem.
301 *
302 * Returns zero on success; non-zero otherwise
303 */
304int ecryptfs_read(char *data, loff_t offset, size_t size,
305 struct file *ecryptfs_file)
306{
307 struct page *ecryptfs_page;
308 char *ecryptfs_page_virt;
309 u64 ecryptfs_file_size = i_size_read(ecryptfs_file->f_dentry->d_inode);
310 loff_t data_offset = 0;
311 loff_t pos;
312 int rc = 0;
313
314 if ((offset + size) > ecryptfs_file_size) {
315 rc = -EINVAL;
316 printk(KERN_ERR "%s: Attempt to read data past the end of the "
317 "file; offset = [%lld]; size = [%td]; "
318 "ecryptfs_file_size = [%lld]\n",
319 __FUNCTION__, offset, size, ecryptfs_file_size);
320 goto out;
321 }
322 pos = offset;
323 while (pos < (offset + size)) {
324 pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
325 size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
326 size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
327 size_t total_remaining_bytes = ((offset + size) - pos);
328
329 if (num_bytes > total_remaining_bytes)
330 num_bytes = total_remaining_bytes;
331 ecryptfs_page = ecryptfs_get1page(ecryptfs_file,
332 ecryptfs_page_idx);
333 if (IS_ERR(ecryptfs_page)) {
334 rc = PTR_ERR(ecryptfs_page);
335 printk(KERN_ERR "%s: Error getting page at "
336 "index [%ld] from eCryptfs inode "
337 "mapping; rc = [%d]\n", __FUNCTION__,
338 ecryptfs_page_idx, rc);
339 goto out;
340 }
341 rc = ecryptfs_decrypt_page(NULL /* placeholder for git-bisect */, ecryptfs_page);
342 if (rc) {
343 printk(KERN_ERR "%s: Error decrypting "
344 "page; rc = [%d]\n", __FUNCTION__, rc);
345 page_cache_release(ecryptfs_page);
346 goto out;
347 }
348 ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
349 memcpy((data + data_offset),
350 ((char *)ecryptfs_page_virt + start_offset_in_page),
351 num_bytes);
352 kunmap_atomic(ecryptfs_page_virt, KM_USER0);
353 page_cache_release(ecryptfs_page);
354 pos += num_bytes;
355 data_offset += num_bytes;
356 }
357out:
358 return rc;
359}