Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ceph: add some fscrypt guardrails

Add the appropriate calls into fscrypt for various actions, including
link, rename, setattr, and the open codepaths.

Disable fallocate for encrypted inodes -- hopefully, just for now.

If we have an encrypted inode, then the client will need to re-encrypt
the contents of the new object. Disable copy offload to or from
encrypted inodes.

Set i_blkbits to crypto block size for encrypted inodes -- some of the
underlying infrastructure for fscrypt relies on i_blkbits being aligned
to crypto blocksize.

Report STATX_ATTR_ENCRYPTED on encrypted inodes.

[ lhenriques: forbid encryption with striped layouts ]

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-and-tested-by: Luís Henriques <lhenriques@suse.de>
Reviewed-by: Milind Changire <mchangir@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Jeff Layton and committed by
Ilya Dryomov
94af0470 79f2f6ad

+55 -9
+4
fs/ceph/crypto.h
··· 9 9 #include <crypto/sha2.h> 10 10 #include <linux/fscrypt.h> 11 11 12 + #define CEPH_FSCRYPT_BLOCK_SHIFT 12 13 + #define CEPH_FSCRYPT_BLOCK_SIZE (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT) 14 + #define CEPH_FSCRYPT_BLOCK_MASK (~(CEPH_FSCRYPT_BLOCK_SIZE-1)) 15 + 12 16 struct ceph_fs_client; 13 17 struct ceph_acl_sec_ctx; 14 18 struct ceph_mds_request;
+9
fs/ceph/dir.c
··· 1148 1148 if (ceph_snap(dir) != CEPH_NOSNAP) 1149 1149 return -EROFS; 1150 1150 1151 + err = fscrypt_prepare_link(old_dentry, dir, dentry); 1152 + if (err) 1153 + return err; 1154 + 1151 1155 dout("link in dir %p %llx.%llx old_dentry %p:'%pd' dentry %p:'%pd'\n", 1152 1156 dir, ceph_vinop(dir), old_dentry, old_dentry, dentry, dentry); 1153 1157 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LINK, USE_AUTH_MDS); ··· 1396 1392 return -EXDEV; 1397 1393 1398 1394 err = ceph_wait_on_conflict_unlink(new_dentry); 1395 + if (err) 1396 + return err; 1397 + 1398 + err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry, 1399 + flags); 1399 1400 if (err) 1400 1401 return err; 1401 1402
+20 -1
fs/ceph/file.c
··· 366 366 367 367 /* filter out O_CREAT|O_EXCL; vfs did that already. yuck. */ 368 368 flags = file->f_flags & ~(O_CREAT|O_EXCL); 369 - if (S_ISDIR(inode->i_mode)) 369 + if (S_ISDIR(inode->i_mode)) { 370 370 flags = O_DIRECTORY; /* mds likes to know */ 371 + } else if (S_ISREG(inode->i_mode)) { 372 + err = fscrypt_file_open(inode, file); 373 + if (err) 374 + return err; 375 + } 371 376 372 377 dout("open inode %p ino %llx.%llx file %p flags %d (%d)\n", inode, 373 378 ceph_vinop(inode), file, flags, file->f_flags); ··· 884 879 dout("atomic_open finish_no_open on dn %p\n", dn); 885 880 err = finish_no_open(file, dn); 886 881 } else { 882 + if (IS_ENCRYPTED(dir) && 883 + !fscrypt_has_permitted_context(dir, d_inode(dentry))) { 884 + pr_warn("Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n", 885 + ceph_vinop(dir), ceph_vinop(d_inode(dentry))); 886 + goto out_req; 887 + } 888 + 887 889 dout("atomic_open finish_open on dn %p\n", dn); 888 890 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { 889 891 struct inode *newino = d_inode(dentry); ··· 2234 2222 if (!S_ISREG(inode->i_mode)) 2235 2223 return -EOPNOTSUPP; 2236 2224 2225 + if (IS_ENCRYPTED(inode)) 2226 + return -EOPNOTSUPP; 2227 + 2237 2228 prealloc_cf = ceph_alloc_cap_flush(); 2238 2229 if (!prealloc_cf) 2239 2230 return -ENOMEM; ··· 2557 2542 dout("Invalid src/dst files layout\n"); 2558 2543 return -EOPNOTSUPP; 2559 2544 } 2545 + 2546 + /* Every encrypted inode gets its own key, so we can't offload them */ 2547 + if (IS_ENCRYPTED(src_inode) || IS_ENCRYPTED(dst_inode)) 2548 + return -EOPNOTSUPP; 2560 2549 2561 2550 if (len < src_ci->i_layout.object_size) 2562 2551 return -EOPNOTSUPP; /* no remote copy will be done */
+18 -8
fs/ceph/inode.c
··· 972 972 issued |= __ceph_caps_dirty(ci); 973 973 new_issued = ~issued & info_caps; 974 974 975 - /* directories have fl_stripe_unit set to zero */ 976 - if (le32_to_cpu(info->layout.fl_stripe_unit)) 977 - inode->i_blkbits = 978 - fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1; 979 - else 980 - inode->i_blkbits = CEPH_BLOCK_SHIFT; 981 - 982 975 __ceph_update_quota(ci, iinfo->max_bytes, iinfo->max_files); 983 976 984 977 #ifdef CONFIG_FS_ENCRYPTION ··· 996 1003 ceph_decode_timespec64(&ci->i_btime, &iinfo->btime); 997 1004 ceph_decode_timespec64(&ci->i_snap_btime, &iinfo->snap_btime); 998 1005 } 1006 + 1007 + /* directories have fl_stripe_unit set to zero */ 1008 + if (IS_ENCRYPTED(inode)) 1009 + inode->i_blkbits = CEPH_FSCRYPT_BLOCK_SHIFT; 1010 + else if (le32_to_cpu(info->layout.fl_stripe_unit)) 1011 + inode->i_blkbits = 1012 + fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1; 1013 + else 1014 + inode->i_blkbits = CEPH_BLOCK_SHIFT; 999 1015 1000 1016 if ((new_version || (new_issued & CEPH_CAP_LINK_SHARED)) && 1001 1017 (issued & CEPH_CAP_LINK_EXCL) == 0) ··· 2497 2495 if (ceph_inode_is_shutdown(inode)) 2498 2496 return -ESTALE; 2499 2497 2498 + err = fscrypt_prepare_setattr(dentry, attr); 2499 + if (err) 2500 + return err; 2501 + 2500 2502 err = setattr_prepare(&nop_mnt_idmap, dentry, attr); 2501 2503 if (err != 0) 2502 2504 return err; ··· 2784 2778 stat->nlink = 1 + 1 + ci->i_subdirs; 2785 2779 } 2786 2780 2787 - stat->attributes_mask |= STATX_ATTR_CHANGE_MONOTONIC; 2788 2781 stat->attributes |= STATX_ATTR_CHANGE_MONOTONIC; 2782 + if (IS_ENCRYPTED(inode)) 2783 + stat->attributes |= STATX_ATTR_ENCRYPTED; 2784 + stat->attributes_mask |= (STATX_ATTR_CHANGE_MONOTONIC | 2785 + STATX_ATTR_ENCRYPTED); 2786 + 2789 2787 stat->result_mask = request_mask & valid_mask; 2790 2788 return err; 2791 2789 }
+4
fs/ceph/ioctl.c
··· 294 294 struct inode *inode = file_inode(file); 295 295 struct ceph_inode_info *ci = ceph_inode(inode); 296 296 297 + /* encrypted directories can't have striped layout */ 298 + if (ci->i_layout.stripe_count > 1) 299 + return -EINVAL; 300 + 297 301 ret = vet_mds_for_fscrypt(file); 298 302 if (ret) 299 303 return ret;