aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2008-02-06 04:38:37 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:13 -0500
commitaf440f52927e4b6941aa94e3cfc698adb0f22663 (patch)
tree00a7fdc2b09e8e6146f0fd0bc055688d58eea939 /fs/ecryptfs
parent19e66a67e9b25874cd5e184e7d381ce1b955df11 (diff)
ecryptfs: check for existing key_tfm at mount time
Jeff Moyer pointed out that a mount; umount loop of ecryptfs, with the same cipher & other mount options, created a new ecryptfs_key_tfm_cache item each time, and the cache could grow quite large this way. Looking at this with mhalcrow, we saw that ecryptfs_parse_options() unconditionally called ecryptfs_add_new_key_tfm(), which is what was adding these items. Refactor ecryptfs_get_tfm_and_mutex_for_cipher_name() to create a new helper function, ecryptfs_tfm_exists(), which checks for the cipher on the cached key_tfm_list, and sets a pointer to it if it exists. This can then be called from ecryptfs_parse_options(), and new key_tfm's can be added only when a cached one is not found. With list locking changes suggested by akpm. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Cc: Michael Halcrow <mhalcrow@us.ibm.com> Cc: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/crypto.c67
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h3
-rw-r--r--fs/ecryptfs/main.c10
3 files changed, 63 insertions, 17 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 40d14625f515..a066e109ad9c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1779,7 +1779,7 @@ out:
1779 1779
1780struct kmem_cache *ecryptfs_key_tfm_cache; 1780struct kmem_cache *ecryptfs_key_tfm_cache;
1781static struct list_head key_tfm_list; 1781static struct list_head key_tfm_list;
1782static struct mutex key_tfm_list_mutex; 1782struct mutex key_tfm_list_mutex;
1783 1783
1784int ecryptfs_init_crypto(void) 1784int ecryptfs_init_crypto(void)
1785{ 1785{
@@ -1788,6 +1788,11 @@ int ecryptfs_init_crypto(void)
1788 return 0; 1788 return 0;
1789} 1789}
1790 1790
1791/**
1792 * ecryptfs_destroy_crypto - free all cached key_tfms on key_tfm_list
1793 *
1794 * Called only at module unload time
1795 */
1791int ecryptfs_destroy_crypto(void) 1796int ecryptfs_destroy_crypto(void)
1792{ 1797{
1793 struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp; 1798 struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp;
@@ -1811,6 +1816,8 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
1811 struct ecryptfs_key_tfm *tmp_tfm; 1816 struct ecryptfs_key_tfm *tmp_tfm;
1812 int rc = 0; 1817 int rc = 0;
1813 1818
1819 BUG_ON(!mutex_is_locked(&key_tfm_list_mutex));
1820
1814 tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL); 1821 tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL);
1815 if (key_tfm != NULL) 1822 if (key_tfm != NULL)
1816 (*key_tfm) = tmp_tfm; 1823 (*key_tfm) = tmp_tfm;
@@ -1837,13 +1844,50 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
1837 (*key_tfm) = NULL; 1844 (*key_tfm) = NULL;
1838 goto out; 1845 goto out;
1839 } 1846 }
1840 mutex_lock(&key_tfm_list_mutex);
1841 list_add(&tmp_tfm->key_tfm_list, &key_tfm_list); 1847 list_add(&tmp_tfm->key_tfm_list, &key_tfm_list);
1842 mutex_unlock(&key_tfm_list_mutex);
1843out: 1848out:
1844 return rc; 1849 return rc;
1845} 1850}
1846 1851
1852/**
1853 * ecryptfs_tfm_exists - Search for existing tfm for cipher_name.
1854 * @cipher_name: the name of the cipher to search for
1855 * @key_tfm: set to corresponding tfm if found
1856 *
1857 * Searches for cached key_tfm matching @cipher_name
1858 * Must be called with &key_tfm_list_mutex held
1859 * Returns 1 if found, with @key_tfm set
1860 * Returns 0 if not found, with @key_tfm set to NULL
1861 */
1862int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm)
1863{
1864 struct ecryptfs_key_tfm *tmp_key_tfm;
1865
1866 BUG_ON(!mutex_is_locked(&key_tfm_list_mutex));
1867
1868 list_for_each_entry(tmp_key_tfm, &key_tfm_list, key_tfm_list) {
1869 if (strcmp(tmp_key_tfm->cipher_name, cipher_name) == 0) {
1870 if (key_tfm)
1871 (*key_tfm) = tmp_key_tfm;
1872 return 1;
1873 }
1874 }
1875 if (key_tfm)
1876 (*key_tfm) = NULL;
1877 return 0;
1878}
1879
1880/**
1881 * ecryptfs_get_tfm_and_mutex_for_cipher_name
1882 *
1883 * @tfm: set to cached tfm found, or new tfm created
1884 * @tfm_mutex: set to mutex for cached tfm found, or new tfm created
1885 * @cipher_name: the name of the cipher to search for and/or add
1886 *
1887 * Sets pointers to @tfm & @tfm_mutex matching @cipher_name.
1888 * Searches for cached item first, and creates new if not found.
1889 * Returns 0 on success, non-zero if adding new cipher failed
1890 */
1847int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, 1891int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
1848 struct mutex **tfm_mutex, 1892 struct mutex **tfm_mutex,
1849 char *cipher_name) 1893 char *cipher_name)
@@ -1853,22 +1897,17 @@ int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
1853 1897
1854 (*tfm) = NULL; 1898 (*tfm) = NULL;
1855 (*tfm_mutex) = NULL; 1899 (*tfm_mutex) = NULL;
1900
1856 mutex_lock(&key_tfm_list_mutex); 1901 mutex_lock(&key_tfm_list_mutex);
1857 list_for_each_entry(key_tfm, &key_tfm_list, key_tfm_list) { 1902 if (!ecryptfs_tfm_exists(cipher_name, &key_tfm)) {
1858 if (strcmp(key_tfm->cipher_name, cipher_name) == 0) { 1903 rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0);
1859 (*tfm) = key_tfm->key_tfm; 1904 if (rc) {
1860 (*tfm_mutex) = &key_tfm->key_tfm_mutex; 1905 printk(KERN_ERR "Error adding new key_tfm to list; "
1861 mutex_unlock(&key_tfm_list_mutex); 1906 "rc = [%d]\n", rc);
1862 goto out; 1907 goto out;
1863 } 1908 }
1864 } 1909 }
1865 mutex_unlock(&key_tfm_list_mutex); 1910 mutex_unlock(&key_tfm_list_mutex);
1866 rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0);
1867 if (rc) {
1868 printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n",
1869 rc);
1870 goto out;
1871 }
1872 (*tfm) = key_tfm->key_tfm; 1911 (*tfm) = key_tfm->key_tfm;
1873 (*tfm_mutex) = &key_tfm->key_tfm_mutex; 1912 (*tfm_mutex) = &key_tfm->key_tfm_mutex;
1874out: 1913out:
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index f44f71b7605a..5007f788da01 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -323,6 +323,8 @@ struct ecryptfs_key_tfm {
323 unsigned char cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; 323 unsigned char cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
324}; 324};
325 325
326extern struct mutex key_tfm_list_mutex;
327
326/** 328/**
327 * This struct is to enable a mount-wide passphrase/salt combo. This 329 * This struct is to enable a mount-wide passphrase/salt combo. This
328 * is more or less a stopgap to provide similar functionality to other 330 * is more or less a stopgap to provide similar functionality to other
@@ -617,6 +619,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
617 size_t key_size); 619 size_t key_size);
618int ecryptfs_init_crypto(void); 620int ecryptfs_init_crypto(void);
619int ecryptfs_destroy_crypto(void); 621int ecryptfs_destroy_crypto(void);
622int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm);
620int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, 623int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
621 struct mutex **tfm_mutex, 624 struct mutex **tfm_mutex,
622 char *cipher_name); 625 char *cipher_name);
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index dc620fc16595..778c420e4cac 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -410,9 +410,13 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
410 if (!cipher_key_bytes_set) { 410 if (!cipher_key_bytes_set) {
411 mount_crypt_stat->global_default_cipher_key_size = 0; 411 mount_crypt_stat->global_default_cipher_key_size = 0;
412 } 412 }
413 rc = ecryptfs_add_new_key_tfm( 413 mutex_lock(&key_tfm_list_mutex);
414 NULL, mount_crypt_stat->global_default_cipher_name, 414 if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
415 mount_crypt_stat->global_default_cipher_key_size); 415 NULL))
416 rc = ecryptfs_add_new_key_tfm(
417 NULL, mount_crypt_stat->global_default_cipher_name,
418 mount_crypt_stat->global_default_cipher_key_size);
419 mutex_unlock(&key_tfm_list_mutex);
416 if (rc) { 420 if (rc) {
417 printk(KERN_ERR "Error attempting to initialize cipher with " 421 printk(KERN_ERR "Error attempting to initialize cipher with "
418 "name = [%s] and key size = [%td]; rc = [%d]\n", 422 "name = [%s] and key size = [%td]; rc = [%d]\n",