• R/O
  • SSH
  • HTTPS

tomoyo: Commit


Commit MetaInfo

Revision1723 (tree)
Time2008-10-20 16:21:19
Authortakedakn

Log Message

lkml-11

Change Summary

Incremental Difference

--- tags/lkml/11/tomoyo-makefile.patch (nonexistent)
+++ tags/lkml/11/tomoyo-makefile.patch (revision 1723)
@@ -0,0 +1,54 @@
1+Subject: Kconfig and Makefile
2+
3+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
4+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+---
6+ security/Kconfig | 1 +
7+ security/Makefile | 2 ++
8+ security/tomoyo/Kconfig | 11 +++++++++++
9+ security/tomoyo/Makefile | 1 +
10+ 4 files changed, 15 insertions(+)
11+
12+--- linux-next.orig/security/Kconfig
13++++ linux-next/security/Kconfig
14+@@ -134,6 +134,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
15+
16+ source security/selinux/Kconfig
17+ source security/smack/Kconfig
18++source security/tomoyo/Kconfig
19+
20+ endmenu
21+
22+--- linux-next.orig/security/Makefile
23++++ linux-next/security/Makefile
24+@@ -5,6 +5,7 @@
25+ obj-$(CONFIG_KEYS) += keys/
26+ subdir-$(CONFIG_SECURITY_SELINUX) += selinux
27+ subdir-$(CONFIG_SECURITY_SMACK) += smack
28++subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
29+
30+ # always enable default capabilities
31+ obj-y += commoncap.o
32+@@ -17,3 +18,4 @@ obj-$(CONFIG_SECURITY_SELINUX) += selin
33+ obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
34+ obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
35+ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
36++obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
37+--- /dev/null
38++++ linux-next/security/tomoyo/Kconfig
39+@@ -0,0 +1,11 @@
40++config SECURITY_TOMOYO
41++ bool "TOMOYO Linux Support"
42++ depends on SECURITY
43++ select SECURITYFS
44++ select SECURITY_PATH
45++ default n
46++ help
47++ This selects TOMOYO Linux, pathname-based access control.
48++ Required userspace tools and further information may be
49++ found at <http://tomoyo.sourceforge.jp/>.
50++ If you are unsure how to answer this question, answer N.
51+--- /dev/null
52++++ linux-next/security/tomoyo/Makefile
53+@@ -0,0 +1 @@
54++obj-y = common.o realpath.o tomoyo.o domain.o file.o
--- tags/lkml/11/tomoyo-realpath.patch (nonexistent)
+++ tags/lkml/11/tomoyo-realpath.patch (revision 1723)
@@ -0,0 +1,627 @@
1+Subject: Memory and pathname management functions.
2+
3+TOMOYO Linux performs pathname based access control.
4+To remove factors that make pathname based access control difficult
5+(e.g. symbolic links, "..", "//" etc.), TOMOYO Linux derives realpath
6+of requested pathname from "struct dentry" and "struct vfsmount".
7+
8+The maximum length of string data is limited to 4000 including trailing '\0'.
9+Since TOMOYO Linux uses '\ooo' style representation for non ASCII printable
10+characters, may be TOMOYO Linux should be able to support 16336 (which means
11+(NAME_MAX * (PATH_MAX / (NAME_MAX + 1)) * 4 + (PATH_MAX / (NAME_MAX + 1)))
12+including trailing '\0'), but I think 4000 is enough for practical use.
13+
14+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
15+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
16+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
17+---
18+ security/tomoyo/realpath.c | 540 +++++++++++++++++++++++++++++++++++++++++++++
19+ security/tomoyo/realpath.h | 60 +++++
20+ 2 files changed, 600 insertions(+)
21+
22+--- /dev/null
23++++ linux-next/security/tomoyo/realpath.c
24+@@ -0,0 +1,540 @@
25++/*
26++ * security/tomoyo/realpath.c
27++ *
28++ * Get the canonicalized absolute pathnames. The basis for TOMOYO.
29++ *
30++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
31++ *
32++ * Version: 2.2.0-pre 2008/10/10
33++ *
34++ */
35++
36++#include <linux/types.h>
37++#include <linux/mount.h>
38++#include <linux/magic.h>
39++#include <linux/sysctl.h>
40++#include "common.h"
41++#include "realpath.h"
42++
43++/**
44++ * tmy_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
45++ *
46++ * @path: Pointer to "struct path".
47++ * @newname: Pointer to buffer to return value in.
48++ * @newname_len: Size of @newname.
49++ *
50++ * Returns 0 on success, negative value otherwise.
51++ *
52++ * If dentry is a directory, trailing '/' is appended.
53++ * Characters out of 0x20 < c < 0x7F range are converted to
54++ * \ooo style octal string.
55++ * Character \ is converted to \\ string.
56++ */
57++int tmy_realpath_from_path2(struct path *path, char *newname, int newname_len)
58++{
59++ int error = -ENOMEM;
60++ struct dentry *dentry = path->dentry;
61++ char *sp;
62++
63++ if (!dentry || !path->mnt || !newname || newname_len <= 2048)
64++ return -EINVAL;
65++ if (dentry->d_op && dentry->d_op->d_dname) {
66++ /* For "socket:[\$]" and "pipe:[\$]". */
67++ static const int offset = 1536;
68++ sp = dentry->d_op->d_dname(dentry, newname + offset,
69++ newname_len - offset);
70++ } else {
71++ path_get(path);
72++ sp = d_realpath(path, newname, newname_len);
73++ path_put(path);
74++ }
75++ if (IS_ERR(sp)) {
76++ error = PTR_ERR(sp);
77++ } else {
78++ char *dp = newname;
79++ newname += newname_len - 5;
80++ while (dp <= newname) {
81++ const unsigned char c = *(unsigned char *) sp++;
82++ *dp++ = c;
83++ if (c == '\\') {
84++ *dp++ = '\\';
85++ } else if (c > ' ' && c < 127) {
86++ continue;
87++ } else if (!c) {
88++ error = 0;
89++ break;
90++ } else {
91++ *dp++ = '\\';
92++ *dp++ = (c >> 6) + '0';
93++ *dp++ = ((c >> 3) & 7) + '0';
94++ *dp++ = (c & 7) + '0';
95++ }
96++ }
97++ }
98++ if (error)
99++ printk(KERN_WARNING "tmy_realpath: Pathname too long.\n");
100++ return error;
101++}
102++
103++/**
104++ * tmy_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
105++ *
106++ * @path: Pointer to "struct path".
107++ *
108++ * Returns the realpath of the given @path on success, NULL otherwise.
109++ *
110++ * These functions use tmy_alloc(), so the caller must call tmy_free()
111++ * if these functions didn't return NULL.
112++ */
113++char *tmy_realpath_from_path(struct path *path)
114++{
115++ char *buf = tmy_alloc(sizeof(struct tmy_page_buffer));
116++
117++ if (buf && tmy_realpath_from_path2(path, buf,
118++ TMY_MAX_PATHNAME_LEN - 1) == 0)
119++ return buf;
120++ tmy_free(buf);
121++ return NULL;
122++}
123++
124++/**
125++ * tmy_realpath - Get realpath of a pathname.
126++ *
127++ * @pathname: The pathname to solve.
128++ *
129++ * Returns the realpath of @pathname on success, NULL otherwise.
130++ */
131++char *tmy_realpath(const char *pathname)
132++{
133++ struct nameidata nd;
134++
135++ if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) {
136++ char *buf = tmy_realpath_from_path(&nd.path);
137++ path_put(&nd.path);
138++ return buf;
139++ }
140++ return NULL;
141++}
142++
143++/**
144++ * tmy_realpath_nofollow - Get realpath of a pathname.
145++ *
146++ * @pathname: The pathname to solve.
147++ *
148++ * Returns the realpath of @pathname on success, NULL otherwise.
149++ */
150++char *tmy_realpath_nofollow(const char *pathname)
151++{
152++ struct nameidata nd;
153++
154++ if (pathname && path_lookup(pathname, 0, &nd) == 0) {
155++ char *buf = tmy_realpath_from_path(&nd.path);
156++ path_put(&nd.path);
157++ return buf;
158++ }
159++ return NULL;
160++}
161++
162++/**
163++ * round_up - Round up an integer so that the returned pointers are appropriately aligned.
164++ *
165++ * @size: Size in bytes.
166++ *
167++ * Returns rounded value of @size.
168++ *
169++ * FIXME: Are there more requirements that is needed for assigning value
170++ * atomically?
171++ */
172++static inline unsigned int round_up(const unsigned int size)
173++{
174++ if (sizeof(void *) >= sizeof(long))
175++ return ((size + sizeof(void *) - 1)
176++ / sizeof(void *)) * sizeof(void *);
177++ else
178++ return ((size + sizeof(long) - 1)
179++ / sizeof(long)) * sizeof(long);
180++}
181++
182++/* Memory allocated for non-string data. */
183++static unsigned int allocated_memory_for_elements;
184++/* Quota for holding non-string data. */
185++static unsigned int quota_for_elements;
186++
187++/**
188++ * tmy_alloc_element - Allocate permanent memory for structures.
189++ *
190++ * @size: Size in bytes.
191++ *
192++ * Returns pointer to allocated memory on success, NULL otherwise.
193++ *
194++ * The RAM is chunked, so NEVER try to kfree() the returned pointer.
195++ */
196++void *tmy_alloc_element(const unsigned int size)
197++{
198++ static char *buf;
199++ static DEFINE_MUTEX(lock);
200++ static unsigned int buf_used_len = PAGE_SIZE;
201++ char *ptr = NULL;
202++ const unsigned int word_aligned_size = round_up(size);
203++
204++ if (word_aligned_size > PAGE_SIZE)
205++ return NULL;
206++ /***** EXCLUSIVE SECTION START *****/
207++ mutex_lock(&lock);
208++ if (buf_used_len + word_aligned_size > PAGE_SIZE) {
209++ if (!quota_for_elements || allocated_memory_for_elements
210++ + PAGE_SIZE <= quota_for_elements)
211++ ptr = kzalloc(PAGE_SIZE, GFP_KERNEL);
212++ if (!ptr) {
213++ printk(KERN_WARNING "ERROR: Out of memory "
214++ "for tmy_alloc_element().\n");
215++ if (!sbin_init_started)
216++ panic("MAC Initialization failed.\n");
217++ } else {
218++ buf = ptr;
219++ allocated_memory_for_elements += PAGE_SIZE;
220++ buf_used_len = word_aligned_size;
221++ ptr = buf;
222++ }
223++ } else if (word_aligned_size) {
224++ int i;
225++ ptr = buf + buf_used_len;
226++ buf_used_len += word_aligned_size;
227++ for (i = 0; i < word_aligned_size; i++) {
228++ if (!ptr[i])
229++ continue;
230++ printk(KERN_ERR "WARNING: Reserved memory was tainted! "
231++ "The system might go wrong.\n");
232++ ptr[i] = '\0';
233++ }
234++ }
235++ mutex_unlock(&lock);
236++ /***** EXCLUSIVE SECTION END *****/
237++ return ptr;
238++}
239++
240++/* Memory allocated for string data. */
241++static unsigned int allocated_memory_for_savename;
242++/* Quota for holding string data. */
243++static unsigned int quota_for_savename;
244++
245++/*
246++ * TOMOYO uses this hash only when appending a string into the string
247++ * table. Frequency of appending strings is very low. So we don't need
248++ * large (e.g. 64k) hash size. 256 will be sufficient.
249++ */
250++#define MAX_HASH 256
251++
252++/* Structure for string data. */
253++struct name_entry {
254++ struct list1_head list;
255++ struct path_info entry;
256++};
257++
258++/* Structure for available memory region. */
259++struct free_memory_block_list {
260++ struct list_head list;
261++ char *ptr; /* Pointer to a free area. */
262++ int len; /* Length of the area. */
263++};
264++
265++/*
266++ * The list for "struct name_entry".
267++ *
268++ * This list is updated only inside tmy_save_name(), thus
269++ * no global mutex exists.
270++ */
271++static struct list1_head name_list[MAX_HASH];
272++
273++/**
274++ * tmy_save_name - Allocate permanent memory for string data.
275++ *
276++ * @name: The string to store into the permernent memory.
277++ *
278++ * Returns pointer to "struct path_info" on success, NULL otherwise.
279++ *
280++ * The RAM is shared, so NEVER try to modify or kfree() the returned name.
281++ */
282++const struct path_info *tmy_save_name(const char *name)
283++{
284++ static LIST_HEAD(fmb_list);
285++ static DEFINE_MUTEX(lock);
286++ struct name_entry *ptr;
287++ unsigned int hash;
288++ struct free_memory_block_list *fmb;
289++ int len;
290++ char *cp;
291++
292++ if (!name)
293++ return NULL;
294++ len = strlen(name) + 1;
295++ if (len > TMY_MAX_PATHNAME_LEN) {
296++ printk(KERN_WARNING "ERROR: Name too long "
297++ "for tmy_save_name().\n");
298++ return NULL;
299++ }
300++ hash = full_name_hash((const unsigned char *) name, len - 1);
301++ /***** EXCLUSIVE SECTION START *****/
302++ mutex_lock(&lock);
303++ list1_for_each_entry(ptr, &name_list[hash % MAX_HASH], list) {
304++ if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
305++ goto out;
306++ }
307++ list_for_each_entry(fmb, &fmb_list, list) {
308++ if (len <= fmb->len)
309++ goto ready;
310++ }
311++ if (!quota_for_savename || allocated_memory_for_savename + PAGE_SIZE
312++ <= quota_for_savename)
313++ cp = kzalloc(PAGE_SIZE, GFP_KERNEL);
314++ else
315++ cp = NULL;
316++ fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
317++ if (!cp || !fmb) {
318++ kfree(cp);
319++ kfree(fmb);
320++ printk(KERN_WARNING "ERROR: Out of memory "
321++ "for tmy_save_name().\n");
322++ if (!sbin_init_started)
323++ panic("MAC Initialization failed.\n");
324++ ptr = NULL;
325++ goto out;
326++ }
327++ allocated_memory_for_savename += PAGE_SIZE;
328++ list_add(&fmb->list, &fmb_list);
329++ fmb->ptr = cp;
330++ fmb->len = PAGE_SIZE;
331++ready:
332++ ptr = tmy_alloc_element(sizeof(*ptr));
333++ if (!ptr)
334++ goto out;
335++ ptr->entry.name = fmb->ptr;
336++ memmove(fmb->ptr, name, len);
337++ tmy_fill_path_info(&ptr->entry);
338++ fmb->ptr += len;
339++ fmb->len -= len;
340++ list1_add_tail(&ptr->list, &name_list[hash % MAX_HASH]);
341++ if (fmb->len == 0) {
342++ list_del(&fmb->list);
343++ kfree(fmb);
344++ }
345++out:
346++ mutex_unlock(&lock);
347++ /***** EXCLUSIVE SECTION END *****/
348++ return ptr ? &ptr->entry : NULL;
349++}
350++
351++/**
352++ * tmy_realpath_init - Initialize realpath related code.
353++ *
354++ * Returns 0.
355++ */
356++static int __init tmy_realpath_init(void)
357++{
358++ int i;
359++
360++ if (TMY_MAX_PATHNAME_LEN > PAGE_SIZE)
361++ panic("Bad size.");
362++ for (i = 0; i < MAX_HASH; i++)
363++ INIT_LIST1_HEAD(&name_list[i]);
364++ INIT_LIST1_HEAD(&KERNEL_DOMAIN.acl_info_list);
365++ KERNEL_DOMAIN.domainname = tmy_save_name(ROOT_NAME);
366++ list1_add_tail(&KERNEL_DOMAIN.list, &domain_list);
367++ if (tmy_find_domain(ROOT_NAME) != &KERNEL_DOMAIN)
368++ panic("Can't register KERNEL_DOMAIN");
369++ return 0;
370++}
371++
372++security_initcall(tmy_realpath_init);
373++
374++/* Memory allocated for temporal purpose. */
375++static atomic_t dynamic_memory_size;
376++
377++/**
378++ * tmy_alloc - Allocate memory for temporal purpose.
379++ *
380++ * @size: Size in bytes.
381++ *
382++ * Returns pointer to allocated memory on success, NULL otherwise.
383++ */
384++void *tmy_alloc(const size_t size)
385++{
386++ void *p = kzalloc(size, GFP_KERNEL);
387++ if (p)
388++ atomic_add(ksize(p), &dynamic_memory_size);
389++ return p;
390++}
391++
392++/**
393++ * tmy_free - Release memory allocated by tmy_alloc().
394++ *
395++ * @p: Pointer returned by tmy_alloc(). May be NULL.
396++ *
397++ * Returns nothing.
398++ */
399++void tmy_free(const void *p)
400++{
401++ if (p)
402++ atomic_sub(ksize(p), &dynamic_memory_size);
403++ kfree(p);
404++}
405++
406++static int tmy_print_ascii(const char *sp, const char *cp,
407++ int *buflen0, char **end0)
408++{
409++ int error = -ENOMEM;
410++ int buflen = *buflen0;
411++ char *end = *end0;
412++
413++ while (sp <= cp) {
414++ unsigned char c;
415++
416++ c = *(unsigned char *) cp;
417++ if (c == '\\') {
418++ buflen -= 2;
419++ if (buflen < 0)
420++ goto out;
421++ *--end = '\\';
422++ *--end = '\\';
423++ } else if (c > ' ' && c < 127) {
424++ if (--buflen < 0)
425++ goto out;
426++ *--end = (char) c;
427++ } else {
428++ buflen -= 4;
429++ if (buflen < 0)
430++ goto out;
431++ *--end = (c & 7) + '0';
432++ *--end = ((c >> 3) & 7) + '0';
433++ *--end = (c >> 6) + '0';
434++ *--end = '\\';
435++ }
436++ cp--;
437++ }
438++
439++ *buflen0 = buflen;
440++ *end0 = end;
441++ error = 0;
442++out:
443++ return error;
444++}
445++
446++
447++/* tmy_realpath_from_path2() for "struct ctl_table". */
448++static int tmy_sysctl_path(struct ctl_table *table, char *buffer, int buflen)
449++{
450++ int error = -ENOMEM;
451++ char *end = buffer + buflen;
452++
453++ if (buflen < 256)
454++ goto out;
455++
456++ *--end = '\0';
457++ buflen--;
458++
459++ buflen -= 9; /* for "/proc/sys" prefix */
460++
461++ while (table) {
462++ char buf[32];
463++ const char *sp = table->procname;
464++ const char *cp;
465++
466++ if (!sp) {
467++ memset(buf, 0, sizeof(buf));
468++ snprintf(buf, sizeof(buf) - 1, "=%d=", table->ctl_name);
469++ sp = buf;
470++ }
471++ cp = strchr(sp, '\0') - 1;
472++
473++ if (tmy_print_ascii(sp, cp, &buflen, &end))
474++ goto out;
475++
476++ if (--buflen < 0)
477++ goto out;
478++
479++ *--end = '/';
480++ table = table->parent;
481++ }
482++
483++ /* Move the pathname to the top of the buffer. */
484++ memmove(buffer, "/proc/sys", 9);
485++ memmove(buffer + 9, end, strlen(end) + 1);
486++ error = 0;
487++out:
488++ return error;
489++}
490++
491++/**
492++ * sysctlpath_from_table - return the realpath of a ctl_table.
493++ * @table: pointer to "struct ctl_table".
494++ *
495++ * Returns realpath(3) of the @table on success.
496++ * Returns NULL on failure.
497++ *
498++ * This function uses tmy_alloc(), so the caller must call tmy_free()
499++ * if this function didn't return NULL.
500++ */
501++char *sysctlpath_from_table(struct ctl_table *table)
502++{
503++ char *buf = tmy_alloc(TMY_MAX_PATHNAME_LEN);
504++
505++ if (buf && tmy_sysctl_path(table, buf, TMY_MAX_PATHNAME_LEN - 1) == 0)
506++ return buf;
507++ tmy_free(buf);
508++ return NULL;
509++}
510++
511++/**
512++ * tmy_read_memory_counter - Check for memory usage.
513++ *
514++ * @head: Pointer to "struct tmy_io_buffer".
515++ *
516++ * Returns memory usage.
517++ */
518++int tmy_read_memory_counter(struct tmy_io_buffer *head)
519++{
520++ if (!head->read_eof) {
521++ const unsigned int shared = allocated_memory_for_savename;
522++ const unsigned int private = allocated_memory_for_elements;
523++ const unsigned int dynamic = atomic_read(&dynamic_memory_size);
524++ char buffer[64];
525++
526++ memset(buffer, 0, sizeof(buffer));
527++ if (quota_for_savename)
528++ snprintf(buffer, sizeof(buffer) - 1,
529++ " (Quota: %10u)", quota_for_savename);
530++ else
531++ buffer[0] = '\0';
532++ tmy_io_printf(head, "Shared: %10u%s\n", shared, buffer);
533++ if (quota_for_elements)
534++ snprintf(buffer, sizeof(buffer) - 1,
535++ " (Quota: %10u)", quota_for_elements);
536++ else
537++ buffer[0] = '\0';
538++ tmy_io_printf(head, "Private: %10u%s\n", private, buffer);
539++ tmy_io_printf(head, "Dynamic: %10u\n", dynamic);
540++ tmy_io_printf(head, "Total: %10u\n",
541++ shared + private + dynamic);
542++ head->read_eof = true;
543++ }
544++ return 0;
545++}
546++
547++/**
548++ * tmy_write_memory_quota - Set memory quota.
549++ *
550++ * @head: Pointer to "struct tmy_io_buffer".
551++ *
552++ * Returns 0.
553++ */
554++int tmy_write_memory_quota(struct tmy_io_buffer *head)
555++{
556++ char *data = head->write_buf;
557++ unsigned int size;
558++
559++ if (sscanf(data, "Shared: %u", &size) == 1)
560++ quota_for_savename = size;
561++ else if (sscanf(data, "Private: %u", &size) == 1)
562++ quota_for_elements = size;
563++ return 0;
564++}
565+--- /dev/null
566++++ linux-next/security/tomoyo/realpath.h
567+@@ -0,0 +1,60 @@
568++/*
569++ * security/tomoyo/realpath.h
570++ *
571++ * Get the canonicalized absolute pathnames. The basis for TOMOYO.
572++ *
573++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
574++ *
575++ * Version: 2.2.0-pre 2008/10/10
576++ *
577++ */
578++
579++#ifndef _SECURITY_TOMOYO_REALPATH_H
580++#define _SECURITY_TOMOYO_REALPATH_H
581++
582++struct path;
583++struct condition_list;
584++struct path_info;
585++struct tmy_io_buffer;
586++
587++/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
588++int tmy_realpath_from_path2(struct path *path, char *newname, int newname_len);
589++
590++/*
591++ * Returns realpath(3) of the given pathname but ignores chroot'ed root.
592++ * These functions use tmy_alloc(), so the caller must call tmy_free()
593++ * if these functions didn't return NULL.
594++ */
595++char *tmy_realpath(const char *pathname);
596++/* Same with tmy_realpath() except that it doesn't follow the final symlink. */
597++char *tmy_realpath_nofollow(const char *pathname);
598++/* Same with tmy_realpath() except that the pathname is already solved. */
599++char *tmy_realpath_from_path(struct path *path);
600++/* Same with tmy_realpath() except that it uses struct ctl_table. */
601++char *sysctlpath_from_table(struct ctl_table *table);
602++
603++/*
604++ * Allocate memory for ACL entry.
605++ * The RAM is chunked, so NEVER try to kfree() the returned pointer.
606++ */
607++void *tmy_alloc_element(const unsigned int size);
608++
609++/*
610++ * Keep the given name on the RAM.
611++ * The RAM is shared, so NEVER try to modify or kfree() the returned name.
612++ */
613++const struct path_info *tmy_save_name(const char *name);
614++
615++/* Allocate memory for temporary use (e.g. permission checks). */
616++void *tmy_alloc(const size_t size);
617++
618++/* Free memory allocated by tmy_alloc(). */
619++void tmy_free(const void *p);
620++
621++/* Check for memory usage. */
622++int tmy_read_memory_counter(struct tmy_io_buffer *head);
623++
624++/* Set memory quota. */
625++int tmy_write_memory_quota(struct tmy_io_buffer *head);
626++
627++#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */
--- tags/lkml/11/tomoyo-domain-transition-part.patch (nonexistent)
+++ tags/lkml/11/tomoyo-domain-transition-part.patch (revision 1723)
@@ -0,0 +1,885 @@
1+Subject: Domain transition handler.
2+
3+This file controls domain creation/deletion/transition.
4+
5+Every process belongs to a domain in TOMOYO Linux.
6+Domain transition occurs when execve(2) is called
7+and the domain is expressed as 'process invocation history',
8+such as '<kernel> /sbin/init /etc/init.d/rc'.
9+Domain information is stored in task_struct->cred->security field.
10+
11+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
12+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
13+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
14+---
15+ security/tomoyo/domain.c | 865 +++++++++++++++++++++++++++++++++++++++++++++++
16+ 1 file changed, 865 insertions(+)
17+
18+--- /dev/null
19++++ linux-next/security/tomoyo/domain.c
20+@@ -0,0 +1,865 @@
21++/*
22++ * security/tomoyo/domain.c
23++ *
24++ * Implementation of the Domain-Based Mandatory Access Control.
25++ *
26++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
27++ *
28++ * Version: 2.2.0-pre 2008/10/10
29++ *
30++ */
31++
32++#include "common.h"
33++#include "tomoyo.h"
34++#include "realpath.h"
35++#include <linux/binfmts.h>
36++
37++/* Variables definitions.*/
38++
39++/* The initial domain. */
40++struct domain_info KERNEL_DOMAIN;
41++
42++/*
43++ * The list for "struct domain_info".
44++ *
45++ * The domain_list_lock mutex protects the domain_list list.
46++ */
47++LIST1_HEAD(domain_list);
48++static DEFINE_MUTEX(domain_list_lock);
49++
50++/* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
51++struct domain_initializer_entry {
52++ struct list1_head list;
53++ const struct path_info *domainname; /* This may be NULL */
54++ const struct path_info *program;
55++ bool is_deleted;
56++ bool is_not; /* True if this entry is "no_initialize_domain". */
57++ bool is_last_name; /* True if the domainname is tmy_get_last_name(). */
58++};
59++
60++/* Structure for "keep_domain" and "no_keep_domain" keyword. */
61++struct domain_keeper_entry {
62++ struct list1_head list;
63++ const struct path_info *domainname;
64++ const struct path_info *program; /* This may be NULL */
65++ bool is_deleted;
66++ bool is_not; /* True if this entry is "no_keep_domain". */
67++ bool is_last_name; /* True if the domainname is tmy_get_last_name(). */
68++};
69++
70++/* Structure for "alias" keyword. */
71++struct alias_entry {
72++ struct list1_head list;
73++ const struct path_info *original_name;
74++ const struct path_info *aliased_name;
75++ bool is_deleted;
76++};
77++
78++/**
79++ * tmy_set_domain_flag - Set or clear domain's attribute flags.
80++ *
81++ * @domain: Pointer to "struct domain_info".
82++ * @is_delete: True if it is a delete request.
83++ * @flags: Flags to set or clear.
84++ *
85++ * Returns nothing.
86++ */
87++void tmy_set_domain_flag(struct domain_info *domain, const bool is_delete,
88++ const u8 flags)
89++{
90++ /* We need to serialize because this is bitfield operation. */
91++ static DEFINE_SPINLOCK(lock);
92++ /***** CRITICAL SECTION START *****/
93++ spin_lock(&lock);
94++ if (!is_delete)
95++ domain->flags |= flags;
96++ else
97++ domain->flags &= ~flags;
98++ spin_unlock(&lock);
99++ /***** CRITICAL SECTION END *****/
100++}
101++
102++/**
103++ * tmy_get_last_name - Get last component of a domainname.
104++ *
105++ * @domain: Pointer to "struct domain_info".
106++ *
107++ * Returns the last component of the domainname.
108++ */
109++const char *tmy_get_last_name(const struct domain_info *domain)
110++{
111++ const char *cp0 = domain->domainname->name;
112++ const char *cp1 = strrchr(cp0, ' ');
113++
114++ if (cp1)
115++ return cp1 + 1;
116++ return cp0;
117++}
118++
119++/*
120++ * The list for "struct domain_initializer_entry".
121++ *
122++ * This list is updated only inside update_domain_initializer_entry(), thus
123++ * no global mutex exists.
124++ */
125++static LIST1_HEAD(domain_initializer_list);
126++
127++/**
128++ * update_domain_initializer_entry - Update "struct domain_initializer_entry" list.
129++ *
130++ * @domainname: The name of domain. May be NULL.
131++ * @program: The name of program.
132++ * @is_not: True if it is "no_initialize_domain" entry.
133++ * @is_delete: True if it is a delete request.
134++ *
135++ * Returns 0 on success, negative value otherwise.
136++ */
137++static int update_domain_initializer_entry(const char *domainname,
138++ const char *program,
139++ const bool is_not,
140++ const bool is_delete)
141++{
142++ struct domain_initializer_entry *new_entry;
143++ struct domain_initializer_entry *ptr;
144++ static DEFINE_MUTEX(lock);
145++ const struct path_info *saved_program;
146++ const struct path_info *saved_domainname = NULL;
147++ int error = -ENOMEM;
148++ bool is_last_name = false;
149++
150++ if (!tmy_is_correct_path(program, 1, -1, -1, __func__))
151++ return -EINVAL; /* No patterns allowed. */
152++ if (domainname) {
153++ if (!tmy_is_domain_def(domainname) &&
154++ tmy_is_correct_path(domainname, 1, -1, -1, __func__))
155++ is_last_name = true;
156++ else if (!tmy_is_correct_domain(domainname, __func__))
157++ return -EINVAL;
158++ saved_domainname = tmy_save_name(domainname);
159++ if (!saved_domainname)
160++ return -ENOMEM;
161++ }
162++ saved_program = tmy_save_name(program);
163++ if (!saved_program)
164++ return -ENOMEM;
165++ /***** EXCLUSIVE SECTION START *****/
166++ mutex_lock(&lock);
167++ list1_for_each_entry(ptr, &domain_initializer_list, list) {
168++ if (ptr->is_not != is_not ||
169++ ptr->domainname != saved_domainname ||
170++ ptr->program != saved_program)
171++ continue;
172++ ptr->is_deleted = is_delete;
173++ error = 0;
174++ goto out;
175++ }
176++ if (is_delete) {
177++ error = -ENOENT;
178++ goto out;
179++ }
180++ new_entry = tmy_alloc_element(sizeof(*new_entry));
181++ if (!new_entry)
182++ goto out;
183++ new_entry->domainname = saved_domainname;
184++ new_entry->program = saved_program;
185++ new_entry->is_not = is_not;
186++ new_entry->is_last_name = is_last_name;
187++ list1_add_tail(&new_entry->list, &domain_initializer_list);
188++ error = 0;
189++out:
190++ mutex_unlock(&lock);
191++ /***** EXCLUSIVE SECTION END *****/
192++ tmy_update_counter(TMY_UPDATES_COUNTER_EXCEPTION_POLICY);
193++ return error;
194++}
195++
196++/**
197++ * tmy_read_domain_initializer_policy - Read "struct domain_initializer_entry" list.
198++ *
199++ * @head: Pointer to "struct tmy_io_buffer".
200++ *
201++ * Returns true on success, false otherwise.
202++ */
203++bool tmy_read_domain_initializer_policy(struct tmy_io_buffer *head)
204++{
205++ struct list1_head *pos;
206++
207++ list1_for_each_cookie(pos, head->read_var2, &domain_initializer_list) {
208++ const char *no;
209++ const char *from = "";
210++ const char *domain = "";
211++ struct domain_initializer_entry *ptr;
212++ ptr = list1_entry(pos, struct domain_initializer_entry, list);
213++ if (ptr->is_deleted)
214++ continue;
215++ no = ptr->is_not ? "no_" : "";
216++ if (ptr->domainname) {
217++ from = " from ";
218++ domain = ptr->domainname->name;
219++ }
220++ if (!tmy_io_printf(head,
221++ "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
222++ no, ptr->program->name, from, domain))
223++ goto out;
224++ }
225++ return true;
226++out:
227++ return false;
228++}
229++
230++/**
231++ * tmy_write_domain_initializer_policy - Write "struct domain_initializer_entry" list.
232++ *
233++ * @data: String to parse.
234++ * @is_not: True if it is "no_initialize_domain" entry.
235++ * @is_delete: True if it is a delete request.
236++ *
237++ * Returns 0 on success, negative value otherwise.
238++ */
239++int tmy_write_domain_initializer_policy(char *data, const bool is_not,
240++ const bool is_delete)
241++{
242++ char *cp = strstr(data, " from ");
243++
244++ if (cp) {
245++ *cp = '\0';
246++ return update_domain_initializer_entry(cp + 6, data, is_not,
247++ is_delete);
248++ }
249++ return update_domain_initializer_entry(NULL, data, is_not, is_delete);
250++}
251++
252++/**
253++ * is_domain_initializer - Check whether the given program causes domainname reinitialization.
254++ *
255++ * @domainname: The name of domain.
256++ * @program: The name of program.
257++ * @last_name: The last component of @domainname.
258++ *
259++ * Returns true if executing @program reinitializes domain transition,
260++ * false otherwise.
261++ */
262++static bool is_domain_initializer(const struct path_info *domainname,
263++ const struct path_info *program,
264++ const struct path_info *last_name)
265++{
266++ struct domain_initializer_entry *ptr;
267++ bool flag = false;
268++
269++ list1_for_each_entry(ptr, &domain_initializer_list, list) {
270++ if (ptr->is_deleted)
271++ continue;
272++ if (ptr->domainname) {
273++ if (!ptr->is_last_name) {
274++ if (ptr->domainname != domainname)
275++ continue;
276++ } else {
277++ if (tmy_pathcmp(ptr->domainname, last_name))
278++ continue;
279++ }
280++ }
281++ if (tmy_pathcmp(ptr->program, program))
282++ continue;
283++ if (ptr->is_not)
284++ return false;
285++ flag = true;
286++ }
287++ return flag;
288++}
289++
290++/*
291++ * The list for "struct domain_keeper_entry".
292++ *
293++ * This list is updated only inside update_domain_keeper_entry(), thus
294++ * no global mutex exists.
295++ */
296++static LIST1_HEAD(domain_keeper_list);
297++
298++/**
299++ * update_domain_keeper_entry - Update "struct domain_keeper_entry" list.
300++ *
301++ * @domainname: The name of domain.
302++ * @program: The name of program. May be NULL.
303++ * @is_not: True if it is "no_keep_domain" entry.
304++ * @is_delete: True if it is a delete request.
305++ *
306++ * Returns 0 on success, negative value otherwise.
307++ */
308++static int update_domain_keeper_entry(const char *domainname,
309++ const char *program,
310++ const bool is_not, const bool is_delete)
311++{
312++ struct domain_keeper_entry *new_entry;
313++ struct domain_keeper_entry *ptr;
314++ const struct path_info *saved_domainname;
315++ const struct path_info *saved_program = NULL;
316++ static DEFINE_MUTEX(lock);
317++ int error = -ENOMEM;
318++ bool is_last_name = false;
319++
320++ if (!tmy_is_domain_def(domainname) &&
321++ tmy_is_correct_path(domainname, 1, -1, -1, __func__))
322++ is_last_name = true;
323++ else if (!tmy_is_correct_domain(domainname, __func__))
324++ return -EINVAL;
325++ if (program) {
326++ if (!tmy_is_correct_path(program, 1, -1, -1, __func__))
327++ return -EINVAL;
328++ saved_program = tmy_save_name(program);
329++ if (!saved_program)
330++ return -ENOMEM;
331++ }
332++ saved_domainname = tmy_save_name(domainname);
333++ if (!saved_domainname)
334++ return -ENOMEM;
335++ /***** EXCLUSIVE SECTION START *****/
336++ mutex_lock(&lock);
337++ list1_for_each_entry(ptr, &domain_keeper_list, list) {
338++ if (ptr->is_not != is_not ||
339++ ptr->domainname != saved_domainname ||
340++ ptr->program != saved_program)
341++ continue;
342++ ptr->is_deleted = is_delete;
343++ error = 0;
344++ goto out;
345++ }
346++ if (is_delete) {
347++ error = -ENOENT;
348++ goto out;
349++ }
350++ new_entry = tmy_alloc_element(sizeof(*new_entry));
351++ if (!new_entry)
352++ goto out;
353++ new_entry->domainname = saved_domainname;
354++ new_entry->program = saved_program;
355++ new_entry->is_not = is_not;
356++ new_entry->is_last_name = is_last_name;
357++ list1_add_tail(&new_entry->list, &domain_keeper_list);
358++ error = 0;
359++out:
360++ mutex_unlock(&lock);
361++ /***** EXCLUSIVE SECTION END *****/
362++ tmy_update_counter(TMY_UPDATES_COUNTER_EXCEPTION_POLICY);
363++ return error;
364++}
365++
366++/**
367++ * tmy_write_domain_keeper_policy - Write "struct domain_keeper_entry" list.
368++ *
369++ * @data: String to parse.
370++ * @is_not: True if it is "no_keep_domain" entry.
371++ * @is_delete: True if it is a delete request.
372++ *
373++ */
374++int tmy_write_domain_keeper_policy(char *data, const bool is_not,
375++ const bool is_delete)
376++{
377++ char *cp = strstr(data, " from ");
378++
379++ if (cp) {
380++ *cp = '\0';
381++ return update_domain_keeper_entry(cp + 6, data,
382++ is_not, is_delete);
383++ }
384++ return update_domain_keeper_entry(data, NULL, is_not, is_delete);
385++}
386++
387++/**
388++ * tmy_read_domain_keeper_policy - Read "struct domain_keeper_entry" list.
389++ *
390++ * @head: Pointer to "struct tmy_io_buffer".
391++ *
392++ * Returns true on success, false otherwise.
393++ */
394++bool tmy_read_domain_keeper_policy(struct tmy_io_buffer *head)
395++{
396++ struct list1_head *pos;
397++
398++ list1_for_each_cookie(pos, head->read_var2, &domain_keeper_list) {
399++ struct domain_keeper_entry *ptr;
400++ const char *no;
401++ const char *from = "";
402++ const char *program = "";
403++
404++ ptr = list1_entry(pos, struct domain_keeper_entry, list);
405++ if (ptr->is_deleted)
406++ continue;
407++ no = ptr->is_not ? "no_" : "";
408++ if (ptr->program) {
409++ from = " from ";
410++ program = ptr->program->name;
411++ }
412++ if (!tmy_io_printf(head,
413++ "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
414++ program, from, ptr->domainname->name))
415++ goto out;
416++ }
417++ return true;
418++out:
419++ return false;
420++}
421++
422++/**
423++ * is_domain_keeper - Check whether the given program causes domain transition suppression.
424++ *
425++ * @domainname: The name of domain.
426++ * @program: The name of program.
427++ * @last_name: The last component of @domainname.
428++ *
429++ * Returns true if executing @program supresses domain transition,
430++ * false otherwise.
431++ */
432++static bool is_domain_keeper(const struct path_info *domainname,
433++ const struct path_info *program,
434++ const struct path_info *last_name)
435++{
436++ struct domain_keeper_entry *ptr;
437++ bool flag = false;
438++
439++ list1_for_each_entry(ptr, &domain_keeper_list, list) {
440++ if (ptr->is_deleted)
441++ continue;
442++ if (!ptr->is_last_name) {
443++ if (ptr->domainname != domainname)
444++ continue;
445++ } else {
446++ if (tmy_pathcmp(ptr->domainname, last_name))
447++ continue;
448++ }
449++ if (ptr->program && tmy_pathcmp(ptr->program, program))
450++ continue;
451++ if (ptr->is_not)
452++ return false;
453++ flag = true;
454++ }
455++ return flag;
456++}
457++
458++/*
459++ * The list for "struct alias_entry".
460++ *
461++ * This list is updated only inside update_alias_entry(), thus
462++ * no global mutex exists.
463++ */
464++static LIST1_HEAD(alias_list);
465++
466++/**
467++ * update_alias_entry - Update "struct alias_entry" list.
468++ *
469++ * @original_name: The original program's real name.
470++ * @aliased_name: The symbolic program's symbolic link's name.
471++ * @is_delete: True if it is a delete request.
472++ *
473++ * Returns 0 on success, negative value otherwise.
474++ */
475++static int update_alias_entry(const char *original_name,
476++ const char *aliased_name,
477++ const bool is_delete)
478++{
479++ struct alias_entry *new_entry;
480++ struct alias_entry *ptr;
481++ static DEFINE_MUTEX(lock);
482++ const struct path_info *saved_original_name;
483++ const struct path_info *saved_aliased_name;
484++ int error = -ENOMEM;
485++
486++ if (!tmy_is_correct_path(original_name, 1, -1, -1, __func__) ||
487++ !tmy_is_correct_path(aliased_name, 1, -1, -1, __func__))
488++ return -EINVAL; /* No patterns allowed. */
489++ saved_original_name = tmy_save_name(original_name);
490++ saved_aliased_name = tmy_save_name(aliased_name);
491++ if (!saved_original_name || !saved_aliased_name)
492++ return -ENOMEM;
493++ /***** EXCLUSIVE SECTION START *****/
494++ mutex_lock(&lock);
495++ list1_for_each_entry(ptr, &alias_list, list) {
496++ if (ptr->original_name != saved_original_name ||
497++ ptr->aliased_name != saved_aliased_name)
498++ continue;
499++ ptr->is_deleted = is_delete;
500++ error = 0;
501++ goto out;
502++ }
503++ if (is_delete) {
504++ error = -ENOENT;
505++ goto out;
506++ }
507++ new_entry = tmy_alloc_element(sizeof(*new_entry));
508++ if (!new_entry)
509++ goto out;
510++ new_entry->original_name = saved_original_name;
511++ new_entry->aliased_name = saved_aliased_name;
512++ list1_add_tail(&new_entry->list, &alias_list);
513++ error = 0;
514++out:
515++ mutex_unlock(&lock);
516++ /***** EXCLUSIVE SECTION END *****/
517++ tmy_update_counter(TMY_UPDATES_COUNTER_EXCEPTION_POLICY);
518++ return error;
519++}
520++
521++/**
522++ * tmy_read_alias_policy - Read "struct alias_entry" list.
523++ *
524++ * @head: Pointer to "struct tmy_io_buffer".
525++ *
526++ * Returns true on success, false otherwise.
527++ */
528++bool tmy_read_alias_policy(struct tmy_io_buffer *head)
529++{
530++ struct list1_head *pos;
531++
532++ list1_for_each_cookie(pos, head->read_var2, &alias_list) {
533++ struct alias_entry *ptr;
534++
535++ ptr = list1_entry(pos, struct alias_entry, list);
536++ if (ptr->is_deleted)
537++ continue;
538++ if (!tmy_io_printf(head, KEYWORD_ALIAS "%s %s\n",
539++ ptr->original_name->name,
540++ ptr->aliased_name->name))
541++ goto out;
542++ }
543++ return true;
544++out:
545++ return false;
546++}
547++
548++/**
549++ * tmy_write_alias_policy - Write "struct alias_entry" list.
550++ *
551++ * @data: String to parse.
552++ * @is_delete: True if it is a delete request.
553++ *
554++ * Returns 0 on success, negative value otherwise.
555++ */
556++int tmy_write_alias_policy(char *data, const bool is_delete)
557++{
558++ char *cp = strchr(data, ' ');
559++
560++ if (!cp)
561++ return -EINVAL;
562++ *cp++ = '\0';
563++ return update_alias_entry(data, cp, is_delete);
564++}
565++
566++/* Domain create/delete/undelete handler. */
567++
568++/* #define DEBUG_DOMAIN_UNDELETE */
569++
570++/**
571++ * tmy_delete_domain - Delete a domain.
572++ *
573++ * @domainname: The name of domain.
574++ *
575++ * Returns 0.
576++ */
577++int tmy_delete_domain(char *domainname)
578++{
579++ struct domain_info *domain;
580++ struct path_info name;
581++
582++ name.name = domainname;
583++ tmy_fill_path_info(&name);
584++ /***** EXCLUSIVE SECTION START *****/
585++ mutex_lock(&domain_list_lock);
586++#ifdef DEBUG_DOMAIN_UNDELETE
587++ printk(KERN_DEBUG "tmy_delete_domain %s\n", domainname);
588++ list1_for_each_entry(domain, &domain_list, list) {
589++ if (tmy_pathcmp(domain->domainname, &name))
590++ continue;
591++ printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
592++ }
593++#endif
594++ /* Is there an active domain? */
595++ list1_for_each_entry(domain, &domain_list, list) {
596++ struct domain_info *domain2;
597++ /* Never delete KERNEL_DOMAIN */
598++ if (domain == &KERNEL_DOMAIN)
599++ continue;
600++ if (domain->is_deleted ||
601++ tmy_pathcmp(domain->domainname, &name))
602++ continue;
603++ /* Mark already deleted domains as non undeletable. */
604++ list1_for_each_entry(domain2, &domain_list, list) {
605++ if (!domain2->is_deleted ||
606++ tmy_pathcmp(domain2->domainname, &name))
607++ continue;
608++#ifdef DEBUG_DOMAIN_UNDELETE
609++ if (domain2->is_deleted != 255)
610++ printk(KERN_DEBUG
611++ "Marked %p as non undeletable\n",
612++ domain2);
613++#endif
614++ domain2->is_deleted = 255;
615++ }
616++ /* Delete and mark active domain as undeletable. */
617++ domain->is_deleted = 1;
618++#ifdef DEBUG_DOMAIN_UNDELETE
619++ printk(KERN_DEBUG "Marked %p as undeletable\n", domain);
620++#endif
621++ break;
622++ }
623++ mutex_unlock(&domain_list_lock);
624++ /***** EXCLUSIVE SECTION END *****/
625++ return 0;
626++}
627++
628++/**
629++ * tmy_undelete_domain - Undelete a domain.
630++ *
631++ * @domainname: The name of domain.
632++ *
633++ * Returns pointer to "struct domain_info" on success, NULL otherwise.
634++ */
635++struct domain_info *tmy_undelete_domain(const char *domainname)
636++{
637++ struct domain_info *domain;
638++ struct domain_info *candidate_domain = NULL;
639++ struct path_info name;
640++
641++ name.name = domainname;
642++ tmy_fill_path_info(&name);
643++ /***** EXCLUSIVE SECTION START *****/
644++ mutex_lock(&domain_list_lock);
645++#ifdef DEBUG_DOMAIN_UNDELETE
646++ printk(KERN_DEBUG "tmy_undelete_domain %s\n", domainname);
647++ list1_for_each_entry(domain, &domain_list, list) {
648++ if (tmy_pathcmp(domain->domainname, &name))
649++ continue;
650++ printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
651++ }
652++#endif
653++ list1_for_each_entry(domain, &domain_list, list) {
654++ if (tmy_pathcmp(&name, domain->domainname))
655++ continue;
656++ if (!domain->is_deleted) {
657++ /* This domain is active. I can't undelete. */
658++ candidate_domain = NULL;
659++#ifdef DEBUG_DOMAIN_UNDELETE
660++ printk(KERN_DEBUG "%p is active. I can't undelete.\n",
661++ domain);
662++#endif
663++ break;
664++ }
665++ /* Is this domain undeletable? */
666++ if (domain->is_deleted == 1)
667++ candidate_domain = domain;
668++ }
669++ if (candidate_domain) {
670++ candidate_domain->is_deleted = 0;
671++#ifdef DEBUG_DOMAIN_UNDELETE
672++ printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);
673++#endif
674++ }
675++ mutex_unlock(&domain_list_lock);
676++ /***** EXCLUSIVE SECTION END *****/
677++ return candidate_domain;
678++}
679++
680++/**
681++ * tmy_find_or_assign_new_domain - Create a domain.
682++ *
683++ * @domainname: The name of domain.
684++ * @profile: Profile number to assign if the domain was newly created.
685++ *
686++ * Returns pointer to "struct domain_info" on success, NULL otherwise.
687++ */
688++struct domain_info *tmy_find_or_assign_new_domain(const char *domainname,
689++ const u8 profile)
690++{
691++ struct domain_info *domain = NULL;
692++ const struct path_info *saved_domainname;
693++
694++ /***** EXCLUSIVE SECTION START *****/
695++ mutex_lock(&domain_list_lock);
696++ domain = tmy_find_domain(domainname);
697++ if (domain)
698++ goto out;
699++ if (!tmy_is_correct_domain(domainname, __func__))
700++ goto out;
701++ saved_domainname = tmy_save_name(domainname);
702++ if (!saved_domainname)
703++ goto out;
704++ /* Can I reuse memory of deleted domain? */
705++ list1_for_each_entry(domain, &domain_list, list) {
706++ struct task_struct *p;
707++ struct acl_info *ptr;
708++ bool flag;
709++ if (!domain->is_deleted ||
710++ domain->domainname != saved_domainname)
711++ continue;
712++ flag = false;
713++ /***** CRITICAL SECTION START *****/
714++ read_lock(&tasklist_lock);
715++ for_each_process(p) {
716++ if (tmy_real_domain(p) != domain)
717++ continue;
718++ flag = true;
719++ break;
720++ }
721++ read_unlock(&tasklist_lock);
722++ /***** CRITICAL SECTION END *****/
723++ if (flag)
724++ continue;
725++#ifdef DEBUG_DOMAIN_UNDELETE
726++ printk(KERN_DEBUG "Reusing %p %s\n", domain,
727++ domain->domainname->name);
728++#endif
729++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
730++ ptr->type |= ACL_DELETED;
731++ }
732++ tmy_set_domain_flag(domain, true, domain->flags);
733++ domain->profile = profile;
734++ domain->quota_warned = false;
735++ mb(); /* Avoid out-of-order execution. */
736++ domain->is_deleted = 0;
737++ goto out;
738++ }
739++ /* No memory reusable. Create using new memory. */
740++ domain = tmy_alloc_element(sizeof(*domain));
741++ if (domain) {
742++ INIT_LIST1_HEAD(&domain->acl_info_list);
743++ domain->domainname = saved_domainname;
744++ domain->profile = profile;
745++ list1_add_tail(&domain->list, &domain_list);
746++ }
747++out:
748++ mutex_unlock(&domain_list_lock);
749++ /***** EXCLUSIVE SECTION END *****/
750++ return domain;
751++}
752++
753++/**
754++ * tmy_find_next_domain - Find a domain.
755++ *
756++ * @bprm: Pointer to "struct linux_binprm".
757++ * @next_domain: Pointer to pointer to "struct domain_info".
758++ *
759++ * Returns 0 on success, negative value otherwise.
760++ */
761++int tmy_find_next_domain(struct linux_binprm *bprm,
762++ struct domain_info **next_domain)
763++{
764++ /*
765++ * This function assumes that the size of buffer returned by
766++ * tmy_realpath() = TMY_MAX_PATHNAME_LEN.
767++ */
768++ struct tmy_page_buffer *tmp = tmy_alloc(sizeof(*tmp));
769++ struct domain_info *old_domain = tmy_domain();
770++ struct domain_info *domain = NULL;
771++ const char *old_domain_name = old_domain->domainname->name;
772++ const char *original_name = bprm->filename;
773++ char *new_domain_name = NULL;
774++ char *real_program_name = NULL;
775++ char *symlink_program_name = NULL;
776++ const u8 mode = tmy_check_flags(old_domain, TMY_TOMOYO_MAC_FOR_FILE);
777++ const bool is_enforce = (mode == 3);
778++ int retval = -ENOMEM;
779++ struct path_info r; /* real name */
780++ struct path_info s; /* symlink name */
781++ struct path_info l; /* last name */
782++
783++ if (!tmp)
784++ goto out;
785++
786++ {
787++ /*
788++ * Built-in initializers. This is needed because policies are
789++ * not loaded until starting /sbin/init.
790++ */
791++ static bool first = true;
792++ if (first) {
793++ update_domain_initializer_entry(NULL, "/sbin/hotplug",
794++ false, false);
795++ update_domain_initializer_entry(NULL, "/sbin/modprobe",
796++ false, false);
797++ first = false;
798++ }
799++ }
800++
801++ /* Get tmy_realpath of program. */
802++ retval = -ENOENT; /* I hope tmy_realpath() won't fail with -ENOMEM. */
803++ real_program_name = tmy_realpath(original_name);
804++ if (!real_program_name)
805++ goto out;
806++ /* Get tmy_realpath of symbolic link. */
807++ symlink_program_name = tmy_realpath_nofollow(original_name);
808++ if (!symlink_program_name)
809++ goto out;
810++
811++ r.name = real_program_name;
812++ tmy_fill_path_info(&r);
813++ s.name = symlink_program_name;
814++ tmy_fill_path_info(&s);
815++ l.name = tmy_get_last_name(old_domain);
816++ tmy_fill_path_info(&l);
817++
818++ /* Check 'alias' directive. */
819++ if (tmy_pathcmp(&r, &s)) {
820++ struct alias_entry *ptr;
821++ /* Is this program allowed to be called via symbolic links? */
822++ list1_for_each_entry(ptr, &alias_list, list) {
823++ if (ptr->is_deleted ||
824++ tmy_pathcmp(&r, ptr->original_name) ||
825++ tmy_pathcmp(&s, ptr->aliased_name))
826++ continue;
827++ memset(real_program_name, 0, TMY_MAX_PATHNAME_LEN);
828++ strncpy(real_program_name, ptr->aliased_name->name,
829++ TMY_MAX_PATHNAME_LEN - 1);
830++ tmy_fill_path_info(&r);
831++ break;
832++ }
833++ }
834++
835++ /* Check execute permission. */
836++ retval = tmy_check_exec_perm(old_domain, &r, tmp);
837++ if (retval < 0)
838++ goto out;
839++
840++ new_domain_name = tmp->buffer;
841++ if (is_domain_initializer(old_domain->domainname, &r, &l)) {
842++ /* Transit to the child of KERNEL_DOMAIN domain. */
843++ snprintf(new_domain_name, TMY_MAX_PATHNAME_LEN + 1,
844++ ROOT_NAME " " "%s", real_program_name);
845++ } else if (old_domain == &KERNEL_DOMAIN && !sbin_init_started) {
846++ /*
847++ * Needn't to transit from kernel domain before starting
848++ * /sbin/init. But transit from kernel domain if executing
849++ * initializers because they might start before /sbin/init.
850++ */
851++ domain = old_domain;
852++ } else if (is_domain_keeper(old_domain->domainname, &r, &l)) {
853++ /* Keep current domain. */
854++ domain = old_domain;
855++ } else {
856++ /* Normal domain transition. */
857++ snprintf(new_domain_name, TMY_MAX_PATHNAME_LEN + 1,
858++ "%s %s", old_domain_name, real_program_name);
859++ }
860++ if (domain || strlen(new_domain_name) >= TMY_MAX_PATHNAME_LEN)
861++ goto done;
862++ domain = tmy_find_domain(new_domain_name);
863++ if (domain)
864++ goto done;
865++ if (is_enforce)
866++ goto done;
867++ domain = tmy_find_or_assign_new_domain(new_domain_name,
868++ old_domain->profile);
869++done:
870++ if (domain)
871++ goto out;
872++ printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
873++ new_domain_name);
874++ if (is_enforce)
875++ retval = -EPERM;
876++ else
877++ tmy_set_domain_flag(old_domain, false,
878++ DOMAIN_FLAGS_TRANSITION_FAILED);
879++out:
880++ tmy_free(real_program_name);
881++ tmy_free(symlink_program_name);
882++ *next_domain = domain ? domain : old_domain;
883++ tmy_free(tmp);
884++ return retval;
885++}
--- tags/lkml/11/tomoyo-hooks.patch (nonexistent)
+++ tags/lkml/11/tomoyo-hooks.patch (revision 1723)
@@ -0,0 +1,497 @@
1+Subject: LSM adapter functions.
2+
3+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
4+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
6+---
7+ security/tomoyo/tomoyo.c | 376 +++++++++++++++++++++++++++++++++++++++++++++++
8+ security/tomoyo/tomoyo.h | 105 +++++++++++++
9+ 2 files changed, 481 insertions(+)
10+
11+--- /dev/null
12++++ linux-next/security/tomoyo/tomoyo.c
13+@@ -0,0 +1,376 @@
14++/*
15++ * security/tomoyo/tomoyo.c
16++ *
17++ * LSM hooks for TOMOYO Linux.
18++ *
19++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
20++ *
21++ * Version: 2.2.0-pre 2008/10/10
22++ *
23++ */
24++
25++#include <linux/security.h>
26++#include "common.h"
27++#include "tomoyo.h"
28++#include "realpath.h"
29++
30++static int tmy_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp)
31++{
32++ /*
33++ * Since "struct domain_info *" is a sharable pointer, we don't need
34++ * to duplicate.
35++ */
36++ new->security = old->security;
37++ return 0;
38++}
39++
40++static int tmy_bprm_set_creds(struct linux_binprm *bprm)
41++{
42++ /*
43++ * Do only if this function is called for the first time of an execve
44++ * operation.
45++ */
46++ if (bprm->cred_prepared)
47++ return 0;
48++ /*
49++ * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
50++ * for the first time.
51++ */
52++ if (!sbin_init_started)
53++ tmy_load_policy(bprm->filename);
54++ /*
55++ * Tell tmy_bprm_check_security() is called for the first time of an
56++ * execve operation.
57++ */
58++ bprm->cred->security = NULL;
59++ return 0;
60++}
61++
62++static int tmy_bprm_check_security(struct linux_binprm *bprm)
63++{
64++ struct domain_info *domain = bprm->cred->security;
65++
66++ /*
67++ * Execute permission is checked against pathname passed to do_execve()
68++ * using current domain.
69++ */
70++ if (!domain) {
71++ struct domain_info *next_domain = NULL;
72++ int retval = tmy_find_next_domain(bprm, &next_domain);
73++
74++ if (!retval)
75++ bprm->cred->security = next_domain;
76++ return retval;
77++ }
78++ /*
79++ * Read permission is checked against interpreters using next domain.
80++ * '1' is the result of open_to_namei_flags(O_RDONLY).
81++ */
82++ return tmy_check_open_permission(domain, &bprm->file->f_path, 1);
83++}
84++
85++static int tmy_sysctl(struct ctl_table *table, int op)
86++{
87++ int error;
88++ char *name;
89++
90++ op &= MAY_READ | MAY_WRITE;
91++ if (!op)
92++ return 0;
93++ name = sysctlpath_from_table(table);
94++ if (!name)
95++ return -ENOMEM;
96++ error = tmy_check_file_perm(tmy_domain(), name, op);
97++ tmy_free(name);
98++ return error;
99++}
100++
101++/**
102++ * tmy_update_result - Update error code.
103++ *
104++ * @error: Return code from security_path_*().
105++ *
106++ * To be able to return DAC's error (if any) to the caller instead of
107++ * MAC's error, we don't return MAC's error at security_path_*().
108++ *
109++ * We remember MAC's error only if security_path_*() returned an error.
110++ *
111++ * Returns 0 on success, -ENOMEM otherwise if @error != 0.
112++ * Returns previously saved error code and clears it if @error == 0.
113++ */
114++static int tmy_update_result(int error)
115++{
116++ /* Structure for holding the result of security_path_*(). */
117++ struct check_result_entry {
118++ struct list_head list;
119++ struct task_struct *task; /* = current */
120++ int error; /* != 0 */
121++ };
122++ static LIST_HEAD(list);
123++ static DEFINE_SPINLOCK(lock);
124++ struct task_struct *task = current;
125++ struct check_result_entry *entry;
126++ if (!error) {
127++ if (!list_empty(&list)) {
128++ struct check_result_entry *p;
129++ entry = NULL;
130++ /***** CRITICAL SECTION START *****/
131++ spin_lock(&lock);
132++ list_for_each_entry(p, &list, list) {
133++ if (p->task != task)
134++ continue;
135++ list_del(&p->list);
136++ entry = p;
137++ break;
138++ }
139++ spin_unlock(&lock);
140++ /***** CRITICAL SECTION END *****/
141++ if (entry) {
142++ error = entry->error;
143++ kfree(entry);
144++ }
145++ }
146++ return error;
147++ }
148++ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
149++ if (!entry)
150++ return -ENOMEM;
151++ entry->task = task;
152++ entry->error = error;
153++ /***** CRITICAL SECTION START *****/
154++ spin_lock(&lock);
155++ list_add(&entry->list, &list);
156++ spin_unlock(&lock);
157++ /***** CRITICAL SECTION END *****/
158++ return 0;
159++}
160++
161++/**
162++ * tmy_save_result - Remember error code for security_inode_*() if any.
163++ *
164++ * @error: Return code from security_path_*().
165++ *
166++ * Returns 0 on success, -ENOMEM otherwise.
167++ *
168++ * We don't save if @error == 0.
169++ */
170++static int tmy_save_result(const int error)
171++{
172++ return error ? tmy_update_result(error) : 0;
173++}
174++
175++/**
176++ * tmy_load_result - Fetch error code for security_inode_*().
177++ *
178++ * Returns error code saved by security_path_*().
179++ */
180++static int tmy_load_result(void)
181++{
182++ return tmy_update_result(0);
183++}
184++
185++/* Clear error code in case security_inode_*() was not called. */
186++static void tmy_path_clear(void)
187++{
188++ tmy_load_result();
189++}
190++
191++static int tmy_path_truncate(struct path *path, loff_t length,
192++ unsigned int time_attrs, struct file *filp)
193++{
194++ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
195++ TMY_TYPE_TRUNCATE_ACL,
196++ path));
197++}
198++
199++static int tmy_path_unlink(struct path *parent, struct dentry *dentry)
200++{
201++ struct path path = { parent->mnt, dentry };
202++ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
203++ TMY_TYPE_UNLINK_ACL,
204++ &path));
205++}
206++
207++static int tmy_path_mkdir(struct path *parent, struct dentry *dentry, int mode)
208++{
209++ struct path path = { parent->mnt, dentry };
210++ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
211++ TMY_TYPE_MKDIR_ACL,
212++ &path));
213++}
214++
215++static int tmy_path_rmdir(struct path *parent, struct dentry *dentry)
216++{
217++ struct path path = { parent->mnt, dentry };
218++ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
219++ TMY_TYPE_RMDIR_ACL,
220++ &path));
221++}
222++
223++static int tmy_path_symlink(struct path *parent, struct dentry *dentry,
224++ const char *old_name)
225++{
226++ struct path path = { parent->mnt, dentry };
227++ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
228++ TMY_TYPE_SYMLINK_ACL,
229++ &path));
230++}
231++
232++static int tmy_path_mknod(struct path *parent, struct dentry *dentry, int mode,
233++ unsigned int dev)
234++{
235++ struct path path = { parent->mnt, dentry };
236++ int type = TMY_TYPE_CREATE_ACL;
237++
238++ switch (mode & S_IFMT) {
239++ case S_IFCHR:
240++ type = TMY_TYPE_MKCHAR_ACL;
241++ break;
242++ case S_IFBLK:
243++ type = TMY_TYPE_MKBLOCK_ACL;
244++ break;
245++ case S_IFIFO:
246++ type = TMY_TYPE_MKFIFO_ACL;
247++ break;
248++ case S_IFSOCK:
249++ type = TMY_TYPE_MKSOCK_ACL;
250++ break;
251++ }
252++ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
253++ type, &path));
254++}
255++
256++static int tmy_path_link(struct dentry *old_dentry, struct path *new_dir,
257++ struct dentry *new_dentry)
258++{
259++ struct path path1 = { new_dir->mnt, old_dentry };
260++ struct path path2 = { new_dir->mnt, new_dentry };
261++ return tmy_save_result(tmy_check_2path_perm(tmy_domain(),
262++ TMY_TYPE_LINK_ACL,
263++ &path1, &path2));
264++}
265++
266++static int tmy_path_rename(struct path *old_parent, struct dentry *old_dentry,
267++ struct path *new_parent, struct dentry *new_dentry)
268++{
269++ struct path path1 = { old_parent->mnt, old_dentry };
270++ struct path path2 = { new_parent->mnt, new_dentry };
271++ return tmy_save_result(tmy_check_2path_perm(tmy_domain(),
272++ TMY_TYPE_RENAME_ACL,
273++ &path1, &path2));
274++}
275++
276++static int tmy_inode_link(struct dentry *old_dentry, struct inode *inode,
277++ struct dentry *new_dentry)
278++{
279++ return tmy_load_result();
280++}
281++
282++static int tmy_inode_unlink(struct inode *inode, struct dentry *dentry)
283++{
284++ return tmy_load_result();
285++}
286++
287++static int tmy_inode_symlink(struct inode *inode, struct dentry *dentry,
288++ const char *name)
289++{
290++ return tmy_load_result();
291++}
292++
293++static int tmy_inode_mkdir(struct inode *inode, struct dentry *dentry,
294++ int mask)
295++{
296++ return tmy_load_result();
297++}
298++
299++static int tmy_inode_rmdir(struct inode *inode, struct dentry *dentry)
300++{
301++ return tmy_load_result();
302++}
303++
304++static int tmy_inode_create(struct inode *dir, struct dentry *dentry, int mode)
305++{
306++ return tmy_load_result();
307++}
308++
309++static int tmy_inode_mknod(struct inode *inode, struct dentry *dentry,
310++ int mode, dev_t dev)
311++{
312++ return tmy_load_result();
313++}
314++
315++static int tmy_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
316++ struct inode *new_inode, struct dentry *new_dentry)
317++{
318++ return tmy_load_result();
319++}
320++
321++static int tmy_inode_setattr(struct dentry *dentry, struct iattr *iattr)
322++{
323++ return tmy_load_result();
324++}
325++
326++static int tmy_file_fcntl(struct file *file, unsigned int cmd,
327++ unsigned long arg)
328++{
329++ if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
330++ return tmy_check_rewrite_permission(tmy_domain(), file);
331++ return 0;
332++}
333++
334++static int tmy_dentry_open(struct file *f, const struct cred *cred)
335++{
336++ int flags = f->f_flags;
337++
338++ if ((flags + 1) & O_ACCMODE)
339++ flags++;
340++ flags |= f->f_flags & (O_APPEND | O_TRUNC);
341++ /* Don't check read permission here if called from do_execve(). */
342++ if (current->in_execve)
343++ return 0;
344++ return tmy_check_open_permission(tmy_domain(), &f->f_path, flags);
345++}
346++
347++static struct security_operations tomoyo_security_ops = {
348++ .name = "tomoyo",
349++ .cred_prepare = tmy_cred_prepare,
350++ .bprm_set_creds = tmy_bprm_set_creds,
351++ .bprm_check_security = tmy_bprm_check_security,
352++ .sysctl = tmy_sysctl,
353++ .file_fcntl = tmy_file_fcntl,
354++ .dentry_open = tmy_dentry_open,
355++ .path_truncate = tmy_path_truncate,
356++ .path_unlink = tmy_path_unlink,
357++ .path_mkdir = tmy_path_mkdir,
358++ .path_rmdir = tmy_path_rmdir,
359++ .path_symlink = tmy_path_symlink,
360++ .path_mknod = tmy_path_mknod,
361++ .path_link = tmy_path_link,
362++ .path_rename = tmy_path_rename,
363++ .inode_create = tmy_inode_create,
364++ .inode_setattr = tmy_inode_setattr,
365++ .inode_unlink = tmy_inode_unlink,
366++ .inode_mkdir = tmy_inode_mkdir,
367++ .inode_rmdir = tmy_inode_rmdir,
368++ .inode_symlink = tmy_inode_symlink,
369++ .inode_mknod = tmy_inode_mknod,
370++ .inode_link = tmy_inode_link,
371++ .inode_rename = tmy_inode_rename,
372++ .path_clear = tmy_path_clear,
373++};
374++
375++static int __init tmy_init(void)
376++{
377++ struct cred *cred = (struct cred *) current_cred();
378++
379++ if (!security_module_enable(&tomoyo_security_ops))
380++ return 0;
381++ /* register ourselves with the security framework */
382++ if (register_security(&tomoyo_security_ops))
383++ panic("Failure registering TOMOYO Linux");
384++ printk(KERN_INFO "TOMOYO Linux initialized\n");
385++ cred->security = &KERNEL_DOMAIN;
386++ return 0;
387++}
388++
389++security_initcall(tmy_init);
390+--- /dev/null
391++++ linux-next/security/tomoyo/tomoyo.h
392+@@ -0,0 +1,105 @@
393++/*
394++ * security/tomoyo/tomoyo.h
395++ *
396++ * Implementation of the Domain-Based Mandatory Access Control.
397++ *
398++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
399++ *
400++ * Version: 2.2.0-pre 2008/10/10
401++ *
402++ */
403++
404++#ifndef _SECURITY_TOMOYO_TOMOYO_H
405++#define _SECURITY_TOMOYO_TOMOYO_H
406++
407++struct path_info;
408++struct path;
409++struct inode;
410++struct linux_binprm;
411++struct pt_regs;
412++struct tmy_page_buffer;
413++
414++int tmy_check_file_perm(struct domain_info *domain, const char *filename,
415++ const u8 perm);
416++int tmy_check_exec_perm(struct domain_info *domain,
417++ const struct path_info *filename,
418++ struct tmy_page_buffer *buf);
419++int tmy_check_open_permission(struct domain_info *domain, struct path *path,
420++ const int flag);
421++int tmy_check_1path_perm(struct domain_info *domain, const u8 operation,
422++ struct path *path);
423++int tmy_check_2path_perm(struct domain_info *domain, const u8 operation,
424++ struct path *path1, struct path *path2);
425++int tmy_check_rewrite_permission(struct domain_info *domain,
426++ struct file *filp);
427++int tmy_find_next_domain(struct linux_binprm *bprm,
428++ struct domain_info **next_domain);
429++
430++/* Index numbers for Access Controls. */
431++
432++#define TYPE_SINGLE_PATH_ACL 0
433++#define TYPE_DOUBLE_PATH_ACL 1
434++
435++/* Index numbers for File Controls. */
436++
437++/*
438++ * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
439++ * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
440++ * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
441++ * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
442++ * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
443++ * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
444++ */
445++
446++#define TMY_TYPE_READ_WRITE_ACL 0
447++#define TMY_TYPE_EXECUTE_ACL 1
448++#define TMY_TYPE_READ_ACL 2
449++#define TMY_TYPE_WRITE_ACL 3
450++#define TMY_TYPE_CREATE_ACL 4
451++#define TMY_TYPE_UNLINK_ACL 5
452++#define TMY_TYPE_MKDIR_ACL 6
453++#define TMY_TYPE_RMDIR_ACL 7
454++#define TMY_TYPE_MKFIFO_ACL 8
455++#define TMY_TYPE_MKSOCK_ACL 9
456++#define TMY_TYPE_MKBLOCK_ACL 10
457++#define TMY_TYPE_MKCHAR_ACL 11
458++#define TMY_TYPE_TRUNCATE_ACL 12
459++#define TMY_TYPE_SYMLINK_ACL 13
460++#define TMY_TYPE_REWRITE_ACL 14
461++#define MAX_SINGLE_PATH_OPERATION 15
462++
463++#define TMY_TYPE_LINK_ACL 0
464++#define TMY_TYPE_RENAME_ACL 1
465++#define MAX_DOUBLE_PATH_OPERATION 2
466++
467++#define TMY_DOMAINPOLICY 0
468++#define TMY_EXCEPTIONPOLICY 1
469++#define TMY_DOMAIN_STATUS 2
470++#define TMY_PROCESS_STATUS 3
471++#define TMY_MEMINFO 4
472++#define TMY_SELFDOMAIN 5
473++#define TMY_VERSION 6
474++#define TMY_PROFILE 7
475++#define TMY_MANAGER 8
476++#define TMY_UPDATESCOUNTER 9
477++
478++extern struct domain_info KERNEL_DOMAIN;
479++
480++static inline struct domain_info *tmy_domain(void)
481++{
482++ return current_cred()->security;
483++}
484++
485++/* Caller holds tasklist_lock spinlock. */
486++static inline struct domain_info *tmy_real_domain(struct task_struct *task)
487++{
488++ /***** CRITICAL SECTION START *****/
489++ const struct cred *cred = get_task_cred(task);
490++ struct domain_info *domain = cred->security;
491++
492++ put_cred(cred);
493++ return domain;
494++ /***** CRITICAL SECTION END *****/
495++}
496++
497++#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */
--- tags/lkml/11/tomoyo-file-restriction-part.patch (nonexistent)
+++ tags/lkml/11/tomoyo-file-restriction-part.patch (revision 1723)
@@ -0,0 +1,1246 @@
1+Subject: File operation restriction part.
2+
3+This file controls file related operations.
4+
5+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
6+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
7+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
8+---
9+ security/tomoyo/file.c | 1232 +++++++++++++++++++++++++++++++++++++++++++++++++
10+ 1 file changed, 1232 insertions(+)
11+
12+--- /dev/null
13++++ linux-next/security/tomoyo/file.c
14+@@ -0,0 +1,1232 @@
15++/*
16++ * security/tomoyo/file.c
17++ *
18++ * Implementation of the Domain-Based Mandatory Access Control.
19++ *
20++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
21++ *
22++ * Version: 2.2.0-pre 2008/10/10
23++ *
24++ */
25++
26++#include "common.h"
27++#include "tomoyo.h"
28++#include "realpath.h"
29++#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
30++
31++/* Structure for "allow_read" keyword. */
32++struct globally_readable_file_entry {
33++ struct list1_head list;
34++ const struct path_info *filename;
35++ bool is_deleted;
36++};
37++
38++/* Structure for "file_pattern" keyword. */
39++struct pattern_entry {
40++ struct list1_head list;
41++ const struct path_info *pattern;
42++ bool is_deleted;
43++};
44++
45++/* Structure for "deny_rewrite" keyword. */
46++struct no_rewrite_entry {
47++ struct list1_head list;
48++ const struct path_info *pattern;
49++ bool is_deleted;
50++};
51++
52++/* Keyword array for single path operations. */
53++static const char *sp_keyword[MAX_SINGLE_PATH_OPERATION] = {
54++ [TMY_TYPE_READ_WRITE_ACL] = "read/write",
55++ [TMY_TYPE_EXECUTE_ACL] = "execute",
56++ [TMY_TYPE_READ_ACL] = "read",
57++ [TMY_TYPE_WRITE_ACL] = "write",
58++ [TMY_TYPE_CREATE_ACL] = "create",
59++ [TMY_TYPE_UNLINK_ACL] = "unlink",
60++ [TMY_TYPE_MKDIR_ACL] = "mkdir",
61++ [TMY_TYPE_RMDIR_ACL] = "rmdir",
62++ [TMY_TYPE_MKFIFO_ACL] = "mkfifo",
63++ [TMY_TYPE_MKSOCK_ACL] = "mksock",
64++ [TMY_TYPE_MKBLOCK_ACL] = "mkblock",
65++ [TMY_TYPE_MKCHAR_ACL] = "mkchar",
66++ [TMY_TYPE_TRUNCATE_ACL] = "truncate",
67++ [TMY_TYPE_SYMLINK_ACL] = "symlink",
68++ [TMY_TYPE_REWRITE_ACL] = "rewrite",
69++};
70++
71++/* Keyword array for double path operations. */
72++static const char *dp_keyword[MAX_DOUBLE_PATH_OPERATION] = {
73++ [TMY_TYPE_LINK_ACL] = "link",
74++ [TMY_TYPE_RENAME_ACL] = "rename",
75++};
76++
77++/**
78++ * tmy_sp2keyword - Get the name of single path operation.
79++ *
80++ * @operation: Type of operation.
81++ *
82++ * Returns the name of single path operation.
83++ */
84++const char *tmy_sp2keyword(const u8 operation)
85++{
86++ return (operation < MAX_SINGLE_PATH_OPERATION)
87++ ? sp_keyword[operation] : NULL;
88++}
89++
90++/**
91++ * tmy_dp2keyword - Get the name of double path operation.
92++ *
93++ * @operation: Type of operation.
94++ *
95++ * Returns the name of double path operation.
96++ */
97++const char *tmy_dp2keyword(const u8 operation)
98++{
99++ return (operation < MAX_DOUBLE_PATH_OPERATION)
100++ ? dp_keyword[operation] : NULL;
101++}
102++
103++/**
104++ * strendswith - Check whether the token ends with the given token.
105++ *
106++ * @name: The token to check.
107++ * @tail: The token to find.
108++ *
109++ * Returns true if @name ends with @tail, false otherwise.
110++ */
111++static bool strendswith(const char *name, const char *tail)
112++{
113++ int len;
114++
115++ if (!name || !tail)
116++ return false;
117++ len = strlen(name) - strlen(tail);
118++ return len >= 0 && !strcmp(name + len, tail);
119++}
120++
121++/**
122++ * tmy_get_path - Get realpath.
123++ *
124++ * @path: Pointer to "struct path".
125++ *
126++ * Returns pointer to "struct path_info" on success, NULL otherwise.
127++ */
128++static struct path_info *tmy_get_path(struct path *path)
129++{
130++ int error;
131++ struct path_info_with_data *buf = tmy_alloc(sizeof(*buf));
132++
133++ if (!buf)
134++ return NULL;
135++ /* Preserve one byte for appending "/". */
136++ error = tmy_realpath_from_path2(path, buf->body,
137++ sizeof(buf->body) - 2);
138++ if (!error) {
139++ buf->head.name = buf->body;
140++ tmy_fill_path_info(&buf->head);
141++ return &buf->head;
142++ }
143++ tmy_free(buf);
144++ return NULL;
145++}
146++
147++static int update_double_path_acl(const u8 type, const char *filename1,
148++ const char *filename2,
149++ struct domain_info * const domain,
150++ const bool is_delete);
151++static int update_single_path_acl(const u8 type, const char *filename,
152++ struct domain_info * const domain,
153++ const bool is_delete);
154++
155++/**
156++ * tmy_add_domain_acl - Add the given ACL to the given domain.
157++ *
158++ * @domain: Pointer to "struct domain_info". May be NULL.
159++ * @acl: Pointer to "struct acl_info".
160++ *
161++ * Returns 0.
162++ */
163++static int tmy_add_domain_acl(struct domain_info *domain, struct acl_info *acl)
164++{
165++ if (domain) {
166++ /*
167++ * We need to serialize because this function is called by
168++ * update_single_path_acl() and update_double_path_acl().
169++ */
170++ static DEFINE_SPINLOCK(lock);
171++ /***** CRITICAL SECTION START *****/
172++ spin_lock(&lock);
173++ list1_add_tail(&acl->list, &domain->acl_info_list);
174++ spin_unlock(&lock);
175++ /***** CRITICAL SECTION END *****/
176++ } else {
177++ acl->type &= ~ACL_DELETED;
178++ }
179++ tmy_update_counter(TMY_UPDATES_COUNTER_DOMAIN_POLICY);
180++ return 0;
181++}
182++
183++/**
184++ * tmy_del_domain_acl - Delete the given ACL from the domain.
185++ *
186++ * @acl: Pointer to "struct acl_info". May be NULL.
187++ *
188++ * Returns 0.
189++ */
190++static int tmy_del_domain_acl(struct acl_info *acl)
191++{
192++ if (acl)
193++ acl->type |= ACL_DELETED;
194++ tmy_update_counter(TMY_UPDATES_COUNTER_DOMAIN_POLICY);
195++ return 0;
196++}
197++
198++/*
199++ * The list for "struct globally_readable_file_entry".
200++ *
201++ * This list is updated only inside update_globally_readable_entry(), thus
202++ * no global mutex exists.
203++ */
204++static LIST1_HEAD(globally_readable_list);
205++
206++/**
207++ * update_globally_readable_entry - Update "struct globally_readable_file_entry" list.
208++ *
209++ * @filename: Filename unconditionally permitted to open() for reading.
210++ * @is_delete: True if it is a delete request.
211++ *
212++ * Returns 0 on success, negative value otherwise.
213++ */
214++static int update_globally_readable_entry(const char *filename,
215++ const bool is_delete)
216++{
217++ struct globally_readable_file_entry *new_entry;
218++ struct globally_readable_file_entry *ptr;
219++ static DEFINE_MUTEX(lock);
220++ const struct path_info *saved_filename;
221++ int error = -ENOMEM;
222++
223++ if (!tmy_is_correct_path(filename, 1, 0, -1, __func__))
224++ return -EINVAL;
225++ saved_filename = tmy_save_name(filename);
226++ if (!saved_filename)
227++ return -ENOMEM;
228++ /***** EXCLUSIVE SECTION START *****/
229++ mutex_lock(&lock);
230++ list1_for_each_entry(ptr, &globally_readable_list, list) {
231++ if (ptr->filename != saved_filename)
232++ continue;
233++ ptr->is_deleted = is_delete;
234++ error = 0;
235++ goto out;
236++ }
237++ if (is_delete) {
238++ error = -ENOENT;
239++ goto out;
240++ }
241++ new_entry = tmy_alloc_element(sizeof(*new_entry));
242++ if (!new_entry)
243++ goto out;
244++ new_entry->filename = saved_filename;
245++ list1_add_tail(&new_entry->list, &globally_readable_list);
246++ error = 0;
247++out:
248++ mutex_unlock(&lock);
249++ /***** EXCLUSIVE SECTION END *****/
250++ tmy_update_counter(TMY_UPDATES_COUNTER_EXCEPTION_POLICY);
251++ return error;
252++}
253++
254++/**
255++ * is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
256++ *
257++ * @filename: The filename to check.
258++ *
259++ * Returns true if any domain can open @filename for reading, false otherwise.
260++ */
261++static bool is_globally_readable_file(const struct path_info *filename)
262++{
263++ struct globally_readable_file_entry *ptr;
264++
265++ list1_for_each_entry(ptr, &globally_readable_list, list) {
266++ if (!ptr->is_deleted &&
267++ tmy_path_matches_pattern(filename, ptr->filename))
268++ return true;
269++ }
270++ return false;
271++}
272++
273++/**
274++ * tmy_write_globally_readable_policy - Write "struct globally_readable_file_entry" list.
275++ *
276++ * @data: String to parse.
277++ * @is_delete: True if it is a delete request.
278++ *
279++ * Returns 0 on success, negative value otherwise.
280++ */
281++int tmy_write_globally_readable_policy(char *data, const bool is_delete)
282++{
283++ return update_globally_readable_entry(data, is_delete);
284++}
285++
286++/**
287++ * tmy_read_globally_readable_policy - Read "struct globally_readable_file_entry" list.
288++ *
289++ * @head: Pointer to "struct tmy_io_buffer".
290++ *
291++ * Returns true on success, false otherwise.
292++ */
293++bool tmy_read_globally_readable_policy(struct tmy_io_buffer *head)
294++{
295++ struct list1_head *pos;
296++
297++ list1_for_each_cookie(pos, head->read_var2, &globally_readable_list) {
298++ struct globally_readable_file_entry *ptr;
299++ ptr = list1_entry(pos, struct globally_readable_file_entry,
300++ list);
301++ if (ptr->is_deleted)
302++ continue;
303++ if (!tmy_io_printf(head, KEYWORD_ALLOW_READ "%s\n",
304++ ptr->filename->name))
305++ goto out;
306++ }
307++ return true;
308++out:
309++ return false;
310++}
311++
312++/*
313++ * The list for "struct pattern_entry".
314++ *
315++ * This list is updated only inside update_file_pattern_entry(), thus
316++ * no global mutex exists.
317++ */
318++static LIST1_HEAD(pattern_list);
319++
320++/**
321++ * update_file_pattern_entry - Update "struct pattern_entry" list.
322++ *
323++ * @pattern: Pathname pattern.
324++ * @is_delete: True if it is a delete request.
325++ *
326++ * Returns 0 on success, negative value otherwise.
327++ */
328++static int update_file_pattern_entry(const char *pattern, const bool is_delete)
329++{
330++ struct pattern_entry *new_entry;
331++ struct pattern_entry *ptr;
332++ static DEFINE_MUTEX(lock);
333++ const struct path_info *saved_pattern;
334++ int error = -ENOMEM;
335++
336++ if (!tmy_is_correct_path(pattern, 0, 1, 0, __func__))
337++ return -EINVAL;
338++ saved_pattern = tmy_save_name(pattern);
339++ if (!saved_pattern)
340++ return -ENOMEM;
341++ /***** EXCLUSIVE SECTION START *****/
342++ mutex_lock(&lock);
343++ list1_for_each_entry(ptr, &pattern_list, list) {
344++ if (saved_pattern != ptr->pattern)
345++ continue;
346++ ptr->is_deleted = is_delete;
347++ error = 0;
348++ goto out;
349++ }
350++ if (is_delete) {
351++ error = -ENOENT;
352++ goto out;
353++ }
354++ new_entry = tmy_alloc_element(sizeof(*new_entry));
355++ if (!new_entry)
356++ goto out;
357++ new_entry->pattern = saved_pattern;
358++ list1_add_tail(&new_entry->list, &pattern_list);
359++ error = 0;
360++out:
361++ mutex_unlock(&lock);
362++ /***** EXCLUSIVE SECTION END *****/
363++ tmy_update_counter(TMY_UPDATES_COUNTER_EXCEPTION_POLICY);
364++ return error;
365++}
366++
367++/**
368++ * get_file_pattern - Get patterned pathname.
369++ *
370++ * @filename: The filename to find patterned pathname.
371++ *
372++ * Returns pointer to pathname pattern if matched, @filename otherwise.
373++ */
374++static const struct path_info *
375++get_file_pattern(const struct path_info *filename)
376++{
377++ struct pattern_entry *ptr;
378++ const struct path_info *pattern = NULL;
379++
380++ list1_for_each_entry(ptr, &pattern_list, list) {
381++ if (ptr->is_deleted)
382++ continue;
383++ if (!tmy_path_matches_pattern(filename, ptr->pattern))
384++ continue;
385++ pattern = ptr->pattern;
386++ if (strendswith(pattern->name, "/\\*")) {
387++ /* Do nothing. Try to find the better match. */
388++ } else {
389++ /* This would be the better match. Use this. */
390++ break;
391++ }
392++ }
393++ if (pattern)
394++ filename = pattern;
395++ return filename;
396++}
397++
398++/**
399++ * tmy_write_pattern_policy - Write "struct pattern_entry" list.
400++ *
401++ * @data: String to parse.
402++ * @is_delete: True if it is a delete request.
403++ *
404++ * Returns 0 on success, negative value otherwise.
405++ */
406++int tmy_write_pattern_policy(char *data, const bool is_delete)
407++{
408++ return update_file_pattern_entry(data, is_delete);
409++}
410++
411++/**
412++ * tmy_read_file_pattern - Read "struct pattern_entry" list.
413++ *
414++ * @head: Pointer to "struct tmy_io_buffer".
415++ *
416++ * Returns true on success, false otherwise.
417++ */
418++bool tmy_read_file_pattern(struct tmy_io_buffer *head)
419++{
420++ struct list1_head *pos;
421++
422++ list1_for_each_cookie(pos, head->read_var2, &pattern_list) {
423++ struct pattern_entry *ptr;
424++ ptr = list1_entry(pos, struct pattern_entry, list);
425++ if (ptr->is_deleted)
426++ continue;
427++ if (!tmy_io_printf(head, KEYWORD_FILE_PATTERN "%s\n",
428++ ptr->pattern->name))
429++ goto out;
430++ }
431++ return true;
432++out:
433++ return false;
434++}
435++
436++/*
437++ * The list for "struct no_rewrite_entry".
438++ *
439++ * This list is updated only inside update_no_rewrite_entry(), thus
440++ * no global mutex exists.
441++ */
442++static LIST1_HEAD(no_rewrite_list);
443++
444++/**
445++ * update_no_rewrite_entry - Update "struct no_rewrite_entry" list.
446++ *
447++ * @pattern: Pathname pattern that are not rewritable by default.
448++ * @is_delete: True if it is a delete request.
449++ *
450++ * Returns 0 on success, negative value otherwise.
451++ */
452++static int update_no_rewrite_entry(const char *pattern, const bool is_delete)
453++{
454++ struct no_rewrite_entry *new_entry, *ptr;
455++ static DEFINE_MUTEX(lock);
456++ const struct path_info *saved_pattern;
457++ int error = -ENOMEM;
458++
459++ if (!tmy_is_correct_path(pattern, 0, 0, 0, __func__))
460++ return -EINVAL;
461++ saved_pattern = tmy_save_name(pattern);
462++ if (!saved_pattern)
463++ return -ENOMEM;
464++ /***** EXCLUSIVE SECTION START *****/
465++ mutex_lock(&lock);
466++ list1_for_each_entry(ptr, &no_rewrite_list, list) {
467++ if (ptr->pattern != saved_pattern)
468++ continue;
469++ ptr->is_deleted = is_delete;
470++ error = 0;
471++ goto out;
472++ }
473++ if (is_delete) {
474++ error = -ENOENT;
475++ goto out;
476++ }
477++ new_entry = tmy_alloc_element(sizeof(*new_entry));
478++ if (!new_entry)
479++ goto out;
480++ new_entry->pattern = saved_pattern;
481++ list1_add_tail(&new_entry->list, &no_rewrite_list);
482++ error = 0;
483++out:
484++ mutex_unlock(&lock);
485++ /***** EXCLUSIVE SECTION END *****/
486++ tmy_update_counter(TMY_UPDATES_COUNTER_EXCEPTION_POLICY);
487++ return error;
488++}
489++
490++/**
491++ * is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
492++ *
493++ * @filename: Filename to check.
494++ *
495++ * Returns true if @filename is specified by "deny_rewrite" directive,
496++ * false otherwise.
497++ */
498++static bool is_no_rewrite_file(const struct path_info *filename)
499++{
500++ struct no_rewrite_entry *ptr;
501++
502++ list1_for_each_entry(ptr, &no_rewrite_list, list) {
503++ if (ptr->is_deleted)
504++ continue;
505++ if (!tmy_path_matches_pattern(filename, ptr->pattern))
506++ continue;
507++ return true;
508++ }
509++ return false;
510++}
511++
512++/**
513++ * tmy_write_no_rewrite_policy - Write "struct no_rewrite_entry" list.
514++ *
515++ * @data: String to parse.
516++ * @is_delete: True if it is a delete request.
517++ *
518++ * Returns 0 on success, negative value otherwise.
519++ */
520++int tmy_write_no_rewrite_policy(char *data, const bool is_delete)
521++{
522++ return update_no_rewrite_entry(data, is_delete);
523++}
524++
525++/**
526++ * tmy_read_no_rewrite_policy - Read "struct no_rewrite_entry" list.
527++ *
528++ * @head: Pointer to "struct tmy_io_buffer".
529++ *
530++ * Returns true on success, false otherwise.
531++ */
532++bool tmy_read_no_rewrite_policy(struct tmy_io_buffer *head)
533++{
534++ struct list1_head *pos;
535++
536++ list1_for_each_cookie(pos, head->read_var2, &no_rewrite_list) {
537++ struct no_rewrite_entry *ptr;
538++ ptr = list1_entry(pos, struct no_rewrite_entry, list);
539++ if (ptr->is_deleted)
540++ continue;
541++ if (!tmy_io_printf(head, KEYWORD_DENY_REWRITE "%s\n",
542++ ptr->pattern->name))
543++ goto out;
544++ }
545++ return true;
546++out:
547++ return false;
548++}
549++
550++/**
551++ * update_file_acl - Update file's read/write/execute ACL.
552++ *
553++ * @filename: Filename.
554++ * @perm: Permission (between 1 to 7).
555++ * @domain: Pointer to "struct domain_info".
556++ * @is_delete: True if it is a delete request.
557++ *
558++ * Returns 0 on success, negative value otherwise.
559++ *
560++ * This is legacy support interface for older policy syntax.
561++ * Current policy syntax uses "allow_read/write" instead of "6",
562++ * "allow_read" instead of "4", "allow_write" instead of "2",
563++ * "allow_execute" instead of "1".
564++ */
565++static int update_file_acl(const char *filename, u8 perm,
566++ struct domain_info * const domain,
567++ const bool is_delete)
568++{
569++ if (perm > 7 || !perm) {
570++ printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
571++ __func__, perm, filename);
572++ return -EINVAL;
573++ }
574++ if (filename[0] != '@' && strendswith(filename, "/"))
575++ /*
576++ * Only 'allow_mkdir' and 'allow_rmdir' are valid for
577++ * directory permissions.
578++ */
579++ return 0;
580++ if (perm & 4)
581++ update_single_path_acl(TMY_TYPE_READ_ACL, filename, domain,
582++ is_delete);
583++ if (perm & 2)
584++ update_single_path_acl(TMY_TYPE_WRITE_ACL, filename, domain,
585++ is_delete);
586++ if (perm & 1)
587++ update_single_path_acl(TMY_TYPE_EXECUTE_ACL, filename, domain,
588++ is_delete);
589++ return 0;
590++}
591++
592++/**
593++ * check_single_path_acl2 - Check permission for single path operation.
594++ *
595++ * @domain: Pointer to "struct domain_info".
596++ * @filename: Filename to check.
597++ * @perm: Permission.
598++ * @may_use_pattern: True if patterned ACL is permitted.
599++ *
600++ * Returns 0 on success, -EPERM otherwise.
601++ */
602++static int check_single_path_acl2(const struct domain_info *domain,
603++ const struct path_info *filename,
604++ const u16 perm, const bool may_use_pattern)
605++{
606++ struct acl_info *ptr;
607++
608++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
609++ struct single_path_acl_record *acl;
610++ if (tmy_acl_type2(ptr) != TYPE_SINGLE_PATH_ACL)
611++ continue;
612++ acl = container_of(ptr, struct single_path_acl_record, head);
613++ if (!(acl->perm & perm))
614++ continue;
615++ if (may_use_pattern || !acl->filename->is_patterned) {
616++ if (!tmy_path_matches_pattern(filename,
617++ acl->filename))
618++ continue;
619++ } else {
620++ continue;
621++ }
622++ return 0;
623++ }
624++ return -EPERM;
625++}
626++
627++/**
628++ * check_file_acl - Check permission for opening files.
629++ *
630++ * @domain: Pointer to "struct domain_info".
631++ * @filename: Filename to check.
632++ * @operation: Mode ("read" or "write" or "read/write" or "execute").
633++ *
634++ * Returns 0 on success, -EPERM otherwise.
635++ */
636++static int check_file_acl(const struct domain_info *domain,
637++ const struct path_info *filename, const u8 operation)
638++{
639++ u16 perm = 0;
640++
641++ if (!tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE))
642++ return 0;
643++ if (operation == 6)
644++ perm = 1 << TMY_TYPE_READ_WRITE_ACL;
645++ else if (operation == 4)
646++ perm = 1 << TMY_TYPE_READ_ACL;
647++ else if (operation == 2)
648++ perm = 1 << TMY_TYPE_WRITE_ACL;
649++ else if (operation == 1)
650++ perm = 1 << TMY_TYPE_EXECUTE_ACL;
651++ else
652++ BUG();
653++ return check_single_path_acl2(domain, filename, perm, operation != 1);
654++}
655++
656++/**
657++ * check_file_perm2 - Check permission for opening files.
658++ *
659++ * @domain: Pointer to "struct domain_info".
660++ * @filename: Filename to check.
661++ * @perm: Mode ("read" or "write" or "read/write" or "execute").
662++ * @operation: Operation name passed used for verbose mode.
663++ * @mode: Access control mode.
664++ *
665++ * Returns 0 on success, negative value otherwise.
666++ */
667++static int check_file_perm2(struct domain_info * const domain,
668++ const struct path_info *filename, const u8 perm,
669++ const char *operation, const u8 mode)
670++{
671++ const bool is_enforce = (mode == 3);
672++ const char *msg = "<unknown>";
673++ int error = 0;
674++
675++ if (!filename)
676++ return 0;
677++ error = check_file_acl(domain, filename, perm);
678++ if (error && perm == 4 &&
679++ (domain->flags & DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0 &&
680++ is_globally_readable_file(filename))
681++ error = 0;
682++ if (perm == 6)
683++ msg = tmy_sp2keyword(TMY_TYPE_READ_WRITE_ACL);
684++ else if (perm == 4)
685++ msg = tmy_sp2keyword(TMY_TYPE_READ_ACL);
686++ else if (perm == 2)
687++ msg = tmy_sp2keyword(TMY_TYPE_WRITE_ACL);
688++ else if (perm == 1)
689++ msg = tmy_sp2keyword(TMY_TYPE_EXECUTE_ACL);
690++ else
691++ BUG();
692++ if (!error)
693++ return 0;
694++ if (tmy_verbose_mode(domain))
695++ printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
696++ "for %s\n", tmy_get_msg(is_enforce), msg, operation,
697++ filename->name, tmy_get_last_name(domain));
698++ if (is_enforce)
699++ return error;
700++ if (mode == 1 && tmy_check_domain_quota(domain)) {
701++ /* Don't use patterns for execute permission. */
702++ const struct path_info *patterned_file = (perm != 1) ?
703++ get_file_pattern(filename) : filename;
704++ update_file_acl(patterned_file->name, perm,
705++ domain, false);
706++ }
707++ return 0;
708++}
709++
710++/**
711++ * tmy_write_file_policy - Update file related list.
712++ *
713++ * @data: String to parse.
714++ * @domain: Pointer to "struct domain_info".
715++ * @is_delete: True if it is a delete request.
716++ *
717++ * Returns 0 on success, negative value otherwise.
718++ */
719++int tmy_write_file_policy(char *data, struct domain_info *domain,
720++ const bool is_delete)
721++{
722++ char *filename = strchr(data, ' ');
723++ char *filename2;
724++ unsigned int perm;
725++ u8 type;
726++
727++ if (!filename)
728++ return -EINVAL;
729++ *filename++ = '\0';
730++ if (sscanf(data, "%u", &perm) == 1)
731++ return update_file_acl(filename, (u8) perm, domain, is_delete);
732++ if (strncmp(data, "allow_", 6))
733++ goto out;
734++ data += 6;
735++ for (type = 0; type < MAX_SINGLE_PATH_OPERATION; type++) {
736++ if (strcmp(data, sp_keyword[type]))
737++ continue;
738++ return update_single_path_acl(type, filename,
739++ domain, is_delete);
740++ }
741++ filename2 = strchr(filename, ' ');
742++ if (!filename2)
743++ goto out;
744++ *filename2++ = '\0';
745++ for (type = 0; type < MAX_DOUBLE_PATH_OPERATION; type++) {
746++ if (strcmp(data, dp_keyword[type]))
747++ continue;
748++ return update_double_path_acl(type, filename, filename2, domain,
749++ is_delete);
750++ }
751++out:
752++ return -EINVAL;
753++}
754++
755++/**
756++ * update_single_path_acl - Update "struct single_path_acl_record" list.
757++ *
758++ * @type: Type of operation.
759++ * @filename: Filename.
760++ * @domain: Pointer to "struct domain_info".
761++ * @is_delete: True if it is a delete request.
762++ *
763++ * Returns 0 on success, negative value otherwise.
764++ */
765++static int update_single_path_acl(const u8 type, const char *filename,
766++ struct domain_info * const domain,
767++ const bool is_delete)
768++{
769++ static DEFINE_MUTEX(lock);
770++ static const u16 rw_mask =
771++ (1 << TMY_TYPE_READ_ACL) | (1 << TMY_TYPE_WRITE_ACL);
772++ const struct path_info *saved_filename;
773++ struct acl_info *ptr;
774++ struct single_path_acl_record *acl;
775++ int error = -ENOMEM;
776++ const u16 perm = 1 << type;
777++
778++ if (!domain)
779++ return -EINVAL;
780++ if (!tmy_is_correct_path(filename, 0, 0, 0, __func__))
781++ return -EINVAL;
782++ saved_filename = tmy_save_name(filename);
783++ if (!saved_filename)
784++ return -ENOMEM;
785++ /***** EXCLUSIVE SECTION START *****/
786++ mutex_lock(&lock);
787++ if (is_delete)
788++ goto delete;
789++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
790++ if (tmy_acl_type1(ptr) != TYPE_SINGLE_PATH_ACL)
791++ continue;
792++ acl = container_of(ptr, struct single_path_acl_record, head);
793++ if (acl->filename != saved_filename)
794++ continue;
795++ /* Special case. Clear all bits if marked as deleted. */
796++ if (ptr->type & ACL_DELETED)
797++ acl->perm = 0;
798++ acl->perm |= perm;
799++ if ((acl->perm & rw_mask) == rw_mask)
800++ acl->perm |= 1 << TMY_TYPE_READ_WRITE_ACL;
801++ else if (acl->perm & (1 << TMY_TYPE_READ_WRITE_ACL))
802++ acl->perm |= rw_mask;
803++ error = tmy_add_domain_acl(NULL, ptr);
804++ goto out;
805++ }
806++ /* Not found. Append it to the tail. */
807++ acl = tmy_alloc_acl_element(TYPE_SINGLE_PATH_ACL);
808++ if (!acl)
809++ goto out;
810++ acl->perm = perm;
811++ acl->filename = saved_filename;
812++ error = tmy_add_domain_acl(domain, &acl->head);
813++ goto out;
814++delete:
815++ error = -ENOENT;
816++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
817++ if (tmy_acl_type2(ptr) != TYPE_SINGLE_PATH_ACL)
818++ continue;
819++ acl = container_of(ptr, struct single_path_acl_record, head);
820++ if (acl->filename != saved_filename)
821++ continue;
822++ acl->perm &= ~perm;
823++ if ((acl->perm & rw_mask) != rw_mask)
824++ acl->perm &= ~(1 << TMY_TYPE_READ_WRITE_ACL);
825++ else if (!(acl->perm & (1 << TMY_TYPE_READ_WRITE_ACL)))
826++ acl->perm &= ~rw_mask;
827++ error = tmy_del_domain_acl(acl->perm ? NULL : ptr);
828++ break;
829++ }
830++out:
831++ mutex_unlock(&lock);
832++ /***** EXCLUSIVE SECTION END *****/
833++ return error;
834++}
835++
836++/**
837++ * update_double_path_acl - Update "struct double_path_acl_record" list.
838++ *
839++ * @type: Type of operation.
840++ * @filename1: First filename.
841++ * @filename2: Second filename.
842++ * @domain: Pointer to "struct domain_info".
843++ * @is_delete: True if it is a delete request.
844++ *
845++ * Returns 0 on success, negative value otherwise.
846++ */
847++static int update_double_path_acl(const u8 type, const char *filename1,
848++ const char *filename2,
849++ struct domain_info * const domain,
850++ const bool is_delete)
851++{
852++ static DEFINE_MUTEX(lock);
853++ const struct path_info *saved_filename1;
854++ const struct path_info *saved_filename2;
855++ struct acl_info *ptr;
856++ struct double_path_acl_record *acl;
857++ int error = -ENOMEM;
858++ const u8 perm = 1 << type;
859++
860++ if (!domain)
861++ return -EINVAL;
862++ if (!tmy_is_correct_path(filename1, 0, 0, 0, __func__) ||
863++ !tmy_is_correct_path(filename2, 0, 0, 0, __func__))
864++ return -EINVAL;
865++ saved_filename1 = tmy_save_name(filename1);
866++ saved_filename2 = tmy_save_name(filename2);
867++ if (!saved_filename1 || !saved_filename2)
868++ return -ENOMEM;
869++ /***** EXCLUSIVE SECTION START *****/
870++ mutex_lock(&lock);
871++ if (is_delete)
872++ goto delete;
873++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
874++ if (tmy_acl_type1(ptr) != TYPE_DOUBLE_PATH_ACL)
875++ continue;
876++ acl = container_of(ptr, struct double_path_acl_record, head);
877++ if (acl->filename1 != saved_filename1 ||
878++ acl->filename2 != saved_filename2)
879++ continue;
880++ /* Special case. Clear all bits if marked as deleted. */
881++ if (ptr->type & ACL_DELETED)
882++ acl->perm = 0;
883++ acl->perm |= perm;
884++ error = tmy_add_domain_acl(NULL, ptr);
885++ goto out;
886++ }
887++ /* Not found. Append it to the tail. */
888++ acl = tmy_alloc_acl_element(TYPE_DOUBLE_PATH_ACL);
889++ if (!acl)
890++ goto out;
891++ acl->perm = perm;
892++ acl->filename1 = saved_filename1;
893++ acl->filename2 = saved_filename2;
894++ error = tmy_add_domain_acl(domain, &acl->head);
895++ goto out;
896++delete:
897++ error = -ENOENT;
898++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
899++ if (tmy_acl_type2(ptr) != TYPE_DOUBLE_PATH_ACL)
900++ continue;
901++ acl = container_of(ptr, struct double_path_acl_record, head);
902++ if (acl->filename1 != saved_filename1 ||
903++ acl->filename2 != saved_filename2)
904++ continue;
905++ acl->perm &= ~perm;
906++ error = tmy_del_domain_acl(acl->perm ? NULL : ptr);
907++ break;
908++ }
909++out:
910++ mutex_unlock(&lock);
911++ /***** EXCLUSIVE SECTION END *****/
912++ return error;
913++}
914++
915++/**
916++ * check_single_path_acl - Check permission for single path operation.
917++ *
918++ * @domain: Pointer to "struct domain_info".
919++ * @type: Type of operation.
920++ * @filename: Filename to check.
921++ *
922++ * Returns 0 on success, negative value otherwise.
923++ */
924++static int check_single_path_acl(struct domain_info *domain, const u8 type,
925++ const struct path_info *filename)
926++{
927++ if (!tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE))
928++ return 0;
929++ return check_single_path_acl2(domain, filename, 1 << type, 1);
930++}
931++
932++/**
933++ * check_double_path_acl - Check permission for double path operation.
934++ *
935++ * @domain: Pointer to "struct domain_info".
936++ * @type: Type of operation.
937++ * @filename1: First filename to check.
938++ * @filename2: Second filename to check.
939++ *
940++ * Returns 0 on success, -EPERM otherwise.
941++ */
942++static int check_double_path_acl(const struct domain_info *domain,
943++ const u8 type,
944++ const struct path_info *filename1,
945++ const struct path_info *filename2)
946++{
947++ struct acl_info *ptr;
948++ const u8 perm = 1 << type;
949++
950++ if (!tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE))
951++ return 0;
952++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
953++ struct double_path_acl_record *acl;
954++ if (tmy_acl_type2(ptr) != TYPE_DOUBLE_PATH_ACL)
955++ continue;
956++ acl = container_of(ptr, struct double_path_acl_record, head);
957++ if (!(acl->perm & perm))
958++ continue;
959++ if (!tmy_path_matches_pattern(filename1, acl->filename1))
960++ continue;
961++ if (!tmy_path_matches_pattern(filename2, acl->filename2))
962++ continue;
963++ return 0;
964++ }
965++ return -EPERM;
966++}
967++
968++/**
969++ * check_single_path_permission2 - Check permission for single path operation.
970++ *
971++ * @domain: Pointer to "struct domain_info".
972++ * @operation: Type of operation.
973++ * @filename: Filename to check.
974++ * @mode: Access control mode.
975++ *
976++ * Returns 0 on success, negative value otherwise.
977++ */
978++static int check_single_path_permission2(struct domain_info * const domain,
979++ u8 operation,
980++ const struct path_info *filename,
981++ const u8 mode)
982++{
983++ const char *msg;
984++ int error;
985++ const bool is_enforce = (mode == 3);
986++
987++ if (!mode)
988++ return 0;
989++next:
990++ error = check_single_path_acl(domain, operation, filename);
991++ msg = tmy_sp2keyword(operation);
992++ if (!error)
993++ goto ok;
994++ if (tmy_verbose_mode(domain))
995++ printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
996++ tmy_get_msg(is_enforce), msg, filename->name,
997++ tmy_get_last_name(domain));
998++ if (mode == 1 && tmy_check_domain_quota(domain))
999++ update_single_path_acl(operation,
1000++ get_file_pattern(filename)->name,
1001++ domain, false);
1002++ if (!is_enforce)
1003++ error = 0;
1004++ok:
1005++ /*
1006++ * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
1007++ * we need to check "allow_rewrite" permission if the filename is
1008++ * specified by "deny_rewrite" keyword.
1009++ */
1010++ if (!error && operation == TMY_TYPE_TRUNCATE_ACL &&
1011++ is_no_rewrite_file(filename)) {
1012++ operation = TMY_TYPE_REWRITE_ACL;
1013++ goto next;
1014++ }
1015++ return error;
1016++}
1017++
1018++/**
1019++ * tmy_check_file_perm - Check permission for sysctl()'s "read" and "write".
1020++ *
1021++ * @domain: Pointer to "struct domain_info".
1022++ * @filename: Filename to check.
1023++ * @perm: Mode ("read" or "write" or "read/write").
1024++ * Returns 0 on success, negative value otherwise.
1025++ */
1026++int tmy_check_file_perm(struct domain_info *domain, const char *filename,
1027++ const u8 perm)
1028++{
1029++ struct path_info name;
1030++ const u8 mode = tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE);
1031++
1032++ if (!mode)
1033++ return 0;
1034++ name.name = filename;
1035++ tmy_fill_path_info(&name);
1036++ return check_file_perm2(domain, &name, perm, "sysctl", mode);
1037++}
1038++
1039++/**
1040++ * tmy_check_exec_perm - Check permission for "execute".
1041++ *
1042++ * @domain: Pointer to "struct domain_info".
1043++ * @filename: Check permission for "execute".
1044++ * @tmp: Buffer for temporal use.
1045++ *
1046++ * Returns 0 on success, negativevalue otherwise.
1047++ */
1048++int tmy_check_exec_perm(struct domain_info *domain,
1049++ const struct path_info *filename,
1050++ struct tmy_page_buffer *tmp)
1051++{
1052++ const u8 mode = tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE);
1053++
1054++ if (!mode)
1055++ return 0;
1056++ return check_file_perm2(domain, filename, 1, "do_execve", mode);
1057++}
1058++
1059++/**
1060++ * tmy_check_open_permission - Check permission for "read" and "write".
1061++ *
1062++ * @domain: Pointer to "struct domain_info".
1063++ * @path: Pointer to "struct path".
1064++ * @flag: Flags for open().
1065++ *
1066++ * Returns 0 on success, negative value otherwise.
1067++ */
1068++int tmy_check_open_permission(struct domain_info *domain,
1069++ struct path *path, const int flag)
1070++{
1071++ const u8 acc_mode = ACC_MODE(flag);
1072++ int error = -ENOMEM;
1073++ struct path_info *buf;
1074++ const u8 mode = tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE);
1075++ const bool is_enforce = (mode == 3);
1076++
1077++ if (!mode || !path->mnt)
1078++ return 0;
1079++ if (acc_mode == 0)
1080++ return 0;
1081++ if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1082++ /*
1083++ * I don't check directories here because mkdir() and rmdir()
1084++ * don't call me.
1085++ */
1086++ return 0;
1087++ buf = tmy_get_path(path);
1088++ if (!buf)
1089++ goto out;
1090++ error = 0;
1091++ /*
1092++ * If the filename is specified by "deny_rewrite" keyword,
1093++ * we need to check "allow_rewrite" permission when the filename is not
1094++ * opened for append mode or the filename is truncated at open time.
1095++ */
1096++ if ((acc_mode & MAY_WRITE) &&
1097++ ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1098++ (is_no_rewrite_file(buf))) {
1099++ error = check_single_path_permission2(domain,
1100++ TMY_TYPE_REWRITE_ACL,
1101++ buf, mode);
1102++ }
1103++ if (!error)
1104++ error = check_file_perm2(domain, buf, acc_mode, "open", mode);
1105++ if (!error && (flag & O_TRUNC))
1106++ error = check_single_path_permission2(domain,
1107++ TMY_TYPE_TRUNCATE_ACL,
1108++ buf, mode);
1109++out:
1110++ tmy_free(buf);
1111++ if (!is_enforce)
1112++ error = 0;
1113++ return error;
1114++}
1115++
1116++/**
1117++ * tmy_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
1118++ *
1119++ * @domain: Pointer to "struct domain_info".
1120++ * @operation: Type of operation.
1121++ * @path: Pointer to "struct path".
1122++ *
1123++ * Returns 0 on success, negative value otherwise.
1124++ */
1125++int tmy_check_1path_perm(struct domain_info *domain, const u8 operation,
1126++ struct path *path)
1127++{
1128++ int error = -ENOMEM;
1129++ struct path_info *buf;
1130++ const u8 mode = tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE);
1131++ const bool is_enforce = (mode == 3);
1132++
1133++ if (!mode || !path->mnt)
1134++ return 0;
1135++ buf = tmy_get_path(path);
1136++ if (!buf)
1137++ goto out;
1138++ switch (operation) {
1139++ case TMY_TYPE_MKDIR_ACL:
1140++ case TMY_TYPE_RMDIR_ACL:
1141++ if (!buf->is_dir) {
1142++ /* tmy_get_path() preserves space for appending "/." */
1143++ strcat((char *) buf->name, "/");
1144++ tmy_fill_path_info(buf);
1145++ }
1146++ }
1147++ error = check_single_path_permission2(domain, operation, buf, mode);
1148++out:
1149++ tmy_free(buf);
1150++ if (!is_enforce)
1151++ error = 0;
1152++ return error;
1153++}
1154++
1155++/**
1156++ * tmy_check_rewrite_permission - Check permission for "rewrite".
1157++ *
1158++ * @domain: Pointer to "struct domain_info".
1159++ * @filp: Pointer to "struct file".
1160++ *
1161++ * Returns 0 on success, negative value otherwise.
1162++ */
1163++int tmy_check_rewrite_permission(struct domain_info *domain, struct file *filp)
1164++{
1165++ int error = -ENOMEM;
1166++ const u8 mode = tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE);
1167++ const bool is_enforce = (mode == 3);
1168++ struct path_info *buf;
1169++
1170++ if (!mode || !filp->f_path.mnt)
1171++ return 0;
1172++ buf = tmy_get_path(&filp->f_path);
1173++ if (!buf)
1174++ goto out;
1175++ if (!is_no_rewrite_file(buf)) {
1176++ error = 0;
1177++ goto out;
1178++ }
1179++ error = check_single_path_permission2(domain, TMY_TYPE_REWRITE_ACL,
1180++ buf, mode);
1181++out:
1182++ tmy_free(buf);
1183++ if (!is_enforce)
1184++ error = 0;
1185++ return error;
1186++}
1187++
1188++/**
1189++ * tmy_check_2path_perm - Check permission for "rename" and "link".
1190++ *
1191++ * @domain: Pointer to "struct domain_info".
1192++ * @operation: Type of operation.
1193++ * @path1: Pointer to "struct path".
1194++ * @path2: Pointer to "struct path".
1195++ *
1196++ * Returns 0 on success, negative value otherwise.
1197++ */
1198++int tmy_check_2path_perm(struct domain_info * const domain, const u8 operation,
1199++ struct path *path1, struct path *path2)
1200++{
1201++ int error = -ENOMEM;
1202++ struct path_info *buf1, *buf2;
1203++ const u8 mode = tmy_check_flags(domain, TMY_TOMOYO_MAC_FOR_FILE);
1204++ const bool is_enforce = (mode == 3);
1205++ const char *msg;
1206++
1207++ if (!mode || !path1->mnt || !path2->mnt)
1208++ return 0;
1209++ buf1 = tmy_get_path(path1);
1210++ buf2 = tmy_get_path(path2);
1211++ if (!buf1 || !buf2)
1212++ goto out;
1213++ {
1214++ struct dentry *dentry = path1->dentry;
1215++ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1216++ /* tmy_get_path() preserves space for appending "/." */
1217++ if (!buf1->is_dir) {
1218++ strcat((char *) buf1->name, "/");
1219++ tmy_fill_path_info(buf1);
1220++ }
1221++ if (!buf2->is_dir) {
1222++ strcat((char *) buf2->name, "/");
1223++ tmy_fill_path_info(buf2);
1224++ }
1225++ }
1226++ }
1227++ error = check_double_path_acl(domain, operation, buf1, buf2);
1228++ msg = tmy_dp2keyword(operation);
1229++ if (!error)
1230++ goto out;
1231++ if (tmy_verbose_mode(domain))
1232++ printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1233++ "denied for %s\n", tmy_get_msg(is_enforce),
1234++ msg, buf1->name, buf2->name, tmy_get_last_name(domain));
1235++ if (mode == 1 && tmy_check_domain_quota(domain))
1236++ update_double_path_acl(operation,
1237++ get_file_pattern(buf1)->name,
1238++ get_file_pattern(buf2)->name,
1239++ domain, false);
1240++out:
1241++ tmy_free(buf1);
1242++ tmy_free(buf2);
1243++ if (!is_enforce)
1244++ error = 0;
1245++ return error;
1246++}
--- tags/lkml/11/introduce-new-lsm-hooks-where-vfsmount-is-available.patch (nonexistent)
+++ tags/lkml/11/introduce-new-lsm-hooks-where-vfsmount-is-available.patch (revision 1723)
@@ -0,0 +1,692 @@
1+Subject: Introduce new LSM hooks where vfsmount is available.
2+
3+----- What is this patch for? -----
4+
5+There are security_inode_*() LSM hooks for attribute-based MAC, but they are not
6+suitable for pathname-based MAC because they don't receive "struct vfsmount"
7+information.
8+
9+----- How this patch was developed? -----
10+
11+Two pathname-based MACs, AppArmor and TOMOYO Linux, are trying to merge
12+upstream. But because of "struct vfsmount" problem, they have been unable to
13+merge upstream.
14+
15+Here are the list of approaches and the reasons of denial.
16+
17+(1) Not using LSM
18+ http://lwn.net/Articles/277833/
19+
20+ This approach was rejected because security modules should use LSM because the
21+ whole idea behind LSM was to have a single set of hooks for all security
22+ modules; if every module now adds its own set of hooks, that purpose will have
23+ been defeated and the kernel will turn into a big mess of security hooks.
24+
25+(2) Retrieving "struct vfsmount" from "struct task_struct".
26+ http://lkml.org/lkml/2007/11/5/388
27+
28+ Since "struct task_struct" contains list of "struct vfsmount",
29+ "struct vfsmount" which corresponds to "struct dentry" can be retrieved from
30+ the list unless "mount --bind" is used.
31+
32+ This approach turned out to cause a critical problem that getting namespace_sem
33+ lock from security_inode_*() triggers AB-BA deadlock.
34+
35+(3) Adding "struct vfsmount" parameter to VFS helper functions.
36+ http://lkml.org/lkml/2008/5/29/207
37+
38+ This approach adds "struct vfsmount" to VFS helper functions (e.g. vfs_mkdir()
39+ and vfs_symlink()) and LSM hooks inside VFS helper functions. This approach is
40+ helpful for not only AppArmor and TOMOYO Linux 2.x but also SELinux and
41+ auditing purpose, for this approach allows existent LSM users to use pathnames
42+ in their access control and audit logs.
43+
44+ This approach was rejected by Al Viro, the VFS maintainer, because he thinks
45+ individual filesystem should remain "struct vfsmount"-unaware and VFS helper
46+ functions should not receive "struct vfsmount".
47+
48+ Al Viro also suggested to move existing security_inode_*() to out of VFS
49+ helper functions so that security_inode_*() can receive "struct vfsmount"
50+ without modifying VFS helper functions, but this suggestion was opposed by
51+ Stephen Smalley because changing the order of permission checks (i.e.
52+ MAC checks before DAC checks) is not acceptable.
53+
54+(4) Passing "struct vfsmount" via "struct task_struct".
55+ http://lkml.org/lkml/2007/11/16/157
56+
57+ Since we didn't understand the reason why accessing "struct vfsmount" from
58+ LSM hooks inside VFS helper functions is not acceptable, we thought the reason
59+ why VFS helper functions don't receive "struct vfsmount" is the amount of
60+ modifications needed to do so. Thus, we proposed to pass "struct vfsmount" via
61+ "struct task_struct" so that modifications remain minimal.
62+
63+ This approach was rejected because this is an abuse of "struct task_struct".
64+
65+(5) Remembering pathname of "struct vfsmount" via "struct task_struct".
66+ http://lkml.org/lkml/2008/8/19/16
67+
68+ Since pathname of a "struct dentry" up to the mount point can be calculated
69+ without "struct vfsmount", absolute pathname of a "struct dentry" can be
70+ calculated if "struct task_struct" can remember absolute pathname of a
71+ "struct vfsmount" which corresponds to "struct dentry".
72+ As we now understand that Al Viro is opposing to access "struct vfsmount" from
73+ LSM hooks inside VFS helper functions, we gave up delivering "struct vfsmount"
74+ to LSM hooks inside VFS helper functions.
75+ Kernel 2.6.26 introduced read-only bind mount feature, and hooks for that
76+ feature (i.e. mnt_want_write() and mnt_drop_write()) were inserted around
77+ VFS helper functions call. Since mnt_want_write() receives "struct vfsmount"
78+ which corresponds to "struct dentry" that will be passed to subsequent VFS
79+ helper functions call, we associated pathname of "struct vfsmount" with
80+ "struct task_struct" instead of associating "struct vfsmount" itself.
81+
82+ This approach was not explicitly rejected, but there seems to be performance
83+ problem.
84+
85+(6) Introducing new LSM hooks.
86+ (this patch)
87+
88+ We understand that adding new LSM hooks which receive "struct vfsmount" outside
89+ VFS helper functions is the most straightforward approach. This approach has
90+ less impact to existing LSM module and no impact to VFS helper functions.
91+
92+(6.1) Introducing security_path_clear() hook.
93+ (this patch)
94+
95+ To perform DAC performed in vfs_foo() before MAC, we let security_path_foo()
96+ save a result into our own hash table and return 0, and let security_inode_foo()
97+ return the saved result. Since security_inode_foo() is not always called after
98+ security_path_foo(), we need security_path_clear() to clear the hash table.
99+
100+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
101+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
102+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
103+Cc: Al Viro <viro@zeniv.linux.org.uk>
104+Cc: Christoph Hellwig <hch@lst.de>
105+Cc: Crispin Cowan <crispin@crispincowan.com>
106+Cc: Stephen Smalley <sds@tycho.nsa.gov>
107+Cc: Casey Schaufler <casey@schaufler-ca.com>
108+Cc: James Morris <jmorris@namei.org>
109+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
110+---
111+
112+ fs/namei.c | 46 ++++++++++++++
113+ fs/open.c | 5 +
114+ include/linux/security.h | 151 +++++++++++++++++++++++++++++++++++++++++++++++
115+ net/unix/af_unix.c | 5 +
116+ security/Kconfig | 9 ++
117+ security/capability.c | 63 +++++++++++++++++++
118+ security/security.c | 73 ++++++++++++++++++++++
119+ 7 files changed, 352 insertions(+)
120+
121+--- linux-next.orig/fs/namei.c
122++++ linux-next/fs/namei.c
123+@@ -1571,12 +1571,17 @@ int may_open(struct nameidata *nd, int a
124+ * Refuse to truncate files with mandatory locks held on them.
125+ */
126+ error = locks_verify_locked(inode);
127++ if (!error)
128++ error = security_path_truncate(&nd->path, 0,
129++ ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
130++ NULL);
131+ if (!error) {
132+ DQUOT_INIT(inode);
133+
134+ error = do_truncate(dentry, 0,
135+ ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
136+ NULL);
137++ security_path_clear();
138+ }
139+ put_write_access(inode);
140+ if (error)
141+@@ -1601,7 +1606,12 @@ static int __open_namei_create(struct na
142+
143+ if (!IS_POSIXACL(dir->d_inode))
144+ mode &= ~current->fs->umask;
145++ error = security_path_mknod(&nd->path, path->dentry, mode, 0);
146++ if (error)
147++ goto out_unlock;
148+ error = vfs_create(dir->d_inode, path->dentry, mode, nd);
149++ security_path_clear();
150++out_unlock:
151+ mutex_unlock(&dir->d_inode->i_mutex);
152+ dput(nd->path.dentry);
153+ nd->path.dentry = path->dentry;
154+@@ -2014,6 +2024,9 @@ asmlinkage long sys_mknodat(int dfd, con
155+ error = mnt_want_write(nd.path.mnt);
156+ if (error)
157+ goto out_dput;
158++ error = security_path_mknod(&nd.path, dentry, mode, dev);
159++ if (error)
160++ goto out_drop_write;
161+ switch (mode & S_IFMT) {
162+ case 0: case S_IFREG:
163+ error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
164+@@ -2026,6 +2039,8 @@ asmlinkage long sys_mknodat(int dfd, con
165+ error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
166+ break;
167+ }
168++ security_path_clear();
169++out_drop_write:
170+ mnt_drop_write(nd.path.mnt);
171+ out_dput:
172+ dput(dentry);
173+@@ -2085,7 +2100,12 @@ asmlinkage long sys_mkdirat(int dfd, con
174+ error = mnt_want_write(nd.path.mnt);
175+ if (error)
176+ goto out_dput;
177++ error = security_path_mkdir(&nd.path, dentry, mode);
178++ if (error)
179++ goto out_drop_write;
180+ error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
181++ security_path_clear();
182++out_drop_write:
183+ mnt_drop_write(nd.path.mnt);
184+ out_dput:
185+ dput(dentry);
186+@@ -2192,7 +2212,12 @@ static long do_rmdir(int dfd, const char
187+ error = mnt_want_write(nd.path.mnt);
188+ if (error)
189+ goto exit3;
190++ error = security_path_rmdir(&nd.path, dentry);
191++ if (error)
192++ goto exit4;
193+ error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
194++ security_path_clear();
195++exit4:
196+ mnt_drop_write(nd.path.mnt);
197+ exit3:
198+ dput(dentry);
199+@@ -2274,7 +2299,12 @@ static long do_unlinkat(int dfd, const c
200+ error = mnt_want_write(nd.path.mnt);
201+ if (error)
202+ goto exit2;
203++ error = security_path_unlink(&nd.path, dentry);
204++ if (error)
205++ goto exit3;
206+ error = vfs_unlink(nd.path.dentry->d_inode, dentry);
207++ security_path_clear();
208++exit3:
209+ mnt_drop_write(nd.path.mnt);
210+ exit2:
211+ dput(dentry);
212+@@ -2355,7 +2385,12 @@ asmlinkage long sys_symlinkat(const char
213+ error = mnt_want_write(nd.path.mnt);
214+ if (error)
215+ goto out_dput;
216++ error = security_path_symlink(&nd.path, dentry, from);
217++ if (error)
218++ goto out_drop_write;
219+ error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
220++ security_path_clear();
221++out_drop_write:
222+ mnt_drop_write(nd.path.mnt);
223+ out_dput:
224+ dput(dentry);
225+@@ -2452,7 +2487,12 @@ asmlinkage long sys_linkat(int olddfd, c
226+ error = mnt_want_write(nd.path.mnt);
227+ if (error)
228+ goto out_dput;
229++ error = security_path_link(old_path.dentry, &nd.path, new_dentry);
230++ if (error)
231++ goto out_drop_write;
232+ error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
233++ security_path_clear();
234++out_drop_write:
235+ mnt_drop_write(nd.path.mnt);
236+ out_dput:
237+ dput(new_dentry);
238+@@ -2684,8 +2724,14 @@ asmlinkage long sys_renameat(int olddfd,
239+ error = mnt_want_write(oldnd.path.mnt);
240+ if (error)
241+ goto exit5;
242++ error = security_path_rename(&oldnd.path, old_dentry,
243++ &newnd.path, new_dentry);
244++ if (error)
245++ goto exit6;
246+ error = vfs_rename(old_dir->d_inode, old_dentry,
247+ new_dir->d_inode, new_dentry);
248++ security_path_clear();
249++exit6:
250+ mnt_drop_write(oldnd.path.mnt);
251+ exit5:
252+ dput(new_dentry);
253+--- linux-next.orig/fs/open.c
254++++ linux-next/fs/open.c
255+@@ -272,6 +272,8 @@ static long do_sys_truncate(const char _
256+ goto put_write_and_out;
257+
258+ error = locks_verify_truncate(inode, NULL, length);
259++ if (!error)
260++ error = security_path_truncate(&path, length, 0, NULL);
261+ if (!error) {
262+ DQUOT_INIT(inode);
263+ error = do_truncate(path.dentry, length, 0, NULL);
264+@@ -329,6 +331,9 @@ static long do_sys_ftruncate(unsigned in
265+
266+ error = locks_verify_truncate(inode, file, length);
267+ if (!error)
268++ error = security_path_truncate(&file->f_path, length,
269++ ATTR_MTIME|ATTR_CTIME, file);
270++ if (!error)
271+ error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
272+ out_putf:
273+ fput(file);
274+--- linux-next.orig/include/linux/security.h
275++++ linux-next/include/linux/security.h
276+@@ -331,17 +331,37 @@ static inline void security_free_mnt_opt
277+ * @dir contains the inode structure of the parent directory of the new link.
278+ * @new_dentry contains the dentry structure for the new link.
279+ * Return 0 if permission is granted.
280++ * @path_link:
281++ * Check permission before creating a new hard link to a file.
282++ * @old_dentry contains the dentry structure for an existing link
283++ * to the file.
284++ * @new_dir contains the path structure of the parent directory of
285++ * the new link.
286++ * @new_dentry contains the dentry structure for the new link.
287++ * Return 0 if permission is granted.
288+ * @inode_unlink:
289+ * Check the permission to remove a hard link to a file.
290+ * @dir contains the inode structure of parent directory of the file.
291+ * @dentry contains the dentry structure for file to be unlinked.
292+ * Return 0 if permission is granted.
293++ * @path_unlink:
294++ * Check the permission to remove a hard link to a file.
295++ * @dir contains the path structure of parent directory of the file.
296++ * @dentry contains the dentry structure for file to be unlinked.
297++ * Return 0 if permission is granted.
298+ * @inode_symlink:
299+ * Check the permission to create a symbolic link to a file.
300+ * @dir contains the inode structure of parent directory of the symbolic link.
301+ * @dentry contains the dentry structure of the symbolic link.
302+ * @old_name contains the pathname of file.
303+ * Return 0 if permission is granted.
304++ * @path_symlink:
305++ * Check the permission to create a symbolic link to a file.
306++ * @dir contains the path structure of parent directory of
307++ * the symbolic link.
308++ * @dentry contains the dentry structure of the symbolic link.
309++ * @old_name contains the pathname of file.
310++ * Return 0 if permission is granted.
311+ * @inode_mkdir:
312+ * Check permissions to create a new directory in the existing directory
313+ * associated with inode strcture @dir.
314+@@ -349,11 +369,25 @@ static inline void security_free_mnt_opt
315+ * @dentry contains the dentry structure of new directory.
316+ * @mode contains the mode of new directory.
317+ * Return 0 if permission is granted.
318++ * @path_mkdir:
319++ * Check permissions to create a new directory in the existing directory
320++ * associated with path strcture @path.
321++ * @dir containst the path structure of parent of the directory
322++ * to be created.
323++ * @dentry contains the dentry structure of new directory.
324++ * @mode contains the mode of new directory.
325++ * Return 0 if permission is granted.
326+ * @inode_rmdir:
327+ * Check the permission to remove a directory.
328+ * @dir contains the inode structure of parent of the directory to be removed.
329+ * @dentry contains the dentry structure of directory to be removed.
330+ * Return 0 if permission is granted.
331++ * @path_rmdir:
332++ * Check the permission to remove a directory.
333++ * @dir contains the path structure of parent of the directory to be
334++ * removed.
335++ * @dentry contains the dentry structure of directory to be removed.
336++ * Return 0 if permission is granted.
337+ * @inode_mknod:
338+ * Check permissions when creating a special file (or a socket or a fifo
339+ * file created via the mknod system call). Note that if mknod operation
340+@@ -364,6 +398,15 @@ static inline void security_free_mnt_opt
341+ * @mode contains the mode of the new file.
342+ * @dev contains the device number.
343+ * Return 0 if permission is granted.
344++ * @path_mknod:
345++ * Check permissions when creating a file. Note that this hook is called
346++ * even if mknod operation is being done for a regular file.
347++ * @dir contains the path structure of parent of the new file.
348++ * @dentry contains the dentry structure of the new file.
349++ * @mode contains the mode of the new file.
350++ * @dev contains the undecoded device number. Use new_decode_dev() to get
351++ * the decoded device number.
352++ * Return 0 if permission is granted.
353+ * @inode_rename:
354+ * Check for permission to rename a file or directory.
355+ * @old_dir contains the inode structure for parent of the old link.
356+@@ -371,6 +414,13 @@ static inline void security_free_mnt_opt
357+ * @new_dir contains the inode structure for parent of the new link.
358+ * @new_dentry contains the dentry structure of the new link.
359+ * Return 0 if permission is granted.
360++ * @path_rename:
361++ * Check for permission to rename a file or directory.
362++ * @old_dir contains the path structure for parent of the old link.
363++ * @old_dentry contains the dentry structure of the old link.
364++ * @new_dir contains the path structure for parent of the new link.
365++ * @new_dentry contains the dentry structure of the new link.
366++ * Return 0 if permission is granted.
367+ * @inode_readlink:
368+ * Check the permission to read the symbolic link.
369+ * @dentry contains the dentry structure for the file link.
370+@@ -399,6 +449,13 @@ static inline void security_free_mnt_opt
371+ * @dentry contains the dentry structure for the file.
372+ * @attr is the iattr structure containing the new file attributes.
373+ * Return 0 if permission is granted.
374++ * @path_truncate:
375++ * Check permission before truncating a file.
376++ * @path contains the path structure for the file.
377++ * @length is the new length of the file.
378++ * @time_attrs is the flags passed to do_truncate().
379++ * @filp is the file structure (may be NULL).
380++ * Return 0 if permission is granted.
381+ * @inode_getattr:
382+ * Check permission before obtaining file attributes.
383+ * @mnt is the vfsmount where the dentry was looked up
384+@@ -466,6 +523,12 @@ static inline void security_free_mnt_opt
385+ * @inode contains a pointer to the inode.
386+ * @secid contains a pointer to the location where result will be saved.
387+ * In case of failure, @secid will be set to zero.
388++ * @path_clear:
389++ * Clear error code stored by security_path_*() in case
390++ * security_inode_*() was not called when DAC returned an error.
391++ * This hook allows LSM modules which use security_path_*() defer
392++ * returning LSM's error code till security_inode_*() is called so that
393++ * DAC's error (if any) is returned to the caller instead of LSM's error.
394+ *
395+ * Security hooks for file operations
396+ *
397+@@ -1327,6 +1390,23 @@ struct security_operations {
398+ struct super_block *newsb);
399+ int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
400+
401++#ifdef CONFIG_SECURITY_PATH
402++ int (*path_unlink) (struct path *dir, struct dentry *dentry);
403++ int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode);
404++ int (*path_rmdir) (struct path *dir, struct dentry *dentry);
405++ int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode,
406++ unsigned int dev);
407++ int (*path_truncate) (struct path *path, loff_t length,
408++ unsigned int time_attrs, struct file *filp);
409++ int (*path_symlink) (struct path *dir, struct dentry *dentry,
410++ const char *old_name);
411++ int (*path_link) (struct dentry *old_dentry, struct path *new_dir,
412++ struct dentry *new_dentry);
413++ int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
414++ struct path *new_dir, struct dentry *new_dentry);
415++ void (*path_clear) (void);
416++#endif
417++
418+ int (*inode_alloc_security) (struct inode *inode);
419+ void (*inode_free_security) (struct inode *inode);
420+ int (*inode_init_security) (struct inode *inode, struct inode *dir,
421+@@ -2685,6 +2765,77 @@ static inline void security_skb_classify
422+
423+ #endif /* CONFIG_SECURITY_NETWORK_XFRM */
424+
425++#ifdef CONFIG_SECURITY_PATH
426++int security_path_unlink(struct path *dir, struct dentry *dentry);
427++int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode);
428++int security_path_rmdir(struct path *dir, struct dentry *dentry);
429++int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
430++ unsigned int dev);
431++int security_path_truncate(struct path *path, loff_t length,
432++ unsigned int time_attrs, struct file *filp);
433++int security_path_symlink(struct path *dir, struct dentry *dentry,
434++ const char *old_name);
435++int security_path_link(struct dentry *old_dentry, struct path *new_dir,
436++ struct dentry *new_dentry);
437++int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
438++ struct path *new_dir, struct dentry *new_dentry);
439++void security_path_clear(void);
440++#else /* CONFIG_SECURITY_PATH */
441++static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
442++{
443++ return 0;
444++}
445++
446++static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
447++ int mode)
448++{
449++ return 0;
450++}
451++
452++static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
453++{
454++ return 0;
455++}
456++
457++static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
458++ int mode, unsigned int dev)
459++{
460++ return 0;
461++}
462++
463++static inline int security_path_truncate(struct path *path, loff_t length,
464++ unsigned int time_attrs,
465++ struct file *filp)
466++{
467++ return 0;
468++}
469++
470++static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
471++ const char *old_name)
472++{
473++ return 0;
474++}
475++
476++static inline int security_path_link(struct dentry *old_dentry,
477++ struct path *new_dir,
478++ struct dentry *new_dentry)
479++{
480++ return 0;
481++}
482++
483++static inline int security_path_rename(struct path *old_dir,
484++ struct dentry *old_dentry,
485++ struct path *new_dir,
486++ struct dentry *new_dentry)
487++{
488++ return 0;
489++}
490++
491++static inline void security_path_clear(void)
492++{
493++}
494++#endif /* CONFIG_SECURITY_PATH */
495++
496+ #ifdef CONFIG_KEYS
497+ #ifdef CONFIG_SECURITY
498+
499+--- linux-next.orig/net/unix/af_unix.c
500++++ linux-next/net/unix/af_unix.c
501+@@ -828,7 +828,12 @@ static int unix_bind(struct socket *sock
502+ err = mnt_want_write(nd.path.mnt);
503+ if (err)
504+ goto out_mknod_dput;
505++ err = security_path_mknod(&nd.path, dentry, mode, 0);
506++ if (err)
507++ goto out_mknod_drop_write;
508+ err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
509++ security_path_clear();
510++out_mknod_drop_write:
511+ mnt_drop_write(nd.path.mnt);
512+ if (err)
513+ goto out_mknod_dput;
514+--- linux-next.orig/security/Kconfig
515++++ linux-next/security/Kconfig
516+@@ -81,6 +81,15 @@ config SECURITY_NETWORK_XFRM
517+ IPSec.
518+ If you are unsure how to answer this question, answer N.
519+
520++config SECURITY_PATH
521++ bool "Security hooks for pathname based access control"
522++ depends on SECURITY
523++ help
524++ This enables the security hooks for pathname based access control.
525++ If enabled, a security module can use these hooks to
526++ implement pathname based access controls.
527++ If you are unsure how to answer this question, answer N.
528++
529+ config SECURITY_FILE_CAPABILITIES
530+ bool "File POSIX Capabilities"
531+ default n
532+--- linux-next.orig/security/capability.c
533++++ linux-next/security/capability.c
534+@@ -263,6 +263,58 @@ static void cap_inode_getsecid(const str
535+ *secid = 0;
536+ }
537+
538++#ifdef CONFIG_SECURITY_PATH
539++static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
540++ unsigned int dev)
541++{
542++ return 0;
543++}
544++
545++static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
546++{
547++ return 0;
548++}
549++
550++static int cap_path_rmdir(struct path *dir, struct dentry *dentry)
551++{
552++ return 0;
553++}
554++
555++static int cap_path_unlink(struct path *dir, struct dentry *dentry)
556++{
557++ return 0;
558++}
559++
560++static int cap_path_symlink(struct path *dir, struct dentry *dentry,
561++ const char *old_name)
562++{
563++ return 0;
564++}
565++
566++static int cap_path_link(struct dentry *old_dentry, struct path *new_dir,
567++ struct dentry *new_dentry)
568++{
569++ return 0;
570++}
571++
572++static int cap_path_rename(struct path *old_path, struct dentry *old_dentry,
573++ struct path *new_path, struct dentry *new_dentry)
574++{
575++ return 0;
576++}
577++
578++static int cap_path_truncate(struct path *path, loff_t length,
579++ unsigned int time_attrs, struct file *filp)
580++{
581++ return 0;
582++}
583++
584++static void cap_path_clear(void)
585++{
586++}
587++
588++#endif
589++
590+ static int cap_file_permission(struct file *file, int mask)
591+ {
592+ return 0;
593+@@ -883,6 +935,17 @@ void security_fixup_ops(struct security_
594+ set_to_cap_if_null(ops, inode_setsecurity);
595+ set_to_cap_if_null(ops, inode_listsecurity);
596+ set_to_cap_if_null(ops, inode_getsecid);
597++#ifdef CONFIG_SECURITY_PATH
598++ set_to_cap_if_null(ops, path_mknod);
599++ set_to_cap_if_null(ops, path_mkdir);
600++ set_to_cap_if_null(ops, path_rmdir);
601++ set_to_cap_if_null(ops, path_unlink);
602++ set_to_cap_if_null(ops, path_symlink);
603++ set_to_cap_if_null(ops, path_link);
604++ set_to_cap_if_null(ops, path_rename);
605++ set_to_cap_if_null(ops, path_truncate);
606++ set_to_cap_if_null(ops, path_clear);
607++#endif
608+ set_to_cap_if_null(ops, file_permission);
609+ set_to_cap_if_null(ops, file_alloc_security);
610+ set_to_cap_if_null(ops, file_free_security);
611+--- linux-next.orig/security/security.c
612++++ linux-next/security/security.c
613+@@ -341,6 +341,79 @@ int security_inode_init_security(struct
614+ }
615+ EXPORT_SYMBOL(security_inode_init_security);
616+
617++#ifdef CONFIG_SECURITY_PATH
618++int security_path_mknod(struct path *path, struct dentry *dentry, int mode,
619++ unsigned int dev)
620++{
621++ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
622++ return 0;
623++ return security_ops->path_mknod(path, dentry, mode, dev);
624++}
625++EXPORT_SYMBOL(security_path_mknod);
626++
627++int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
628++{
629++ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
630++ return 0;
631++ return security_ops->path_mkdir(path, dentry, mode);
632++}
633++
634++int security_path_rmdir(struct path *path, struct dentry *dentry)
635++{
636++ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
637++ return 0;
638++ return security_ops->path_rmdir(path, dentry);
639++}
640++
641++int security_path_unlink(struct path *path, struct dentry *dentry)
642++{
643++ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
644++ return 0;
645++ return security_ops->path_unlink(path, dentry);
646++}
647++
648++int security_path_symlink(struct path *path, struct dentry *dentry,
649++ const char *old_name)
650++{
651++ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
652++ return 0;
653++ return security_ops->path_symlink(path, dentry, old_name);
654++}
655++
656++int security_path_link(struct dentry *old_dentry, struct path *new_dir,
657++ struct dentry *new_dentry)
658++{
659++ if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
660++ return 0;
661++ return security_ops->path_link(old_dentry, new_dir, new_dentry);
662++}
663++
664++int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
665++ struct path *new_dir, struct dentry *new_dentry)
666++{
667++ if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
668++ (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
669++ return 0;
670++ return security_ops->path_rename(old_dir, old_dentry, new_dir,
671++ new_dentry);
672++}
673++
674++int security_path_truncate(struct path *path, loff_t length,
675++ unsigned int time_attrs, struct file *filp)
676++{
677++ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
678++ return 0;
679++ return security_ops->path_truncate(path, length, time_attrs, filp);
680++}
681++
682++void security_path_clear(void)
683++{
684++ return security_ops->path_clear();
685++}
686++EXPORT_SYMBOL(security_path_clear);
687++
688++#endif
689++
690+ int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
691+ {
692+ if (unlikely(IS_PRIVATE(dir)))
--- tags/lkml/11/tomoyo-common.patch (nonexistent)
+++ tags/lkml/11/tomoyo-common.patch (revision 1723)
@@ -0,0 +1,2547 @@
1+Subject: Common functions for TOMOYO Linux.
2+
3+This file contains common functions (e.g. policy I/O, pattern matching).
4+
5+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
6+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
7+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
8+---
9+ security/tomoyo/common.c | 2209 +++++++++++++++++++++++++++++++++++++++++++++++
10+ security/tomoyo/common.h | 320 ++++++
11+ 2 files changed, 2529 insertions(+)
12+
13+--- /dev/null
14++++ linux-next/security/tomoyo/common.c
15+@@ -0,0 +1,2209 @@
16++/*
17++ * security/tomoyo/common.c
18++ *
19++ * Common functions for TOMOYO.
20++ *
21++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
22++ *
23++ * Version: 2.2.0-pre 2008/10/10
24++ *
25++ */
26++
27++#include <linux/uaccess.h>
28++#include <linux/security.h>
29++#include <linux/hardirq.h>
30++#include "realpath.h"
31++#include "common.h"
32++#include "tomoyo.h"
33++
34++/* Set default specified by the kernel config. */
35++#define MAX_ACCEPT_ENTRY 2048
36++
37++/* Has /sbin/init started? */
38++bool sbin_init_started;
39++
40++/* String table for functionality that takes 4 modes. */
41++static const char *mode_4[4] = {
42++ "disabled", "learning", "permissive", "enforcing"
43++};
44++/* String table for functionality that takes 2 modes. */
45++static const char *mode_2[4] = {
46++ "disabled", "enabled", "enabled", "enabled"
47++};
48++
49++/* Table for profile. */
50++static struct {
51++ const char *keyword;
52++ unsigned int current_value;
53++ const unsigned int max_value;
54++} tmy_control_array[TMY_MAX_CONTROL_INDEX] = {
55++ [TMY_TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
56++ [TMY_TOMOYO_MAX_ACCEPT_ENTRY]
57++ = { "MAX_ACCEPT_ENTRY", MAX_ACCEPT_ENTRY, INT_MAX },
58++ [TMY_TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
59++};
60++
61++/* Profile table. Memory is allocated as needed. */
62++static struct profile {
63++ unsigned int value[TMY_MAX_CONTROL_INDEX];
64++ const struct path_info *comment;
65++} *profile_ptr[MAX_PROFILES];
66++
67++/* Permit policy management by non-root user? */
68++static bool manage_by_non_root;
69++
70++/* Utility functions. */
71++
72++/* Open operation for /sys/kernel/security/tomoyo/ interface. */
73++static int tmy_open_control(const u8 type, struct file *file);
74++/* Close /sys/kernel/security/tomoyo/ interface. */
75++static int tmy_close_control(struct file *file);
76++/* Read operation for /sys/kernel/security/tomoyo/ interface. */
77++static int tmy_read_control(struct file *file, char __user *buffer,
78++ const int buffer_len);
79++/* Write operation for /sys/kernel/security/tomoyo/ interface. */
80++static int tmy_write_control(struct file *file, const char __user *buffer,
81++ const int buffer_len);
82++
83++/**
84++ * is_byte_range - Check whether the string isa \ooo style octal value.
85++ *
86++ * @str: Pointer to the string.
87++ *
88++ * Returns true if @str is a \ooo style octal value, false otherwise.
89++ */
90++static bool is_byte_range(const char *str)
91++{
92++ return *str >= '0' && *str++ <= '3' &&
93++ *str >= '0' && *str++ <= '7' &&
94++ *str >= '0' && *str <= '7';
95++}
96++
97++/**
98++ * is_decimal - Check whether the character is a decimal character.
99++ *
100++ * @c: The character to check.
101++ *
102++ * Returns true if @c is a decimal character, false otherwise.
103++ */
104++static bool is_decimal(const char c)
105++{
106++ return c >= '0' && c <= '9';
107++}
108++
109++/**
110++ * is_hexadecimal - Check whether the character is a hexadecimal character.
111++ *
112++ * @c: The character to check.
113++ *
114++ * Returns true if @c is a hexadecimal character, false otherwise.
115++ */
116++static bool is_hexadecimal(const char c)
117++{
118++ return (c >= '0' && c <= '9') ||
119++ (c >= 'A' && c <= 'F') ||
120++ (c >= 'a' && c <= 'f');
121++}
122++
123++/**
124++ * is_alphabet_char - Check whether the character is an alphabet.
125++ *
126++ * @c: The character to check.
127++ *
128++ * Returns true if @c is an alphabet character, false otherwise.
129++ */
130++static bool is_alphabet_char(const char c)
131++{
132++ return (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
133++}
134++
135++/**
136++ * make_byte - Make byte value from three octal characters.
137++ *
138++ * @c1: The first character.
139++ * @c2: The second character.
140++ * @c3: The third character.
141++ *
142++ * Returns byte value.
143++ */
144++static u8 make_byte(const u8 c1, const u8 c2, const u8 c3)
145++{
146++ return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
147++}
148++
149++/**
150++ * str_starts - Check whether the given string starts with the given keyword.
151++ *
152++ * @src: Pointer to pointer to the string.
153++ * @find: Pointer to the keyword.
154++ *
155++ * Returns true if @src starts with @find, false otherwise.
156++ *
157++ * The @src is updated to point the first character after the @find
158++ * if @src starts with @find.
159++ */
160++static bool str_starts(char **src, const char *find)
161++{
162++ const int len = strlen(find);
163++ char *tmp = *src;
164++
165++ if (strncmp(tmp, find, len))
166++ return false;
167++ tmp += len;
168++ *src = tmp;
169++ return true;
170++}
171++
172++/**
173++ * normalize_line - Format string.
174++ *
175++ * @buffer: The line to normalize.
176++ *
177++ * Leading and trailing whitespaces are removed.
178++ * Multiple whitespaces are packed into single space.
179++ *
180++ * Returns nothing.
181++ */
182++static void normalize_line(unsigned char *buffer)
183++{
184++ unsigned char *sp = buffer;
185++ unsigned char *dp = buffer;
186++ bool first = true;
187++
188++ while (*sp && (*sp <= ' ' || *sp >= 127))
189++ sp++;
190++ while (*sp) {
191++ if (!first)
192++ *dp++ = ' ';
193++ first = false;
194++ while (*sp > ' ' && *sp < 127)
195++ *dp++ = *sp++;
196++ while (*sp && (*sp <= ' ' || *sp >= 127))
197++ sp++;
198++ }
199++ *dp = '\0';
200++}
201++
202++/**
203++ * tmy_is_correct_path - Validate a pathname.
204++ * @filename: The pathname to check.
205++ * @start_type: Should the pathname start with '/'?
206++ * 1 = must / -1 = must not / 0 = don't care
207++ * @pattern_type: Can the pathname contain a wildcard?
208++ * 1 = must / -1 = must not / 0 = don't care
209++ * @end_type: Should the pathname end with '/'?
210++ * 1 = must / -1 = must not / 0 = don't care
211++ * @function: The name of function calling me.
212++ *
213++ * Check whether the given filename follows the naming rules.
214++ * Returns true if @filename follows the naming rules, false otherwise.
215++ */
216++bool tmy_is_correct_path(const char *filename, const s8 start_type,
217++ const s8 pattern_type, const s8 end_type,
218++ const char *function)
219++{
220++ bool contains_pattern = false;
221++ unsigned char c;
222++ unsigned char d;
223++ unsigned char e;
224++ const char *original_filename = filename;
225++
226++ if (!filename)
227++ goto out;
228++ c = *filename;
229++ if (start_type == 1) { /* Must start with '/' */
230++ if (c != '/')
231++ goto out;
232++ } else if (start_type == -1) { /* Must not start with '/' */
233++ if (c == '/')
234++ goto out;
235++ }
236++ if (c)
237++ c = *(strchr(filename, '\0') - 1);
238++ if (end_type == 1) { /* Must end with '/' */
239++ if (c != '/')
240++ goto out;
241++ } else if (end_type == -1) { /* Must not end with '/' */
242++ if (c == '/')
243++ goto out;
244++ }
245++ while ((c = *filename++) != '\0') {
246++ if (c == '\\') {
247++ switch ((c = *filename++)) {
248++ case '\\': /* "\\" */
249++ continue;
250++ case '$': /* "\$" */
251++ case '+': /* "\+" */
252++ case '?': /* "\?" */
253++ case '*': /* "\*" */
254++ case '@': /* "\@" */
255++ case 'x': /* "\x" */
256++ case 'X': /* "\X" */
257++ case 'a': /* "\a" */
258++ case 'A': /* "\A" */
259++ case '-': /* "\-" */
260++ if (pattern_type == -1)
261++ break; /* Must not contain pattern */
262++ contains_pattern = true;
263++ continue;
264++ case '0': /* "\ooo" */
265++ case '1':
266++ case '2':
267++ case '3':
268++ d = *filename++;
269++ if (d < '0' || d > '7')
270++ break;
271++ e = *filename++;
272++ if (e < '0' || e > '7')
273++ break;
274++ c = make_byte(c, d, e);
275++ if (c && (c <= ' ' || c >= 127))
276++ continue; /* pattern is not \000 */
277++ }
278++ goto out;
279++ } else if (c <= ' ' || c >= 127) {
280++ goto out;
281++ }
282++ }
283++ if (pattern_type == 1) { /* Must contain pattern */
284++ if (!contains_pattern)
285++ goto out;
286++ }
287++ return true;
288++out:
289++ printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
290++ original_filename);
291++ return false;
292++}
293++
294++/**
295++ * tmy_is_correct_domain - Check whether the given domainname follows the naming rules.
296++ * @domainname: The domainname to check.
297++ * @function: The name of function calling me.
298++ *
299++ * Returns true if @domainname follows the naming rules, false otherwise.
300++ */
301++bool tmy_is_correct_domain(const unsigned char *domainname,
302++ const char *function)
303++{
304++ unsigned char c;
305++ unsigned char d;
306++ unsigned char e;
307++ const char *org_domainname = domainname;
308++
309++ if (!domainname || strncmp(domainname, ROOT_NAME, ROOT_NAME_LEN))
310++ goto out;
311++ domainname += ROOT_NAME_LEN;
312++ if (!*domainname)
313++ return true;
314++ do {
315++ if (*domainname++ != ' ')
316++ goto out;
317++ if (*domainname++ != '/')
318++ goto out;
319++ while ((c = *domainname) != '\0' && c != ' ') {
320++ domainname++;
321++ if (c == '\\') {
322++ c = *domainname++;
323++ switch ((c)) {
324++ case '\\': /* "\\" */
325++ continue;
326++ case '0': /* "\ooo" */
327++ case '1':
328++ case '2':
329++ case '3':
330++ d = *domainname++;
331++ if (d < '0' || d > '7')
332++ break;
333++ e = *domainname++;
334++ if (e < '0' || e > '7')
335++ break;
336++ c = make_byte(c, d, e);
337++ if (c && (c <= ' ' || c >= 127))
338++ /* pattern is not \000 */
339++ continue;
340++ }
341++ goto out;
342++ } else if (c < ' ' || c >= 127) {
343++ goto out;
344++ }
345++ }
346++ } while (*domainname);
347++ return true;
348++out:
349++ printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
350++ org_domainname);
351++ return false;
352++}
353++
354++/**
355++ * tmy_is_domain_def - Check whether the given token can be a domainname.
356++ *
357++ * @buffer: The token to check.
358++ *
359++ * Returns true if @buffer possibly be a domainname, false otherwise.
360++ */
361++bool tmy_is_domain_def(const unsigned char *buffer)
362++{
363++ return !strncmp(buffer, ROOT_NAME, ROOT_NAME_LEN);
364++}
365++
366++/**
367++ * tmy_find_domain - Find a domain by the given name.
368++ *
369++ * @domainname: The domainname to find.
370++ *
371++ * Returns pointer to "struct domain_info" if found, NULL otherwise.
372++ */
373++struct domain_info *tmy_find_domain(const char *domainname)
374++{
375++ struct domain_info *domain;
376++ struct path_info name;
377++
378++ name.name = domainname;
379++ tmy_fill_path_info(&name);
380++ list1_for_each_entry(domain, &domain_list, list) {
381++ if (!domain->is_deleted &&
382++ !tmy_pathcmp(&name, domain->domainname))
383++ return domain;
384++ }
385++ return NULL;
386++}
387++
388++/**
389++ * path_depth - Evaluate the number of '/' in a string.
390++ *
391++ * @pathname: The string to evaluate.
392++ *
393++ * Returns path depth of the string.
394++ *
395++ * I score 2 for each of the '/' in the @pathname
396++ * and score 1 if the @pathname ends with '/'.
397++ */
398++static int path_depth(const char *pathname)
399++{
400++ int i = 0;
401++
402++ if (pathname) {
403++ char *ep = strchr(pathname, '\0');
404++ if (pathname < ep--) {
405++ if (*ep != '/')
406++ i++;
407++ while (pathname <= ep)
408++ if (*ep-- == '/')
409++ i += 2;
410++ }
411++ }
412++ return i;
413++}
414++
415++/**
416++ * const_part_length - Evaluate the initial length without a pattern in a token.
417++ *
418++ * @filename: The string to evaluate.
419++ *
420++ * Returns the initial length without a pattern in @filename.
421++ */
422++static int const_part_length(const char *filename)
423++{
424++ char c;
425++ int len = 0;
426++
427++ if (!filename)
428++ return 0;
429++ while ((c = *filename++) != '\0') {
430++ if (c != '\\') {
431++ len++;
432++ continue;
433++ }
434++ c = *filename++;
435++ switch (c) {
436++ case '\\': /* "\\" */
437++ len += 2;
438++ continue;
439++ case '0': /* "\ooo" */
440++ case '1':
441++ case '2':
442++ case '3':
443++ c = *filename++;
444++ if (c < '0' || c > '7')
445++ break;
446++ c = *filename++;
447++ if (c < '0' || c > '7')
448++ break;
449++ len += 4;
450++ continue;
451++ }
452++ break;
453++ }
454++ return len;
455++}
456++
457++/**
458++ * tmy_fill_path_info - Fill in "struct path_info" members.
459++ *
460++ * @ptr: Pointer to "struct path_info" to fill in.
461++ *
462++ * The caller sets "struct path_info"->name.
463++ */
464++void tmy_fill_path_info(struct path_info *ptr)
465++{
466++ const char *name = ptr->name;
467++ const int len = strlen(name);
468++
469++ ptr->total_len = len;
470++ ptr->const_len = const_part_length(name);
471++ ptr->is_dir = len && (name[len - 1] == '/');
472++ ptr->is_patterned = (ptr->const_len < len);
473++ ptr->hash = full_name_hash(name, len);
474++ ptr->depth = path_depth(name);
475++}
476++
477++/**
478++ * file_matches_to_pattern2 - Pattern matching without '/' character
479++ * and "\-" pattern.
480++ *
481++ * @filename: The start of string to check.
482++ * @filename_end: The end of string to check.
483++ * @pattern: The start of pattern to compare.
484++ * @pattern_end: The end of pattern to compare.
485++ *
486++ * Returns true if @filename matches @pattern, false otherwise.
487++ */
488++static bool file_matches_to_pattern2(const char *filename,
489++ const char *filename_end,
490++ const char *pattern,
491++ const char *pattern_end)
492++{
493++ while (filename < filename_end && pattern < pattern_end) {
494++ char c;
495++ if (*pattern != '\\') {
496++ if (*filename++ != *pattern++)
497++ return false;
498++ continue;
499++ }
500++ c = *filename;
501++ pattern++;
502++ switch (*pattern) {
503++ int i;
504++ int j;
505++ case '?':
506++ if (c == '/') {
507++ return false;
508++ } else if (c == '\\') {
509++ if (filename[1] == '\\')
510++ filename++;
511++ else if (is_byte_range(filename + 1))
512++ filename += 3;
513++ else
514++ return false;
515++ }
516++ break;
517++ case '\\':
518++ if (c != '\\')
519++ return false;
520++ if (*++filename != '\\')
521++ return false;
522++ break;
523++ case '+':
524++ if (!is_decimal(c))
525++ return false;
526++ break;
527++ case 'x':
528++ if (!is_hexadecimal(c))
529++ return false;
530++ break;
531++ case 'a':
532++ if (!is_alphabet_char(c))
533++ return false;
534++ break;
535++ case '0':
536++ case '1':
537++ case '2':
538++ case '3':
539++ if (c == '\\' && is_byte_range(filename + 1)
540++ && strncmp(filename + 1, pattern, 3) == 0) {
541++ filename += 3;
542++ pattern += 2;
543++ break;
544++ }
545++ return false; /* Not matched. */
546++ case '*':
547++ case '@':
548++ for (i = 0; i <= filename_end - filename; i++) {
549++ if (file_matches_to_pattern2(filename + i,
550++ filename_end,
551++ pattern + 1,
552++ pattern_end))
553++ return true;
554++ c = filename[i];
555++ if (c == '.' && *pattern == '@')
556++ break;
557++ if (c != '\\')
558++ continue;
559++ if (filename[i + 1] == '\\')
560++ i++;
561++ else if (is_byte_range(filename + i + 1))
562++ i += 3;
563++ else
564++ break; /* Bad pattern. */
565++ }
566++ return false; /* Not matched. */
567++ default:
568++ j = 0;
569++ c = *pattern;
570++ if (c == '$') {
571++ while (is_decimal(filename[j]))
572++ j++;
573++ } else if (c == 'X') {
574++ while (is_hexadecimal(filename[j]))
575++ j++;
576++ } else if (c == 'A') {
577++ while (is_alphabet_char(filename[j]))
578++ j++;
579++ }
580++ for (i = 1; i <= j; i++) {
581++ if (file_matches_to_pattern2(filename + i,
582++ filename_end,
583++ pattern + 1,
584++ pattern_end))
585++ return true;
586++ }
587++ return false; /* Not matched or bad pattern. */
588++ }
589++ filename++;
590++ pattern++;
591++ }
592++ while (*pattern == '\\' &&
593++ (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
594++ pattern += 2;
595++ return filename == filename_end && pattern == pattern_end;
596++}
597++
598++/**
599++ * file_matches_to_pattern - Pattern matching without without '/' character.
600++ *
601++ * @filename: The start of string to check.
602++ * @filename_end: The end of string to check.
603++ * @pattern: The start of pattern to compare.
604++ * @pattern_end: The end of pattern to compare.
605++ *
606++ * Returns true if @filename matches @pattern, false otherwise.
607++ */
608++static bool file_matches_to_pattern(const char *filename,
609++ const char *filename_end,
610++ const char *pattern,
611++ const char *pattern_end)
612++{
613++ const char *pattern_start = pattern;
614++ bool first = true;
615++ bool result;
616++
617++ while (pattern < pattern_end - 1) {
618++ /* Split at "\-" pattern. */
619++ if (*pattern++ != '\\' || *pattern++ != '-')
620++ continue;
621++ result = file_matches_to_pattern2(filename, filename_end,
622++ pattern_start, pattern - 2);
623++ if (first)
624++ result = !result;
625++ if (result)
626++ return false;
627++ first = false;
628++ pattern_start = pattern;
629++ }
630++ result = file_matches_to_pattern2(filename, filename_end,
631++ pattern_start, pattern_end);
632++ return first ? result : !result;
633++}
634++
635++/**
636++ * tmy_path_matches_pattern - Check whether the given filename matches the given pattern.
637++ * @filename: The filename to check.
638++ * @pattern: The pattern to compare.
639++ *
640++ * Returns true if matches, false otherwise.
641++ *
642++ * The following patterns are available.
643++ * \\ \ itself.
644++ * \ooo Octal representation of a byte.
645++ * \* More than or equals to 0 character other than '/'.
646++ * \@ More than or equals to 0 character other than '/' or '.'.
647++ * \? 1 byte character other than '/'.
648++ * \$ More than or equals to 1 decimal digit.
649++ * \+ 1 decimal digit.
650++ * \X More than or equals to 1 hexadecimal digit.
651++ * \x 1 hexadecimal digit.
652++ * \A More than or equals to 1 alphabet character.
653++ * \a 1 alphabet character.
654++ * \- Subtraction operator.
655++ */
656++bool tmy_path_matches_pattern(const struct path_info *filename,
657++ const struct path_info *pattern)
658++{
659++ /*
660++ if (!filename || !pattern)
661++ return false;
662++ */
663++ const char *f = filename->name;
664++ const char *p = pattern->name;
665++ const int len = pattern->const_len;
666++
667++ /* If @pattern doesn't contain pattern, I can use strcmp(). */
668++ if (!pattern->is_patterned)
669++ return !tmy_pathcmp(filename, pattern);
670++ /* Dont compare if the number of '/' differs. */
671++ if (filename->depth != pattern->depth)
672++ return false;
673++ /* Compare the initial length without patterns. */
674++ if (strncmp(f, p, len))
675++ return false;
676++ f += len;
677++ p += len;
678++ /* Main loop. Compare each directory component. */
679++ while (*f && *p) {
680++ const char *f_delimiter = strchr(f, '/');
681++ const char *p_delimiter = strchr(p, '/');
682++ if (!f_delimiter)
683++ f_delimiter = strchr(f, '\0');
684++ if (!p_delimiter)
685++ p_delimiter = strchr(p, '\0');
686++ if (!file_matches_to_pattern(f, f_delimiter, p, p_delimiter))
687++ return false;
688++ f = f_delimiter;
689++ if (*f)
690++ f++;
691++ p = p_delimiter;
692++ if (*p)
693++ p++;
694++ }
695++ /* Ignore trailing "\*" and "\@" in @pattern. */
696++ while (*p == '\\' &&
697++ (*(p + 1) == '*' || *(p + 1) == '@'))
698++ p += 2;
699++ return !*f && !*p;
700++}
701++
702++/**
703++ * tmy_io_printf - Transactional printf() to "struct tmy_io_buffer" structure.
704++ *
705++ * @head: Pointer to "struct tmy_io_buffer".
706++ * @fmt: The printf()'s format string, followed by parameters.
707++ *
708++ * Returns true on success, false otherwise.
709++ *
710++ * The snprintf() will truncate, but tmy_io_printf() won't.
711++ */
712++bool tmy_io_printf(struct tmy_io_buffer *head, const char *fmt, ...)
713++{
714++ va_list args;
715++ int len;
716++ int pos = head->read_avail;
717++ int size = head->readbuf_size - pos;
718++
719++ if (size <= 0)
720++ return false;
721++ va_start(args, fmt);
722++ len = vsnprintf(head->read_buf + pos, size, fmt, args);
723++ va_end(args);
724++ if (pos + len >= head->readbuf_size)
725++ return false;
726++ head->read_avail += len;
727++ return true;
728++}
729++
730++/**
731++ * tmy_get_exe - Get tmy_realpath() of current process.
732++ *
733++ * Returns the tmy_realpath() of current process on success, NULL otherwise.
734++ *
735++ * This function uses tmy_alloc(), so the caller must call tmy_free()
736++ * if this function didn't return NULL.
737++ */
738++static const char *tmy_get_exe(void)
739++{
740++ struct mm_struct *mm = current->mm;
741++ struct vm_area_struct *vma;
742++ const char *cp = NULL;
743++
744++ if (!mm)
745++ return NULL;
746++ down_read(&mm->mmap_sem);
747++ for (vma = mm->mmap; vma; vma = vma->vm_next) {
748++ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
749++ cp = tmy_realpath_from_path(&vma->vm_file->f_path);
750++ break;
751++ }
752++ }
753++ up_read(&mm->mmap_sem);
754++ return cp;
755++}
756++
757++/**
758++ * tmy_get_msg - Get warning message.
759++ *
760++ * @is_enforce: Is it enforcing mode?
761++ *
762++ * Returns "ERROR" or "WARNING".
763++ */
764++const char *tmy_get_msg(const bool is_enforce)
765++{
766++ if (is_enforce)
767++ return "ERROR";
768++ else
769++ return "WARNING";
770++}
771++
772++/**
773++ * tmy_check_flags - Check mode for specified functionality.
774++ *
775++ * @domain: Pointer to "struct domain_info".
776++ * @index: The functionality to check mode.
777++ *
778++ * Returns the mode of specified functionality.
779++ */
780++unsigned int tmy_check_flags(const struct domain_info *domain, const u8 index)
781++{
782++ const u8 profile = domain->profile;
783++
784++ if (unlikely(in_interrupt())) {
785++ static u8 count = 20;
786++ if (count) {
787++ count--;
788++ printk(KERN_ERR "BUG: sleeping function called "
789++ "from invalid context.\n");
790++ dump_stack();
791++ }
792++ return 0;
793++ }
794++ return sbin_init_started && index < TMY_MAX_CONTROL_INDEX
795++#if MAX_PROFILES != 256
796++ && profile < MAX_PROFILES
797++#endif
798++ && profile_ptr[profile] ?
799++ profile_ptr[profile]->value[index] : 0;
800++}
801++
802++/**
803++ * tmy_verbose_mode - Check whether TOMOYO is verbose mode.
804++ *
805++ * @domain: Pointer to "struct domain_info".
806++ *
807++ * Returns true if domain policy violation warning should be printed to
808++ * console.
809++ */
810++bool tmy_verbose_mode(const struct domain_info *domain)
811++{
812++ return tmy_check_flags(domain, TMY_TOMOYO_VERBOSE) != 0;
813++}
814++
815++/**
816++ * tmy_check_domain_quota - Check for domain's quota.
817++ *
818++ * @domain: Pointer to "struct domain_info".
819++ *
820++ * Returns true if the domain is not exceeded quota, false otherwise.
821++ */
822++bool tmy_check_domain_quota(struct domain_info * const domain)
823++{
824++ unsigned int count = 0;
825++ struct acl_info *ptr;
826++
827++ if (!domain)
828++ return true;
829++ list1_for_each_entry(ptr, &domain->acl_info_list, list) {
830++ if (ptr->type & ACL_DELETED)
831++ continue;
832++ switch (tmy_acl_type2(ptr)) {
833++ struct single_path_acl_record *acl1;
834++ struct double_path_acl_record *acl2;
835++ u16 perm;
836++ case TYPE_SINGLE_PATH_ACL:
837++ acl1 = container_of(ptr, struct single_path_acl_record,
838++ head);
839++ perm = acl1->perm;
840++ if (perm & (1 << TMY_TYPE_EXECUTE_ACL))
841++ count++;
842++ if (perm &
843++ ((1 << TMY_TYPE_READ_ACL) |
844++ (1 << TMY_TYPE_WRITE_ACL)))
845++ count++;
846++ if (perm & (1 << TMY_TYPE_CREATE_ACL))
847++ count++;
848++ if (perm & (1 << TMY_TYPE_UNLINK_ACL))
849++ count++;
850++ if (perm & (1 << TMY_TYPE_MKDIR_ACL))
851++ count++;
852++ if (perm & (1 << TMY_TYPE_RMDIR_ACL))
853++ count++;
854++ if (perm & (1 << TMY_TYPE_MKFIFO_ACL))
855++ count++;
856++ if (perm & (1 << TMY_TYPE_MKSOCK_ACL))
857++ count++;
858++ if (perm & (1 << TMY_TYPE_MKBLOCK_ACL))
859++ count++;
860++ if (perm & (1 << TMY_TYPE_MKCHAR_ACL))
861++ count++;
862++ if (perm & (1 << TMY_TYPE_TRUNCATE_ACL))
863++ count++;
864++ if (perm & (1 << TMY_TYPE_SYMLINK_ACL))
865++ count++;
866++ if (perm & (1 << TMY_TYPE_REWRITE_ACL))
867++ count++;
868++ break;
869++ case TYPE_DOUBLE_PATH_ACL:
870++ acl2 = container_of(ptr, struct double_path_acl_record,
871++ head);
872++ perm = acl2->perm;
873++ if (perm & (1 << TMY_TYPE_LINK_ACL))
874++ count++;
875++ if (perm & (1 << TMY_TYPE_RENAME_ACL))
876++ count++;
877++ break;
878++ }
879++ }
880++ if (count < tmy_check_flags(domain, TMY_TOMOYO_MAX_ACCEPT_ENTRY))
881++ return true;
882++ if (!domain->quota_warned) {
883++ domain->quota_warned = true;
884++ printk(KERN_WARNING "TOMOYO-WARNING: "
885++ "Domain '%s' has so many ACLs to hold. "
886++ "Stopped learning mode.\n", domain->domainname->name);
887++ }
888++ return false;
889++}
890++
891++/**
892++ * tmy_find_or_assign_new_profile - Create a new profile.
893++ *
894++ * @profile: Profile number to create.
895++ *
896++ * Returns pointer to "struct profile" on success, NULL otherwise.
897++ */
898++static struct profile *tmy_find_or_assign_new_profile(const unsigned int
899++ profile)
900++{
901++ static DEFINE_MUTEX(lock);
902++ struct profile *ptr = NULL;
903++
904++ /***** EXCLUSIVE SECTION START *****/
905++ mutex_lock(&lock);
906++ if (profile < MAX_PROFILES) {
907++ ptr = profile_ptr[profile];
908++ if (ptr)
909++ goto ok;
910++ ptr = tmy_alloc_element(sizeof(*ptr));
911++ if (ptr) {
912++ int i;
913++ for (i = 0; i < TMY_MAX_CONTROL_INDEX; i++)
914++ ptr->value[i]
915++ = tmy_control_array[i].current_value;
916++ mb(); /* Avoid out-of-order execution. */
917++ profile_ptr[profile] = ptr;
918++ }
919++ }
920++ok:
921++ mutex_unlock(&lock);
922++ /***** EXCLUSIVE SECTION END *****/
923++ return ptr;
924++}
925++
926++/**
927++ * write_profile - Write profile table.
928++ *
929++ * @head: Pointer to "struct tmy_io_buffer"
930++ *
931++ * Returns 0 on success, negative value otherwise.
932++ */
933++static int write_profile(struct tmy_io_buffer *head)
934++{
935++ char *data = head->write_buf;
936++ unsigned int i;
937++ unsigned int value;
938++ char *cp;
939++ struct profile *profile;
940++ unsigned long num;
941++
942++ cp = strchr(data, '-');
943++ if (cp)
944++ *cp = '\0';
945++ if (strict_strtoul(data, 10, &num))
946++ return -EINVAL;
947++ if (cp)
948++ data = cp + 1;
949++ profile = tmy_find_or_assign_new_profile(num);
950++ if (!profile)
951++ return -EINVAL;
952++ cp = strchr(data, '=');
953++ if (!cp)
954++ return -EINVAL;
955++ *cp = '\0';
956++ tmy_update_counter(TMY_UPDATES_COUNTER_PROFILE);
957++ if (!strcmp(data, "COMMENT")) {
958++ profile->comment = tmy_save_name(cp + 1);
959++ return 0;
960++ }
961++ for (i = 0; i < TMY_MAX_CONTROL_INDEX; i++) {
962++ if (strcmp(data, tmy_control_array[i].keyword))
963++ continue;
964++ if (sscanf(cp + 1, "%u", &value) != 1) {
965++ int j;
966++ const char **modes;
967++ switch (i) {
968++ case TMY_TOMOYO_VERBOSE:
969++ modes = mode_2;
970++ break;
971++ default:
972++ modes = mode_4;
973++ break;
974++ }
975++ for (j = 0; j < 4; j++) {
976++ if (strcmp(cp + 1, modes[j]))
977++ continue;
978++ value = j;
979++ break;
980++ }
981++ if (j == 4)
982++ return -EINVAL;
983++ } else if (value > tmy_control_array[i].max_value) {
984++ value = tmy_control_array[i].max_value;
985++ }
986++ profile->value[i] = value;
987++ return 0;
988++ }
989++ return -EINVAL;
990++}
991++
992++/**
993++ * read_profile - Read profile table.
994++ *
995++ * @head: Pointer to "struct tmy_io_buffer"
996++ *
997++ * Returns 0.
998++ */
999++static int read_profile(struct tmy_io_buffer *head)
1000++{
1001++ static const int total = TMY_MAX_CONTROL_INDEX + 1;
1002++ int step;
1003++
1004++ if (head->read_eof)
1005++ return 0;
1006++ for (step = head->read_step; step < MAX_PROFILES * total; step++) {
1007++ const u8 index = step / total;
1008++ u8 type = step % total;
1009++ const struct profile *profile = profile_ptr[index];
1010++ head->read_step = step;
1011++ if (!profile)
1012++ continue;
1013++ if (!type) { /* Print profile' comment tag. */
1014++ if (!tmy_io_printf(head, "%u-COMMENT=%s\n",
1015++ index, profile->comment ?
1016++ profile->comment->name : ""))
1017++ break;
1018++ continue;
1019++ }
1020++ type--;
1021++ if (type < TMY_MAX_CONTROL_INDEX) {
1022++ const unsigned int value = profile->value[type];
1023++ const char **modes = NULL;
1024++ const char *keyword = tmy_control_array[type].keyword;
1025++ switch (tmy_control_array[type].max_value) {
1026++ case 3:
1027++ modes = mode_4;
1028++ break;
1029++ case 1:
1030++ modes = mode_2;
1031++ break;
1032++ }
1033++ if (modes) {
1034++ if (!tmy_io_printf(head, "%u-%s=%s\n", index,
1035++ keyword, modes[value]))
1036++ break;
1037++ } else {
1038++ if (!tmy_io_printf(head, "%u-%s=%u\n", index,
1039++ keyword, value))
1040++ break;
1041++ }
1042++ }
1043++ }
1044++ if (step == MAX_PROFILES * total)
1045++ head->read_eof = true;
1046++ return 0;
1047++}
1048++
1049++/* Structure for policy manager. */
1050++struct policy_manager_entry {
1051++ struct list1_head list;
1052++ /* A path to program or a domainname. */
1053++ const struct path_info *manager;
1054++ bool is_domain; /* True if manager is a domainname. */
1055++ bool is_deleted; /* True if this entry is deleted. */
1056++};
1057++
1058++/*
1059++ * The list for "struct policy_manager_entry".
1060++ *
1061++ * This list is updated only inside update_manager_entry(), thus
1062++ * no global mutex exists.
1063++ */
1064++static LIST1_HEAD(policy_manager_list);
1065++
1066++/**
1067++ * update_manager_entry - Add a manager entry.
1068++ *
1069++ * @manager: The path to manager or the domainnamme.
1070++ * @is_delete: True if it is a delete request.
1071++ *
1072++ * Returns 0 on success, negative value otherwise.
1073++ */
1074++static int update_manager_entry(const char *manager, const bool is_delete)
1075++{
1076++ struct policy_manager_entry *new_entry;
1077++ struct policy_manager_entry *ptr;
1078++ static DEFINE_MUTEX(lock);
1079++ const struct path_info *saved_manager;
1080++ int error = -ENOMEM;
1081++ bool is_domain = false;
1082++
1083++ if (tmy_is_domain_def(manager)) {
1084++ if (!tmy_is_correct_domain(manager, __func__))
1085++ return -EINVAL;
1086++ is_domain = true;
1087++ } else {
1088++ if (!tmy_is_correct_path(manager, 1, -1, -1, __func__))
1089++ return -EINVAL;
1090++ }
1091++ saved_manager = tmy_save_name(manager);
1092++ if (!saved_manager)
1093++ return -ENOMEM;
1094++ /***** EXCLUSIVE SECTION START *****/
1095++ mutex_lock(&lock);
1096++ list1_for_each_entry(ptr, &policy_manager_list, list) {
1097++ if (ptr->manager != saved_manager)
1098++ continue;
1099++ ptr->is_deleted = is_delete;
1100++ error = 0;
1101++ goto out;
1102++ }
1103++ if (is_delete) {
1104++ error = -ENOENT;
1105++ goto out;
1106++ }
1107++ new_entry = tmy_alloc_element(sizeof(*new_entry));
1108++ if (!new_entry)
1109++ goto out;
1110++ new_entry->manager = saved_manager;
1111++ new_entry->is_domain = is_domain;
1112++ list1_add_tail(&new_entry->list, &policy_manager_list);
1113++ error = 0;
1114++out:
1115++ mutex_unlock(&lock);
1116++ /***** EXCLUSIVE SECTION END *****/
1117++ if (!error)
1118++ tmy_update_counter(TMY_UPDATES_COUNTER_MANAGER);
1119++ return error;
1120++}
1121++
1122++/**
1123++ * write_manager_policy - Write manager policy.
1124++ *
1125++ * @head: Pointer to "struct tmy_io_buffer"
1126++ *
1127++ * Returns 0 on success, negative value otherwise.
1128++ */
1129++static int write_manager_policy(struct tmy_io_buffer *head)
1130++{
1131++ char *data = head->write_buf;
1132++ bool is_delete = str_starts(&data, KEYWORD_DELETE);
1133++
1134++ if (!strcmp(data, "manage_by_non_root")) {
1135++ manage_by_non_root = !is_delete;
1136++ return 0;
1137++ }
1138++ return update_manager_entry(data, is_delete);
1139++}
1140++
1141++/**
1142++ * read_manager_policy - Read manager policy.
1143++ *
1144++ * @head: Pointer to "struct tmy_io_buffer"
1145++ *
1146++ * Returns 0.
1147++ */
1148++static int read_manager_policy(struct tmy_io_buffer *head)
1149++{
1150++ struct list1_head *pos;
1151++
1152++ if (head->read_eof)
1153++ return 0;
1154++ list1_for_each_cookie(pos, head->read_var2, &policy_manager_list) {
1155++ struct policy_manager_entry *ptr;
1156++ ptr = list1_entry(pos, struct policy_manager_entry, list);
1157++ if (ptr->is_deleted)
1158++ continue;
1159++ if (!tmy_io_printf(head, "%s\n", ptr->manager->name))
1160++ return 0;
1161++ }
1162++ head->read_eof = true;
1163++ return 0;
1164++}
1165++
1166++/**
1167++ * is_policy_manager - Check whether the current process is a policy manager.
1168++ *
1169++ * Returns true if the current process is permitted to modify policy
1170++ * via /sys/kernel/security/tomoyo/ interface.
1171++ */
1172++static bool is_policy_manager(void)
1173++{
1174++ struct policy_manager_entry *ptr;
1175++ const char *exe;
1176++ const struct task_struct *task = current;
1177++ const struct path_info *domainname = tmy_domain()->domainname;
1178++ bool found = false;
1179++
1180++ if (!sbin_init_started)
1181++ return true;
1182++ if (!manage_by_non_root && (task->cred->uid || task->cred->euid))
1183++ return false;
1184++ list1_for_each_entry(ptr, &policy_manager_list, list) {
1185++ if (!ptr->is_deleted && ptr->is_domain
1186++ && !tmy_pathcmp(domainname, ptr->manager))
1187++ return true;
1188++ }
1189++ exe = tmy_get_exe();
1190++ if (!exe)
1191++ return false;
1192++ list1_for_each_entry(ptr, &policy_manager_list, list) {
1193++ if (!ptr->is_deleted && !ptr->is_domain
1194++ && !strcmp(exe, ptr->manager->name)) {
1195++ found = true;
1196++ break;
1197++ }
1198++ }
1199++ if (!found) { /* Reduce error messages. */
1200++ static pid_t last_pid;
1201++ const pid_t pid = current->pid;
1202++ if (last_pid != pid) {
1203++ printk(KERN_WARNING "%s ( %s ) is not permitted to "
1204++ "update policies.\n", domainname->name, exe);
1205++ last_pid = pid;
1206++ }
1207++ }
1208++ tmy_free(exe);
1209++ return found;
1210++}
1211++
1212++/**
1213++ * is_select_one - Parse select command.
1214++ *
1215++ * @head: Pointer to "struct tmy_io_buffer".
1216++ * @data: String to parse.
1217++ *
1218++ * Returns true on success, false otherwise.
1219++ */
1220++static bool is_select_one(struct tmy_io_buffer *head, const char *data)
1221++{
1222++ unsigned int pid;
1223++ struct domain_info *domain = NULL;
1224++
1225++ if (sscanf(data, "pid=%u", &pid) == 1) {
1226++ struct task_struct *p;
1227++ /***** CRITICAL SECTION START *****/
1228++ read_lock(&tasklist_lock);
1229++ p = find_task_by_vpid(pid);
1230++ if (p)
1231++ domain = tmy_real_domain(p);
1232++ read_unlock(&tasklist_lock);
1233++ /***** CRITICAL SECTION END *****/
1234++ } else if (!strncmp(data, "domain=", 7)) {
1235++ if (tmy_is_domain_def(data + 7))
1236++ domain = tmy_find_domain(data + 7);
1237++ } else
1238++ return false;
1239++ head->read_avail = 0;
1240++ tmy_io_printf(head, "# select %s\n", data);
1241++ head->read_single_domain = true;
1242++ head->read_eof = !domain;
1243++ if (domain) {
1244++ struct domain_info *d;
1245++ head->read_var1 = NULL;
1246++ list1_for_each_entry(d, &domain_list, list) {
1247++ if (d == domain)
1248++ break;
1249++ head->read_var1 = &d->list;
1250++ }
1251++ head->read_var2 = NULL;
1252++ head->read_bit = 0;
1253++ head->read_step = 0;
1254++ if (domain->is_deleted)
1255++ tmy_io_printf(head, "# This is a deleted domain.\n");
1256++ }
1257++ head->write_var1 = domain;
1258++ return true;
1259++}
1260++
1261++/**
1262++ * write_domain_policy - Write domain policy.
1263++ *
1264++ * @head: Pointer to "struct tmy_io_buffer".
1265++ *
1266++ * Returns 0 on success, negative value otherwise.
1267++ */
1268++static int write_domain_policy(struct tmy_io_buffer *head)
1269++{
1270++ char *data = head->write_buf;
1271++ struct domain_info *domain = head->write_var1;
1272++ bool is_delete = false;
1273++ bool is_select = false;
1274++ bool is_undelete = false;
1275++ unsigned int profile;
1276++
1277++ if (str_starts(&data, KEYWORD_DELETE))
1278++ is_delete = true;
1279++ else if (str_starts(&data, KEYWORD_SELECT))
1280++ is_select = true;
1281++ else if (str_starts(&data, KEYWORD_UNDELETE))
1282++ is_undelete = true;
1283++ if (is_select && is_select_one(head, data))
1284++ return 0;
1285++ /* Don't allow updating policies by non manager programs. */
1286++ if (!is_policy_manager())
1287++ return -EPERM;
1288++ if (tmy_is_domain_def(data)) {
1289++ domain = NULL;
1290++ if (is_delete)
1291++ tmy_delete_domain(data);
1292++ else if (is_select)
1293++ domain = tmy_find_domain(data);
1294++ else if (is_undelete)
1295++ domain = tmy_undelete_domain(data);
1296++ else
1297++ domain = tmy_find_or_assign_new_domain(data, 0);
1298++ head->write_var1 = domain;
1299++ tmy_update_counter(TMY_UPDATES_COUNTER_DOMAIN_POLICY);
1300++ return 0;
1301++ }
1302++ if (!domain)
1303++ return -EINVAL;
1304++
1305++ if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1
1306++ && profile < MAX_PROFILES) {
1307++ if (profile_ptr[profile] || !sbin_init_started)
1308++ domain->profile = (u8) profile;
1309++ return 0;
1310++ }
1311++ if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1312++ tmy_set_domain_flag(domain, is_delete,
1313++ DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1314++ return 0;
1315++ }
1316++ return tmy_write_file_policy(data, domain, is_delete);
1317++}
1318++
1319++/**
1320++ * print_single_path_acl - Print a single path ACL entry.
1321++ *
1322++ * @head: Pointer to "struct tmy_io_buffer".
1323++ * @ptr: Pointer to "struct single_path_acl_record".
1324++ *
1325++ * Returns true on success, false otherwise.
1326++ */
1327++static bool print_single_path_acl(struct tmy_io_buffer *head,
1328++ struct single_path_acl_record *ptr)
1329++{
1330++ int pos;
1331++ u8 bit;
1332++ const char *atmark = "";
1333++ const char *filename;
1334++ const u16 perm = ptr->perm;
1335++
1336++ filename = ptr->filename->name;
1337++ for (bit = head->read_bit; bit < MAX_SINGLE_PATH_OPERATION; bit++) {
1338++ const char *msg;
1339++ if (!(perm & (1 << bit)))
1340++ continue;
1341++ /* Print "read/write" instead of "read" and "write". */
1342++ if ((bit == TMY_TYPE_READ_ACL || bit == TMY_TYPE_WRITE_ACL)
1343++ && (perm & (1 << TMY_TYPE_READ_WRITE_ACL)))
1344++ continue;
1345++ msg = tmy_sp2keyword(bit);
1346++ pos = head->read_avail;
1347++ if (!tmy_io_printf(head, "allow_%s %s%s\n", msg,
1348++ atmark, filename))
1349++ goto out;
1350++ }
1351++ head->read_bit = 0;
1352++ return true;
1353++out:
1354++ head->read_bit = bit;
1355++ head->read_avail = pos;
1356++ return false;
1357++}
1358++
1359++/**
1360++ * print_double_path_acl - Print a double path ACL entry.
1361++ *
1362++ * @head: Pointer to "struct tmy_io_buffer".
1363++ * @ptr: Pointer to "struct double_path_acl_record".
1364++ *
1365++ * Returns true on success, false otherwise.
1366++ */
1367++static bool print_double_path_acl(struct tmy_io_buffer *head,
1368++ struct double_path_acl_record *ptr)
1369++{
1370++ int pos;
1371++ const char *atmark1 = "";
1372++ const char *atmark2 = "";
1373++ const char *filename1;
1374++ const char *filename2;
1375++ const u8 perm = ptr->perm;
1376++ u8 bit;
1377++
1378++ filename1 = ptr->filename1->name;
1379++ filename2 = ptr->filename2->name;
1380++ for (bit = head->read_bit; bit < MAX_DOUBLE_PATH_OPERATION; bit++) {
1381++ const char *msg;
1382++ if (!(perm & (1 << bit)))
1383++ continue;
1384++ msg = tmy_dp2keyword(bit);
1385++ pos = head->read_avail;
1386++ if (!tmy_io_printf(head, "allow_%s %s%s %s%s\n", msg,
1387++ atmark1, filename1, atmark2, filename2))
1388++ goto out;
1389++ }
1390++ head->read_bit = 0;
1391++ return true;
1392++out:
1393++ head->read_bit = bit;
1394++ head->read_avail = pos;
1395++ return false;
1396++}
1397++
1398++/**
1399++ * print_entry - Print an ACL entry.
1400++ *
1401++ * @head: Pointer to "struct tmy_io_buffer".
1402++ * @ptr: Pointer to an ACL entry.
1403++ *
1404++ * Returns true on success, false otherwise.
1405++ */
1406++static bool print_entry(struct tmy_io_buffer *head, struct acl_info *ptr)
1407++{
1408++ const u8 acl_type = tmy_acl_type2(ptr);
1409++
1410++ if (acl_type & ACL_DELETED)
1411++ return true;
1412++ if (acl_type == TYPE_SINGLE_PATH_ACL) {
1413++ struct single_path_acl_record *acl
1414++ = container_of(ptr, struct single_path_acl_record,
1415++ head);
1416++ return print_single_path_acl(head, acl);
1417++ }
1418++ if (acl_type == TYPE_DOUBLE_PATH_ACL) {
1419++ struct double_path_acl_record *acl
1420++ = container_of(ptr, struct double_path_acl_record,
1421++ head);
1422++ return print_double_path_acl(head, acl);
1423++ }
1424++ BUG(); /* This must not happen. */
1425++ return false;
1426++}
1427++
1428++/**
1429++ * read_domain_policy - Read domain policy.
1430++ *
1431++ * @head: Pointer to "struct tmy_io_buffer".
1432++ *
1433++ * Returns 0.
1434++ */
1435++static int read_domain_policy(struct tmy_io_buffer *head)
1436++{
1437++ struct list1_head *dpos;
1438++ struct list1_head *apos;
1439++
1440++ if (head->read_eof)
1441++ return 0;
1442++ if (head->read_step == 0)
1443++ head->read_step = 1;
1444++ list1_for_each_cookie(dpos, head->read_var1, &domain_list) {
1445++ struct domain_info *domain;
1446++ const char *quota_exceeded = "";
1447++ const char *transition_failed = "";
1448++ const char *ignore_global_allow_read = "";
1449++ domain = list1_entry(dpos, struct domain_info, list);
1450++ if (head->read_step != 1)
1451++ goto acl_loop;
1452++ if (domain->is_deleted && !head->read_single_domain)
1453++ continue;
1454++ /* Print domainname and flags. */
1455++ if (domain->quota_warned)
1456++ quota_exceeded = "quota_exceeded\n";
1457++ if (domain->flags & DOMAIN_FLAGS_TRANSITION_FAILED)
1458++ transition_failed = "transition_failed\n";
1459++ if (domain->flags & DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1460++ ignore_global_allow_read
1461++ = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1462++ if (!tmy_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n"
1463++ "%s%s%s\n", domain->domainname->name,
1464++ domain->profile, quota_exceeded,
1465++ transition_failed, ignore_global_allow_read))
1466++ return 0;
1467++ head->read_step = 2;
1468++acl_loop:
1469++ if (head->read_step == 3)
1470++ goto tail_mark;
1471++ /* Print ACL entries in the domain. */
1472++ list1_for_each_cookie(apos, head->read_var2,
1473++ &domain->acl_info_list) {
1474++ struct acl_info *ptr
1475++ = list1_entry(apos, struct acl_info, list);
1476++ if (!print_entry(head, ptr))
1477++ return 0;
1478++ }
1479++ head->read_step = 3;
1480++tail_mark:
1481++ if (!tmy_io_printf(head, "\n"))
1482++ return 0;
1483++ head->read_step = 1;
1484++ if (head->read_single_domain)
1485++ break;
1486++ }
1487++ head->read_eof = true;
1488++ return 0;
1489++}
1490++
1491++/**
1492++ * write_domain_profile - Assign profile for specified domain.
1493++ *
1494++ * @head: Pointer to "struct tmy_io_buffer".
1495++ *
1496++ * Returns 0 on success, -EINVAL otherwise.
1497++ *
1498++ * This is equivalent to doing
1499++ *
1500++ * ( echo "select " $domainname; echo "use_profile " $profile ) |
1501++ * /usr/lib/ccs/loadpolicy -d
1502++ */
1503++static int write_domain_profile(struct tmy_io_buffer *head)
1504++{
1505++ char *data = head->write_buf;
1506++ char *cp = strchr(data, ' ');
1507++ struct domain_info *domain;
1508++ unsigned long profile;
1509++
1510++ if (!cp)
1511++ return -EINVAL;
1512++ *cp = '\0';
1513++ domain = tmy_find_domain(cp + 1);
1514++ strict_strtoul(data, 10, &profile);
1515++ if (domain && profile < MAX_PROFILES
1516++ && (profile_ptr[profile] || !sbin_init_started))
1517++ domain->profile = (u8) profile;
1518++ tmy_update_counter(TMY_UPDATES_COUNTER_DOMAIN_POLICY);
1519++ return 0;
1520++}
1521++
1522++/**
1523++ * read_domain_profile - Read only domainname and profile.
1524++ *
1525++ * @head: Pointer to "struct tmy_io_buffer".
1526++ *
1527++ * Returns list of profile number and domainname pairs.
1528++ *
1529++ * This is equivalent to doing
1530++ *
1531++ * grep -A 1 '^<kernel>' /sys/kernel/security/tomoyo/domain_policy |
1532++ * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1533++ * domainname = $0; } else if ( $1 == "use_profile" ) {
1534++ * print $2 " " domainname; domainname = ""; } } ; '
1535++ */
1536++static int read_domain_profile(struct tmy_io_buffer *head)
1537++{
1538++ struct list1_head *pos;
1539++
1540++ if (head->read_eof)
1541++ return 0;
1542++ list1_for_each_cookie(pos, head->read_var1, &domain_list) {
1543++ struct domain_info *domain;
1544++ domain = list1_entry(pos, struct domain_info, list);
1545++ if (domain->is_deleted)
1546++ continue;
1547++ if (!tmy_io_printf(head, "%u %s\n", domain->profile,
1548++ domain->domainname->name))
1549++ return 0;
1550++ }
1551++ head->read_eof = true;
1552++ return 0;
1553++}
1554++
1555++/**
1556++ * write_pid: Specify PID to obtain domainname.
1557++ *
1558++ * @head: Pointer to "struct tmy_io_buffer".
1559++ *
1560++ * Returns 0.
1561++ */
1562++static int write_pid(struct tmy_io_buffer *head)
1563++{
1564++ unsigned long pid;
1565++ strict_strtoul(head->write_buf, 10, &pid);
1566++ head->read_step = (int) pid;
1567++ head->read_eof = false;
1568++ return 0;
1569++}
1570++
1571++/**
1572++ * read_pid - Get domainname of the specified PID.
1573++ *
1574++ * @head: Pointer to "struct tmy_io_buffer".
1575++ *
1576++ * Returns the domainname which the specified PID is in on success,
1577++ * empty string otherwise.
1578++ * The PID is specified by write_pid() so that the user can obtain
1579++ * using read()/write() interface rather than sysctl() interface.
1580++ */
1581++static int read_pid(struct tmy_io_buffer *head)
1582++{
1583++ if (head->read_avail == 0 && !head->read_eof) {
1584++ const int pid = head->read_step;
1585++ struct task_struct *p;
1586++ struct domain_info *domain = NULL;
1587++ /***** CRITICAL SECTION START *****/
1588++ read_lock(&tasklist_lock);
1589++ p = find_task_by_vpid(pid);
1590++ if (p)
1591++ domain = tmy_real_domain(p);
1592++ read_unlock(&tasklist_lock);
1593++ /***** CRITICAL SECTION END *****/
1594++ if (domain)
1595++ tmy_io_printf(head, "%d %u %s", pid, domain->profile,
1596++ domain->domainname->name);
1597++ head->read_eof = true;
1598++ }
1599++ return 0;
1600++}
1601++
1602++/**
1603++ * write_exception_policy - Write exception policy.
1604++ *
1605++ * @head: Pointer to "struct tmy_io_buffer".
1606++ *
1607++ * Returns 0 on success, negative value otherwise.
1608++ */
1609++static int write_exception_policy(struct tmy_io_buffer *head)
1610++{
1611++ char *data = head->write_buf;
1612++ bool is_delete = str_starts(&data, KEYWORD_DELETE);
1613++
1614++ if (str_starts(&data, KEYWORD_KEEP_DOMAIN))
1615++ return tmy_write_domain_keeper_policy(data, false, is_delete);
1616++ if (str_starts(&data, KEYWORD_NO_KEEP_DOMAIN))
1617++ return tmy_write_domain_keeper_policy(data, true, is_delete);
1618++ if (str_starts(&data, KEYWORD_INITIALIZE_DOMAIN))
1619++ return tmy_write_domain_initializer_policy(data, false,
1620++ is_delete);
1621++ if (str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN))
1622++ return tmy_write_domain_initializer_policy(data, true,
1623++ is_delete);
1624++ if (str_starts(&data, KEYWORD_ALIAS))
1625++ return tmy_write_alias_policy(data, is_delete);
1626++ if (str_starts(&data, KEYWORD_ALLOW_READ))
1627++ return tmy_write_globally_readable_policy(data, is_delete);
1628++ if (str_starts(&data, KEYWORD_FILE_PATTERN))
1629++ return tmy_write_pattern_policy(data, is_delete);
1630++ if (str_starts(&data, KEYWORD_DENY_REWRITE))
1631++ return tmy_write_no_rewrite_policy(data, is_delete);
1632++ return -EINVAL;
1633++}
1634++
1635++/**
1636++ * read_exception_policy - Read exception policy.
1637++ *
1638++ * @head: Pointer to "struct tmy_io_buffer".
1639++ *
1640++ * Returns 0 on success, -EINVAL otherwise.
1641++ */
1642++static int read_exception_policy(struct tmy_io_buffer *head)
1643++{
1644++ if (!head->read_eof) {
1645++ switch (head->read_step) {
1646++ case 0:
1647++ head->read_var2 = NULL;
1648++ head->read_step = 1;
1649++ case 1:
1650++ if (!tmy_read_domain_keeper_policy(head))
1651++ break;
1652++ head->read_var2 = NULL;
1653++ head->read_step = 2;
1654++ case 2:
1655++ if (!tmy_read_globally_readable_policy(head))
1656++ break;
1657++ head->read_var2 = NULL;
1658++ head->read_step = 3;
1659++ case 3:
1660++ head->read_var2 = NULL;
1661++ head->read_step = 4;
1662++ case 4:
1663++ if (!tmy_read_domain_initializer_policy(head))
1664++ break;
1665++ head->read_var2 = NULL;
1666++ head->read_step = 5;
1667++ case 5:
1668++ if (!tmy_read_alias_policy(head))
1669++ break;
1670++ head->read_var2 = NULL;
1671++ head->read_step = 6;
1672++ case 6:
1673++ head->read_var2 = NULL;
1674++ head->read_step = 7;
1675++ case 7:
1676++ if (!tmy_read_file_pattern(head))
1677++ break;
1678++ head->read_var2 = NULL;
1679++ head->read_step = 8;
1680++ case 8:
1681++ if (!tmy_read_no_rewrite_policy(head))
1682++ break;
1683++ head->read_var2 = NULL;
1684++ head->read_step = 9;
1685++ case 9:
1686++ head->read_eof = true;
1687++ break;
1688++ default:
1689++ return -EINVAL;
1690++ }
1691++ }
1692++ return 0;
1693++}
1694++
1695++/* path to policy loader */
1696++static const char *tmy_loader = "/sbin/tomoyo-init";
1697++
1698++/**
1699++ * policy_loader_exists - Check whether /sbin/tomoyo-init exists.
1700++ *
1701++ * Returns true if /sbin/tomoyo-init exists, false otherwise.
1702++ */
1703++static bool policy_loader_exists(void)
1704++{
1705++ /*
1706++ * Don't activate MAC if the policy loader doesn't exist.
1707++ * If the initrd includes /sbin/init but real-root-dev has not
1708++ * mounted on / yet, activating MAC will block the system since
1709++ * policies are not loaded yet.
1710++ * Thus, let do_execve() call this function everytime.
1711++ */
1712++ struct nameidata nd;
1713++
1714++ if (path_lookup(tmy_loader, LOOKUP_FOLLOW, &nd)) {
1715++ printk(KERN_INFO "Not activating Mandatory Access Control now "
1716++ "since %s doesn't exist.\n", tmy_loader);
1717++ return false;
1718++ }
1719++ path_put(&nd.path);
1720++ return true;
1721++}
1722++
1723++/**
1724++ * tmy_load_policy - Run external policy loader to load policy.
1725++ *
1726++ * @filename: The program about to start.
1727++ *
1728++ * This function checks whether @filename is /sbin/init , and if so
1729++ * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
1730++ * and then continues invocation of /sbin/init.
1731++ * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
1732++ * writes to /sys/kernel/security/tomoyo/ interfaces.
1733++ *
1734++ * Returns nothing.
1735++ */
1736++void tmy_load_policy(const char *filename)
1737++{
1738++ char *argv[2];
1739++ char *envp[3];
1740++
1741++ if (sbin_init_started)
1742++ return;
1743++ /*
1744++ * Check filename is /sbin/init or /sbin/tomoyo-start.
1745++ * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
1746++ * be passed.
1747++ * You can create /sbin/tomoyo-start by
1748++ * "ln -s /bin/true /sbin/tomoyo-start".
1749++ */
1750++ if (strcmp(filename, "/sbin/init") &&
1751++ strcmp(filename, "/sbin/tomoyo-start"))
1752++ return;
1753++ if (!policy_loader_exists())
1754++ return;
1755++
1756++ printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
1757++ tmy_loader);
1758++ argv[0] = (char *) tmy_loader;
1759++ argv[1] = NULL;
1760++ envp[0] = "HOME=/";
1761++ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
1762++ envp[2] = NULL;
1763++ call_usermodehelper(argv[0], argv, envp, 1);
1764++
1765++ printk(KERN_INFO "TOMOYO: 2.2.0-pre 2008/10/10\n");
1766++ printk(KERN_INFO "Mandatory Access Control activated.\n");
1767++ sbin_init_started = true;
1768++ { /* Check all profiles currently assigned to domains are defined. */
1769++ struct domain_info *domain;
1770++ list1_for_each_entry(domain, &domain_list, list) {
1771++ const u8 profile = domain->profile;
1772++ if (profile_ptr[profile])
1773++ continue;
1774++ panic("Profile %u (used by '%s') not defined.\n",
1775++ profile, domain->domainname->name);
1776++ }
1777++ }
1778++}
1779++
1780++/* Policy updates counter. */
1781++static atomic_t updates_counter[MAX_TMY_UPDATES_COUNTER];
1782++
1783++/**
1784++ * tmy_update_counter - Increment policy change counter.
1785++ *
1786++ * @index: Type of policy.
1787++ *
1788++ * Returns nothing.
1789++ */
1790++void tmy_update_counter(const unsigned char index)
1791++{
1792++ if (index < MAX_TMY_UPDATES_COUNTER)
1793++ atomic_inc(&updates_counter[index]);
1794++}
1795++
1796++/**
1797++ * read_updates_counter - Check for policy change counter.
1798++ *
1799++ * @head: Pointer to "struct tmy_io_buffer".
1800++ *
1801++ * Returns how many times policy has changed since the previous check.
1802++ */
1803++static int read_updates_counter(struct tmy_io_buffer *head)
1804++{
1805++ if (head->read_eof)
1806++ return 0;
1807++ tmy_io_printf(head,
1808++ "/sys/kernel/security/tomoyo/domain_policy: %10u\n"
1809++ "/sys/kernel/security/tomoyo/exception_policy: %10u\n"
1810++ "/sys/kernel/security/tomoyo/profile: %10u\n"
1811++ "/sys/kernel/security/tomoyo/manager: %10u\n",
1812++ atomic_xchg(&updates_counter
1813++ [TMY_UPDATES_COUNTER_DOMAIN_POLICY], 0),
1814++ atomic_xchg(&updates_counter
1815++ [TMY_UPDATES_COUNTER_EXCEPTION_POLICY], 0),
1816++ atomic_xchg(&updates_counter
1817++ [TMY_UPDATES_COUNTER_PROFILE], 0),
1818++ atomic_xchg(&updates_counter
1819++ [TMY_UPDATES_COUNTER_MANAGER], 0));
1820++ head->read_eof = true;
1821++ return 0;
1822++}
1823++
1824++/**
1825++ * read_version: Get version.
1826++ *
1827++ * @head: Pointer to "struct tmy_io_buffer".
1828++ *
1829++ * Returns version information.
1830++ */
1831++static int read_version(struct tmy_io_buffer *head)
1832++{
1833++ if (!head->read_eof) {
1834++ tmy_io_printf(head, "2.2.0-pre");
1835++ head->read_eof = true;
1836++ }
1837++ return 0;
1838++}
1839++
1840++/**
1841++ * read_self_domain - Get the current process's domainname.
1842++ *
1843++ * @head: Pointer to "struct tmy_io_buffer".
1844++ *
1845++ * Returns the current process's domainname.
1846++ */
1847++static int read_self_domain(struct tmy_io_buffer *head)
1848++{
1849++ if (!head->read_eof) {
1850++ /*
1851++ * tmy_domain()->domainname != NULL
1852++ * because every process belongs to a domain and
1853++ * the domain's name cannot be NULL.
1854++ */
1855++ tmy_io_printf(head, "%s", tmy_domain()->domainname->name);
1856++ head->read_eof = true;
1857++ }
1858++ return 0;
1859++}
1860++
1861++/**
1862++ * tmy_open_control - open() for /sys/kernel/security/tomoyo/ interface.
1863++ *
1864++ * @type: Type of interface.
1865++ * @file: Pointer to "struct file".
1866++ *
1867++ * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1868++ */
1869++static int tmy_open_control(const u8 type, struct file *file)
1870++{
1871++ struct tmy_io_buffer *head = tmy_alloc(sizeof(*head));
1872++
1873++ if (!head)
1874++ return -ENOMEM;
1875++ mutex_init(&head->io_sem);
1876++ switch (type) {
1877++ case TMY_DOMAINPOLICY:
1878++ /* /sys/kernel/security/tomoyo/domain_policy */
1879++ head->write = write_domain_policy;
1880++ head->read = read_domain_policy;
1881++ break;
1882++ case TMY_EXCEPTIONPOLICY:
1883++ /* /sys/kernel/security/tomoyo/exception_policy */
1884++ head->write = write_exception_policy;
1885++ head->read = read_exception_policy;
1886++ break;
1887++ case TMY_SELFDOMAIN:
1888++ /* /sys/kernel/security/tomoyo/self_domain */
1889++ head->read = read_self_domain;
1890++ break;
1891++ case TMY_DOMAIN_STATUS:
1892++ /* /sys/kernel/security/tomoyo/.domain_status */
1893++ head->write = write_domain_profile;
1894++ head->read = read_domain_profile;
1895++ break;
1896++ case TMY_PROCESS_STATUS:
1897++ /* /sys/kernel/security/tomoyo/.process_status */
1898++ head->write = write_pid;
1899++ head->read = read_pid;
1900++ break;
1901++ case TMY_VERSION:
1902++ /* /sys/kernel/security/tomoyo/version */
1903++ head->read = read_version;
1904++ head->readbuf_size = 128;
1905++ break;
1906++ case TMY_MEMINFO:
1907++ /* /sys/kernel/security/tomoyo/meminfo */
1908++ head->write = tmy_write_memory_quota;
1909++ head->read = tmy_read_memory_counter;
1910++ head->readbuf_size = 512;
1911++ break;
1912++ case TMY_PROFILE:
1913++ /* /sys/kernel/security/tomoyo/profile */
1914++ head->write = write_profile;
1915++ head->read = read_profile;
1916++ break;
1917++ case TMY_MANAGER:
1918++ /* /sys/kernel/security/tomoyo/manager */
1919++ head->write = write_manager_policy;
1920++ head->read = read_manager_policy;
1921++ break;
1922++ case TMY_UPDATESCOUNTER:
1923++ /* /sys/kernel/security/tomoyo/.updates_counter */
1924++ head->read = read_updates_counter;
1925++ break;
1926++ }
1927++ if (!(file->f_mode & FMODE_READ)) {
1928++ /*
1929++ * No need to allocate read_buf since it is not opened
1930++ * for reading.
1931++ */
1932++ head->read = NULL;
1933++ } else {
1934++ if (!head->readbuf_size)
1935++ head->readbuf_size = 4096 * 2;
1936++ head->read_buf = tmy_alloc(head->readbuf_size);
1937++ if (!head->read_buf) {
1938++ tmy_free(head);
1939++ return -ENOMEM;
1940++ }
1941++ }
1942++ if (!(file->f_mode & FMODE_WRITE)) {
1943++ /*
1944++ * No need to allocate write_buf since it is not opened
1945++ * for writing.
1946++ */
1947++ head->write = NULL;
1948++ } else if (head->write) {
1949++ head->writebuf_size = 4096 * 2;
1950++ head->write_buf = tmy_alloc(head->writebuf_size);
1951++ if (!head->write_buf) {
1952++ tmy_free(head->read_buf);
1953++ tmy_free(head);
1954++ return -ENOMEM;
1955++ }
1956++ }
1957++ file->private_data = head;
1958++ /*
1959++ * Call the handler now if the file is
1960++ * /sys/kernel/security/tomoyo/self_domain
1961++ * so that the user can use
1962++ * cat < /sys/kernel/security/tomoyo/self_domain"
1963++ * to know the current process's domainname.
1964++ */
1965++ if (type == TMY_SELFDOMAIN)
1966++ tmy_read_control(file, NULL, 0);
1967++ return 0;
1968++}
1969++
1970++/**
1971++ * tmy_read_control - read() for /sys/kernel/security/tomoyo/ interface.
1972++ *
1973++ * @file: Pointer to "struct file".
1974++ * @buffer: Poiner to buffer to write to.
1975++ * @buffer_len: Size of @buffer.
1976++ *
1977++ * Returns bytes read on success, negative value otherwise.
1978++ */
1979++static int tmy_read_control(struct file *file, char __user *buffer,
1980++ const int buffer_len)
1981++{
1982++ int len = 0;
1983++ struct tmy_io_buffer *head = file->private_data;
1984++ char *cp;
1985++
1986++ if (!head->read)
1987++ return -ENOSYS;
1988++ if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
1989++ return -EFAULT;
1990++ if (mutex_lock_interruptible(&head->io_sem))
1991++ return -EINTR;
1992++ /* Call the policy handler. */
1993++ len = head->read(head);
1994++ if (len < 0)
1995++ goto out;
1996++ /* Write to buffer. */
1997++ len = head->read_avail;
1998++ if (len > buffer_len)
1999++ len = buffer_len;
2000++ if (!len)
2001++ goto out;
2002++ /* head->read_buf changes by some functions. */
2003++ cp = head->read_buf;
2004++ if (copy_to_user(buffer, cp, len)) {
2005++ len = -EFAULT;
2006++ goto out;
2007++ }
2008++ head->read_avail -= len;
2009++ memmove(cp, cp + len, head->read_avail);
2010++out:
2011++ mutex_unlock(&head->io_sem);
2012++ return len;
2013++}
2014++
2015++/**
2016++ * tmy_write_control - write() for /sys/kernel/security/tomoyo/ interface.
2017++ *
2018++ * @file: Pointer to "struct file".
2019++ * @buffer: Pointer to buffer to read from.
2020++ * @buffer_len: Size of @buffer.
2021++ *
2022++ * Returns @buffer_len on success, negative value otherwise.
2023++ */
2024++static int tmy_write_control(struct file *file, const char __user *buffer,
2025++ const int buffer_len)
2026++{
2027++ struct tmy_io_buffer *head = file->private_data;
2028++ int error = buffer_len;
2029++ int avail_len = buffer_len;
2030++ char *cp0 = head->write_buf;
2031++
2032++ if (!head->write)
2033++ return -ENOSYS;
2034++ if (!access_ok(VERIFY_READ, buffer, buffer_len))
2035++ return -EFAULT;
2036++ /* Don't allow updating policies by non manager programs. */
2037++ if (head->write != write_pid && head->write != write_domain_policy &&
2038++ !is_policy_manager())
2039++ return -EPERM;
2040++ if (mutex_lock_interruptible(&head->io_sem))
2041++ return -EINTR;
2042++ /* Read a line and dispatch it to the policy handler. */
2043++ while (avail_len > 0) {
2044++ char c;
2045++ if (head->write_avail >= head->writebuf_size - 1) {
2046++ error = -ENOMEM;
2047++ break;
2048++ } else if (get_user(c, buffer)) {
2049++ error = -EFAULT;
2050++ break;
2051++ }
2052++ buffer++;
2053++ avail_len--;
2054++ cp0[head->write_avail++] = c;
2055++ if (c != '\n')
2056++ continue;
2057++ cp0[head->write_avail - 1] = '\0';
2058++ head->write_avail = 0;
2059++ normalize_line(cp0);
2060++ head->write(head);
2061++ }
2062++ mutex_unlock(&head->io_sem);
2063++ return error;
2064++}
2065++
2066++/**
2067++ * tmy_close_control - close() for /sys/kernel/security/tomoyo/ interface.
2068++ *
2069++ * @file: Pointer to "struct file".
2070++ *
2071++ * Releases memory and returns 0.
2072++ */
2073++static int tmy_close_control(struct file *file)
2074++{
2075++ struct tmy_io_buffer *head = file->private_data;
2076++
2077++ /* Release memory used for policy I/O. */
2078++ tmy_free(head->read_buf);
2079++ head->read_buf = NULL;
2080++ tmy_free(head->write_buf);
2081++ head->write_buf = NULL;
2082++ tmy_free(head);
2083++ head = NULL;
2084++ file->private_data = NULL;
2085++ return 0;
2086++}
2087++
2088++/**
2089++ * tmy_alloc_acl_element - Allocate permanent memory for ACL entry.
2090++ *
2091++ * @acl_type: Type of ACL entry.
2092++ *
2093++ * Returns pointer to the ACL entry on success, NULL otherwise.
2094++ */
2095++void *tmy_alloc_acl_element(const u8 acl_type)
2096++{
2097++ int len;
2098++ struct acl_info *ptr;
2099++
2100++ switch (acl_type) {
2101++ case TYPE_SINGLE_PATH_ACL:
2102++ len = sizeof(struct single_path_acl_record);
2103++ break;
2104++ case TYPE_DOUBLE_PATH_ACL:
2105++ len = sizeof(struct double_path_acl_record);
2106++ break;
2107++ default:
2108++ return NULL;
2109++ }
2110++ ptr = tmy_alloc_element(len);
2111++ if (!ptr)
2112++ return NULL;
2113++ ptr->type = acl_type;
2114++ return ptr;
2115++}
2116++
2117++/**
2118++ * tmy_open - open() for /sys/kernel/security/tomoyo/ interface.
2119++ *
2120++ * @inode: Pointer to "struct inode".
2121++ * @file: Pointer to "struct file".
2122++ *
2123++ * Returns 0 on success, negative value otherwise.
2124++ */
2125++static int tmy_open(struct inode *inode, struct file *file)
2126++{
2127++ return tmy_open_control(((u8 *) file->f_path.dentry->d_inode->i_private)
2128++ - ((u8 *) NULL), file);
2129++}
2130++
2131++/**
2132++ * tmy_release - close() for /sys/kernel/security/tomoyo/ interface.
2133++ *
2134++ * @inode: Pointer to "struct inode".
2135++ * @file: Pointer to "struct file".
2136++ *
2137++ * Returns 0 on success, negative value otherwise.
2138++ */
2139++static int tmy_release(struct inode *inode, struct file *file)
2140++{
2141++ return tmy_close_control(file);
2142++}
2143++
2144++/**
2145++ * tmy_read - read() for /sys/kernel/security/tomoyo/ interface.
2146++ *
2147++ * @file: Pointer to "struct file".
2148++ * @buf: Pointer to buffer.
2149++ * @count: Size of @buf.
2150++ * @ppos: Unused.
2151++ *
2152++ * Returns bytes read on success, negative value otherwise.
2153++ */
2154++static ssize_t tmy_read(struct file *file, char __user *buf, size_t count,
2155++ loff_t *ppos)
2156++{
2157++ return tmy_read_control(file, buf, count);
2158++}
2159++
2160++/**
2161++ * tmy_write - write() for /sys/kernel/security/tomoyo/ interface.
2162++ *
2163++ * @file: Pointer to "struct file".
2164++ * @buf: Pointer to buffer.
2165++ * @count: Size of @buf.
2166++ * @ppos: Unused.
2167++ *
2168++ * Returns @count on success, negative value otherwise.
2169++ */
2170++static ssize_t tmy_write(struct file *file, const char __user *buf,
2171++ size_t count, loff_t *ppos)
2172++{
2173++ return tmy_write_control(file, buf, count);
2174++}
2175++
2176++/* Operations for /sys/kernel/security/tomoyo/ interface. */
2177++static struct file_operations tmy_operations = {
2178++ .open = tmy_open,
2179++ .release = tmy_release,
2180++ .read = tmy_read,
2181++ .write = tmy_write,
2182++};
2183++
2184++/**
2185++ * create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
2186++ *
2187++ * @name: The name of the interface file.
2188++ * @mode: The permission of the interface file.
2189++ * @parent: The parent directory.
2190++ * @key: Type of interface.
2191++ *
2192++ * Returns nothing.
2193++ */
2194++static void __init create_entry(const char *name, const mode_t mode,
2195++ struct dentry *parent, const u8 key)
2196++{
2197++ securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
2198++ &tmy_operations);
2199++}
2200++
2201++/**
2202++ * tmy_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
2203++ *
2204++ * Returns 0.
2205++ */
2206++static int __init tmy_initerface_init(void)
2207++{
2208++ struct dentry *tmy_dir;
2209++
2210++ tmy_dir = securityfs_create_dir("tomoyo", NULL);
2211++ create_entry("domain_policy", 0600, tmy_dir, TMY_DOMAINPOLICY);
2212++ create_entry("exception_policy", 0600, tmy_dir, TMY_EXCEPTIONPOLICY);
2213++ create_entry("self_domain", 0400, tmy_dir, TMY_SELFDOMAIN);
2214++ create_entry(".domain_status", 0600, tmy_dir, TMY_DOMAIN_STATUS);
2215++ create_entry(".process_status", 0600, tmy_dir, TMY_PROCESS_STATUS);
2216++ create_entry("meminfo", 0600, tmy_dir, TMY_MEMINFO);
2217++ create_entry("profile", 0600, tmy_dir, TMY_PROFILE);
2218++ create_entry("manager", 0600, tmy_dir, TMY_MANAGER);
2219++ create_entry(".updates_counter", 0400, tmy_dir, TMY_UPDATESCOUNTER);
2220++ create_entry("version", 0400, tmy_dir, TMY_VERSION);
2221++ return 0;
2222++}
2223++
2224++fs_initcall(tmy_initerface_init);
2225+--- /dev/null
2226++++ linux-next/security/tomoyo/common.h
2227+@@ -0,0 +1,320 @@
2228++/*
2229++ * security/tomoyo/common.h
2230++ *
2231++ * Common functions for TOMOYO.
2232++ *
2233++ * Copyright (C) 2005-2008 NTT DATA CORPORATION
2234++ *
2235++ * Version: 2.2.0-pre 2008/10/10
2236++ *
2237++ */
2238++
2239++#ifndef _SECURITY_TOMOYO_COMMON_H
2240++#define _SECURITY_TOMOYO_COMMON_H
2241++
2242++#include <linux/string.h>
2243++#include <linux/mm.h>
2244++#include <linux/file.h>
2245++#include <linux/kmod.h>
2246++#include <linux/fs.h>
2247++#include <linux/sched.h>
2248++#include <linux/namei.h>
2249++#include <linux/mount.h>
2250++#include <linux/list1.h>
2251++
2252++struct dentry;
2253++struct vfsmount;
2254++
2255++#define false 0
2256++#define true 1
2257++
2258++/* Temporary buffer for holding pathnames. */
2259++struct tmy_page_buffer {
2260++ char buffer[4096];
2261++};
2262++
2263++/* Structure for attribute checks in addition to pathname checks. */
2264++struct obj_info {
2265++ struct tmy_page_buffer *tmp;
2266++};
2267++
2268++/* Structure for holding a token. */
2269++struct path_info {
2270++ const char *name;
2271++ u32 hash; /* = full_name_hash(name, strlen(name)) */
2272++ u16 total_len; /* = strlen(name) */
2273++ u16 const_len; /* = const_part_length(name) */
2274++ bool is_dir; /* = strendswith(name, "/") */
2275++ bool is_patterned; /* = path_contains_pattern(name) */
2276++ u16 depth; /* = path_depth(name) */
2277++};
2278++
2279++/*
2280++ * This is the max length of a token.
2281++ *
2282++ * A token consists of only ASCII printable characters.
2283++ * Non printable characters in a token is represented in \ooo style
2284++ * octal string. Thus, \ itself is represented as \\.
2285++ */
2286++#define TMY_MAX_PATHNAME_LEN 4000
2287++
2288++/* Structure for holding requested pathname. */
2289++struct path_info_with_data {
2290++ /* Keep "head" first, for this pointer is passed to tmy_free(). */
2291++ struct path_info head;
2292++ char bariier1[16]; /* Safeguard for overrun. */
2293++ char body[TMY_MAX_PATHNAME_LEN];
2294++ char barrier2[16]; /* Safeguard for overrun. */
2295++};
2296++
2297++/* Common header for holding ACL entries. */
2298++struct acl_info {
2299++ struct list1_head list;
2300++ /*
2301++ * Type of this ACL entry.
2302++ *
2303++ * MSB is is_deleted flag.
2304++ */
2305++ u8 type;
2306++} __attribute__((__packed__));
2307++
2308++/* This ACL entry is deleted. */
2309++#define ACL_DELETED 0x80
2310++
2311++/* Structure for domain information. */
2312++struct domain_info {
2313++ struct list1_head list;
2314++ struct list1_head acl_info_list;
2315++ /* Name of this domain. Never NULL. */
2316++ const struct path_info *domainname;
2317++ u8 profile; /* Profile number to use. */
2318++ u8 is_deleted; /* Delete flag.
2319++ 0 = active.
2320++ 1 = deleted but undeletable.
2321++ 255 = deleted and no longer undeletable. */
2322++ bool quota_warned; /* Quota warnning flag. */
2323++ /* DOMAIN_FLAGS_*. Use tmy_set_domain_flag() to modify. */
2324++ u8 flags;
2325++};
2326++
2327++/* Profile number is an integer between 0 and 255. */
2328++#define MAX_PROFILES 256
2329++
2330++/* Ignore "allow_read" directive in exception policy. */
2331++#define DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
2332++/*
2333++ * This domain was unable to create a new domain at tmy_find_next_domain()
2334++ * because the name of the domain to be created was too long or
2335++ * it could not allocate memory.
2336++ * More than one process continued execve() without domain transition.
2337++ */
2338++#define DOMAIN_FLAGS_TRANSITION_FAILED 2
2339++
2340++/*
2341++ * Structure for "allow_read/write", "allow_execute", "allow_read",
2342++ * "allow_write", "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
2343++ * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
2344++ * "allow_truncate", "allow_symlink" and "allow_rewrite" directive.
2345++ */
2346++struct single_path_acl_record {
2347++ struct acl_info head; /* type = TYPE_SINGLE_PATH_ACL */
2348++ u16 perm;
2349++ /* Pointer to single pathname. */
2350++ const struct path_info *filename;
2351++};
2352++
2353++/* Structure for "allow_rename" and "allow_link" directive. */
2354++struct double_path_acl_record {
2355++ struct acl_info head; /* type = TYPE_DOUBLE_PATH_ACL */
2356++ u8 perm;
2357++ /* Pointer to single pathname. */
2358++ const struct path_info *filename1;
2359++ /* Pointer to single pathname. */
2360++ const struct path_info *filename2;
2361++};
2362++
2363++/* Keywords for ACLs. */
2364++#define KEYWORD_ALIAS "alias "
2365++#define KEYWORD_ALLOW_READ "allow_read "
2366++#define KEYWORD_DELETE "delete "
2367++#define KEYWORD_DENY_REWRITE "deny_rewrite "
2368++#define KEYWORD_FILE_PATTERN "file_pattern "
2369++#define KEYWORD_INITIALIZE_DOMAIN "initialize_domain "
2370++#define KEYWORD_KEEP_DOMAIN "keep_domain "
2371++#define KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
2372++#define KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
2373++#define KEYWORD_SELECT "select "
2374++#define KEYWORD_UNDELETE "undelete "
2375++#define KEYWORD_USE_PROFILE "use_profile "
2376++#define KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
2377++/* A domain definition starts with <kernel>. */
2378++#define ROOT_NAME "<kernel>"
2379++#define ROOT_NAME_LEN (sizeof(ROOT_NAME) - 1)
2380++
2381++/* Index numbers for Access Controls. */
2382++#define TMY_TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */
2383++#define TMY_TOMOYO_MAX_ACCEPT_ENTRY 1
2384++#define TMY_TOMOYO_VERBOSE 2
2385++#define TMY_MAX_CONTROL_INDEX 3
2386++
2387++/* Index numbers for updates counter. */
2388++#define TMY_UPDATES_COUNTER_DOMAIN_POLICY 0
2389++#define TMY_UPDATES_COUNTER_EXCEPTION_POLICY 1
2390++#define TMY_UPDATES_COUNTER_PROFILE 2
2391++#define TMY_UPDATES_COUNTER_MANAGER 3
2392++#define MAX_TMY_UPDATES_COUNTER 4
2393++
2394++/* Structure for reading/writing policy via securityfs interfaces. */
2395++struct tmy_io_buffer {
2396++ int (*read) (struct tmy_io_buffer *);
2397++ int (*write) (struct tmy_io_buffer *);
2398++ /* Exclusive lock for this structure. */
2399++ struct mutex io_sem;
2400++ /* The position currently reading from. */
2401++ struct list1_head *read_var1;
2402++ /* Extra variables for reading. */
2403++ struct list1_head *read_var2;
2404++ /* The position currently writing to. */
2405++ struct domain_info *write_var1;
2406++ /* The step for reading. */
2407++ int read_step;
2408++ /* Buffer for reading. */
2409++ char *read_buf;
2410++ /* EOF flag for reading. */
2411++ bool read_eof;
2412++ /* Read domain ACL of specified PID? */
2413++ bool read_single_domain;
2414++ /* Extra variable for reading. */
2415++ u8 read_bit;
2416++ /* Bytes available for reading. */
2417++ int read_avail;
2418++ /* Size of read buffer. */
2419++ int readbuf_size;
2420++ /* Buffer for writing. */
2421++ char *write_buf;
2422++ /* Bytes available for writing. */
2423++ int write_avail;
2424++ /* Size of write buffer. */
2425++ int writebuf_size;
2426++};
2427++
2428++/* Check whether the domain has too many ACL entries to hold. */
2429++bool tmy_check_domain_quota(struct domain_info * const domain);
2430++/* Transactional sprintf() for policy dump. */
2431++bool tmy_io_printf(struct tmy_io_buffer *head, const char *fmt, ...)
2432++ __attribute__ ((format(printf, 2, 3)));
2433++/* Check whether the domainname is correct. */
2434++bool tmy_is_correct_domain(const unsigned char *domainname,
2435++ const char *function);
2436++/* Check whether the token is correct. */
2437++bool tmy_is_correct_path(const char *filename, const s8 start_type,
2438++ const s8 pattern_type, const s8 end_type,
2439++ const char *function);
2440++/* Check whether the token can be a domainname. */
2441++bool tmy_is_domain_def(const unsigned char *buffer);
2442++/* Check whether the given filename matches the given pattern. */
2443++bool tmy_path_matches_pattern(const struct path_info *filename,
2444++ const struct path_info *pattern);
2445++/* Read "alias" entry in exception policy. */
2446++bool tmy_read_alias_policy(struct tmy_io_buffer *head);
2447++/*
2448++ * Read "initialize_domain" and "no_initialize_domain" entry
2449++ * in exception policy.
2450++ */
2451++bool tmy_read_domain_initializer_policy(struct tmy_io_buffer *head);
2452++/* Read "keep_domain" and "no_keep_domain" entry in exception policy. */
2453++bool tmy_read_domain_keeper_policy(struct tmy_io_buffer *head);
2454++/* Read "file_pattern" entry in exception policy. */
2455++bool tmy_read_file_pattern(struct tmy_io_buffer *head);
2456++/* Read "allow_read" entry in exception policy. */
2457++bool tmy_read_globally_readable_policy(struct tmy_io_buffer *head);
2458++/* Read "deny_rewrite" entry in exception policy. */
2459++bool tmy_read_no_rewrite_policy(struct tmy_io_buffer *head);
2460++/* Write domain policy violation warning message to console? */
2461++bool tmy_verbose_mode(const struct domain_info *domain);
2462++/* Convert double path operation to operation name. */
2463++const char *tmy_dp2keyword(const u8 operation);
2464++/* Get the last component of the given domainname. */
2465++const char *tmy_get_last_name(const struct domain_info *domain);
2466++/* Get warning message. */
2467++const char *tmy_get_msg(const bool is_enforce);
2468++/* Convert single path operation to operation name. */
2469++const char *tmy_sp2keyword(const u8 operation);
2470++/* Delete a domain. */
2471++int tmy_delete_domain(char *data);
2472++/* Create "alias" entry in exception policy. */
2473++int tmy_write_alias_policy(char *data, const bool is_delete);
2474++/*
2475++ * Create "initialize_domain" and "no_initialize_domain" entry
2476++ * in exception policy.
2477++ */
2478++int tmy_write_domain_initializer_policy(char *data, const bool is_not,
2479++ const bool is_delete);
2480++/* Create "keep_domain" and "no_keep_domain" entry in exception policy. */
2481++int tmy_write_domain_keeper_policy(char *data, const bool is_not,
2482++ const bool is_delete);
2483++/*
2484++ * Create "allow_read/write", "allow_execute", "allow_read", "allow_write",
2485++ * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
2486++ * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
2487++ * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and
2488++ * "allow_link" entry in domain policy.
2489++ */
2490++int tmy_write_file_policy(char *data, struct domain_info *domain,
2491++ const bool is_delete);
2492++/* Create "allow_read" entry in exception policy. */
2493++int tmy_write_globally_readable_policy(char *data, const bool is_delete);
2494++/* Create "deny_rewrite" entry in exception policy. */
2495++int tmy_write_no_rewrite_policy(char *data, const bool is_delete);
2496++/* Create "file_pattern" entry in exception policy. */
2497++int tmy_write_pattern_policy(char *data, const bool is_delete);
2498++/* Find a domain by the given name. */
2499++struct domain_info *tmy_find_domain(const char *domainname);
2500++/* Find or create a domain by the given name. */
2501++struct domain_info *tmy_find_or_assign_new_domain(const char *domainname,
2502++ const u8 profile);
2503++/* Undelete a domain. */
2504++struct domain_info *tmy_undelete_domain(const char *domainname);
2505++/* Check mode for specified functionality. */
2506++unsigned int tmy_check_flags(const struct domain_info *domain, const u8 index);
2507++/* Allocate memory for structures. */
2508++void *tmy_alloc_acl_element(const u8 acl_type);
2509++/* Fill in "struct path_info" members. */
2510++void tmy_fill_path_info(struct path_info *ptr);
2511++/* Run policy loader when /sbin/init starts. */
2512++void tmy_load_policy(const char *filename);
2513++/* Change "struct domain_info"->flags. */
2514++void tmy_set_domain_flag(struct domain_info *domain, const bool is_delete,
2515++ const u8 flags);
2516++/* Update the policy change counter. */
2517++void tmy_update_counter(const unsigned char index);
2518++
2519++/* strcmp() for "struct path_info" structure. */
2520++static inline bool tmy_pathcmp(const struct path_info *a,
2521++ const struct path_info *b)
2522++{
2523++ return a->hash != b->hash || strcmp(a->name, b->name);
2524++}
2525++
2526++/* Get type of an ACL entry. */
2527++static inline u8 tmy_acl_type1(struct acl_info *ptr)
2528++{
2529++ return ptr->type & ~ACL_DELETED;
2530++}
2531++
2532++/* Get type of an ACL entry. */
2533++static inline u8 tmy_acl_type2(struct acl_info *ptr)
2534++{
2535++ return ptr->type;
2536++}
2537++
2538++/* The list for "struct domain_info". */
2539++extern struct list1_head domain_list;
2540++
2541++/* Has /sbin/init started? */
2542++extern bool sbin_init_started;
2543++
2544++/* The kernel's domain. */
2545++extern struct domain_info KERNEL_DOMAIN;
2546++
2547++#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
--- tags/lkml/11/add-in_execve-flag-into-task_struct.patch (nonexistent)
+++ tags/lkml/11/add-in_execve-flag-into-task_struct.patch (revision 1723)
@@ -0,0 +1,85 @@
1+Subject: Add in_execve flag into task_struct.
2+
3+This patch allows LSM modules to determine whether current process is in an
4+execve operation or not so that they can behave differently while an execve
5+operation is in progress.
6+
7+This allows TOMOYO to dispense with a readability check on a file to be
8+executed under the process's current credentials, and to do it instead under
9+the proposed credentials.
10+
11+This is required with the new COW credentials because TOMOYO is no longer
12+allowed to mark the state temporarily in the security struct attached to the
13+task_struct.
14+
15+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
16+Signed-off-by: David Howells <dhowells@redhat.com>
17+---
18+ fs/compat.c | 3 +++
19+ fs/exec.c | 3 +++
20+ include/linux/sched.h | 2 ++
21+ 3 files changed, 8 insertions(+)
22+
23+--- linux-next.orig/fs/compat.c
24++++ linux-next/fs/compat.c
25+@@ -1396,6 +1396,7 @@ int compat_do_execve(char * filename,
26+ retval = mutex_lock_interruptible(&current->cred_exec_mutex);
27+ if (retval < 0)
28+ goto out_free;
29++ current->in_execve = 1;
30+
31+ retval = -ENOMEM;
32+ bprm->cred = prepare_exec_creds();
33+@@ -1448,6 +1449,7 @@ int compat_do_execve(char * filename,
34+ goto out;
35+
36+ /* execve succeeded */
37++ current->in_execve = 0;
38+ mutex_unlock(&current->cred_exec_mutex);
39+ acct_update_integrals(current);
40+ free_bprm(bprm);
41+@@ -1464,6 +1466,7 @@ out_file:
42+ }
43+
44+ out_unlock:
45++ current->in_execve = 0;
46+ mutex_unlock(&current->cred_exec_mutex);
47+
48+ out_free:
49+--- linux-next.orig/fs/exec.c
50++++ linux-next/fs/exec.c
51+@@ -1303,6 +1303,7 @@ int do_execve(char * filename,
52+ retval = mutex_lock_interruptible(&current->cred_exec_mutex);
53+ if (retval < 0)
54+ goto out_free;
55++ current->in_execve = 1;
56+
57+ retval = -ENOMEM;
58+ bprm->cred = prepare_exec_creds();
59+@@ -1356,6 +1357,7 @@ int do_execve(char * filename,
60+ goto out;
61+
62+ /* execve succeeded */
63++ current->in_execve = 0;
64+ mutex_unlock(&current->cred_exec_mutex);
65+ acct_update_integrals(current);
66+ free_bprm(bprm);
67+@@ -1374,6 +1376,7 @@ out_file:
68+ }
69+
70+ out_unlock:
71++ current->in_execve = 0;
72+ mutex_unlock(&current->cred_exec_mutex);
73+
74+ out_free:
75+--- linux-next.orig/include/linux/sched.h
76++++ linux-next/include/linux/sched.h
77+@@ -1089,6 +1089,8 @@ struct task_struct {
78+ /* ??? */
79+ unsigned int personality;
80+ unsigned did_exec:1;
81++ unsigned in_execve:1; /* Tell the LSMs that the process is doing an
82++ * execve */
83+ pid_t pid;
84+ pid_t tgid;
85+
--- tags/lkml/11/introduce-d_realpath.patch (nonexistent)
+++ tags/lkml/11/introduce-d_realpath.patch (revision 1723)
@@ -0,0 +1,124 @@
1+Subject: Introduce d_realpath().
2+
3+To remove factors that make pathname based access control difficult
4+(e.g. symbolic links, "..", "//", chroot() etc.), a variant of d_path()
5+which traverses up to the root of the namespace is needed.
6+
7+Three differences compared to d_path().
8+(1) Ignores current process's root directory.
9+(2) Trailing '/' is added if the pathname refers to a directory.
10+(3) /proc/PID/ is represented as /proc/self/ if PID equals current->tgid.
11+
12+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
13+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
14+Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
15+---
16+ fs/dcache.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++
17+ include/linux/dcache.h | 1
18+ 2 files changed, 80 insertions(+)
19+
20+--- linux-next.orig/fs/dcache.c
21++++ linux-next/fs/dcache.c
22+@@ -33,6 +33,7 @@
23+ #include <linux/swap.h>
24+ #include <linux/bootmem.h>
25+ #include <linux/backing-dev.h>
26++#include <linux/magic.h>
27+ #include "internal.h"
28+
29+
30+@@ -1972,6 +1973,84 @@ Elong:
31+ }
32+
33+ /**
34++ * d_realpath - Get the realpath of a dentry.
35++ *
36++ * @path: Pointer to "struct path".
37++ * @buffer: Pointer to buffer to return value in.
38++ * @buflen: Sizeof @buffer.
39++ *
40++ * Returns pointer to the realpath on success, an error code othersize.
41++ *
42++ * If @dentry is a directory, trailing '/' is appended.
43++ * If /proc/PID/ is replaced by /proc/self/ if PID == current->tgid.
44++ */
45++char *d_realpath(struct path *path, char *buffer, int buflen)
46++{
47++ struct dentry *dentry = path->dentry;
48++ struct vfsmount *vfsmnt = path->mnt;
49++ char *end = buffer + buflen;
50++ char self_pid[16];
51++
52++ snprintf(self_pid, sizeof(self_pid), "%u", current->tgid);
53++ spin_lock(&dcache_lock);
54++ spin_lock(&vfsmount_lock);
55++ if (buflen < 1 || prepend(&end, &buflen, "", 1))
56++ goto Elong;
57++ /*
58++ * Exception: Add trailing '/' for directory.
59++ */
60++ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode) &&
61++ prepend(&end, &buflen, "/", 1))
62++ goto Elong;
63++ for (;;) {
64++ struct dentry *parent;
65++ const char *name;
66++
67++ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
68++ /* Global root? */
69++ if (vfsmnt->mnt_parent == vfsmnt)
70++ break;
71++ dentry = vfsmnt->mnt_mountpoint;
72++ vfsmnt = vfsmnt->mnt_parent;
73++ continue;
74++ }
75++ parent = dentry->d_parent;
76++ prefetch(parent);
77++ /*
78++ * Exception: Use /proc/self/ rather than /proc/\$/
79++ * for current process.
80++ */
81++ name = dentry->d_name.name;
82++ if (IS_ROOT(parent) &&
83++ parent->d_sb->s_magic == PROC_SUPER_MAGIC &&
84++ !strcmp(name, self_pid)) {
85++ if (prepend(&end, &buflen, "self", 4))
86++ goto Elong;
87++ } else {
88++ if (prepend_name(&end, &buflen, &dentry->d_name))
89++ goto Elong;
90++ }
91++ if (prepend(&end, &buflen, "/", 1))
92++ goto Elong;
93++ dentry = parent;
94++ }
95++ if (*end == '/') {
96++ /* hit the slash */
97++ buflen++;
98++ end++;
99++ }
100++ if (prepend_name(&end, &buflen, &dentry->d_name))
101++ goto Elong;
102++ out:
103++ spin_unlock(&vfsmount_lock);
104++ spin_unlock(&dcache_lock);
105++ return end;
106++ Elong:
107++ end = ERR_PTR(-ENAMETOOLONG);
108++ goto out;
109++}
110++
111++/**
112+ * d_path - return the path of a dentry
113+ * @path: path to report
114+ * @buf: buffer to return value in
115+--- linux-next.orig/include/linux/dcache.h
116++++ linux-next/include/linux/dcache.h
117+@@ -304,6 +304,7 @@ extern char *dynamic_dname(struct dentry
118+ extern char *__d_path(const struct path *path, struct path *root, char *, int);
119+ extern char *d_path(const struct path *, char *, int);
120+ extern char *dentry_path(struct dentry *, char *, int);
121++extern char *d_realpath(struct path *, char *, int);
122+
123+ /* Allocation counts.. */
124+
--- tags/lkml/11/introduce-write-once-read-many-linked-list.patch (nonexistent)
+++ tags/lkml/11/introduce-write-once-read-many-linked-list.patch (revision 1723)
@@ -0,0 +1,92 @@
1+Subject: Singly linked list implementation.
2+
3+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
4+Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
5+---
6+ include/linux/list1.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++
7+ 1 file changed, 81 insertions(+)
8+
9+--- /dev/null
10++++ linux-next/include/linux/list1.h
11+@@ -0,0 +1,81 @@
12++#ifndef _LINUX_LIST1_H
13++#define _LINUX_LIST1_H
14++
15++#include <linux/list.h>
16++#include <linux/rcupdate.h>
17++
18++/*
19++ * Singly linked list implementation.
20++ *
21++ * This list supports only two operations.
22++ * (1) Append an entry to the tail of the list.
23++ * (2) Read all entries starting from the head of the list.
24++ *
25++ * This list is designed for holding "write once, read many" entries.
26++ * This list requires no locks for read operation.
27++ * This list doesn't support "remove an entry from the list" operation.
28++ */
29++
30++/* To reduce memory usage, this list doesn't use "->prev" pointer. */
31++struct list1_head {
32++ struct list1_head *next;
33++};
34++
35++#define LIST1_HEAD_INIT(name) { &(name) }
36++#define LIST1_HEAD(name) struct list1_head name = LIST1_HEAD_INIT(name)
37++
38++static inline void INIT_LIST1_HEAD(struct list1_head *list)
39++{
40++ list->next = list;
41++}
42++
43++/* Reuse list_entry because it doesn't use "->prev" pointer. */
44++#define list1_entry list_entry
45++
46++/* Reuse list_for_each_rcu because it doesn't use "->prev" pointer. */
47++#define list1_for_each list_for_each_rcu
48++/* Reuse list_for_each_entry_rcu because it doesn't use "->prev" pointer. */
49++#define list1_for_each_entry list_for_each_entry_rcu
50++
51++/**
52++ * list1_for_each_cookie - iterate over a list with cookie.
53++ * @pos: the &struct list1_head to use as a loop cursor.
54++ * @cookie: the &struct list1_head to use as a cookie.
55++ * @head: the head for your list.
56++ *
57++ * Same with list_for_each_rcu() except that this primitive uses @cookie
58++ * so that we can continue iteration.
59++ * @cookie must be NULL when iteration starts, and @cookie will become
60++ * NULL when iteration finishes.
61++ *
62++ * Since list elements are never removed, we don't need to get a lock
63++ * or a reference count.
64++ */
65++#define list1_for_each_cookie(pos, cookie, head) \
66++ for (({ if (!cookie) \
67++ cookie = head; }), \
68++ pos = rcu_dereference((cookie)->next); \
69++ prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
70++ (cookie) = pos, pos = rcu_dereference(pos->next))
71++
72++/**
73++ * list1_add_tail - add a new entry to list1 list.
74++ * @new: new entry to be added.
75++ * @head: list head to add it before.
76++ *
77++ * Same with list_add_tail_rcu() without "->prev" pointer.
78++ *
79++ * Caller must hold a lock for protecting @head.
80++ */
81++static inline void list1_add_tail(struct list1_head *new,
82++ struct list1_head *head)
83++{
84++ struct list1_head *prev = head;
85++
86++ new->next = head;
87++ while (prev->next != head)
88++ prev = prev->next;
89++ rcu_assign_pointer(prev->next, new);
90++}
91++
92++#endif
--- tags/lkml/11/tomoyo-maintainers.patch (nonexistent)
+++ tags/lkml/11/tomoyo-maintainers.patch (revision 1723)
@@ -0,0 +1,38 @@
1+Subject: MAINTAINERS info
2+
3+The archive of tomoyo-users-en mailing list is available at
4+http://lists.sourceforge.jp/mailman/archives/tomoyo-users-en/ .
5+Mailing lists for Japanese users are at
6+http://lists.sourceforge.jp/mailman/archives/tomoyo-users/ and
7+http://lists.sourceforge.jp/mailman/archives/tomoyo-dev/ .
8+
9+TOMOYO Linux English portal is at
10+http://elinux.org/TomoyoLinux .
11+
12+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
13+---
14+ MAINTAINERS | 13 +++++++++++++
15+ 1 file changed, 13 insertions(+)
16+
17+--- linux-next.orig/MAINTAINERS
18++++ linux-next/MAINTAINERS
19+@@ -4110,6 +4110,19 @@ L: tlan-devel@lists.sourceforge.net (sub
20+ W: http://sourceforge.net/projects/tlan/
21+ S: Maintained
22+
23++TOMOYO SECURITY MODULE
24++P: Kentaro Takeda
25++M: takedakn@nttdata.co.jp
26++P: Tetsuo Handa
27++M: penguin-kernel@I-love.SAKURA.ne.jp
28++L: linux-kernel@vger.kernel.org (kernel issues)
29++L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for developers and users in English)
30++L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
31++L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
32++W: http://tomoyo.sourceforge.jp/
33++T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches/
34++S: Maintained
35++
36+ TOSHIBA ACPI EXTRAS DRIVER
37+ P: John Belmonte
38+ M: toshiba_acpi@memebeam.org
Show on old repository browser