/* Get the inode number */
inode_number = name_end + 1;
ret = kstrtou64(inode_number, 10, &vino.ino); if (ret) {
doutc(cl, "failed to parse inode number: %s\n", str); return ERR_PTR(ret);
}
/* And finally the inode */
dir = ceph_find_inode(parent->i_sb, vino); if (!dir) { /* This can happen if we're not mounting cephfs on the root */
dir = ceph_get_inode(parent->i_sb, vino, NULL); if (IS_ERR(dir))
doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
} return dir;
}
int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int elen)
{ struct ceph_client *cl = ceph_inode_to_client(parent); struct inode *dir = parent; char *p = buf;
u32 len; int name_len = elen; int ret;
u8 *cryptbuf = NULL;
/* Handle the special case of snapshot names that start with '_' */ if (ceph_snap(dir) == CEPH_SNAPDIR && *p == '_') {
dir = parse_longname(parent, p, &name_len); if (IS_ERR(dir)) return PTR_ERR(dir);
p++; /* skip initial '_' */
}
/* Allocate a buffer appropriate to hold the result */
cryptbuf = kmalloc(len > CEPH_NOHASH_NAME_MAX ? NAME_MAX : len,
GFP_KERNEL); if (!cryptbuf) {
elen = -ENOMEM; goto out;
}
ret = fscrypt_fname_encrypt(dir,
&(struct qstr)QSTR_INIT(p, name_len),
cryptbuf, len); if (ret) {
elen = ret; goto out;
}
/* hash the end if the name is long enough */ if (len > CEPH_NOHASH_NAME_MAX) {
u8 hash[SHA256_DIGEST_SIZE];
u8 *extra = cryptbuf + CEPH_NOHASH_NAME_MAX;
/* *hashtheextrabytesandoverwritecrypttextbeyondthat *pointwithit
*/
sha256(extra, len - CEPH_NOHASH_NAME_MAX, hash);
memcpy(extra, hash, SHA256_DIGEST_SIZE);
len = CEPH_NOHASH_NAME_MAX + SHA256_DIGEST_SIZE;
}
/* base64 encode the encrypted name */
elen = ceph_base64_encode(cryptbuf, len, p);
doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, p);
/* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */
WARN_ON(elen > 240); if (dir != parent) // leading _ is already there; append _<inum>
elen += 1 + sprintf(p + elen, "_%ld", dir->i_ino);
out:
kfree(cryptbuf); if (dir != parent) { if ((dir->i_state & I_NEW))
discard_new_inode(dir); else
iput(dir);
} return elen;
}
/* Sanity check that the resulting name will fit in the buffer */ if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX) return -EIO;
/* Handle the special case of snapshot names that start with '_' */ if ((ceph_snap(dir) == CEPH_SNAPDIR) && (name_len > 0) &&
(name[0] == '_')) {
dir = parse_longname(dir, name, &name_len); if (IS_ERR(dir)) return PTR_ERR(dir);
name++; /* skip initial '_' */
}
if (!IS_ENCRYPTED(dir)) {
oname->name = fname->name;
oname->len = fname->name_len;
ret = 0; goto out_inode;
}
ret = ceph_fscrypt_prepare_readdir(dir); if (ret) goto out_inode;
/* *UsetherawdentrynameassentbytheMDSinsteadof *generatinganokeynameviafscrypt.
*/ if (!fscrypt_has_encryption_key(dir)) { if (fname->no_copy)
oname->name = fname->name; else
memcpy(oname->name, fname->name, fname->name_len);
oname->len = fname->name_len; if (is_nokey)
*is_nokey = true;
ret = 0; goto out_inode;
}
if (fname->ctext_len == 0) { int declen;
if (!tname) {
ret = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname); if (ret) goto out_inode;
tname = &_tname;
}
err = __fscrypt_prepare_readdir(dir); if (err) return err; if (!had_key && fscrypt_has_encryption_key(dir)) { /* directory just got unlocked, mark it as not complete */
ceph_dir_clear_complete(dir); return1;
} return0;
}
/** *ceph_fscrypt_decrypt_pages-decryptanarrayofpages *@inode:pointertoinodeassociatedwiththesepages *@page:pointertopagearray *@off:offsetintothefilethatthereaddatastarts *@len:maxlengthtodecrypt * *Decryptanarrayoffscrypt'edpagesandreturntheamountof *datadecrypted.Anydatainthepagepriortothestartofthe *firstcompleteblockinthereadisignored.Anyincomplete *cryptoblocksattheendofthearrayareignored(andshould *probablybezeroedbythecaller). * *Returnsthelengthofthedecrypteddataoranegativeerrno.
*/ int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page,
u64 off, int len)
{ int i, num_blocks;
u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT; int ret = 0;
/* *Wecan'tdealwithpartialblocksonanencryptedfile,somaskoff *thelastbit.
*/
num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK);
/* Decrypt each block */ for (i = 0; i < num_blocks; ++i) { int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT; int pgidx = blkoff >> PAGE_SHIFT; unsignedint pgoffs = offset_in_page(blkoff); int fret;
fret = ceph_fscrypt_decrypt_block_inplace(inode, page[pgidx],
CEPH_FSCRYPT_BLOCK_SIZE, pgoffs,
baseblk + i); if (fret < 0) { if (ret == 0)
ret = fret; break;
}
ret += CEPH_FSCRYPT_BLOCK_SIZE;
} return ret;
}
for (i = 0; i < ext_cnt; ++i) { struct ceph_sparse_extent *ext = &map[i]; int pgsoff = ext->off - objoff; int pgidx = pgsoff >> PAGE_SHIFT; int fret;
if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) {
pr_warn_client(cl, "%p %llx.%llx bad encrypted sparse extent " "idx %d off %llx len %llx\n",
inode, ceph_vinop(inode), i, ext->off,
ext->len); return -EIO;
}
fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx],
off + pgsoff, ext->len);
doutc(cl, "%p %llx.%llx [%d] 0x%llx~0x%llx fret %d\n", inode,
ceph_vinop(inode), i, ext->off, ext->len, fret); if (fret < 0) { if (ret == 0)
ret = fret; break;
}
ret = pgsoff + fret;
}
doutc(cl, "ret %d\n", ret); return ret;
}
/** *ceph_fscrypt_encrypt_pages-encryptanarrayofpages *@inode:pointertoinodeassociatedwiththesepages *@page:pointertopagearray *@off:offsetintothefilethatthedatastarts *@len:maxlengthtoencrypt * *Encryptanarrayofcleartextpagesandreturntheamountof *dataencrypted.Anydatainthepagepriortothestartofthe *firstcompleteblockinthereadisignored.Anyincomplete *cryptoblocksattheendofthearrayareignored. * *Returnsthelengthoftheencrypteddataoranegativeerrno.
*/ int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off, int len)
{ int i, num_blocks;
u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT; int ret = 0;
/* *Wecan'tdealwithpartialblocksonanencryptedfile,somaskoff *thelastbit.
*/
num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK);
/* Encrypt each block */ for (i = 0; i < num_blocks; ++i) { int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT; int pgidx = blkoff >> PAGE_SHIFT; unsignedint pgoffs = offset_in_page(blkoff); int fret;
fret = ceph_fscrypt_encrypt_block_inplace(inode, page[pgidx],
CEPH_FSCRYPT_BLOCK_SIZE, pgoffs,
baseblk + i); if (fret < 0) { if (ret == 0)
ret = fret; break;
}
ret += CEPH_FSCRYPT_BLOCK_SIZE;
} return ret;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.