Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6:
  ecryptfs: dont call lookup_one_len to avoid NULL nameidata
  fs/ecryptfs/file.c: introduce missing free
  ecryptfs: release reference to lower mount if interpose fails
  eCryptfs: Handle ioctl calls with unlocked and compat functions
  ecryptfs: Fix warning in ecryptfs_process_response()
This commit is contained in:
Linus Torvalds 2010-08-10 12:14:39 -07:00
commit 26b55633a8
3 changed files with 118 additions and 38 deletions

View File

@ -199,7 +199,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
"the persistent file for the dentry with name " "the persistent file for the dentry with name "
"[%s]; rc = [%d]\n", __func__, "[%s]; rc = [%d]\n", __func__,
ecryptfs_dentry->d_name.name, rc); ecryptfs_dentry->d_name.name, rc);
goto out; goto out_free;
} }
} }
if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY) if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
@ -207,7 +207,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
rc = -EPERM; rc = -EPERM;
printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
"file must hence be opened RO\n", __func__); "file must hence be opened RO\n", __func__);
goto out; goto out_free;
} }
ecryptfs_set_file_lower( ecryptfs_set_file_lower(
file, ecryptfs_inode_to_private(inode)->lower_file); file, ecryptfs_inode_to_private(inode)->lower_file);
@ -292,12 +292,40 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)
return rc; return rc;
} }
static int ecryptfs_ioctl(struct inode *inode, struct file *file, static long
unsigned int cmd, unsigned long arg); ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct file *lower_file = NULL;
long rc = -ENOTTY;
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl)
rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
return rc;
}
#ifdef CONFIG_COMPAT
static long
ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct file *lower_file = NULL;
long rc = -ENOIOCTLCMD;
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl)
rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
return rc;
}
#endif
const struct file_operations ecryptfs_dir_fops = { const struct file_operations ecryptfs_dir_fops = {
.readdir = ecryptfs_readdir, .readdir = ecryptfs_readdir,
.ioctl = ecryptfs_ioctl, .unlocked_ioctl = ecryptfs_unlocked_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ecryptfs_compat_ioctl,
#endif
.open = ecryptfs_open, .open = ecryptfs_open,
.flush = ecryptfs_flush, .flush = ecryptfs_flush,
.release = ecryptfs_release, .release = ecryptfs_release,
@ -313,7 +341,10 @@ const struct file_operations ecryptfs_main_fops = {
.write = do_sync_write, .write = do_sync_write,
.aio_write = generic_file_aio_write, .aio_write = generic_file_aio_write,
.readdir = ecryptfs_readdir, .readdir = ecryptfs_readdir,
.ioctl = ecryptfs_ioctl, .unlocked_ioctl = ecryptfs_unlocked_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ecryptfs_compat_ioctl,
#endif
.mmap = generic_file_mmap, .mmap = generic_file_mmap,
.open = ecryptfs_open, .open = ecryptfs_open,
.flush = ecryptfs_flush, .flush = ecryptfs_flush,
@ -322,20 +353,3 @@ const struct file_operations ecryptfs_main_fops = {
.fasync = ecryptfs_fasync, .fasync = ecryptfs_fasync,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
}; };
static int
ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
int rc = 0;
struct file *lower_file = NULL;
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->ioctl)
rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode),
lower_file, cmd, arg);
else
rc = -ENOTTY;
return rc;
}

View File

@ -264,7 +264,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
printk(KERN_ERR "%s: Out of memory whilst attempting " printk(KERN_ERR "%s: Out of memory whilst attempting "
"to allocate ecryptfs_dentry_info struct\n", "to allocate ecryptfs_dentry_info struct\n",
__func__); __func__);
goto out_dput; goto out_put;
} }
ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry);
ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt);
@ -339,13 +339,84 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
out_free_kmem: out_free_kmem:
kmem_cache_free(ecryptfs_header_cache_2, page_virt); kmem_cache_free(ecryptfs_header_cache_2, page_virt);
goto out; goto out;
out_dput: out_put:
dput(lower_dentry); dput(lower_dentry);
mntput(lower_mnt);
d_drop(ecryptfs_dentry); d_drop(ecryptfs_dentry);
out: out:
return rc; return rc;
} }
/**
* ecryptfs_new_lower_dentry
* @ename: The name of the new dentry.
* @lower_dir_dentry: Parent directory of the new dentry.
* @nd: nameidata from last lookup.
*
* Create a new dentry or get it from lower parent dir.
*/
static struct dentry *
ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry,
struct nameidata *nd)
{
struct dentry *new_dentry;
struct dentry *tmp;
struct inode *lower_dir_inode;
lower_dir_inode = lower_dir_dentry->d_inode;
tmp = d_alloc(lower_dir_dentry, name);
if (!tmp)
return ERR_PTR(-ENOMEM);
mutex_lock(&lower_dir_inode->i_mutex);
new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd);
mutex_unlock(&lower_dir_inode->i_mutex);
if (!new_dentry)
new_dentry = tmp;
else
dput(tmp);
return new_dentry;
}
/**
* ecryptfs_lookup_one_lower
* @ecryptfs_dentry: The eCryptfs dentry that we are looking up
* @lower_dir_dentry: lower parent directory
*
* Get the lower dentry from vfs. If lower dentry does not exist yet,
* create it.
*/
static struct dentry *
ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry,
struct dentry *lower_dir_dentry)
{
struct nameidata nd;
struct vfsmount *lower_mnt;
struct qstr *name;
int err;
name = &ecryptfs_dentry->d_name;
lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
ecryptfs_dentry->d_parent));
err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd);
mntput(lower_mnt);
if (!err) {
/* we dont need the mount */
mntput(nd.path.mnt);
return nd.path.dentry;
}
if (err != -ENOENT)
return ERR_PTR(err);
/* create a new lower dentry */
return ecryptfs_new_lower_dentry(name, lower_dir_dentry, &nd);
}
/** /**
* ecryptfs_lookup * ecryptfs_lookup
* @ecryptfs_dir_inode: The eCryptfs directory inode * @ecryptfs_dir_inode: The eCryptfs directory inode
@ -373,14 +444,12 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
goto out_d_drop; goto out_d_drop;
} }
lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry,
lower_dir_dentry, lower_dir_dentry);
ecryptfs_dentry->d_name.len);
mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) { if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry); rc = PTR_ERR(lower_dentry);
ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned "
"[%d] on lower_dentry = [%s]\n", __func__, rc, "[%d] on lower_dentry = [%s]\n", __func__, rc,
encrypted_and_encoded_name); encrypted_and_encoded_name);
goto out_d_drop; goto out_d_drop;
@ -402,14 +471,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
"filename; rc = [%d]\n", __func__, rc); "filename; rc = [%d]\n", __func__, rc);
goto out_d_drop; goto out_d_drop;
} }
mutex_lock(&lower_dir_dentry->d_inode->i_mutex); lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry,
lower_dentry = lookup_one_len(encrypted_and_encoded_name, lower_dir_dentry);
lower_dir_dentry,
encrypted_and_encoded_name_size - 1);
mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
if (IS_ERR(lower_dentry)) { if (IS_ERR(lower_dentry)) {
rc = PTR_ERR(lower_dentry); rc = PTR_ERR(lower_dentry);
ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned "
"[%d] on lower_dentry = [%s]\n", __func__, rc, "[%d] on lower_dentry = [%s]\n", __func__, rc,
encrypted_and_encoded_name); encrypted_and_encoded_name);
goto out_d_drop; goto out_d_drop;

View File

@ -274,7 +274,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
struct user_namespace *user_ns, struct pid *pid, struct user_namespace *user_ns, struct pid *pid,
u32 seq) u32 seq)
{ {
struct ecryptfs_daemon *daemon; struct ecryptfs_daemon *uninitialized_var(daemon);
struct ecryptfs_msg_ctx *msg_ctx; struct ecryptfs_msg_ctx *msg_ctx;
size_t msg_size; size_t msg_size;
struct nsproxy *nsproxy; struct nsproxy *nsproxy;