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 <roberto.sassu@xxxxxxxxx> --- 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
Attachment:
smime.p7s
Description: S/MIME cryptographic signature