1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * The base64 encode/decode code was copied from fscrypt: 4 * Copyright (C) 2015, Google, Inc. 5 * Copyright (C) 2015, Motorola Mobility 6 * Written by Uday Savagaonkar, 2014. 7 * Modified by Jaegeuk Kim, 2015. 8 */ 9 #include <linux/ceph/ceph_debug.h> 10 #include <linux/xattr.h> 11 #include <linux/fscrypt.h> 12 #include <linux/ceph/striper.h> 13 14 #include "super.h" 15 #include "mds_client.h" 16 #include "crypto.h" 17 18 /* 19 * The base64url encoding used by fscrypt includes the '_' character, which may 20 * cause problems in snapshot names (which can not start with '_'). Thus, we 21 * used the base64 encoding defined for IMAP mailbox names (RFC 3501) instead, 22 * which replaces '-' and '_' by '+' and ','. 23 */ 24 static const char base64_table[65] = 25 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; 26 27 int ceph_base64_encode(const u8 *src, int srclen, char *dst) 28 { 29 u32 ac = 0; 30 int bits = 0; 31 int i; 32 char *cp = dst; 33 34 for (i = 0; i < srclen; i++) { 35 ac = (ac << 8) | src[i]; 36 bits += 8; 37 do { 38 bits -= 6; 39 *cp++ = base64_table[(ac >> bits) & 0x3f]; 40 } while (bits >= 6); 41 } 42 if (bits) 43 *cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; 44 return cp - dst; 45 } 46 47 int ceph_base64_decode(const char *src, int srclen, u8 *dst) 48 { 49 u32 ac = 0; 50 int bits = 0; 51 int i; 52 u8 *bp = dst; 53 54 for (i = 0; i < srclen; i++) { 55 const char *p = strchr(base64_table, src[i]); 56 57 if (p == NULL || src[i] == 0) 58 return -1; 59 ac = (ac << 6) | (p - base64_table); 60 bits += 6; 61 if (bits >= 8) { 62 bits -= 8; 63 *bp++ = (u8)(ac >> bits); 64 } 65 } 66 if (ac & ((1 << bits) - 1)) 67 return -1; 68 return bp - dst; 69 } 70 71 static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len) 72 { 73 struct ceph_inode_info *ci = ceph_inode(inode); 74 struct ceph_fscrypt_auth *cfa = (struct ceph_fscrypt_auth *)ci->fscrypt_auth; 75 u32 ctxlen; 76 77 /* Non existent or too short? */ 78 if (!cfa || (ci->fscrypt_auth_len < (offsetof(struct ceph_fscrypt_auth, cfa_blob) + 1))) 79 return -ENOBUFS; 80 81 /* Some format we don't recognize? */ 82 if (le32_to_cpu(cfa->cfa_version) != CEPH_FSCRYPT_AUTH_VERSION) 83 return -ENOBUFS; 84 85 ctxlen = le32_to_cpu(cfa->cfa_blob_len); 86 if (len < ctxlen) 87 return -ERANGE; 88 89 memcpy(ctx, cfa->cfa_blob, ctxlen); 90 return ctxlen; 91 } 92 93 static int ceph_crypt_set_context(struct inode *inode, const void *ctx, 94 size_t len, void *fs_data) 95 { 96 int ret; 97 struct iattr attr = { }; 98 struct ceph_iattr cia = { }; 99 struct ceph_fscrypt_auth *cfa; 100 101 WARN_ON_ONCE(fs_data); 102 103 if (len > FSCRYPT_SET_CONTEXT_MAX_SIZE) 104 return -EINVAL; 105 106 cfa = kzalloc(sizeof(*cfa), GFP_KERNEL); 107 if (!cfa) 108 return -ENOMEM; 109 110 cfa->cfa_version = cpu_to_le32(CEPH_FSCRYPT_AUTH_VERSION); 111 cfa->cfa_blob_len = cpu_to_le32(len); 112 memcpy(cfa->cfa_blob, ctx, len); 113 114 cia.fscrypt_auth = cfa; 115 116 ret = __ceph_setattr(&nop_mnt_idmap, inode, &attr, &cia); 117 if (ret == 0) 118 inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED); 119 kfree(cia.fscrypt_auth); 120 return ret; 121 } 122 123 static bool ceph_crypt_empty_dir(struct inode *inode) 124 { 125 struct ceph_inode_info *ci = ceph_inode(inode); 126 127 return ci->i_rsubdirs + ci->i_rfiles == 1; 128 } 129 130 static const union fscrypt_policy *ceph_get_dummy_policy(struct super_block *sb) 131 { 132 return ceph_sb_to_fs_client(sb)->fsc_dummy_enc_policy.policy; 133 } 134 135 static struct fscrypt_operations ceph_fscrypt_ops = { 136 .needs_bounce_pages = 1, 137 .get_context = ceph_crypt_get_context, 138 .set_context = ceph_crypt_set_context, 139 .get_dummy_policy = ceph_get_dummy_policy, 140 .empty_dir = ceph_crypt_empty_dir, 141 }; 142 143 void ceph_fscrypt_set_ops(struct super_block *sb) 144 { 145 fscrypt_set_ops(sb, &ceph_fscrypt_ops); 146 } 147 148 void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc) 149 { 150 fscrypt_free_dummy_policy(&fsc->fsc_dummy_enc_policy); 151 } 152 153 int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, 154 struct ceph_acl_sec_ctx *as) 155 { 156 int ret, ctxsize; 157 bool encrypted = false; 158 struct ceph_inode_info *ci = ceph_inode(inode); 159 160 ret = fscrypt_prepare_new_inode(dir, inode, &encrypted); 161 if (ret) 162 return ret; 163 if (!encrypted) 164 return 0; 165 166 as->fscrypt_auth = kzalloc(sizeof(*as->fscrypt_auth), GFP_KERNEL); 167 if (!as->fscrypt_auth) 168 return -ENOMEM; 169 170 ctxsize = fscrypt_context_for_new_inode(as->fscrypt_auth->cfa_blob, 171 inode); 172 if (ctxsize < 0) 173 return ctxsize; 174 175 as->fscrypt_auth->cfa_version = cpu_to_le32(CEPH_FSCRYPT_AUTH_VERSION); 176 as->fscrypt_auth->cfa_blob_len = cpu_to_le32(ctxsize); 177 178 WARN_ON_ONCE(ci->fscrypt_auth); 179 kfree(ci->fscrypt_auth); 180 ci->fscrypt_auth_len = ceph_fscrypt_auth_len(as->fscrypt_auth); 181 ci->fscrypt_auth = kmemdup(as->fscrypt_auth, ci->fscrypt_auth_len, 182 GFP_KERNEL); 183 if (!ci->fscrypt_auth) 184 return -ENOMEM; 185 186 inode->i_flags |= S_ENCRYPTED; 187 188 return 0; 189 } 190 191 void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, 192 struct ceph_acl_sec_ctx *as) 193 { 194 swap(req->r_fscrypt_auth, as->fscrypt_auth); 195 } 196 197 /* 198 * User-created snapshots can't start with '_'. Snapshots that start with this 199 * character are special (hint: there aren't real snapshots) and use the 200 * following format: 201 * 202 * _<SNAPSHOT-NAME>_<INODE-NUMBER> 203 * 204 * where: 205 * - <SNAPSHOT-NAME> - the real snapshot name that may need to be decrypted, 206 * - <INODE-NUMBER> - the inode number (in decimal) for the actual snapshot 207 * 208 * This function parses these snapshot names and returns the inode 209 * <INODE-NUMBER>. 'name_len' will also bet set with the <SNAPSHOT-NAME> 210 * length. 211 */ 212 static struct inode *parse_longname(const struct inode *parent, 213 const char *name, int *name_len) 214 { 215 struct ceph_client *cl = ceph_inode_to_client(parent); 216 struct inode *dir = NULL; 217 struct ceph_vino vino = { .snap = CEPH_NOSNAP }; 218 char *inode_number; 219 char *name_end; 220 int orig_len = *name_len; 221 int ret = -EIO; 222 223 /* Skip initial '_' */ 224 name++; 225 name_end = strrchr(name, '_'); 226 if (!name_end) { 227 doutc(cl, "failed to parse long snapshot name: %s\n", name); 228 return ERR_PTR(-EIO); 229 } 230 *name_len = (name_end - name); 231 if (*name_len <= 0) { 232 pr_err_client(cl, "failed to parse long snapshot name\n"); 233 return ERR_PTR(-EIO); 234 } 235 236 /* Get the inode number */ 237 inode_number = kmemdup_nul(name_end + 1, 238 orig_len - *name_len - 2, 239 GFP_KERNEL); 240 if (!inode_number) 241 return ERR_PTR(-ENOMEM); 242 ret = kstrtou64(inode_number, 10, &vino.ino); 243 if (ret) { 244 doutc(cl, "failed to parse inode number: %s\n", name); 245 dir = ERR_PTR(ret); 246 goto out; 247 } 248 249 /* And finally the inode */ 250 dir = ceph_find_inode(parent->i_sb, vino); 251 if (!dir) { 252 /* This can happen if we're not mounting cephfs on the root */ 253 dir = ceph_get_inode(parent->i_sb, vino, NULL); 254 if (IS_ERR(dir)) 255 doutc(cl, "can't find inode %s (%s)\n", inode_number, name); 256 } 257 258 out: 259 kfree(inode_number); 260 return dir; 261 } 262 263 int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, 264 char *buf) 265 { 266 struct ceph_client *cl = ceph_inode_to_client(parent); 267 struct inode *dir = parent; 268 struct qstr iname; 269 u32 len; 270 int name_len; 271 int elen; 272 int ret; 273 u8 *cryptbuf = NULL; 274 275 iname.name = d_name->name; 276 name_len = d_name->len; 277 278 /* Handle the special case of snapshot names that start with '_' */ 279 if ((ceph_snap(dir) == CEPH_SNAPDIR) && (name_len > 0) && 280 (iname.name[0] == '_')) { 281 dir = parse_longname(parent, iname.name, &name_len); 282 if (IS_ERR(dir)) 283 return PTR_ERR(dir); 284 iname.name++; /* skip initial '_' */ 285 } 286 iname.len = name_len; 287 288 if (!fscrypt_has_encryption_key(dir)) { 289 memcpy(buf, d_name->name, d_name->len); 290 elen = d_name->len; 291 goto out; 292 } 293 294 /* 295 * Convert cleartext d_name to ciphertext. If result is longer than 296 * CEPH_NOHASH_NAME_MAX, sha256 the remaining bytes 297 * 298 * See: fscrypt_setup_filename 299 */ 300 if (!fscrypt_fname_encrypted_size(dir, iname.len, NAME_MAX, &len)) { 301 elen = -ENAMETOOLONG; 302 goto out; 303 } 304 305 /* Allocate a buffer appropriate to hold the result */ 306 cryptbuf = kmalloc(len > CEPH_NOHASH_NAME_MAX ? NAME_MAX : len, 307 GFP_KERNEL); 308 if (!cryptbuf) { 309 elen = -ENOMEM; 310 goto out; 311 } 312 313 ret = fscrypt_fname_encrypt(dir, &iname, cryptbuf, len); 314 if (ret) { 315 elen = ret; 316 goto out; 317 } 318 319 /* hash the end if the name is long enough */ 320 if (len > CEPH_NOHASH_NAME_MAX) { 321 u8 hash[SHA256_DIGEST_SIZE]; 322 u8 *extra = cryptbuf + CEPH_NOHASH_NAME_MAX; 323 324 /* 325 * hash the extra bytes and overwrite crypttext beyond that 326 * point with it 327 */ 328 sha256(extra, len - CEPH_NOHASH_NAME_MAX, hash); 329 memcpy(extra, hash, SHA256_DIGEST_SIZE); 330 len = CEPH_NOHASH_NAME_MAX + SHA256_DIGEST_SIZE; 331 } 332 333 /* base64 encode the encrypted name */ 334 elen = ceph_base64_encode(cryptbuf, len, buf); 335 doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, buf); 336 337 /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */ 338 WARN_ON(elen > 240); 339 if ((elen > 0) && (dir != parent)) { 340 char tmp_buf[NAME_MAX]; 341 342 elen = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%ld", 343 elen, buf, dir->i_ino); 344 memcpy(buf, tmp_buf, elen); 345 } 346 347 out: 348 kfree(cryptbuf); 349 if (dir != parent) { 350 if ((dir->i_state & I_NEW)) 351 discard_new_inode(dir); 352 else 353 iput(dir); 354 } 355 return elen; 356 } 357 358 int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, 359 char *buf) 360 { 361 WARN_ON_ONCE(!fscrypt_has_encryption_key(parent)); 362 363 return ceph_encode_encrypted_dname(parent, &dentry->d_name, buf); 364 } 365 366 /** 367 * ceph_fname_to_usr - convert a filename for userland presentation 368 * @fname: ceph_fname to be converted 369 * @tname: temporary name buffer to use for conversion (may be NULL) 370 * @oname: where converted name should be placed 371 * @is_nokey: set to true if key wasn't available during conversion (may be NULL) 372 * 373 * Given a filename (usually from the MDS), format it for presentation to 374 * userland. If @parent is not encrypted, just pass it back as-is. 375 * 376 * Otherwise, base64 decode the string, and then ask fscrypt to format it 377 * for userland presentation. 378 * 379 * Returns 0 on success or negative error code on error. 380 */ 381 int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, 382 struct fscrypt_str *oname, bool *is_nokey) 383 { 384 struct inode *dir = fname->dir; 385 struct fscrypt_str _tname = FSTR_INIT(NULL, 0); 386 struct fscrypt_str iname; 387 char *name = fname->name; 388 int name_len = fname->name_len; 389 int ret; 390 391 /* Sanity check that the resulting name will fit in the buffer */ 392 if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX) 393 return -EIO; 394 395 /* Handle the special case of snapshot names that start with '_' */ 396 if ((ceph_snap(dir) == CEPH_SNAPDIR) && (name_len > 0) && 397 (name[0] == '_')) { 398 dir = parse_longname(dir, name, &name_len); 399 if (IS_ERR(dir)) 400 return PTR_ERR(dir); 401 name++; /* skip initial '_' */ 402 } 403 404 if (!IS_ENCRYPTED(dir)) { 405 oname->name = fname->name; 406 oname->len = fname->name_len; 407 ret = 0; 408 goto out_inode; 409 } 410 411 ret = ceph_fscrypt_prepare_readdir(dir); 412 if (ret) 413 goto out_inode; 414 415 /* 416 * Use the raw dentry name as sent by the MDS instead of 417 * generating a nokey name via fscrypt. 418 */ 419 if (!fscrypt_has_encryption_key(dir)) { 420 if (fname->no_copy) 421 oname->name = fname->name; 422 else 423 memcpy(oname->name, fname->name, fname->name_len); 424 oname->len = fname->name_len; 425 if (is_nokey) 426 *is_nokey = true; 427 ret = 0; 428 goto out_inode; 429 } 430 431 if (fname->ctext_len == 0) { 432 int declen; 433 434 if (!tname) { 435 ret = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname); 436 if (ret) 437 goto out_inode; 438 tname = &_tname; 439 } 440 441 declen = ceph_base64_decode(name, name_len, tname->name); 442 if (declen <= 0) { 443 ret = -EIO; 444 goto out; 445 } 446 iname.name = tname->name; 447 iname.len = declen; 448 } else { 449 iname.name = fname->ctext; 450 iname.len = fname->ctext_len; 451 } 452 453 ret = fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, oname); 454 if (!ret && (dir != fname->dir)) { 455 char tmp_buf[CEPH_BASE64_CHARS(NAME_MAX)]; 456 457 name_len = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%ld", 458 oname->len, oname->name, dir->i_ino); 459 memcpy(oname->name, tmp_buf, name_len); 460 oname->len = name_len; 461 } 462 463 out: 464 fscrypt_fname_free_buffer(&_tname); 465 out_inode: 466 if (dir != fname->dir) { 467 if ((dir->i_state & I_NEW)) 468 discard_new_inode(dir); 469 else 470 iput(dir); 471 } 472 return ret; 473 } 474 475 /** 476 * ceph_fscrypt_prepare_readdir - simple __fscrypt_prepare_readdir() wrapper 477 * @dir: directory inode for readdir prep 478 * 479 * Simple wrapper around __fscrypt_prepare_readdir() that will mark directory as 480 * non-complete if this call results in having the directory unlocked. 481 * 482 * Returns: 483 * 1 - if directory was locked and key is now loaded (i.e. dir is unlocked) 484 * 0 - if directory is still locked 485 * < 0 - if __fscrypt_prepare_readdir() fails 486 */ 487 int ceph_fscrypt_prepare_readdir(struct inode *dir) 488 { 489 bool had_key = fscrypt_has_encryption_key(dir); 490 int err; 491 492 if (!IS_ENCRYPTED(dir)) 493 return 0; 494 495 err = __fscrypt_prepare_readdir(dir); 496 if (err) 497 return err; 498 if (!had_key && fscrypt_has_encryption_key(dir)) { 499 /* directory just got unlocked, mark it as not complete */ 500 ceph_dir_clear_complete(dir); 501 return 1; 502 } 503 return 0; 504 } 505 506 int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, 507 struct page *page, unsigned int len, 508 unsigned int offs, u64 lblk_num) 509 { 510 struct ceph_client *cl = ceph_inode_to_client(inode); 511 512 doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode, 513 ceph_vinop(inode), len, offs, lblk_num); 514 return fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num); 515 } 516 517 int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, 518 struct page *page, unsigned int len, 519 unsigned int offs, u64 lblk_num, 520 gfp_t gfp_flags) 521 { 522 struct ceph_client *cl = ceph_inode_to_client(inode); 523 524 doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode, 525 ceph_vinop(inode), len, offs, lblk_num); 526 return fscrypt_encrypt_block_inplace(inode, page, len, offs, lblk_num, 527 gfp_flags); 528 } 529 530 /** 531 * ceph_fscrypt_decrypt_pages - decrypt an array of pages 532 * @inode: pointer to inode associated with these pages 533 * @page: pointer to page array 534 * @off: offset into the file that the read data starts 535 * @len: max length to decrypt 536 * 537 * Decrypt an array of fscrypt'ed pages and return the amount of 538 * data decrypted. Any data in the page prior to the start of the 539 * first complete block in the read is ignored. Any incomplete 540 * crypto blocks at the end of the array are ignored (and should 541 * probably be zeroed by the caller). 542 * 543 * Returns the length of the decrypted data or a negative errno. 544 */ 545 int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page, 546 u64 off, int len) 547 { 548 int i, num_blocks; 549 u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT; 550 int ret = 0; 551 552 /* 553 * We can't deal with partial blocks on an encrypted file, so mask off 554 * the last bit. 555 */ 556 num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK); 557 558 /* Decrypt each block */ 559 for (i = 0; i < num_blocks; ++i) { 560 int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT; 561 int pgidx = blkoff >> PAGE_SHIFT; 562 unsigned int pgoffs = offset_in_page(blkoff); 563 int fret; 564 565 fret = ceph_fscrypt_decrypt_block_inplace(inode, page[pgidx], 566 CEPH_FSCRYPT_BLOCK_SIZE, pgoffs, 567 baseblk + i); 568 if (fret < 0) { 569 if (ret == 0) 570 ret = fret; 571 break; 572 } 573 ret += CEPH_FSCRYPT_BLOCK_SIZE; 574 } 575 return ret; 576 } 577 578 /** 579 * ceph_fscrypt_decrypt_extents: decrypt received extents in given buffer 580 * @inode: inode associated with pages being decrypted 581 * @page: pointer to page array 582 * @off: offset into the file that the data in page[0] starts 583 * @map: pointer to extent array 584 * @ext_cnt: length of extent array 585 * 586 * Given an extent map and a page array, decrypt the received data in-place, 587 * skipping holes. Returns the offset into buffer of end of last decrypted 588 * block. 589 */ 590 int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page, 591 u64 off, struct ceph_sparse_extent *map, 592 u32 ext_cnt) 593 { 594 struct ceph_client *cl = ceph_inode_to_client(inode); 595 int i, ret = 0; 596 struct ceph_inode_info *ci = ceph_inode(inode); 597 u64 objno, objoff; 598 u32 xlen; 599 600 /* Nothing to do for empty array */ 601 if (ext_cnt == 0) { 602 doutc(cl, "%p %llx.%llx empty array, ret 0\n", inode, 603 ceph_vinop(inode)); 604 return 0; 605 } 606 607 ceph_calc_file_object_mapping(&ci->i_layout, off, map[0].len, 608 &objno, &objoff, &xlen); 609 610 for (i = 0; i < ext_cnt; ++i) { 611 struct ceph_sparse_extent *ext = &map[i]; 612 int pgsoff = ext->off - objoff; 613 int pgidx = pgsoff >> PAGE_SHIFT; 614 int fret; 615 616 if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) { 617 pr_warn_client(cl, 618 "%p %llx.%llx bad encrypted sparse extent " 619 "idx %d off %llx len %llx\n", 620 inode, ceph_vinop(inode), i, ext->off, 621 ext->len); 622 return -EIO; 623 } 624 fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx], 625 off + pgsoff, ext->len); 626 doutc(cl, "%p %llx.%llx [%d] 0x%llx~0x%llx fret %d\n", inode, 627 ceph_vinop(inode), i, ext->off, ext->len, fret); 628 if (fret < 0) { 629 if (ret == 0) 630 ret = fret; 631 break; 632 } 633 ret = pgsoff + fret; 634 } 635 doutc(cl, "ret %d\n", ret); 636 return ret; 637 } 638 639 /** 640 * ceph_fscrypt_encrypt_pages - encrypt an array of pages 641 * @inode: pointer to inode associated with these pages 642 * @page: pointer to page array 643 * @off: offset into the file that the data starts 644 * @len: max length to encrypt 645 * @gfp: gfp flags to use for allocation 646 * 647 * Decrypt an array of cleartext pages and return the amount of 648 * data encrypted. Any data in the page prior to the start of the 649 * first complete block in the read is ignored. Any incomplete 650 * crypto blocks at the end of the array are ignored. 651 * 652 * Returns the length of the encrypted data or a negative errno. 653 */ 654 int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off, 655 int len, gfp_t gfp) 656 { 657 int i, num_blocks; 658 u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT; 659 int ret = 0; 660 661 /* 662 * We can't deal with partial blocks on an encrypted file, so mask off 663 * the last bit. 664 */ 665 num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK); 666 667 /* Encrypt each block */ 668 for (i = 0; i < num_blocks; ++i) { 669 int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT; 670 int pgidx = blkoff >> PAGE_SHIFT; 671 unsigned int pgoffs = offset_in_page(blkoff); 672 int fret; 673 674 fret = ceph_fscrypt_encrypt_block_inplace(inode, page[pgidx], 675 CEPH_FSCRYPT_BLOCK_SIZE, pgoffs, 676 baseblk + i, gfp); 677 if (fret < 0) { 678 if (ret == 0) 679 ret = fret; 680 break; 681 } 682 ret += CEPH_FSCRYPT_BLOCK_SIZE; 683 } 684 return ret; 685 } 686
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.