mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
Fixes maximum filename length and filesystem type reporting in statfs() calls
and also fixes stale inode mode bits on eCryptfs inodes after a POSIX ACL was set on the lower filesystem's inode. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABCgAGBQJPPZzXAAoJENaSAD2qAscKNjsP/0KEqvVV7SXFXq/4yXEij/02 +wHS8/4SsTXcE2fkzQM2Jx/osoZfO0Tse8VMADwpX+aNyYlfnsdI4RLYm0y5X1JL kKdSKNuuEQaA0+YEge4KicsjMQ6nVmYIHGWs3kpEpkk3dKeafVKgh5/+k+NCOs7U tZricmWrLV/Rn9pb7S1tp4hOo4cVQEJQGPqaFJ0QwORcdmBWTw904yFsZV+TojFf 1kEV6ue/mFav7ZPOhz8Cx2xIukUHk8EUykbScTWx3kpdkffF3INsf9b3mt34lEFB chuLdcJZuABBBe8RL4g/qRcDOHNUmZx01uX4eHwejs7sYFDfnmNz+tjomr1MRaCv JEUgE31n407HR3ChA8IxX1bqHOfjN0mgVnOwnmK4nbnLKX0WvmogaIDV7hZK3Z9Q lGeKN0qwU3Cr1N9K/+JLHB3xB/yieE/53tlksHDjRgJAEXy7SV0fcftmgDLxyx5m DX4u+eFKdFt+3YBFzTBWRtDO5GVgbylT31JVnKJUi+RDFiOWUf0PzAOXUp5nmr8w Md8zZ/kCZY/pbnrETNVcXPrEP9eDb6nY5b16ZP5nADMRtZLQdKiKRRdHtwnKg5N6 7nU/cS1bpG7bUekJkkRgzrAz+ziDielzVvkhwb7sq3sac9fegjW67K3/SEiJiQJC XTBZCrTW3RdEAt6WCTVV =hwGP -----END PGP SIGNATURE----- Merge tag 'ecryptfs-3.3-rc4-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs Fixes maximum filename length and filesystem type reporting in statfs() calls and also fixes stale inode mode bits on eCryptfs inodes after a POSIX ACL was set on the lower filesystem's inode. * tag 'ecryptfs-3.3-rc4-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs: ecryptfs: remove the second argument of k[un]map_atomic() eCryptfs: Copy up lower inode attrs after setting lower xattr eCryptfs: Improve statfs reporting
This commit is contained in:
commit
4686066689
@ -1990,6 +1990,17 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t ecryptfs_max_decoded_size(size_t encoded_size)
|
||||
{
|
||||
/* Not exact; conservatively long. Every block of 4
|
||||
* encoded characters decodes into a block of 3
|
||||
* decoded characters. This segment of code provides
|
||||
* the caller with the maximum amount of allocated
|
||||
* space that @dst will need to point to in a
|
||||
* subsequent call. */
|
||||
return ((encoded_size + 1) * 3) / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* ecryptfs_decode_from_filename
|
||||
* @dst: If NULL, this function only sets @dst_size and returns. If
|
||||
@ -2008,13 +2019,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
|
||||
size_t dst_byte_offset = 0;
|
||||
|
||||
if (dst == NULL) {
|
||||
/* Not exact; conservatively long. Every block of 4
|
||||
* encoded characters decodes into a block of 3
|
||||
* decoded characters. This segment of code provides
|
||||
* the caller with the maximum amount of allocated
|
||||
* space that @dst will need to point to in a
|
||||
* subsequent call. */
|
||||
(*dst_size) = (((src_size + 1) * 3) / 4);
|
||||
(*dst_size) = ecryptfs_max_decoded_size(src_size);
|
||||
goto out;
|
||||
}
|
||||
while (src_byte_offset < src_size) {
|
||||
@ -2239,3 +2244,52 @@ out_free:
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define ENC_NAME_MAX_BLOCKLEN_8_OR_16 143
|
||||
|
||||
int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
|
||||
{
|
||||
struct blkcipher_desc desc;
|
||||
struct mutex *tfm_mutex;
|
||||
size_t cipher_blocksize;
|
||||
int rc;
|
||||
|
||||
if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
|
||||
(*namelen) = lower_namelen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex,
|
||||
mount_crypt_stat->global_default_fn_cipher_name);
|
||||
if (unlikely(rc)) {
|
||||
(*namelen) = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
mutex_lock(tfm_mutex);
|
||||
cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm);
|
||||
mutex_unlock(tfm_mutex);
|
||||
|
||||
/* Return an exact amount for the common cases */
|
||||
if (lower_namelen == NAME_MAX
|
||||
&& (cipher_blocksize == 8 || cipher_blocksize == 16)) {
|
||||
(*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a safe estimate for the uncommon cases */
|
||||
(*namelen) = lower_namelen;
|
||||
(*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
|
||||
/* Since this is the max decoded size, subtract 1 "decoded block" len */
|
||||
(*namelen) = ecryptfs_max_decoded_size(*namelen) - 3;
|
||||
(*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE;
|
||||
(*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES;
|
||||
/* Worst case is that the filename is padded nearly a full block size */
|
||||
(*namelen) -= cipher_blocksize - 1;
|
||||
|
||||
if ((*namelen) < 0)
|
||||
(*namelen) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,6 +162,10 @@ ecryptfs_get_key_payload_data(struct key *key)
|
||||
#define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE
|
||||
#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \
|
||||
+ ECRYPTFS_SIG_SIZE + 1 + 1)
|
||||
#define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (1 + ECRYPTFS_MAX_PKT_LEN_SIZE \
|
||||
+ ECRYPTFS_SIG_SIZE + 1 + 1)
|
||||
#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED."
|
||||
#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23
|
||||
#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
|
||||
@ -701,6 +705,8 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
|
||||
size_t *packet_size,
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
char *data, size_t max_packet_size);
|
||||
int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
|
||||
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
|
||||
loff_t offset);
|
||||
|
||||
|
@ -1085,6 +1085,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
}
|
||||
|
||||
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
|
||||
if (!rc)
|
||||
fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
@ -679,10 +679,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
|
||||
* Octets N3-N4: Block-aligned encrypted filename
|
||||
* - Consists of a minimum number of random characters, a \0
|
||||
* separator, and then the filename */
|
||||
s->max_packet_size = (1 /* Tag 70 identifier */
|
||||
+ 3 /* Max Tag 70 packet size */
|
||||
+ ECRYPTFS_SIG_SIZE /* FNEK sig */
|
||||
+ 1 /* Cipher identifier */
|
||||
s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE
|
||||
+ s->block_aligned_filename_size);
|
||||
if (dest == NULL) {
|
||||
(*packet_size) = s->max_packet_size;
|
||||
@ -934,10 +931,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
|
||||
goto out;
|
||||
}
|
||||
s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) {
|
||||
if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {
|
||||
printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "
|
||||
"at least [%d]\n", __func__, max_packet_size,
|
||||
(1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1));
|
||||
ECRYPTFS_TAG_70_MIN_METADATA_SIZE);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
|
||||
/* This is a header extent */
|
||||
char *page_virt;
|
||||
|
||||
page_virt = kmap_atomic(page, KM_USER0);
|
||||
page_virt = kmap_atomic(page);
|
||||
memset(page_virt, 0, PAGE_CACHE_SIZE);
|
||||
/* TODO: Support more than one header extent */
|
||||
if (view_extent_num == 0) {
|
||||
@ -163,7 +163,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
|
||||
crypt_stat,
|
||||
&written);
|
||||
}
|
||||
kunmap_atomic(page_virt, KM_USER0);
|
||||
kunmap_atomic(page_virt);
|
||||
flush_dcache_page(page);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "%s: Error reading xattr "
|
||||
|
@ -156,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
||||
ecryptfs_page_idx, rc);
|
||||
goto out;
|
||||
}
|
||||
ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
|
||||
ecryptfs_page_virt = kmap_atomic(ecryptfs_page);
|
||||
|
||||
/*
|
||||
* pos: where we're now writing, offset: where the request was
|
||||
@ -179,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
|
||||
(data + data_offset), num_bytes);
|
||||
data_offset += num_bytes;
|
||||
}
|
||||
kunmap_atomic(ecryptfs_page_virt, KM_USER0);
|
||||
kunmap_atomic(ecryptfs_page_virt);
|
||||
flush_dcache_page(ecryptfs_page);
|
||||
SetPageUptodate(ecryptfs_page);
|
||||
unlock_page(ecryptfs_page);
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/magic.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
struct kmem_cache *ecryptfs_inode_info_cache;
|
||||
@ -102,10 +104,20 @@ static void ecryptfs_destroy_inode(struct inode *inode)
|
||||
static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
{
|
||||
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
int rc;
|
||||
|
||||
if (!lower_dentry->d_sb->s_op->statfs)
|
||||
return -ENOSYS;
|
||||
return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
|
||||
|
||||
rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
buf->f_type = ECRYPTFS_SUPER_MAGIC;
|
||||
rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen,
|
||||
&ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user