Linux Audio

Check our new training course

Loading...
v4.10.11
  1/**
 
  2 * eCryptfs: Linux filesystem encryption layer
  3 *
  4 * Copyright (C) 2008 International Business Machines Corp.
  5 *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  6 *
  7 * This program is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU General Public License as
  9 * published by the Free Software Foundation; either version 2 of the
 10 * License, or (at your option) any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful, but
 13 * WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15 * General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 20 * 02111-1307, USA.
 21 */
 22
 23#include <linux/kthread.h>
 24#include <linux/freezer.h>
 25#include <linux/slab.h>
 26#include <linux/wait.h>
 27#include <linux/mount.h>
 28#include "ecryptfs_kernel.h"
 29
 30struct ecryptfs_open_req {
 31	struct file **lower_file;
 32	struct path path;
 33	struct completion done;
 34	struct list_head kthread_ctl_list;
 35};
 36
 37static struct ecryptfs_kthread_ctl {
 38#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
 39	u32 flags;
 40	struct mutex mux;
 41	struct list_head req_list;
 42	wait_queue_head_t wait;
 43} ecryptfs_kthread_ctl;
 44
 45static struct task_struct *ecryptfs_kthread;
 46
 47/**
 48 * ecryptfs_threadfn
 49 * @ignored: ignored
 50 *
 51 * The eCryptfs kernel thread that has the responsibility of getting
 52 * the lower file with RW permissions.
 53 *
 54 * Returns zero on success; non-zero otherwise
 55 */
 56static int ecryptfs_threadfn(void *ignored)
 57{
 58	set_freezable();
 59	while (1)  {
 60		struct ecryptfs_open_req *req;
 61
 62		wait_event_freezable(
 63			ecryptfs_kthread_ctl.wait,
 64			(!list_empty(&ecryptfs_kthread_ctl.req_list)
 65			 || kthread_should_stop()));
 66		mutex_lock(&ecryptfs_kthread_ctl.mux);
 67		if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
 68			mutex_unlock(&ecryptfs_kthread_ctl.mux);
 69			goto out;
 70		}
 71		while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {
 72			req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
 73					       struct ecryptfs_open_req,
 74					       kthread_ctl_list);
 75			list_del(&req->kthread_ctl_list);
 76			*req->lower_file = dentry_open(&req->path,
 77				(O_RDWR | O_LARGEFILE), current_cred());
 78			complete(&req->done);
 79		}
 80		mutex_unlock(&ecryptfs_kthread_ctl.mux);
 81	}
 82out:
 83	return 0;
 84}
 85
 86int __init ecryptfs_init_kthread(void)
 87{
 88	int rc = 0;
 89
 90	mutex_init(&ecryptfs_kthread_ctl.mux);
 91	init_waitqueue_head(&ecryptfs_kthread_ctl.wait);
 92	INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list);
 93	ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL,
 94				       "ecryptfs-kthread");
 95	if (IS_ERR(ecryptfs_kthread)) {
 96		rc = PTR_ERR(ecryptfs_kthread);
 97		printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
 98		       "\n", __func__, rc);
 99	}
100	return rc;
101}
102
103void ecryptfs_destroy_kthread(void)
104{
105	struct ecryptfs_open_req *req, *tmp;
106
107	mutex_lock(&ecryptfs_kthread_ctl.mux);
108	ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
109	list_for_each_entry_safe(req, tmp, &ecryptfs_kthread_ctl.req_list,
110				 kthread_ctl_list) {
111		list_del(&req->kthread_ctl_list);
112		*req->lower_file = ERR_PTR(-EIO);
113		complete(&req->done);
114	}
115	mutex_unlock(&ecryptfs_kthread_ctl.mux);
116	kthread_stop(ecryptfs_kthread);
117	wake_up(&ecryptfs_kthread_ctl.wait);
118}
119
120/**
121 * ecryptfs_privileged_open
122 * @lower_file: Result of dentry_open by root on lower dentry
123 * @lower_dentry: Lower dentry for file to open
124 * @lower_mnt: Lower vfsmount for file to open
 
125 *
126 * This function gets a r/w file opened againt the lower dentry.
127 *
128 * Returns zero on success; non-zero otherwise
129 */
130int ecryptfs_privileged_open(struct file **lower_file,
131			     struct dentry *lower_dentry,
132			     struct vfsmount *lower_mnt,
133			     const struct cred *cred)
134{
135	struct ecryptfs_open_req req;
136	int flags = O_LARGEFILE;
137	int rc = 0;
138
139	init_completion(&req.done);
140	req.lower_file = lower_file;
141	req.path.dentry = lower_dentry;
142	req.path.mnt = lower_mnt;
143
144	/* Corresponding dput() and mntput() are done when the
145	 * lower file is fput() when all eCryptfs files for the inode are
146	 * released. */
147	flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
148	(*lower_file) = dentry_open(&req.path, flags, cred);
149	if (!IS_ERR(*lower_file))
150		goto out;
151	if ((flags & O_ACCMODE) == O_RDONLY) {
152		rc = PTR_ERR((*lower_file));
153		goto out;
154	}
155	mutex_lock(&ecryptfs_kthread_ctl.mux);
156	if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
157		rc = -EIO;
158		mutex_unlock(&ecryptfs_kthread_ctl.mux);
159		printk(KERN_ERR "%s: We are in the middle of shutting down; "
160		       "aborting privileged request to open lower file\n",
161			__func__);
162		goto out;
163	}
164	list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
165	mutex_unlock(&ecryptfs_kthread_ctl.mux);
166	wake_up(&ecryptfs_kthread_ctl.wait);
167	wait_for_completion(&req.done);
168	if (IS_ERR(*lower_file))
169		rc = PTR_ERR(*lower_file);
170out:
171	return rc;
172}
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * eCryptfs: Linux filesystem encryption layer
  4 *
  5 * Copyright (C) 2008 International Business Machines Corp.
  6 *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  7 */
  8
  9#include <linux/kthread.h>
 10#include <linux/freezer.h>
 11#include <linux/slab.h>
 12#include <linux/wait.h>
 13#include <linux/mount.h>
 14#include "ecryptfs_kernel.h"
 15
 16struct ecryptfs_open_req {
 17	struct file **lower_file;
 18	struct path path;
 19	struct completion done;
 20	struct list_head kthread_ctl_list;
 21};
 22
 23static struct ecryptfs_kthread_ctl {
 24#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
 25	u32 flags;
 26	struct mutex mux;
 27	struct list_head req_list;
 28	wait_queue_head_t wait;
 29} ecryptfs_kthread_ctl;
 30
 31static struct task_struct *ecryptfs_kthread;
 32
 33/**
 34 * ecryptfs_threadfn
 35 * @ignored: ignored
 36 *
 37 * The eCryptfs kernel thread that has the responsibility of getting
 38 * the lower file with RW permissions.
 39 *
 40 * Returns zero on success; non-zero otherwise
 41 */
 42static int ecryptfs_threadfn(void *ignored)
 43{
 44	set_freezable();
 45	while (1)  {
 46		struct ecryptfs_open_req *req;
 47
 48		wait_event_freezable(
 49			ecryptfs_kthread_ctl.wait,
 50			(!list_empty(&ecryptfs_kthread_ctl.req_list)
 51			 || kthread_should_stop()));
 52		mutex_lock(&ecryptfs_kthread_ctl.mux);
 53		if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
 54			mutex_unlock(&ecryptfs_kthread_ctl.mux);
 55			goto out;
 56		}
 57		while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {
 58			req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
 59					       struct ecryptfs_open_req,
 60					       kthread_ctl_list);
 61			list_del(&req->kthread_ctl_list);
 62			*req->lower_file = dentry_open(&req->path,
 63				(O_RDWR | O_LARGEFILE), current_cred());
 64			complete(&req->done);
 65		}
 66		mutex_unlock(&ecryptfs_kthread_ctl.mux);
 67	}
 68out:
 69	return 0;
 70}
 71
 72int __init ecryptfs_init_kthread(void)
 73{
 74	int rc = 0;
 75
 76	mutex_init(&ecryptfs_kthread_ctl.mux);
 77	init_waitqueue_head(&ecryptfs_kthread_ctl.wait);
 78	INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list);
 79	ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL,
 80				       "ecryptfs-kthread");
 81	if (IS_ERR(ecryptfs_kthread)) {
 82		rc = PTR_ERR(ecryptfs_kthread);
 83		printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
 84		       "\n", __func__, rc);
 85	}
 86	return rc;
 87}
 88
 89void ecryptfs_destroy_kthread(void)
 90{
 91	struct ecryptfs_open_req *req, *tmp;
 92
 93	mutex_lock(&ecryptfs_kthread_ctl.mux);
 94	ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
 95	list_for_each_entry_safe(req, tmp, &ecryptfs_kthread_ctl.req_list,
 96				 kthread_ctl_list) {
 97		list_del(&req->kthread_ctl_list);
 98		*req->lower_file = ERR_PTR(-EIO);
 99		complete(&req->done);
100	}
101	mutex_unlock(&ecryptfs_kthread_ctl.mux);
102	kthread_stop(ecryptfs_kthread);
103	wake_up(&ecryptfs_kthread_ctl.wait);
104}
105
106/**
107 * ecryptfs_privileged_open
108 * @lower_file: Result of dentry_open by root on lower dentry
109 * @lower_dentry: Lower dentry for file to open
110 * @lower_mnt: Lower vfsmount for file to open
111 * @cred: credential to use for this call
112 *
113 * This function gets a r/w file opened against the lower dentry.
114 *
115 * Returns zero on success; non-zero otherwise
116 */
117int ecryptfs_privileged_open(struct file **lower_file,
118			     struct dentry *lower_dentry,
119			     struct vfsmount *lower_mnt,
120			     const struct cred *cred)
121{
122	struct ecryptfs_open_req req;
123	int flags = O_LARGEFILE;
124	int rc = 0;
125
126	init_completion(&req.done);
127	req.lower_file = lower_file;
128	req.path.dentry = lower_dentry;
129	req.path.mnt = lower_mnt;
130
131	/* Corresponding dput() and mntput() are done when the
132	 * lower file is fput() when all eCryptfs files for the inode are
133	 * released. */
134	flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
135	(*lower_file) = dentry_open(&req.path, flags, cred);
136	if (!IS_ERR(*lower_file))
137		goto out;
138	if ((flags & O_ACCMODE) == O_RDONLY) {
139		rc = PTR_ERR((*lower_file));
140		goto out;
141	}
142	mutex_lock(&ecryptfs_kthread_ctl.mux);
143	if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
144		rc = -EIO;
145		mutex_unlock(&ecryptfs_kthread_ctl.mux);
146		printk(KERN_ERR "%s: We are in the middle of shutting down; "
147		       "aborting privileged request to open lower file\n",
148			__func__);
149		goto out;
150	}
151	list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
152	mutex_unlock(&ecryptfs_kthread_ctl.mux);
153	wake_up(&ecryptfs_kthread_ctl.wait);
154	wait_for_completion(&req.done);
155	if (IS_ERR(*lower_file))
156		rc = PTR_ERR(*lower_file);
157out:
158	return rc;
159}