brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · ae4cb4e Raw
160 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * eCryptfs: Linux filesystem encryption layer4 *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 0x0000000125	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_threadfn35 * @ignored: ignored36 *37 * The eCryptfs kernel thread that has the responsibility of getting38 * the lower file with RW permissions.39 *40 * Returns zero on success; non-zero otherwise41 */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_open108 * @lower_file: Result of dentry_open by root on lower dentry109 * @lower_dentry: Lower dentry for file to open110 * @lower_mnt: Lower vfsmount for file to open111 * @cred: credential to use for this call112 *113 * This function gets a r/w file opened against the lower dentry.114 *115 * Returns zero on success; non-zero otherwise116 */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 the132	 * lower file is fput() when all eCryptfs files for the inode are133	 * 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}160