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

fscrypt: export fscrypt_fname_encrypt and fscrypt_fname_encrypted_size

For ceph, we want to use our own scheme for handling filenames that are
are longer than NAME_MAX after encryption and Base64 encoding. This
allows us to have a consistent view of the encrypted filenames for
clients that don't support fscrypt and clients that do but that don't
have the key.

Currently, fs/crypto only supports encrypting filenames using
fscrypt_setup_filename, but that also handles encoding nokey names. Ceph
can't use that because it handles nokey names in a different way.

Export fscrypt_fname_encrypt. Rename fscrypt_fname_encrypted_size to
__fscrypt_fname_encrypted_size and add a new wrapper called
fscrypt_fname_encrypted_size that takes an inode argument rather than a
pointer to a fscrypt_policy union.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Acked-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Jeff Layton and committed by
Ilya Dryomov
d3e94fdc 18cc912b

+40 -15
+30 -6
fs/crypto/fname.c
··· 86 86 /** 87 87 * fscrypt_fname_encrypt() - encrypt a filename 88 88 * @inode: inode of the parent directory (for regular filenames) 89 - * or of the symlink (for symlink targets) 89 + * or of the symlink (for symlink targets). Key must already be 90 + * set up. 90 91 * @iname: the filename to encrypt 91 92 * @out: (output) the encrypted filename 92 93 * @olen: size of the encrypted filename. It must be at least @iname->len. ··· 138 137 139 138 return 0; 140 139 } 140 + EXPORT_SYMBOL_GPL(fscrypt_fname_encrypt); 141 141 142 142 /** 143 143 * fname_decrypt() - decrypt a filename ··· 266 264 return bp - dst; 267 265 } 268 266 269 - bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy, 270 - u32 orig_len, u32 max_len, 271 - u32 *encrypted_len_ret) 267 + bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy, 268 + u32 orig_len, u32 max_len, 269 + u32 *encrypted_len_ret) 272 270 { 273 271 int padding = 4 << (fscrypt_policy_flags(policy) & 274 272 FSCRYPT_POLICY_FLAGS_PAD_MASK); ··· 281 279 *encrypted_len_ret = min(encrypted_len, max_len); 282 280 return true; 283 281 } 282 + 283 + /** 284 + * fscrypt_fname_encrypted_size() - calculate length of encrypted filename 285 + * @inode: parent inode of dentry name being encrypted. Key must 286 + * already be set up. 287 + * @orig_len: length of the original filename 288 + * @max_len: maximum length to return 289 + * @encrypted_len_ret: where calculated length should be returned (on success) 290 + * 291 + * Filenames that are shorter than the maximum length may have their lengths 292 + * increased slightly by encryption, due to padding that is applied. 293 + * 294 + * Return: false if the orig_len is greater than max_len. Otherwise, true and 295 + * fill out encrypted_len_ret with the length (up to max_len). 296 + */ 297 + bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, 298 + u32 max_len, u32 *encrypted_len_ret) 299 + { 300 + return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy, 301 + orig_len, max_len, 302 + encrypted_len_ret); 303 + } 304 + EXPORT_SYMBOL_GPL(fscrypt_fname_encrypted_size); 284 305 285 306 /** 286 307 * fscrypt_fname_alloc_buffer() - allocate a buffer for presented filenames ··· 460 435 return ret; 461 436 462 437 if (fscrypt_has_encryption_key(dir)) { 463 - if (!fscrypt_fname_encrypted_size(&dir->i_crypt_info->ci_policy, 464 - iname->len, NAME_MAX, 438 + if (!fscrypt_fname_encrypted_size(dir, iname->len, NAME_MAX, 465 439 &fname->crypto_buf.len)) 466 440 return -ENAMETOOLONG; 467 441 fname->crypto_buf.name = kmalloc(fname->crypto_buf.len,
+3 -6
fs/crypto/fscrypt_private.h
··· 297 297 const struct fscrypt_info *ci); 298 298 299 299 /* fname.c */ 300 - int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, 301 - u8 *out, unsigned int olen); 302 - bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy, 303 - u32 orig_len, u32 max_len, 304 - u32 *encrypted_len_ret); 300 + bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy, 301 + u32 orig_len, u32 max_len, 302 + u32 *encrypted_len_ret); 305 303 306 304 /* hkdf.c */ 307 - 308 305 struct fscrypt_hkdf { 309 306 struct crypto_shash *hmac_tfm; 310 307 };
+3 -3
fs/crypto/hooks.c
··· 228 228 * counting it (even though it is meaningless for ciphertext) is simpler 229 229 * for now since filesystems will assume it is there and subtract it. 230 230 */ 231 - if (!fscrypt_fname_encrypted_size(policy, len, 232 - max_len - sizeof(struct fscrypt_symlink_data), 233 - &disk_link->len)) 231 + if (!__fscrypt_fname_encrypted_size(policy, len, 232 + max_len - sizeof(struct fscrypt_symlink_data), 233 + &disk_link->len)) 234 234 return -ENAMETOOLONG; 235 235 disk_link->len += sizeof(struct fscrypt_symlink_data); 236 236
+4
include/linux/fscrypt.h
··· 327 327 int fscrypt_drop_inode(struct inode *inode); 328 328 329 329 /* fname.c */ 330 + int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, 331 + u8 *out, unsigned int olen); 332 + bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, 333 + u32 max_len, u32 *encrypted_len_ret); 330 334 int fscrypt_setup_filename(struct inode *inode, const struct qstr *iname, 331 335 int lookup, struct fscrypt_name *fname); 332 336