stx->stx_mask |= (CEPH_STATX_CTIME|CEPH_STATX_VERSION);
}
- // Check that the flag has no garbage, if is_encrypted() is false
- bool en = in->is_encrypted();
- ceph_assert(en || !(stx->stx_attributes & STATX_ATTR_ENCRYPTED));
- stx->stx_attributes |= en ? STATX_ATTR_ENCRYPTED : 0;
}
void Client::touch_dn(Dentry *dn)
}
// --- subvolume metrics tracking --- //
-int Client::get_inode_flags(const Inode* in, int* file_attr_out) {
- ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
-
- if (!file_attr_out)
- return -EINVAL;
-
- *file_attr_out = 0;
- // set or clear the encryption flag depending on the inode status
- if (in->is_encrypted()) {
- *file_attr_out |= FS_ENCRYPT_FL;
- } else {
- *file_attr_out &= ~FS_ENCRYPT_FL;
- }
- return 0;
-}
-
-int Client::get_inode_flags(int fd, int* file_attr_out) {
- std::scoped_lock l{client_lock};
-
- Fh *fh = get_filehandle(fd);
- if (!fh) {
- return -EBADF;
- }
- return get_inode_flags(fh->inode.get(), file_attr_out);
-}
-
int Client::fcopyfile(const char *spath, const char *dpath, UserPerm& perms, mode_t mode) {
ldout(cct, 10) << "fcopyfile spath=" << spath << " dpath=" << dpath << " mode=" << mode << dendl;
int remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user = 0);
int get_fscrypt_key_status(fscrypt_get_key_status_arg* arg);
- int get_inode_flags(const Inode* in, int* file_attr_out);
- int get_inode_flags(int fd, int* file_attr_out);
-
int fcopyfile(const char *sname, const char *dname, UserPerm& perms, mode_t mode);
int set_fscrypt_policy_v2(int fd, const struct fscrypt_policy_v2& policy);
FSCryptContextRef Inode::init_fscrypt_ctx(FSCrypt *fscrypt)
{
- auto res = fscrypt->init_ctx(fscrypt_auth);
- // at this point, if fscrypt is enabled, the fscrypt_auth is not empty
- // and we can set the S_ENCRYPTED flag
- set_is_encrypted_flag();
- return res;
+ return fscrypt->init_ctx(fscrypt_auth);
}
void Inode::gen_inherited_fscrypt_auth(std::vector<uint8_t> *fsa)
// use i_flags as 1 << 14 will overlap with other mode bits.
bool is_encrypted() const { return (i_flags & S_ENCRYPTED) == S_ENCRYPTED; }
- // this function sets S_ENCRYPTED bit in i_flag
- // is called when the is_fscrypt_enabled
- void set_is_encrypted_flag() {
- bool en = is_fscrypt_enabled();
- // just to make sure that no garbage is set in the flag, if fscrypt is disabled
- ceph_assert(en || !(i_flags & S_ENCRYPTED));
- i_flags |= en ? S_ENCRYPTED : 0;
- }
bool has_dir_layout() const {
return layout != file_layout_t();
fuse_reply_ioctl(req, 0, arg, sizeof(*arg));
}
break;
- case FS_IOC_GETFLAGS: {
- generic_dout(10) << __FILE__ << ":" << __LINE__ << ": FS_IOC_GETFLAGS ioctl" << dendl;
-
- int file_attr = 0;
- if (out_bufsz < sizeof(file_attr)) {
- fuse_reply_err(req, ERANGE);
- break;
- }
-
- Fh *fh = (Fh*)fi->fh;
- cfuse->client->get_inode_flags(fh->inode.get(), &file_attr);
- fuse_reply_ioctl(req, 0, &file_attr, sizeof(file_attr));
-}
-break;
default:
fuse_reply_err(req, EINVAL);
}
struct timespec stx_mtime;
struct timespec stx_btime;
uint64_t stx_version;
- uint64_t stx_attributes;
};
#define CEPH_STATX_MODE 0x00000001U /* Want/got stx_mode */
#define CEPH_STATX_VERSION 0x00001000U /* Want/got stx_version */
#define CEPH_STATX_ALL_STATS 0x00001fffU /* All supported stats */
-// the value of STATX_ATTR_ENCRYPTED on most systems is equal to FS_ENCRYPT_FL
-// to identify encrypted files uniformly,
-// simplifying operations that need to check encryption status.
-#ifndef STATX_ATTR_ENCRYPTED
-#define STATX_ATTR_ENCRYPTED 0x00000800 /* File requires key to decrypt in fs */
-#endif
-
/*
* Compatibility macros until these defines make their way into glibc
*/
#define FALLOC_FL_PUNCH_HOLE 0x02
#endif
-/* fscrypt IOCTL flags*/
-// the value of FS_ENCRYPT_FL on most systems is equal to STATX_ATTR_ENCRYPTED
-// to identify encrypted files uniformly,
-// simplifying operations that need to check encryption status.
-#ifndef FS_ENCRYPT_FL
-#define FS_ENCRYPT_FL 0x00000800 /* Encrypted file */
-#endif
-#ifndef FS_IOC_GETFLAGS
-#define FS_IOC_GETFLAGS _IOR('f', 1, int32_t)
-#endif
-
/** ceph_deleg_cb_t: Delegation recalls
*
* Called when there is an outstanding Delegation and there is conflicting
*/
int ceph_is_encrypted(struct ceph_mount_info *cmount,
int fd, char* enctag);
-/**
- * Fill file_attr_out with content of i_flags
- * @param cmount the ceph mount handle to use.
- * @param fd open directory file descriptor
- * @param file_attr_out will have result bits set
- * @returns zero on success, other returns a negative error code.
- */
-int get_inode_flags(struct ceph_mount_info *cmount, int fd, int* file_attr_out);
/* Low Level */
struct Inode *ceph_ll_get_inode(struct ceph_mount_info *cmount,
return outbl.length();
}
-extern "C" int get_inode_flags(struct ceph_mount_info *cmount, int fd, int* file_attr_out) {
- if (!cmount->is_mounted())
- return -ENOTCONN;
-
- return cmount->get_client()->get_inode_flags(fd, file_attr_out);
-}
-
extern "C" int ceph_fcopyfile(struct ceph_mount_info *cmount, const char *spath, const char *dpath, mode_t mode)
{
if (!cmount->is_mounted())
ceph_shutdown(cmount);
}
-TEST(FSCrypt, QuerySEncryptFlag) {
- struct ceph_fscrypt_key_identifier kid;
-
- struct ceph_mount_info *cmount;
- int r = init_mount(&cmount);
- ASSERT_EQ(0, r);
-
- //add dir
- string dir_path = "sencrypt_test_dir1";
- ceph_mkdir(cmount, dir_path.c_str(), 0777);
- int fd1 = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
-
- //query S_ENCRYPTED flag with statx on non encrypted directory
- struct ceph_statx stx;
- r = ceph_statx(cmount, dir_path.c_str(), &stx,
- CEPH_STATX_ALL_STATS,
- 0);
- ASSERT_EQ(0, r);
- ASSERT_EQ(0, stx.stx_attributes & STATX_ATTR_ENCRYPTED);
-
- //query S_ENCRYPTED flag with ioctl on non encr directory
- int file_attr_out;
- r = get_inode_flags(cmount, fd1, &file_attr_out);
- ASSERT_EQ(0, r);
- ASSERT_EQ(0, file_attr_out & FS_ENCRYPT_FL);
-
- // enable fscrypt
- r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
- ASSERT_EQ(0, r);
- struct fscrypt_policy_v2 policy;
- populate_policy(kid, &policy);
-
- r = ceph_set_fscrypt_policy_v2(cmount, fd1, &policy);
- ASSERT_EQ(0, r);
-
- //add file to encrypted directory
- string file_path = "sencrypt_test_file";
- string path = "";
- path.append(dir_path);
- path.append("/");
- path.append(file_path);
- int fd2 = ceph_open(cmount, path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
- r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
- ASSERT_EQ(32, r);
- ceph_close(cmount, fd1);
-
- //query S_ENCRYPTED flag with statx on encrypted file
- r = ceph_statx(cmount, path.c_str(), &stx,
- CEPH_STATX_ALL_STATS,
- 0);
- ASSERT_EQ(0, r);
- ASSERT_EQ(STATX_ATTR_ENCRYPTED, stx.stx_attributes & STATX_ATTR_ENCRYPTED);
-
- //query S_ENCRYPTED flag with ioctl on encrypted file
- r = get_inode_flags(cmount, fd2, &file_attr_out);
- ASSERT_EQ(FS_ENCRYPT_FL, file_attr_out & FS_ENCRYPT_FL);
-
- // cleanup
- ceph_close(cmount, fd2);
- ceph_unlink(cmount, file_path.c_str());
- ceph_rmdir(cmount, dir_path.c_str());
- fscrypt_remove_key_arg arg;
- generate_remove_key_arg(kid, &arg);
- r = ceph_remove_fscrypt_key(cmount, &arg, 1299);
- ASSERT_EQ(0, r);
- ASSERT_EQ(0, arg.removal_status_flags);
- ceph_shutdown(cmount);
-}
-
// this test verifies that fuse client doesn't support falloate ops
// FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_INSERT_RANGE
// if this test fails, it means that these ops has been impleneted AND we must reject these ops for encrypted files