fscrypto: make filename crypto functions return 0 on success

Several filename crypto functions: fname_decrypt(),
fscrypt_fname_disk_to_usr(), and fscrypt_fname_usr_to_disk(), returned
the output length on success or -errno on failure.  However, the output
length was redundant with the value written to 'oname->len'.  It is also
potentially error-prone to make callers have to check for '< 0' instead
of '!= 0'.

Therefore, make these functions return 0 instead of a length, and make
the callers who cared about the return value being a length use
'oname->len' instead.  For consistency also make other callers check for
a nonzero result rather than a negative result.

This change also fixes the inconsistency of fname_encrypt() actually
already returning 0 on success, not a length like the other filename
crypto functions and as documented in its function comment.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Acked-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Eric Biggers 2016-09-15 17:25:55 -04:00 committed by Theodore Ts'o
parent 53fd7550ec
commit ef1eb3aa50
6 changed files with 47 additions and 39 deletions

View File

@ -35,11 +35,11 @@ static void fname_crypt_complete(struct crypto_async_request *req, int res)
} }
/** /**
* fname_encrypt() - * fname_encrypt() - encrypt a filename
* *
* This function encrypts the input filename, and returns the length of the * The caller must have allocated sufficient memory for the @oname string.
* ciphertext. Errors are returned as negative numbers. We trust the caller to *
* allocate sufficient memory to oname string. * Return: 0 on success, -errno on failure
*/ */
static int fname_encrypt(struct inode *inode, static int fname_encrypt(struct inode *inode,
const struct qstr *iname, struct fscrypt_str *oname) const struct qstr *iname, struct fscrypt_str *oname)
@ -105,20 +105,22 @@ static int fname_encrypt(struct inode *inode,
} }
kfree(alloc_buf); kfree(alloc_buf);
skcipher_request_free(req); skcipher_request_free(req);
if (res < 0) if (res < 0) {
printk_ratelimited(KERN_ERR printk_ratelimited(KERN_ERR
"%s: Error (error code %d)\n", __func__, res); "%s: Error (error code %d)\n", __func__, res);
return res;
}
oname->len = ciphertext_len; oname->len = ciphertext_len;
return res; return 0;
} }
/* /**
* fname_decrypt() * fname_decrypt() - decrypt a filename
* This function decrypts the input filename, and returns *
* the length of the plaintext. * The caller must have allocated sufficient memory for the @oname string.
* Errors are returned as negative numbers. *
* We trust the caller to allocate sufficient memory to oname string. * Return: 0 on success, -errno on failure
*/ */
static int fname_decrypt(struct inode *inode, static int fname_decrypt(struct inode *inode,
const struct fscrypt_str *iname, const struct fscrypt_str *iname,
@ -168,7 +170,7 @@ static int fname_decrypt(struct inode *inode,
} }
oname->len = strnlen(oname->name, iname->len); oname->len = strnlen(oname->name, iname->len);
return oname->len; return 0;
} }
static const char *lookup_table = static const char *lookup_table =
@ -279,6 +281,10 @@ EXPORT_SYMBOL(fscrypt_fname_free_buffer);
/** /**
* fscrypt_fname_disk_to_usr() - converts a filename from disk space to user * fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
* space * space
*
* The caller must have allocated sufficient memory for the @oname string.
*
* Return: 0 on success, -errno on failure
*/ */
int fscrypt_fname_disk_to_usr(struct inode *inode, int fscrypt_fname_disk_to_usr(struct inode *inode,
u32 hash, u32 minor_hash, u32 hash, u32 minor_hash,
@ -287,13 +293,12 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
{ {
const struct qstr qname = FSTR_TO_QSTR(iname); const struct qstr qname = FSTR_TO_QSTR(iname);
char buf[24]; char buf[24];
int ret;
if (fscrypt_is_dot_dotdot(&qname)) { if (fscrypt_is_dot_dotdot(&qname)) {
oname->name[0] = '.'; oname->name[0] = '.';
oname->name[iname->len - 1] = '.'; oname->name[iname->len - 1] = '.';
oname->len = iname->len; oname->len = iname->len;
return oname->len; return 0;
} }
if (iname->len < FS_CRYPTO_BLOCK_SIZE) if (iname->len < FS_CRYPTO_BLOCK_SIZE)
@ -303,9 +308,9 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
return fname_decrypt(inode, iname, oname); return fname_decrypt(inode, iname, oname);
if (iname->len <= FS_FNAME_CRYPTO_DIGEST_SIZE) { if (iname->len <= FS_FNAME_CRYPTO_DIGEST_SIZE) {
ret = digest_encode(iname->name, iname->len, oname->name); oname->len = digest_encode(iname->name, iname->len,
oname->len = ret; oname->name);
return ret; return 0;
} }
if (hash) { if (hash) {
memcpy(buf, &hash, 4); memcpy(buf, &hash, 4);
@ -315,15 +320,18 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
} }
memcpy(buf + 8, iname->name + iname->len - 16, 16); memcpy(buf + 8, iname->name + iname->len - 16, 16);
oname->name[0] = '_'; oname->name[0] = '_';
ret = digest_encode(buf, 24, oname->name + 1); oname->len = 1 + digest_encode(buf, 24, oname->name + 1);
oname->len = ret + 1; return 0;
return ret + 1;
} }
EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
/** /**
* fscrypt_fname_usr_to_disk() - converts a filename from user space to disk * fscrypt_fname_usr_to_disk() - converts a filename from user space to disk
* space * space
*
* The caller must have allocated sufficient memory for the @oname string.
*
* Return: 0 on success, -errno on failure
*/ */
int fscrypt_fname_usr_to_disk(struct inode *inode, int fscrypt_fname_usr_to_disk(struct inode *inode,
const struct qstr *iname, const struct qstr *iname,
@ -333,7 +341,7 @@ int fscrypt_fname_usr_to_disk(struct inode *inode,
oname->name[0] = '.'; oname->name[0] = '.';
oname->name[iname->len - 1] = '.'; oname->name[iname->len - 1] = '.';
oname->len = iname->len; oname->len = iname->len;
return oname->len; return 0;
} }
if (inode->i_crypt_info) if (inode->i_crypt_info)
return fname_encrypt(inode, iname, oname); return fname_encrypt(inode, iname, oname);
@ -367,10 +375,10 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
if (dir->i_crypt_info) { if (dir->i_crypt_info) {
ret = fscrypt_fname_alloc_buffer(dir, iname->len, ret = fscrypt_fname_alloc_buffer(dir, iname->len,
&fname->crypto_buf); &fname->crypto_buf);
if (ret < 0) if (ret)
return ret; return ret;
ret = fname_encrypt(dir, iname, &fname->crypto_buf); ret = fname_encrypt(dir, iname, &fname->crypto_buf);
if (ret < 0) if (ret)
goto errout; goto errout;
fname->disk_name.name = fname->crypto_buf.name; fname->disk_name.name = fname->crypto_buf.name;
fname->disk_name.len = fname->crypto_buf.len; fname->disk_name.len = fname->crypto_buf.len;

View File

@ -260,11 +260,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
/* Directory is encrypted */ /* Directory is encrypted */
err = fscrypt_fname_disk_to_usr(inode, err = fscrypt_fname_disk_to_usr(inode,
0, 0, &de_name, &fstr); 0, 0, &de_name, &fstr);
de_name = fstr;
fstr.len = save_len; fstr.len = save_len;
if (err < 0) if (err)
goto errout; goto errout;
if (!dir_emit(ctx, if (!dir_emit(ctx,
fstr.name, err, de_name.name, de_name.len,
le32_to_cpu(de->inode), le32_to_cpu(de->inode),
get_dtype(sb, de->file_type))) get_dtype(sb, de->file_type)))
goto done; goto done;

View File

@ -639,7 +639,7 @@ static struct stats dx_show_leaf(struct inode *dir,
res = fscrypt_fname_alloc_buffer( res = fscrypt_fname_alloc_buffer(
dir, len, dir, len,
&fname_crypto_str); &fname_crypto_str);
if (res < 0) if (res)
printk(KERN_WARNING "Error " printk(KERN_WARNING "Error "
"allocating crypto " "allocating crypto "
"buffer--skipping " "buffer--skipping "
@ -647,7 +647,7 @@ static struct stats dx_show_leaf(struct inode *dir,
res = fscrypt_fname_disk_to_usr(dir, res = fscrypt_fname_disk_to_usr(dir,
0, 0, &de_name, 0, 0, &de_name,
&fname_crypto_str); &fname_crypto_str);
if (res < 0) { if (res) {
printk(KERN_WARNING "Error " printk(KERN_WARNING "Error "
"converting filename " "converting filename "
"from disk to usr" "from disk to usr"
@ -1011,7 +1011,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
err = fscrypt_fname_disk_to_usr(dir, hinfo->hash, err = fscrypt_fname_disk_to_usr(dir, hinfo->hash,
hinfo->minor_hash, &de_name, hinfo->minor_hash, &de_name,
&fname_crypto_str); &fname_crypto_str);
if (err < 0) { if (err) {
count = err; count = err;
goto errout; goto errout;
} }
@ -3144,7 +3144,7 @@ static int ext4_symlink(struct inode *dir,
istr.name = (const unsigned char *) symname; istr.name = (const unsigned char *) symname;
istr.len = len; istr.len = len;
err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr); err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
if (err < 0) if (err)
goto err_drop_inode; goto err_drop_inode;
sd->len = cpu_to_le16(ostr.len); sd->len = cpu_to_le16(ostr.len);
disk_link.name = (char *) sd; disk_link.name = (char *) sd;

View File

@ -68,12 +68,11 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
paddr = pstr.name; paddr = pstr.name;
res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
if (res < 0) if (res)
goto errout; goto errout;
/* Null-terminate the name */ /* Null-terminate the name */
if (res <= pstr.len) paddr[pstr.len] = '\0';
paddr[res] = '\0';
if (cpage) if (cpage)
put_page(cpage); put_page(cpage);
set_delayed_call(done, kfree_link, paddr); set_delayed_call(done, kfree_link, paddr);

View File

@ -786,7 +786,7 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
if (f2fs_encrypted_inode(d->inode)) { if (f2fs_encrypted_inode(d->inode)) {
int save_len = fstr->len; int save_len = fstr->len;
int ret; int err;
de_name.name = f2fs_kmalloc(de_name.len, GFP_NOFS); de_name.name = f2fs_kmalloc(de_name.len, GFP_NOFS);
if (!de_name.name) if (!de_name.name)
@ -794,11 +794,11 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
memcpy(de_name.name, d->filename[bit_pos], de_name.len); memcpy(de_name.name, d->filename[bit_pos], de_name.len);
ret = fscrypt_fname_disk_to_usr(d->inode, err = fscrypt_fname_disk_to_usr(d->inode,
(u32)de->hash_code, 0, (u32)de->hash_code, 0,
&de_name, fstr); &de_name, fstr);
kfree(de_name.name); kfree(de_name.name);
if (ret < 0) if (err)
return true; return true;
de_name = *fstr; de_name = *fstr;

View File

@ -449,7 +449,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
ostr.name = sd->encrypted_path; ostr.name = sd->encrypted_path;
ostr.len = disk_link.len; ostr.len = disk_link.len;
err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr); err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
if (err < 0) if (err)
goto err_out; goto err_out;
sd->len = cpu_to_le16(ostr.len); sd->len = cpu_to_le16(ostr.len);
@ -1048,7 +1048,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
goto errout; goto errout;
res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
if (res < 0) if (res)
goto errout; goto errout;
/* this is broken symlink case */ /* this is broken symlink case */
@ -1060,7 +1060,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
paddr = pstr.name; paddr = pstr.name;
/* Null-terminate the name */ /* Null-terminate the name */
paddr[res] = '\0'; paddr[pstr.len] = '\0';
put_page(cpage); put_page(cpage);
set_delayed_call(done, kfree_link, paddr); set_delayed_call(done, kfree_link, paddr);