From 4885a48fcf1799a0566789d280301d80b651fb04 Mon Sep 17 00:00:00 2001 From: Christopher Hoffman Date: Thu, 16 Oct 2025 17:33:05 +0000 Subject: [PATCH] cephfs: Only build client with fscrypt on linux Do not build client with fscrypt on non-linux distros. Fixes: https://tracker.ceph.com/issues/70324 Signed-off-by: Christopher Hoffman --- src/client/Client.cc | 194 ++++++++++++++++++++++++---------- src/client/Client.h | 42 ++++++-- src/client/FSCrypt.cc | 2 + src/client/FSCrypt.h | 4 +- src/client/Inode.cc | 5 +- src/client/Inode.h | 7 +- src/client/fscrypt_uapi.h | 3 + src/client/fuse_ll.cc | 2 + src/libcephfs.cc | 4 +- src/test/client/TestClient.h | 18 ++-- src/test/libcephfs/fscrypt.cc | 12 ++- src/test/libcephfs/test.cc | 4 +- 12 files changed, 214 insertions(+), 83 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index dec0dbe989ed8..2e048f06278d0 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -650,8 +650,9 @@ void Client::_pre_init() objecter_finisher.start(); filer.reset(new Filer(objecter, &objecter_finisher)); +#if defined(__linux__) fscrypt.reset(new FSCrypt(cct)); - +#endif objectcacher->start(); } @@ -967,7 +968,11 @@ void Client::update_inode_file_size(Inode *in, int issued, uint64_t size, ldout(cct, 10) << "size " << in->effective_size() << " -> " << size << dendl; if (in->is_fscrypt_enabled()) { in->set_effective_size(size); +#if defined(__linux__) in->size = in->reported_size = fscrypt_next_block_start(size); +#else + in->size = in->reported_size = size; +#endif } else { in->size = in->reported_size = size; } @@ -980,14 +985,15 @@ void Client::update_inode_file_size(Inode *in, int issued, uint64_t size, // truncate cached file data if (prior_size > size) { +#if defined(__linux__) if (in->is_fscrypt_enabled()) { // in the case of fscrypt truncate, you'll want to invalidate // the whole fscrypt block (from start of block to end) // otherwise on a read you'll have an invalid fscrypt block _invalidate_inode_cache(in, fscrypt_block_start(size), FSCRYPT_BLOCK_SIZE); - } else { + } else +#endif _invalidate_inode_cache(in, size, prior_size - size); - } } } @@ -1145,7 +1151,9 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, in->snap_btime = st->snap_btime; in->snap_metadata = st->snap_metadata; in->fscrypt_auth = st->fscrypt_auth; +#if defined(__linux__) in->fscrypt_ctx = in->init_fscrypt_ctx(fscrypt.get()); +#endif need_snapdir_attr_refresh = true; } @@ -1401,6 +1409,7 @@ bool Client::_wrap_name(Inode& diri, std::string& dname, std::string& alternate_ } /* else: no normalization / folding / encoding */ } +#if defined(__linux__) auto fscrypt_denc = fscrypt->get_fname_denc(diri.fscrypt_ctx, &diri.fscrypt_key_validator, true); if (fscrypt_denc) { string _enc_name; @@ -1424,6 +1433,7 @@ bool Client::_wrap_name(Inode& diri, std::string& dname, std::string& alternate_ alternate_name = _alt_name.empty() ? std::move(_enc_name) : std::move(_alt_name); } } +#endif return true; } @@ -1434,6 +1444,7 @@ std::string Client::_unwrap_name(Inode& diri, const std::string& dname, const st std::string newdname = dname; std::string newaltn = alternate_name; +#if defined(__linux__) auto fscrypt_denc = fscrypt->get_fname_denc(diri.fscrypt_ctx, &diri.fscrypt_key_validator, true); if (fscrypt_denc) { std::string plaintext; @@ -1448,7 +1459,7 @@ std::string Client::_unwrap_name(Inode& diri, const std::string& dname, const st newaltn = newdname; } } - +#endif if (diri.has_charmap()) { auto& cs = diri.get_charmap(); ldout(cct, 25) << __func__ << ": " << cs << dendl; @@ -3930,9 +3941,11 @@ int Client::get_caps(Fh *fh, int need, int want, int *phave, loff_t endoff) endoff > (loff_t)in->wanted_max_size) { ldout(cct, 10) << "wanted_max_size " << in->wanted_max_size << " -> " << endoff << dendl; uint64_t want = endoff; +#if defined(__linux__) if (in->fscrypt_auth.size()) { want = fscrypt_block_start(endoff + FSCRYPT_BLOCK_SIZE - 1); - } + } +#endif in->wanted_max_size = want; } if (in->wanted_max_size > in->max_size && @@ -3981,9 +3994,12 @@ int Client::get_caps(Fh *fh, int need, int want, int *phave, loff_t endoff) } if ((need & CEPH_CAP_FILE_WR) && - ((in->auth_cap && in->auth_cap->session->readonly) || + ((in->auth_cap && in->auth_cap->session->readonly) // (is locked) - (in->is_fscrypt_enabled() && is_inode_locked(in) && fscrypt_as))) +#if defined(__linux__) + || (in->is_fscrypt_enabled() && is_inode_locked(in) && fscrypt_as) +#endif + )) return -EROFS; if (in->flags & I_CAP_DROPPED) { @@ -6370,8 +6386,10 @@ int Client::may_open(const InodeRef& in, int flags, const UserPerm& perms) ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl; unsigned want = 0; +#if defined(__linux__) if (!in->is_dir() && is_inode_locked(in) && fscrypt_as) return -ENOKEY; +#endif if ((flags & O_ACCMODE) == O_WRONLY) want = CLIENT_MAY_WRITE; @@ -6426,9 +6444,10 @@ out: int Client::may_create(const InodeRef& dir, const UserPerm& perms) { ldout(cct, 20) << __func__ << " " << *dir << "; " << perms << dendl; +#if defined(__linux__) if (dir->is_dir() && is_inode_locked(dir) && fscrypt_as) return -ENOKEY; - +#endif int r = _getattr_for_perm(dir, perms); if (r < 0) goto out; @@ -7003,6 +7022,7 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms, } } +#if defined(__linux__) // dummy encryption? if (cct->_conf.get_val("client_fscrypt_dummy_encryption")) { client_lock.unlock(); @@ -7014,6 +7034,7 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms, client_lock.lock(); } +#endif /* ldout(cct, 3) << "op: // client trace data structs" << dendl; ldout(cct, 3) << "op: struct stat st;" << dendl; @@ -7323,6 +7344,7 @@ void Client::abort_conn() _unmount(true); } +#if defined(__linux__) int Client::fscrypt_dummy_encryption() { // get add key char key[FSCRYPT_KEY_IDENTIFIER_SIZE]; @@ -7360,6 +7382,7 @@ int Client::fscrypt_dummy_encryption() { r = remove_fscrypt_key(&arg); return r; } +#endif void Client::flush_cap_releases() { uint64_t nr_caps = 0; @@ -7973,9 +7996,10 @@ int Client::path_walk(InodeRef dirinode, const filepath& origpath, goto out; } + std::string symlink; +#if defined(__linux__) auto fscrypt_denc = fscrypt->get_fname_denc(next->fscrypt_ctx, &next->fscrypt_key_validator, true); - std::string symlink; if (fscrypt_denc) { int ret = fscrypt_denc->get_decrypted_symlink(next->symlink, &symlink); if (ret < 0) { @@ -7984,9 +8008,9 @@ int Client::path_walk(InodeRef dirinode, const filepath& origpath, goto out; } ldout(cct, 25) << "decrypted symlink is: " << binstrprint(symlink) << dendl; - } else { + } else +#endif symlink = next->symlink; - } if (i < path.depth() - 1) { // dir symlink @@ -8251,6 +8275,7 @@ int Client::_readlink(const InodeRef& diri, const char* relpath, char *buf, size if (r > (int)size) r = size; +#if defined(__linux__) auto fscrypt_denc = fscrypt->get_fname_denc(in->fscrypt_ctx, &in->fscrypt_key_validator, true); //There are three states a symlink could be in @@ -8268,7 +8293,9 @@ int Client::_readlink(const InodeRef& diri, const char* relpath, char *buf, size } else { memcpy(buf, in->symlink.c_str(), r); } - +#else + memcpy(buf, in->symlink.c_str(), r); +#endif return r; } @@ -8529,7 +8556,9 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, if (!do_sync && in->caps_issued_mask(CEPH_CAP_AUTH_EXCL)) { in->ctime = ceph_clock_now(); in->fscrypt_auth = *aux; +#if defined(__linux__) in->fscrypt_ctx = in->init_fscrypt_ctx(fscrypt.get()); +#endif in->mark_caps_dirty(CEPH_CAP_AUTH_EXCL); mask &= ~CEPH_SETATTR_FSCRYPT_AUTH; } else if (!in->caps_issued_mask(CEPH_CAP_AUTH_SHARED) || @@ -8547,8 +8576,9 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, mask |= CEPH_SETATTR_FSCRYPT_FILE; } +#if defined(__linux__) if (in->fscrypt_ctx && - (!(mask & CEPH_SETATTR_FSCRYPT_FILE))) { + (!(mask & CEPH_SETATTR_FSCRYPT_FILE))) { ldout(cct,10) << "fscrypt: set file size: orig stx_size=" << stx->stx_size <<" new stx_size=" << stx_size << dendl; alt_aux.resize(sizeof(stx->stx_size)); @@ -8557,6 +8587,7 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, mask |= CEPH_SETATTR_FSCRYPT_FILE; } +#endif if ((uint64_t)stx_size >= mdsmap->get_max_filesize()) { //too big! @@ -8566,6 +8597,7 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, ldout(cct,10) << "changing size to " << stx_size << dendl; +#if defined(__linux__) //fscrypt last block // //last block is only needed when truncating smaller @@ -8601,6 +8633,7 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, offset, stx->stx_size, in->size, &read_start, &read_len, &fscrypt_denc); + read_start = offset; get_cap_ref(in, CEPH_CAP_FILE_CACHE); std::vector holes; @@ -8651,7 +8684,7 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, ldout(cct, 10) << "finished preparing last block" << dendl; setting_smaller = 1; } - +#endif if (!do_sync && in->caps_issued_mask(CEPH_CAP_FILE_EXCL) && !(mask & CEPH_SETATTR_KILL_SGUID) && stx_size >= in->effective_size()) { @@ -8659,7 +8692,9 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, uint64_t size = stx_size; if (in->is_fscrypt_enabled()) { in->set_effective_size(size); +#if defined(__linux__) size = fscrypt_next_block_start(size); +#endif } in->size = in->reported_size = size; in->cap_dirtier_uid = perms.uid(); @@ -8673,8 +8708,10 @@ int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask, } } else { uint64_t size = stx_size; +#if defined(__linux__) if (in->is_fscrypt_enabled()) size = fscrypt_next_block_start(stx_size); +#endif args.setattr.size = size; inode_drop |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; @@ -10082,12 +10119,12 @@ int Client::_readdir_r_cb(int op, << dirp->inode->is_complete_and_ordered() << " issued " << ccap_string(dirp->inode->caps_issued()) << dendl; - +#if defined(__linux__) if (dirp->inode->fscrypt_key_validator && !dirp->inode->fscrypt_key_validator->is_valid()) { clear_dir_complete_and_ordered(dirp->inode.get(), true); } - +#endif if (!bypass_cache && dirp->inode->snapid != CEPH_SNAPDIR && dirp->inode->is_complete_and_ordered() && @@ -10879,6 +10916,7 @@ int Client::_release_fh(Fh *f) in->unset_deleg(f); if (in->snapid == CEPH_NOSNAP) { +#if defined(__linux__) FSCryptKeyHandlerRef kh; get_keyhandler(in->fscrypt_ctx, kh); if (kh) { @@ -10887,6 +10925,7 @@ int Client::_release_fh(Fh *f) di->del_inode(in->ino); } } +#endif if (in->put_open_ref(f->mode)) { _flush(in, new C_Client_FlushComplete(this, in)); check_caps(in, 0); @@ -10938,6 +10977,7 @@ int Client::_open(const InodeRef& in, int flags, mode_t mode, Fh **fhp, int want = ceph_caps_for_mode(cmode); int result = 0; +#if defined(__linux__) FSCryptKeyHandlerRef kh; get_keyhandler(in->fscrypt_ctx, kh); if (kh) { @@ -10946,7 +10986,7 @@ int Client::_open(const InodeRef& in, int flags, mode_t mode, Fh **fhp, di->add_inode(in->ino); } } - +#endif in->get_open_ref(cmode); // make note of pending open, since it effects _wanted_ caps. int do_sync = true; @@ -11029,6 +11069,7 @@ int Client::_open(const InodeRef& in, int flags, mode_t mode, Fh **fhp, } } } else { +#if defined(__linux__) FSCryptKeyHandlerRef kh; get_keyhandler(in->fscrypt_ctx, kh); if (kh) { @@ -11037,6 +11078,7 @@ int Client::_open(const InodeRef& in, int flags, mode_t mode, Fh **fhp, di->del_inode(in->ino); } } +#endif in->put_open_ref(cmode); } @@ -11382,6 +11424,7 @@ void Client::C_Read_Finisher::finish_io(int r) } void Client::C_Read_Sync_NonBlocking::start() { +#if defined(__linux__) clnt->fscrypt->prepare_data_read(in->fscrypt_ctx, &in->fscrypt_key_validator, off, len, in->size, @@ -11390,6 +11433,11 @@ void Client::C_Read_Sync_NonBlocking::start() pos = read_start; left = read_len; +#else + pos = off; + left = len; + +#endif retry(); } void Client::C_Read_Sync_NonBlocking::retry() @@ -11408,11 +11456,13 @@ void Client::C_Read_Sync_NonBlocking::finish(int r) auto effective_size = in->effective_size(); +#if defined(__linux__) auto target_len = std::min(len, effective_size - off); - bufferlist encbl; bufferlist *pbl = (fscrypt_denc ? &encbl : bl); - +#else + bufferlist *pbl = bl; +#endif if (r == -ENOENT) { // if we get ENOENT from OSD, assume 0 bytes returned r = 0; @@ -11466,6 +11516,7 @@ void Client::C_Read_Sync_NonBlocking::finish(int r) success: if (r >= 0) { +#if defined(__linux__) if (fscrypt_denc) { std::vector holes; r = fscrypt_denc->decrypt_bl(off, target_len, read_start, holes, pbl); @@ -11474,7 +11525,7 @@ success: } bl->claim_append(*pbl); } - +#endif // r is expected to hold value of effective bytes read. // in the case of fscrypt, this will be the logical size. So if all bytes read // is equal to read_len, then display logical size. @@ -11755,6 +11806,7 @@ void Client::do_readahead(Fh *f, Inode *in, uint64_t off, uint64_t len) void Client::C_Read_Async_Finisher::finish(int r) { +#if defined(__linux__) if (denc && r > 0) { std::vector holes; r = denc->decrypt_bl(off, len, read_start, holes, bl); @@ -11764,7 +11816,7 @@ void Client::C_Read_Async_Finisher::finish(int r) r = bl->length(); } } - +#endif // Do read ahead as long as we aren't completing with 0 bytes if (r != 0) clnt->do_readahead(f, in, off, len); @@ -11792,12 +11844,17 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, len = effective_size - off; } +#if defined(__linux__) FSCryptFDataDencRef fscrypt_denc; fscrypt->prepare_data_read(in->fscrypt_ctx, &in->fscrypt_key_validator, off, len, in->size, &read_start, &read_len, &fscrypt_denc); +#else + read_start = off; + read_len = len; +#endif // get Fc cap ref before commencing read get_cap_ref(in, CEPH_CAP_FILE_CACHE); @@ -11805,7 +11862,10 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, if (onfinish != nullptr) { io_finish.reset(new C_Read_Async_Finisher(this, onfinish, f, in, bl, f->pos, off, len, - fscrypt_denc, read_start, read_len)); +#if defined(__linux__) + fscrypt_denc, +#endif + read_start, read_len)); } // trim read based on file size? @@ -11830,9 +11890,8 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, // Signal async completion return 0; } - auto target_len = std::min(len, effective_size - off); - + ldout(cct, 10) << " min_bytes=" << f->readahead.get_min_readahead_size() << " max_bytes=" << f->readahead.get_max_readahead_size() << " max_periods=" << conf->client_readahead_max_periods << dendl; @@ -11877,6 +11936,7 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, } if (r >= 0) { +#if defined(__linux__) if (fscrypt_denc) { r = fscrypt_denc->decrypt_bl(off, target_len, read_start, holes, bl); if (r < 0) { @@ -11884,7 +11944,7 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, return r; } } - +#endif r = bl->length(); update_read_io_size(bl->length()); @@ -11906,25 +11966,31 @@ int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, Inode *in = f->inode.get(); auto effective_size = in->effective_size(); - auto target_len = std::min(len, effective_size - off); - uint64_t read_start; +uint64_t read_start; uint64_t read_len; +#if defined(__linux__) FSCryptFDataDencRef fscrypt_denc; fscrypt->prepare_data_read(in->fscrypt_ctx, &in->fscrypt_key_validator, off, len, in->size, &read_start, &read_len, &fscrypt_denc); - +#else + read_start = off; + read_len = len; +#endif uint64_t pos = read_start; int left = read_len; int read = 0; bufferlist encbl; +#if defined(__linux__) bufferlist *pbl = (fscrypt_denc ? &encbl : bl); - +#else + bufferlist *pbl = bl; +#endif ldout(cct, 10) << __func__ << " " << *in << " " << off << "~" << len << dendl; // 0 success, 1 continue and < 0 error happen. @@ -11992,6 +12058,7 @@ int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, } if (r >= 0) { +#if defined(__linux__) if (fscrypt_denc) { std::vector holes; r = fscrypt_denc->decrypt_bl(off, target_len, read_start, holes, pbl); @@ -12001,9 +12068,9 @@ int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl, read = pbl->length(); bl->claim_append(*pbl); - } else { + } else +#endif read = pbl->length(); - } } return read; } @@ -12305,13 +12372,17 @@ Client::WriteEncMgr::WriteEncMgr(Client *clnt, Fh *f, int64_t offset, uint64_t size, bufferlist& bl, bool async) : clnt(clnt), whoami(clnt->whoami), - cct(clnt->cct), fscrypt(clnt->fscrypt.get()), - f(f), in(f->inode.get()), + cct(clnt->cct), +#if defined(__linux__) + fscrypt(clnt->fscrypt.get()), +#endif + f(f), in(f->inode.get()), offset(offset), size(size), bl(bl), async(async) { +#if defined(__linux__) denc = fscrypt->get_fdata_denc(in->fscrypt_ctx, &in->fscrypt_key_validator); - +#endif pbl = &bl; } @@ -12321,6 +12392,7 @@ Client::WriteEncMgr::~WriteEncMgr() int Client::WriteEncMgr::init() { +#if defined(__linux__) if (!denc) { return 0; } @@ -12333,7 +12405,7 @@ int Client::WriteEncMgr::init() if (r < 0) { return r; } - +#endif return 0; } @@ -12369,10 +12441,14 @@ int Client::WriteEncMgr::read_modify_write(Context *_iofinish) } }); - if (!denc) { +#if defined(__linux__) + if (!denc) return do_write(); - } +#else + return do_write(); +#endif +#if defined(__linux__) ceph_assert(ceph_mutex_is_locked_by_me(clnt->client_lock)); int r = 0; @@ -12447,11 +12523,11 @@ done: } try_finish(r); - return r; +#endif } - +#if defined(__linux__) void Client::WriteEncMgr::finish_read_start(int r) { ceph_assert(ceph_mutex_is_locked_by_me(clnt->client_lock)); @@ -12536,6 +12612,7 @@ bool Client::WriteEncMgr::do_try_finish(int r) r = do_write(); return true; } +#endif void Client::WriteEncMgr_Buffered::update_write_params() { @@ -15783,7 +15860,9 @@ int Client::_mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev, req->set_inode_owner_uid_gid(perms.uid(), perms.gid()); req->set_alternate_name(wdr.alternate_name); +#if defined(__linux__) wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth); +#endif req->set_filepath(wdr.getpath()); req->set_inode(wdr.diri); req->head.args.mknod.rdev = rdev; @@ -15920,9 +15999,10 @@ int Client::_create(const walk_dentry_result& wdr, int flags, mode_t mode, req->set_inode(wdr.diri); if (fscrypt_options.fscrypt_auth.size()) req->fscrypt_auth = fscrypt_options.fscrypt_auth; +#if defined(__linux__) else wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth); - +#endif if (fscrypt_options.fscrypt_file.size()) req->fscrypt_file = fscrypt_options.fscrypt_file; @@ -15958,6 +16038,7 @@ int Client::_create(const walk_dentry_result& wdr, int flags, mode_t mode, /* If the caller passed a value in fhp, do the open */ if(fhp) { +#if defined(__linux__) FSCryptKeyHandlerRef kh; get_keyhandler((*inp)->fscrypt_ctx, kh); if (kh) { @@ -15966,6 +16047,7 @@ int Client::_create(const walk_dentry_result& wdr, int flags, mode_t mode, di->add_inode((*inp)->ino); } } +#endif (*inp)->get_open_ref(cmode); *fhp = _create_fh(inp->get(), flags, cmode, perms); @@ -16020,9 +16102,10 @@ int Client::_mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& p req->set_alternate_name(alternate_name.empty() ? wdr.alternate_name : alternate_name); if (fscrypt_options.fscrypt_auth.size()) req->fscrypt_auth = fscrypt_options.fscrypt_auth; +#if defined(__linux__) else wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth); - +#endif if (fscrypt_options.fscrypt_file.size()) req->fscrypt_file = fscrypt_options.fscrypt_file; @@ -16165,12 +16248,13 @@ int Client::_symlink(Inode *dir, const char *name, const char *target, if (fscrypt_options.fscrypt_auth.size()) req->fscrypt_auth = fscrypt_options.fscrypt_auth; +#if defined(__linux__) else wdr.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth); - +#endif if (fscrypt_options.fscrypt_file.size()) req->fscrypt_file = fscrypt_options.fscrypt_file; - +#if defined(__linux__) auto fscrypt_ctx = fscrypt->init_ctx(req->fscrypt_auth); if (fscrypt_ctx && fscrypt_as) { auto fscrypt_denc = fscrypt->get_fname_denc(fscrypt_ctx, nullptr, true); @@ -16183,9 +16267,9 @@ int Client::_symlink(Inode *dir, const char *name, const char *target, } ldout(cct, 25) << "encrypted symlink is: " << binstrprint(enc_target) << dendl; req->set_string2(enc_target.c_str()); - } else { + } else +#endif req->set_string2(target); - } req->set_inode_owner_uid_gid(perms.uid(), perms.gid()); @@ -16390,6 +16474,7 @@ int Client::ll_rmdir(Inode *in, const char *name, const UserPerm& perms) return _rmdir(in, name, perms); } +#if defined(__linux__) int Client::get_keyhandler(FSCryptContextRef fscrypt_ctx, FSCryptKeyHandlerRef& kh){ if (fscrypt_ctx) { int r = fscrypt->get_key_store().find(fscrypt_ctx->master_key_identifier, kh); @@ -16417,7 +16502,7 @@ bool Client::is_inode_locked(const InodeRef& to_check) } return false; } - +#endif int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const char *toname, const UserPerm& perm, std::string alternate_name) { ldout(cct, 8) << "_rename(" << fromdir->ino << " " << fromname << " to " @@ -16454,11 +16539,12 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch return -EINVAL; } +#if defined(__linux__) bool source_locked = is_inode_locked(wdr_from.diri); bool dest_locked = is_inode_locked(wdr_to.diri); if (source_locked || dest_locked) return -ENOKEY; - +#endif if (wdr_from.diri->snapid != wdr_to.diri->snapid) return -EXDEV; @@ -16496,8 +16582,9 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch req->set_filepath(wdr_to.getpath()); req->set_filepath2(wdr_from.getpath()); req->set_alternate_name(alternate_name.empty() ? wdr_to.alternate_name : alternate_name); +#if defined(__linux__) wdr_to.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth); - +#endif int res; if (op == CEPH_MDS_OP_RENAME) { req->set_old_dentry(wdr_from.dn); @@ -16607,7 +16694,9 @@ int Client::_link(Inode *diri_from, const char* path_from, Inode* diri_to, const req->set_filepath(wdr_to.getpath()); req->set_alternate_name(alternate_name.empty() ? wdr_to.alternate_name : alternate_name); +#if defined(__linux__) wdr_to.diri->gen_inherited_fscrypt_auth(&req->fscrypt_auth); +#endif req->set_filepath2(wdr_from.getpath()); req->set_inode(wdr_to.diri); req->inode_drop = CEPH_CAP_FILE_SHARED; @@ -17482,7 +17571,9 @@ int Client::_fallocate(Fh *fh, int mode, int64_t offset, int64_t length) if (size > in->effective_size()) { if (in->is_fscrypt_enabled()) { in->set_effective_size(size); +#if defined(__linux__) size = fscrypt_next_block_start(size); +#endif } in->size = size; in->mtime = in->ctime = ceph_clock_now(); @@ -18370,6 +18461,7 @@ void Client::set_uuid(const std::string& uuid) _close_sessions(); } +#if defined(__linux__) int Client::add_fscrypt_key(const char *key_data, int key_len, char* keyid, int user) { @@ -18387,7 +18479,6 @@ int Client::add_fscrypt_key(const char *key_data, int key_len, if (keyid) { memcpy(keyid, &k->get_identifier().raw, FSCRYPT_KEY_IDENTIFIER_SIZE); } - return 0; } @@ -18399,7 +18490,6 @@ int Client::remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user) if (kid->removal_status_flags & (FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY == 0)) { sync_fs(); } - return r; } @@ -18429,7 +18519,6 @@ int Client::_is_empty_directory(Inode *in, const UserPerm& perms) return r; } - int Client::ll_set_fscrypt_policy_v2(Inode *in, const struct fscrypt_policy_v2& policy) { UserPerm perms(in->uid, in->gid); @@ -18502,7 +18591,6 @@ int Client::ll_get_fscrypt_policy_v2(Inode *in, struct fscrypt_policy_v2* policy } return -ENODATA; } - int Client::is_encrypted(int fd, UserPerm& perms, char* enctag) { Fh *f = get_filehandle(fd); @@ -18574,7 +18662,7 @@ out: arg->user_count = user_count; return 0; } - +#endif // called before mount. 0 means infinite void Client::set_session_timeout(unsigned timeout) { diff --git a/src/client/Client.h b/src/client/Client.h index 14e61830b7784..42459f40a5998 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -46,7 +46,10 @@ #include "InodeRef.h" #include "MetaSession.h" #include "UserPerm.h" + +#if defined(__linux__) #include "FSCrypt.h" +#endif #include #include @@ -382,15 +385,16 @@ public: } /* fscrypt */ +#if defined(__linux__) int add_fscrypt_key(const char *key_data, int key_len, char* keyid, int user = 0); int remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user = 0); int get_fscrypt_key_status(fscrypt_get_key_status_arg* arg); - 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); int get_fscrypt_policy_v2(int fd, struct fscrypt_policy_v2* policy); int is_encrypted(int fd, UserPerm& perms, char* enctag); +#endif + int fcopyfile(const char *sname, const char *dname, UserPerm& perms, mode_t mode); int mds_command( const std::string &mds_spec, @@ -751,10 +755,11 @@ public: bool ll_handle_umask() { return acl_type != NO_ACL; } - +#if defined(__linux__) int ll_set_fscrypt_policy_v2(Inode *in, const struct fscrypt_policy_v2& policy); int ll_get_fscrypt_policy_v2(Inode *in, struct fscrypt_policy_v2* policy); int ll_is_encrypted(Inode *in, UserPerm& perms, char* enctag); +#endif int ll_get_stripe_osd(struct Inode *in, uint64_t blockno, file_layout_t* layout); @@ -1033,9 +1038,9 @@ public: std::unique_ptr logger; std::unique_ptr mdsmap; - +#if defined(__linux__) std::unique_ptr fscrypt; - +#endif bool _collect_and_send_global_metrics; @@ -1494,8 +1499,9 @@ private: } void start(); +#if defined(__linux__) FSCryptFDataDencRef fscrypt_denc; - +#endif private: Client *clnt; Context *onfinish; @@ -1532,11 +1538,17 @@ private: C_Read_Async_Finisher(Client *clnt, Context *onfinish, Fh *f, Inode *in, bufferlist *bl, uint64_t fpos, uint64_t off, uint64_t len, +#if defined(__linux__) FSCryptFDataDencRef denc, - uint64_t read_start, +#endif + uint64_t read_start, uint64_t read_len) : clnt(clnt), onfinish(onfinish), f(f), in(in), bl(bl), off(off), len(len), - start_time(mono_clock_now()), denc(denc), read_start(read_start), read_len(read_len) {} + start_time(mono_clock_now()), +#if defined(__linux__) + denc(denc), +#endif + read_start(read_start), read_len(read_len) {} private: Client *clnt; @@ -1548,7 +1560,9 @@ private: uint64_t len; utime_t start_time; +#if defined(__linux__) FSCryptFDataDencRef denc; +#endif uint64_t read_start; uint64_t read_len; @@ -1701,8 +1715,9 @@ private: client_t const whoami; CephContext *cct; +#if defined(__linux__) FSCrypt *fscrypt; - +#endif ceph::mutex lock = ceph::make_mutex("Client::WriteEncMgr"); Fh *f; @@ -1719,8 +1734,9 @@ private: bool async; +#if defined(__linux__) FSCryptFDataDencRef denc; - +#endif uint64_t start_block; uint64_t start_block_ofs; uint64_t ofs_in_start_block; @@ -1782,7 +1798,11 @@ private: } bool encrypted() const { +#if defined(__linux__) return !!denc; +#else + return 0; +#endif } int read_modify_write(Context *iofinish); @@ -2068,8 +2088,10 @@ private: int _link(Inode *diri_from, const char* path_from, Inode* diri_to, const char* path_to, const UserPerm& perm, std::string alternate_name); int _unlink(Inode *dir, const char *name, const UserPerm& perm); +#if defined(__linux__) int get_keyhandler(FSCryptContextRef fscrypt_ctx, FSCryptKeyHandlerRef& kh); bool is_inode_locked(const InodeRef& to_check); +#endif int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm, std::string alternate_name); int _mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& perm, InodeRef *inp = 0, const std::map &metadata={}, diff --git a/src/client/FSCrypt.cc b/src/client/FSCrypt.cc index 090f97af17f3a..85cda61e566e0 100644 --- a/src/client/FSCrypt.cc +++ b/src/client/FSCrypt.cc @@ -33,6 +33,7 @@ #define dout_subsys ceph_subsys_client +#if defined(__linux__) using ceph::crypto::HMACSHA512; /* * base64 encode/decode. @@ -1160,3 +1161,4 @@ void FSCrypt::prepare_data_read(const FSCryptContextRef& ctx, } *read_len = end - *read_start; } +#endif diff --git a/src/client/FSCrypt.h b/src/client/FSCrypt.h index 97baee7fdb543..b13ec4dbf4f0a 100644 --- a/src/client/FSCrypt.h +++ b/src/client/FSCrypt.h @@ -1,3 +1,5 @@ + +#if defined(__linux__) #pragma once #include "fscrypt_uapi.h" @@ -140,7 +142,6 @@ public: return true; } - void init(const struct fscrypt_policy_v2& policy) { version = policy.version; contents_encryption_mode = policy.contents_encryption_mode; @@ -424,3 +425,4 @@ public: uint64_t *read_len, FSCryptFDataDencRef *denc); }; +#endif diff --git a/src/client/Inode.cc b/src/client/Inode.cc index 04c88f54a7a16..7bdba8ed99a13 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -344,10 +344,12 @@ int Inode::caps_file_wanted() if (cnt) { want |= ceph_caps_for_mode(mode); +#if defined(__linux__) //want Fr cap during fscrypt rmw if ((mode == CEPH_FILE_MODE_WR) && fscrypt_ctx) { want |= CEPH_CAP_FILE_RD; } +#endif } return want; } @@ -851,6 +853,7 @@ void Inode::mark_caps_clean() dirty_cap_item.remove_myself(); } +#if defined(__linux__) FSCryptContextRef Inode::init_fscrypt_ctx(FSCrypt *fscrypt) { return fscrypt->init_ctx(fscrypt_auth); @@ -873,7 +876,7 @@ void Inode::gen_inherited_fscrypt_auth(std::vector *fsa) fsa->resize(bl.length()); memcpy(fsa->data(), bl.c_str(), bl.length()); } - +#endif uint64_t Inode::effective_size() const { if (fscrypt_file.size() < sizeof(uint64_t) || !client->get_fscrypt_as()) { diff --git a/src/client/Inode.h b/src/client/Inode.h index fc70ce3a662a1..b563111d796ff 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -179,10 +179,10 @@ struct Inode : RefCountedObject { decltype(InodeStat::optmetadata) optmetadata; using optkind_t = decltype(InodeStat::optmetadata)::optkind_t; - +#if defined(__linux__) FSCryptContextRef fscrypt_ctx; FSCryptKeyValidatorRef fscrypt_key_validator; - +#endif uint64_t effective_size() const; void set_effective_size(uint64_t size); @@ -192,11 +192,12 @@ struct Inode : RefCountedObject { bool is_fscrypt_enabled() { return !!fscrypt_auth.size(); } +#if defined(__linux__) FSCryptContextRef init_fscrypt_ctx(FSCrypt *fscrypt); void gen_inherited_fscrypt_auth(std::vector *ctx); - +#endif bool is_root() const { return ino == CEPH_INO_ROOT; } bool is_symlink() const { return (mode & S_IFMT) == S_IFLNK; } bool is_dir() const { return (mode & S_IFMT) == S_IFDIR; } diff --git a/src/client/fscrypt_uapi.h b/src/client/fscrypt_uapi.h index 507115a72513d..4ab670a97614c 100644 --- a/src/client/fscrypt_uapi.h +++ b/src/client/fscrypt_uapi.h @@ -7,6 +7,8 @@ */ #ifndef _UAPI_LINUX_FSCRYPT_H #define _UAPI_LINUX_FSCRYPT_H +#if defined(__linux__) + #include struct fscrypt_policy_arg { @@ -29,3 +31,4 @@ struct fscrypt_add_key64_arg { #define FS_IOC_GET_ENCRYPTION_POLICY_EX_RESTRICTED _IOWR('f', 22, struct fscrypt_get_policy_ex_arg) /* size + version */ #define FS_IOC_ADD_ENCRYPTION_KEY64 _IOWR('f', 23, struct fscrypt_add_key64_arg) #endif +#endif diff --git a/src/client/fuse_ll.cc b/src/client/fuse_ll.cc index 1b1e51106d941..45a4deb45f532 100644 --- a/src/client/fuse_ll.cc +++ b/src/client/fuse_ll.cc @@ -960,6 +960,7 @@ static void fuse_ll_ioctl(fuse_req_t req, fuse_ino_t ino, fuse_reply_ioctl(req, 0, &l, sizeof(struct ceph_ioctl_layout)); } break; +#if defined(__linux__) case FS_IOC_GET_ENCRYPTION_POLICY_EX_RESTRICTED: case FS_IOC_GET_ENCRYPTION_POLICY_EX: { generic_dout(10) << __FILE__ << ":" << __LINE__ << ": in_bufsz=" << in_bufsz << " out_bufsz=" << out_bufsz << dendl; @@ -1128,6 +1129,7 @@ static void fuse_ll_ioctl(fuse_req_t req, fuse_ino_t ino, fuse_reply_ioctl(req, 0, arg, sizeof(*arg)); } break; +#endif default: fuse_reply_err(req, EINVAL); } diff --git a/src/libcephfs.cc b/src/libcephfs.cc index e80976de25524..0eeddd7167e02 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -2503,7 +2503,7 @@ extern "C" void ceph_finish_reclaim(class ceph_mount_info *cmount) { cmount->get_client()->finish_reclaim(); } - +#if defined(__linux__) extern "C" int ceph_add_fscrypt_key(struct ceph_mount_info *cmount, const char *key_data, int key_len, char* out_keyid, @@ -2587,7 +2587,7 @@ extern "C" int ceph_ll_is_encrypted(struct ceph_mount_info *cmount, return cmount->get_client()->ll_is_encrypted(in, cmount->default_perms, enctag); } - +#endif // This is deprecated, use ceph_ll_register_callbacks2 instead. extern "C" void ceph_ll_register_callbacks(class ceph_mount_info *cmount, struct ceph_client_callback_args *args) diff --git a/src/test/client/TestClient.h b/src/test/client/TestClient.h index 4e0fd6c103574..ad79baa6186fd 100644 --- a/src/test/client/TestClient.h +++ b/src/test/client/TestClient.h @@ -127,7 +127,7 @@ public: int walk(std::string_view path, struct walk_dentry_result* result, const UserPerm& perms, bool followsym=true) { return Client::walk(path, result, perms, followsym); } - +#if defined(__linux__) bool encrypt(const UserPerm& myperm) { if (!fscrypt_enabled || fse->encrypted) { return false; @@ -198,7 +198,7 @@ public: return true; } - +#endif int do_mount(const std::string &mount_root, const UserPerm& perms, bool require_mds=false, const std::string &fs_name="") { int r; @@ -214,14 +214,14 @@ public: std::clog << __func__ << "() do_mount r=" << r << std::endl; return r; } - +#if defined(__linux__) char keyid[FSCRYPT_KEY_IDENTIFIER_SIZE]; r = add_fscrypt_key(fse->key, sizeof(fse->key), keyid); if (r < 0) { std::clog << __func__ << "() ceph_mount add_fscrypt_key r=" << r << std::endl; return r; } - +#endif return 0; } }; @@ -235,7 +235,7 @@ public: static void TearDownTestSuite() { icp.stop(); } - +#if defined(__linux__) bool encrypt() { bool encrypted = client->encrypt(myperm); if (encrypted) { @@ -244,7 +244,7 @@ public: } return encrypted; } - +#endif void SetUp() override { messenger = Messenger::create_client_messenger(g_ceph_context, "client"); if (messenger->start() != 0) { @@ -266,12 +266,14 @@ public: objecter->init(); messenger->add_dispatcher_tail(objecter); objecter->start(); - +#if defined(__linux__) do { +#endif client = new ClientScaffold(messenger, mc, objecter, &fse); client->init(); +#if defined(__linux__) } while (encrypt()); - +#endif client->do_mount("/", myperm, true); } void TearDown() override { diff --git a/src/test/libcephfs/fscrypt.cc b/src/test/libcephfs/fscrypt.cc index 5534dea95f0d7..d97d89e31fcc0 100644 --- a/src/test/libcephfs/fscrypt.cc +++ b/src/test/libcephfs/fscrypt.cc @@ -45,7 +45,7 @@ using namespace std; rados_t cluster; - +#if defined(__linux__) static string fscrypt_dir; static char fscrypt_key[32]; @@ -1152,13 +1152,16 @@ TEST(FSCrypt, FSCryptDummyEncryptionNoExistingRegularPolicy) { ceph_shutdown(cmount); } +#endif int main(int argc, char **argv) { - int r = update_root_mode(); + int r; +#if defined(__linux__) + r = update_root_mode(); if (r < 0) exit(1); - +#endif ::testing::InitGoogleTest(&argc, argv); srand(getpid()); @@ -1176,10 +1179,11 @@ int main(int argc, char **argv) if (r < 0) exit(1); +#if defined(__linux__) r = init_fscrypt(); if (r < 0) exit(1); - +#endif r = RUN_ALL_TESTS(); rados_shutdown(cluster); diff --git a/src/test/libcephfs/test.cc b/src/test/libcephfs/test.cc index fc1d177ecf4e6..b79c10320909d 100644 --- a/src/test/libcephfs/test.cc +++ b/src/test/libcephfs/test.cc @@ -3820,6 +3820,7 @@ TEST(LibCephFS, SetMountTimeout) { ceph_shutdown(cmount); } +#if defined(__linux__) TEST(LibCephFS, FsCrypt) { struct ceph_mount_info *cmount; ASSERT_EQ(ceph_create(&cmount, NULL), 0); @@ -3871,6 +3872,7 @@ TEST(LibCephFS, EncTag) { ASSERT_EQ(0, ceph_fsetxattr(cmount, fd, "user.ceph.subvolume.enctag", enctagbuf, sizeof(enctagbuf), CEPH_XATTR_CREATE)); char enctagread[4]; + ASSERT_EQ(1, ceph_is_encrypted(cmount, fd, enctagread)); ASSERT_EQ(0, strcmp(enctagbuf, enctagread)); ASSERT_EQ(0, ceph_close(cmount, fd)); @@ -3878,7 +3880,7 @@ TEST(LibCephFS, EncTag) { ASSERT_EQ(0, ceph_unmount(cmount)); ceph_shutdown(cmount); } - +#endif TEST(LibCephFS, SnapdirAttrs) { struct ceph_mount_info *cmount; ASSERT_EQ(ceph_create(&cmount, NULL), 0); -- 2.39.5