2010-11-03 10:13:04

by Roberto Sassu

[permalink] [raw]
Subject: [PATCH 5/5] ecryptfs: open lower files with kthread credentials

Ecryptfs allows concurrent accesses to an encrypted file by opening the
relative lower inode only once and making the returned file descriptor
available until the ecryptfs inode is destroyed.
The file descriptor is obtained by calling the function dentry_open() for
the lower inode with flag O_RDWR and the credentials of the process that
issued the open request.
During this procedure two issues may be encountered when using ecryptfs in
conjunction with SELinux: first, a process needs read/write permission
for opening a file even with flag O_RDONLY; second a process needs the
'use' permission in the 'fd' class if the lower file was opened by another
process with different credentials.
This patch replaces the 'cred' structure of the current process, passed to
the function dentry_open(), with the one associated with the 'kthread'
kernel service.

Signed-off-by: Roberto Sassu <[email protected]>
---
fs/ecryptfs/ecryptfs_kernel.h | 3 +--
fs/ecryptfs/kthread.c | 17 +++++++++++++----
fs/ecryptfs/main.c | 3 +--
3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 452be3c..14d167f 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -759,8 +759,7 @@ int ecryptfs_init_kthread(void);
void ecryptfs_destroy_kthread(void);
int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
- struct vfsmount *lower_mnt,
- const struct cred *cred);
+ struct vfsmount *lower_mnt);
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
int
ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index d8c3a37..5094601 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -38,6 +38,7 @@ static struct ecryptfs_kthread_ctl {
} ecryptfs_kthread_ctl;

static struct task_struct *ecryptfs_kthread;
+static struct cred *ecryptfs_kthread_cred;

/**
* ecryptfs_threadfn
@@ -74,7 +75,7 @@ static int ecryptfs_threadfn(void *ignored)
mntget(req->lower_mnt);
(*req->lower_file) = dentry_open(
req->lower_dentry, req->lower_mnt,
- (O_RDWR | O_LARGEFILE), current_cred());
+ (O_RDWR | O_LARGEFILE), ecryptfs_kthread_cred);
req->flags |= ECRYPTFS_REQ_PROCESSED;
}
wake_up(&req->wait);
@@ -99,7 +100,15 @@ int ecryptfs_init_kthread(void)
rc = PTR_ERR(ecryptfs_kthread);
printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
"\n", __func__, rc);
+ goto out;
+ }
+ ecryptfs_kthread_cred = prepare_kernel_cred(ecryptfs_kthread);
+ if (IS_ERR(ecryptfs_kthread_cred)) {
+ rc = PTR_ERR(ecryptfs_kthread_cred);
+ printk(KERN_ERR "%s: Failed to obtain the credential struct; "
+ "rc = [%d]\n", __func__, rc);
}
+out:
return rc;
}

@@ -119,6 +128,7 @@ void ecryptfs_destroy_kthread(void)
mutex_unlock(&ecryptfs_kthread_ctl.mux);
kthread_stop(ecryptfs_kthread);
wake_up(&ecryptfs_kthread_ctl.wait);
+ put_cred(ecryptfs_kthread_cred);
}

/**
@@ -133,8 +143,7 @@ void ecryptfs_destroy_kthread(void)
*/
int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
- struct vfsmount *lower_mnt,
- const struct cred *cred)
+ struct vfsmount *lower_mnt)
{
struct ecryptfs_open_req *req;
int flags = O_LARGEFILE;
@@ -146,7 +155,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
dget(lower_dentry);
mntget(lower_mnt);
flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
- (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
+ (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, ecryptfs_kthread_cred);
if (!IS_ERR(*lower_file))
goto out;
if (flags & O_RDONLY) {
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 81821d7..c07bb9a 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -117,7 +117,6 @@ void __ecryptfs_printk(const char *fmt, ...)
*/
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
{
- const struct cred *cred = current_cred();
struct ecryptfs_inode_info *inode_info =
ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
int rc = 0;
@@ -130,7 +129,7 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)

lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
rc = ecryptfs_privileged_open(&inode_info->lower_file,
- lower_dentry, lower_mnt, cred);
+ lower_dentry, lower_mnt);
if (rc) {
printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
--
1.7.2.3


Attachments:
smime.p7s (4.60 kB)