~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/ccsecurity/load_policy.c

Version: ~ [ linux-5.16-rc1 ] ~ [ linux-5.15.2 ] ~ [ linux-5.14.18 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.79 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.159 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.217 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.255 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.290 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.292 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * security/ccsecurity/load_policy.c
  3  *
  4  * Copyright (C) 2005-2012  NTT DATA CORPORATION
  5  *
  6  * Version: 1.8.5   2015/11/11
  7  */
  8 
  9 #include <linux/version.h>
 10 #include <linux/module.h>
 11 #include <linux/init.h>
 12 #include <linux/binfmts.h>
 13 #include <linux/sched.h>
 14 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
 15 #include <linux/kmod.h>
 16 /*
 17  * Regarding 2.4 kernels, we need to define __KERNEL_SYSCALLS__ in order to use
 18  * waitpid() because call_usermodehelper() does not support UMH_WAIT_PROC.
 19  */
 20 #define __KERNEL_SYSCALLS__
 21 #include <linux/unistd.h>
 22 #else
 23 #include <linux/fs.h>
 24 #include <linux/namei.h>
 25 #endif
 26 #ifndef LOOKUP_POSITIVE
 27 #define LOOKUP_POSITIVE 0
 28 #endif
 29 
 30 /*
 31  * TOMOYO specific part start.
 32  */
 33 
 34 #include <linux/ccsecurity.h>
 35 
 36 /**
 37  * ccs_setup - Set enable/disable upon boot.
 38  *
 39  * @str: "off" to disable, "on" to enable.
 40  *
 41  * Returns 0.
 42  */
 43 static int __init ccs_setup(char *str)
 44 {
 45         if (!strcmp(str, "off"))
 46                 ccsecurity_ops.disabled = 1;
 47         else if (!strcmp(str, "on"))
 48                 ccsecurity_ops.disabled = 0;
 49         return 0;
 50 }
 51 
 52 __setup("ccsecurity=", ccs_setup);
 53 
 54 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
 55 #include "lsm2ccsecurity.c"
 56 #endif
 57 
 58 #ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
 59 
 60 /* Path to the policy loader. (default = CONFIG_CCSECURITY_POLICY_LOADER) */
 61 static const char *ccs_loader;
 62 
 63 /**
 64  * ccs_loader_setup - Set policy loader.
 65  *
 66  * @str: Program to use as a policy loader (e.g. /sbin/ccs-init ).
 67  *
 68  * Returns 0.
 69  */
 70 static int __init ccs_loader_setup(char *str)
 71 {
 72         ccs_loader = str;
 73         return 0;
 74 }
 75 
 76 __setup("CCS_loader=", ccs_loader_setup);
 77 
 78 /**
 79  * ccs_policy_loader_exists - Check whether /sbin/ccs-init exists.
 80  *
 81  * Returns true if /sbin/ccs-init exists, false otherwise.
 82  */
 83 static _Bool ccs_policy_loader_exists(void)
 84 {
 85 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
 86         struct path path;
 87         if (!ccs_loader)
 88                 ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER;
 89         if (kern_path(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE,
 90                       &path) == 0) {
 91                 path_put(&path);
 92                 return 1;
 93         }
 94 #else
 95         struct nameidata nd;
 96         if (!ccs_loader)
 97                 ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER;
 98         if (path_lookup(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE,
 99                         &nd) == 0) {
100 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
101                 path_put(&nd.path);
102 #else
103                 path_release(&nd);
104 #endif
105                 return 1;
106         }
107 #endif
108         printk(KERN_INFO "Not activating Mandatory Access Control "
109                "as %s does not exist.\n", ccs_loader);
110         return 0;
111 }
112 
113 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
114 
115 /**
116  * ccs_run_loader - Start /sbin/ccs-init.
117  *
118  * @unused: Not used.
119  *
120  * Returns PID of /sbin/ccs-init on success, negative value otherwise.
121  */
122 static int ccs_run_loader(void *unused)
123 {
124         char *argv[2];
125         char *envp[3];
126         printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
127                ccs_loader);
128         argv[0] = (char *) ccs_loader;
129         argv[1] = NULL;
130         envp[0] = "HOME=/";
131         envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
132         envp[2] = NULL;
133         return exec_usermodehelper(argv[0], argv, envp);
134 }
135 
136 #endif
137 
138 /* Path to the trigger. (default = CONFIG_CCSECURITY_ACTIVATION_TRIGGER) */
139 static const char *ccs_trigger;
140 
141 /**
142  * ccs_trigger_setup - Set trigger for activation.
143  *
144  * @str: Program to use as an activation trigger (e.g. /sbin/init ).
145  *
146  * Returns 0.
147  */
148 static int __init ccs_trigger_setup(char *str)
149 {
150         ccs_trigger = str;
151         return 0;
152 }
153 
154 __setup("CCS_trigger=", ccs_trigger_setup);
155 
156 /**
157  * ccs_load_policy - Run external policy loader to load policy.
158  *
159  * @filename: The program about to start.
160  *
161  * Returns nothing.
162  *
163  * This function checks whether @filename is /sbin/init, and if so
164  * invoke /sbin/ccs-init and wait for the termination of /sbin/ccs-init
165  * and then continues invocation of /sbin/init.
166  * /sbin/ccs-init reads policy files in /etc/ccs/ directory and
167  * writes to /proc/ccs/ interfaces.
168  */
169 static void ccs_load_policy(const char *filename)
170 {
171         static _Bool done;
172         if (ccsecurity_ops.disabled || done)
173                 return;
174         if (!ccs_trigger)
175                 ccs_trigger = CONFIG_CCSECURITY_ACTIVATION_TRIGGER;
176         if (strcmp(filename, ccs_trigger))
177                 return;
178         if (!ccs_policy_loader_exists())
179                 return;
180         done = 1;
181 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
182         {
183                 char *argv[2];
184                 char *envp[3];
185                 printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
186                        ccs_loader);
187                 argv[0] = (char *) ccs_loader;
188                 argv[1] = NULL;
189                 envp[0] = "HOME=/";
190                 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
191                 envp[2] = NULL;
192 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) || defined(UMH_WAIT_PROC)
193                 call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
194 #else
195                 call_usermodehelper(argv[0], argv, envp, 1);
196 #endif
197         }
198 #elif defined(TASK_DEAD)
199         {
200                 /* Copied from kernel/kmod.c */
201                 struct task_struct *task = current;
202                 pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
203                 sigset_t tmpsig;
204                 spin_lock_irq(&task->sighand->siglock);
205                 tmpsig = task->blocked;
206                 siginitsetinv(&task->blocked,
207                               sigmask(SIGKILL) | sigmask(SIGSTOP));
208                 recalc_sigpending();
209                 spin_unlock_irq(&task->sighand->siglock);
210                 if (pid >= 0)
211                         waitpid(pid, NULL, __WCLONE);
212                 spin_lock_irq(&task->sighand->siglock);
213                 task->blocked = tmpsig;
214                 recalc_sigpending();
215                 spin_unlock_irq(&task->sighand->siglock);
216         }
217 #else
218         {
219                 /* Copied from kernel/kmod.c */
220                 struct task_struct *task = current;
221                 pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
222                 sigset_t tmpsig;
223                 spin_lock_irq(&task->sigmask_lock);
224                 tmpsig = task->blocked;
225                 siginitsetinv(&task->blocked,
226                               sigmask(SIGKILL) | sigmask(SIGSTOP));
227                 recalc_sigpending(task);
228                 spin_unlock_irq(&task->sigmask_lock);
229                 if (pid >= 0)
230                         waitpid(pid, NULL, __WCLONE);
231                 spin_lock_irq(&task->sigmask_lock);
232                 task->blocked = tmpsig;
233                 recalc_sigpending(task);
234                 spin_unlock_irq(&task->sigmask_lock);
235         }
236 #endif
237         if (ccsecurity_ops.check_profile)
238                 ccsecurity_ops.check_profile();
239         else
240                 panic("Failed to load policy.");
241 }
242 
243 #endif
244 
245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
246 
247 /**
248  * __ccs_search_binary_handler - Load policy before calling search_binary_handler().
249  *
250  * @bprm: Pointer to "struct linux_binprm".
251  *
252  * Returns 0 on success, negative value otherwise.
253  */
254 static int __ccs_search_binary_handler(struct linux_binprm *bprm)
255 {
256 #ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
257         ccs_load_policy(bprm->filename);
258 #endif
259         /*
260          * ccs_load_policy() executes /sbin/ccs-init if bprm->filename is
261          * /sbin/init. /sbin/ccs-init executes /etc/ccs/ccs-load-module to
262          * load loadable kernel module. The loadable kernel module modifies
263          * "struct ccsecurity_ops". Thus, we need to transfer control to
264          * __ccs_search_binary_handler() in security/ccsecurity/permission.c
265          * if "struct ccsecurity_ops" was modified.
266          */
267         if (ccsecurity_ops.search_binary_handler
268             != __ccs_search_binary_handler)
269                 return ccsecurity_ops.search_binary_handler(bprm);
270         return search_binary_handler(bprm);
271 }
272 
273 #else
274 
275 /**
276  * __ccs_search_binary_handler - Load policy before calling search_binary_handler().
277  *
278  * @bprm: Pointer to "struct linux_binprm".
279  * @regs: Pointer to "struct pt_regs".
280  *
281  * Returns 0 on success, negative value otherwise.
282  */
283 static int __ccs_search_binary_handler(struct linux_binprm *bprm,
284                                        struct pt_regs *regs)
285 {
286 #ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
287         ccs_load_policy(bprm->filename);
288 #endif
289         /*
290          * ccs_load_policy() executes /sbin/ccs-init if bprm->filename is
291          * /sbin/init. /sbin/ccs-init executes /etc/ccs/ccs-load-module to
292          * load loadable kernel module. The loadable kernel module modifies
293          * "struct ccsecurity_ops". Thus, we need to transfer control to
294          * __ccs_search_binary_handler() in security/ccsecurity/permission.c
295          * if "struct ccsecurity_ops" was modified.
296          */
297         if (ccsecurity_ops.search_binary_handler
298             != __ccs_search_binary_handler)
299                 return ccsecurity_ops.search_binary_handler(bprm, regs);
300         return search_binary_handler(bprm, regs);
301 }
302 
303 #endif
304 
305 /*
306  * Some exports for loadable kernel module part.
307  *
308  * Although scripts/checkpatch.pl complains about use of "extern" in C file,
309  * we don't put these into security/ccsecurity/internal.h because we want to
310  * split built-in part and loadable kernel module part.
311  */
312 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
313 extern spinlock_t vfsmount_lock;
314 #endif
315 
316 /* For exporting variables and functions. */
317 const struct ccsecurity_exports ccsecurity_exports = {
318 #ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
319         .load_policy = ccs_load_policy,
320 #endif
321 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
322         .d_absolute_path = d_absolute_path,
323 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
324         .__d_path = __d_path,
325 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
326         .vfsmount_lock = &vfsmount_lock,
327 #endif
328 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
329         .find_task_by_vpid = find_task_by_vpid,
330         .find_task_by_pid_ns = find_task_by_pid_ns,
331 #endif
332 };
333 #ifdef CONFIG_CCSECURITY_LKM
334 /* Only ccsecurity module need to access this struct. */
335 EXPORT_SYMBOL_GPL(ccsecurity_exports);
336 #endif
337 
338 /* Members are updated by loadable kernel module. */
339 struct ccsecurity_operations ccsecurity_ops = {
340         .search_binary_handler = __ccs_search_binary_handler,
341 #ifdef CONFIG_CCSECURITY_DISABLE_BY_DEFAULT
342         .disabled = 1,
343 #endif
344 };
345 /*
346  * Non-GPL modules might need to access this struct via inlined functions
347  * embedded into include/linux/security.h and include/net/ip.h
348  */
349 EXPORT_SYMBOL(ccsecurity_ops);
350 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp