| 1 | |
| 2 | |
| 3 | * eCryptfs: Linux filesystem encryption layer
|
| 4 | *
|
| 5 | * Copyright (C) 2007 International Business Machines Corp.
|
| 6 | * Author(s): Michael A. Halcrow <[email protected]>
|
| 7 |
|
| 8 |
|
| 9 | #include <linux/fs.h>
|
| 10 | #include <linux/pagemap.h>
|
| 11 | #include <linux/sched/signal.h>
|
| 12 |
|
| 13 | #include "ecryptfs_kernel.h"
|
| 14 |
|
| 15 | |
| 16 | * ecryptfs_write_lower
|
| 17 | * @ecryptfs_inode: The eCryptfs inode
|
| 18 | * @data: Data to write
|
| 19 | * @offset: Byte offset in the lower file to which to write the data
|
| 20 | * @size: Number of bytes from @data to write at @offset in the lower
|
| 21 | * file
|
| 22 | *
|
| 23 | * Write data to the lower file.
|
| 24 | *
|
| 25 | * Returns bytes written on success; less than zero on error
|
| 26 |
|
| 27 | int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
| 28 | loff_t offset, size_t size)
|
| 29 | {
|
| 30 | struct file *lower_file;
|
| 31 | ssize_t rc;
|
| 32 |
|
| 33 | lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
|
| 34 | if (!lower_file)
|
| 35 | return -EIO;
|
| 36 | rc = kernel_write(lower_file, data, size, &offset);
|
| 37 | mark_inode_dirty_sync(ecryptfs_inode);
|
| 38 | return rc;
|
| 39 | }
|
| 40 |
|
| 41 | |
| 42 | * ecryptfs_write_lower_page_segment
|
| 43 | * @ecryptfs_inode: The eCryptfs inode
|
| 44 | * @folio_for_lower: The folio containing the data to be written to the
|
| 45 | * lower file
|
| 46 | * @offset_in_page: The offset in the @folio_for_lower from which to
|
| 47 | * start writing the data
|
| 48 | * @size: The amount of data from @folio_for_lower to write to the
|
| 49 | * lower file
|
| 50 | *
|
| 51 | * Determines the byte offset in the file for the given page and
|
| 52 | * offset within the page, maps the page, and makes the call to write
|
| 53 | * the contents of @folio_for_lower to the lower inode.
|
| 54 | *
|
| 55 | * Returns zero on success; non-zero otherwise
|
| 56 |
|
| 57 | int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
|
| 58 | struct folio *folio_for_lower,
|
| 59 | size_t offset_in_page, size_t size)
|
| 60 | {
|
| 61 | char *virt;
|
| 62 | loff_t offset;
|
| 63 | int rc;
|
| 64 |
|
| 65 | offset = (loff_t)folio_for_lower->index * PAGE_SIZE + offset_in_page;
|
| 66 | virt = kmap_local_folio(folio_for_lower, 0);
|
| 67 | rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
|
| 68 | if (rc > 0)
|
| 69 | rc = 0;
|
| 70 | kunmap_local(virt);
|
| 71 | return rc;
|
| 72 | }
|
| 73 |
|
| 74 | |
| 75 | * ecryptfs_write
|
| 76 | * @ecryptfs_inode: The eCryptfs file into which to write
|
| 77 | * @data: Virtual address where data to write is located
|
| 78 | * @offset: Offset in the eCryptfs file at which to begin writing the
|
| 79 | * data from @data
|
| 80 | * @size: The number of bytes to write from @data
|
| 81 | *
|
| 82 | * Write an arbitrary amount of data to an arbitrary location in the
|
| 83 | * eCryptfs inode page cache. This is done on a page-by-page, and then
|
| 84 | * by an extent-by-extent, basis; individual extents are encrypted and
|
| 85 | * written to the lower page cache (via VFS writes). This function
|
| 86 | * takes care of all the address translation to locations in the lower
|
| 87 | * filesystem; it also handles truncate events, writing out zeros
|
| 88 | * where necessary.
|
| 89 | *
|
| 90 | * Returns zero on success; non-zero otherwise
|
| 91 |
|
| 92 | int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
| 93 | size_t size)
|
| 94 | {
|
| 95 | struct ecryptfs_crypt_stat *crypt_stat;
|
| 96 | char *ecryptfs_page_virt;
|
| 97 | loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
|
| 98 | loff_t data_offset = 0;
|
| 99 | loff_t pos;
|
| 100 | int rc = 0;
|
| 101 |
|
| 102 | crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
|
| 103 | |
| 104 | * if we are writing beyond current size, then start pos
|
| 105 | * at the current size - we'll fill in zeros from there.
|
| 106 |
|
| 107 | if (offset > ecryptfs_file_size)
|
| 108 | pos = ecryptfs_file_size;
|
| 109 | else
|
| 110 | pos = offset;
|
| 111 | while (pos < (offset + size)) {
|
| 112 | struct folio *ecryptfs_folio;
|
| 113 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_SHIFT);
|
| 114 | size_t start_offset_in_page = (pos & ~PAGE_MASK);
|
| 115 | size_t num_bytes = (PAGE_SIZE - start_offset_in_page);
|
| 116 | loff_t total_remaining_bytes = ((offset + size) - pos);
|
| 117 |
|
| 118 | if (fatal_signal_pending(current)) {
|
| 119 | rc = -EINTR;
|
| 120 | break;
|
| 121 | }
|
| 122 |
|
| 123 | if (num_bytes > total_remaining_bytes)
|
| 124 | num_bytes = total_remaining_bytes;
|
| 125 | if (pos < offset) {
|
| 126 |
|
| 127 | loff_t total_remaining_zeros = (offset - pos);
|
| 128 |
|
| 129 | if (num_bytes > total_remaining_zeros)
|
| 130 | num_bytes = total_remaining_zeros;
|
| 131 | }
|
| 132 | ecryptfs_folio = read_mapping_folio(ecryptfs_inode->i_mapping,
|
| 133 | ecryptfs_page_idx, NULL);
|
| 134 | if (IS_ERR(ecryptfs_folio)) {
|
| 135 | rc = PTR_ERR(ecryptfs_folio);
|
| 136 | printk(KERN_ERR "%s: Error getting page at "
|
| 137 | "index [%ld] from eCryptfs inode "
|
| 138 | "mapping; rc = [%d]\n", __func__,
|
| 139 | ecryptfs_page_idx, rc);
|
| 140 | goto out;
|
| 141 | }
|
| 142 | folio_lock(ecryptfs_folio);
|
| 143 | ecryptfs_page_virt = kmap_local_folio(ecryptfs_folio, 0);
|
| 144 |
|
| 145 | |
| 146 | * pos: where we're now writing, offset: where the request was
|
| 147 | * If current pos is before request, we are filling zeros
|
| 148 | * If we are at or beyond request, we are writing the *data*
|
| 149 | * If we're in a fresh page beyond eof, zero it in either case
|
| 150 |
|
| 151 | if (pos < offset || !start_offset_in_page) {
|
| 152 | |
| 153 | * Fill in zero values to the end of the page
|
| 154 | memset(((char *)ecryptfs_page_virt
|
| 155 | + start_offset_in_page), 0,
|
| 156 | PAGE_SIZE - start_offset_in_page);
|
| 157 | }
|
| 158 |
|
| 159 |
|
| 160 | if (pos >= offset) {
|
| 161 | memcpy(((char *)ecryptfs_page_virt
|
| 162 | + start_offset_in_page),
|
| 163 | (data + data_offset), num_bytes);
|
| 164 | data_offset += num_bytes;
|
| 165 | }
|
| 166 | kunmap_local(ecryptfs_page_virt);
|
| 167 | flush_dcache_folio(ecryptfs_folio);
|
| 168 | folio_mark_uptodate(ecryptfs_folio);
|
| 169 | folio_unlock(ecryptfs_folio);
|
| 170 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED)
|
| 171 | rc = ecryptfs_encrypt_page(ecryptfs_folio);
|
| 172 | else
|
| 173 | rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
|
| 174 | ecryptfs_folio,
|
| 175 | start_offset_in_page,
|
| 176 | data_offset);
|
| 177 | folio_put(ecryptfs_folio);
|
| 178 | if (rc) {
|
| 179 | printk(KERN_ERR "%s: Error encrypting "
|
| 180 | "page; rc = [%d]\n", __func__, rc);
|
| 181 | goto out;
|
| 182 | }
|
| 183 | pos += num_bytes;
|
| 184 | }
|
| 185 | if (pos > ecryptfs_file_size) {
|
| 186 | i_size_write(ecryptfs_inode, pos);
|
| 187 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
|
| 188 | int rc2;
|
| 189 |
|
| 190 | rc2 = ecryptfs_write_inode_size_to_metadata(
|
| 191 | ecryptfs_inode);
|
| 192 | if (rc2) {
|
| 193 | printk(KERN_ERR "Problem with "
|
| 194 | "ecryptfs_write_inode_size_to_metadata; "
|
| 195 | "rc = [%d]\n", rc2);
|
| 196 | if (!rc)
|
| 197 | rc = rc2;
|
| 198 | goto out;
|
| 199 | }
|
| 200 | }
|
| 201 | }
|
| 202 | out:
|
| 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 bytes read on success; 0 on EOF; less than zero on error
|
| 218 |
|
| 219 | int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
| 220 | struct inode *ecryptfs_inode)
|
| 221 | {
|
| 222 | struct file *lower_file;
|
| 223 | lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
|
| 224 | if (!lower_file)
|
| 225 | return -EIO;
|
| 226 | return kernel_read(lower_file, data, size, &offset);
|
| 227 | }
|
| 228 |
|
| 229 | |
| 230 | * ecryptfs_read_lower_page_segment
|
| 231 | * @folio_for_ecryptfs: The folio into which data for eCryptfs will be
|
| 232 | * written
|
| 233 | * @page_index: Page index in @page_for_ecryptfs from which to start
|
| 234 | * writing
|
| 235 | * @offset_in_page: Offset in @page_for_ecryptfs from which to start
|
| 236 | * writing
|
| 237 | * @size: The number of bytes to write into @page_for_ecryptfs
|
| 238 | * @ecryptfs_inode: The eCryptfs inode
|
| 239 | *
|
| 240 | * Determines the byte offset in the file for the given page and
|
| 241 | * offset within the page, maps the page, and makes the call to read
|
| 242 | * the contents of @page_for_ecryptfs from the lower inode.
|
| 243 | *
|
| 244 | * Returns zero on success; non-zero otherwise
|
| 245 |
|
| 246 | int ecryptfs_read_lower_page_segment(struct folio *folio_for_ecryptfs,
|
| 247 | pgoff_t page_index,
|
| 248 | size_t offset_in_page, size_t size,
|
| 249 | struct inode *ecryptfs_inode)
|
| 250 | {
|
| 251 | char *virt;
|
| 252 | loff_t offset;
|
| 253 | int rc;
|
| 254 |
|
| 255 | offset = (loff_t)page_index * PAGE_SIZE + offset_in_page;
|
| 256 | virt = kmap_local_folio(folio_for_ecryptfs, 0);
|
| 257 | rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
|
| 258 | if (rc > 0)
|
| 259 | rc = 0;
|
| 260 | kunmap_local(virt);
|
| 261 | flush_dcache_folio(folio_for_ecryptfs);
|
| 262 | return rc;
|
| 263 | }
|