root/fs/ecryptfs/kthread.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ecryptfs_threadfn
  2. ecryptfs_init_kthread
  3. ecryptfs_destroy_kthread
  4. ecryptfs_privileged_open

   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 
  16 struct 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 
  23 static 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 
  31 static 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  */
  42 static 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         }
  68 out:
  69         return 0;
  70 }
  71 
  72 int __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 
  89 void 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  *
 112  * This function gets a r/w file opened against the lower dentry.
 113  *
 114  * Returns zero on success; non-zero otherwise
 115  */
 116 int ecryptfs_privileged_open(struct file **lower_file,
 117                              struct dentry *lower_dentry,
 118                              struct vfsmount *lower_mnt,
 119                              const struct cred *cred)
 120 {
 121         struct ecryptfs_open_req req;
 122         int flags = O_LARGEFILE;
 123         int rc = 0;
 124 
 125         init_completion(&req.done);
 126         req.lower_file = lower_file;
 127         req.path.dentry = lower_dentry;
 128         req.path.mnt = lower_mnt;
 129 
 130         /* Corresponding dput() and mntput() are done when the
 131          * lower file is fput() when all eCryptfs files for the inode are
 132          * released. */
 133         flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
 134         (*lower_file) = dentry_open(&req.path, flags, cred);
 135         if (!IS_ERR(*lower_file))
 136                 goto out;
 137         if ((flags & O_ACCMODE) == O_RDONLY) {
 138                 rc = PTR_ERR((*lower_file));
 139                 goto out;
 140         }
 141         mutex_lock(&ecryptfs_kthread_ctl.mux);
 142         if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
 143                 rc = -EIO;
 144                 mutex_unlock(&ecryptfs_kthread_ctl.mux);
 145                 printk(KERN_ERR "%s: We are in the middle of shutting down; "
 146                        "aborting privileged request to open lower file\n",
 147                         __func__);
 148                 goto out;
 149         }
 150         list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
 151         mutex_unlock(&ecryptfs_kthread_ctl.mux);
 152         wake_up(&ecryptfs_kthread_ctl.wait);
 153         wait_for_completion(&req.done);
 154         if (IS_ERR(*lower_file))
 155                 rc = PTR_ERR(*lower_file);
 156 out:
 157         return rc;
 158 }

/* [<][>][^][v][top][bottom][index][help] */