diff options
author | Theodore Ts'o <tytso@mit.edu> | 2015-05-31 13:35:22 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2015-05-31 13:35:22 -0400 |
commit | 82d0d3e7e69ab509b5c91b61f12bd3593a7c6dcb (patch) | |
tree | 3fc181cfc0c02ca2a1236ebefeb8fe6733ade2cb /fs/ext4 | |
parent | d87f6d78e996bbba27b649c0e0eed7a37d6b73ba (diff) | |
download | linux-exynos-82d0d3e7e69ab509b5c91b61f12bd3593a7c6dcb.tar.gz linux-exynos-82d0d3e7e69ab509b5c91b61f12bd3593a7c6dcb.tar.bz2 linux-exynos-82d0d3e7e69ab509b5c91b61f12bd3593a7c6dcb.zip |
ext4 crypto: clean up error handling in ext4_fname_setup_filename
Fix a potential memory leak where fname->crypto_buf.name wouldn't get
freed in some error paths, and also make the error handling easier to
understand/audit.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/crypto_fname.c | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index 29a2dc9a6f82..23af41f73e90 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c @@ -401,7 +401,7 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname, ((iname->name[1] == '.') && (iname->len == 2))))) { fname->disk_name.name = (unsigned char *) iname->name; fname->disk_name.len = iname->len; - goto out; + return 0; } ret = ext4_get_encryption_info(dir); if (ret) @@ -411,19 +411,16 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname, ret = ext4_fname_crypto_alloc_buffer(dir, iname->len, &fname->crypto_buf); if (ret < 0) - goto out; + return ret; ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf); if (ret < 0) - goto out; + goto errout; fname->disk_name.name = fname->crypto_buf.name; fname->disk_name.len = fname->crypto_buf.len; - ret = 0; - goto out; - } - if (!lookup) { - ret = -EACCES; - goto out; + return 0; } + if (!lookup) + return -EACCES; /* We don't have the key and we are doing a lookup; decode the * user-supplied name @@ -431,19 +428,17 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname, if (iname->name[0] == '_') bigname = 1; if ((bigname && (iname->len != 33)) || - (!bigname && (iname->len > 43))) { - ret = -ENOENT; - } + (!bigname && (iname->len > 43))) + return -ENOENT; + fname->crypto_buf.name = kmalloc(32, GFP_KERNEL); - if (fname->crypto_buf.name == NULL) { - ret = -ENOMEM; - goto out; - } + if (fname->crypto_buf.name == NULL) + return -ENOMEM; ret = digest_decode(iname->name + bigname, iname->len - bigname, fname->crypto_buf.name); if (ret < 0) { ret = -ENOENT; - goto out; + goto errout; } fname->crypto_buf.len = ret; if (bigname) { @@ -453,8 +448,10 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname, fname->disk_name.name = fname->crypto_buf.name; fname->disk_name.len = fname->crypto_buf.len; } - ret = 0; -out: + return 0; +errout: + kfree(fname->crypto_buf.name); + fname->crypto_buf.name = NULL; return ret; } |