All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC & PATCH] inherited type definition.
@ 2005-03-13 16:36 KaiGai Kohei
  2005-03-14 13:17 ` KaiGai Kohei
                   ` (2 more replies)
  0 siblings, 3 replies; 58+ messages in thread
From: KaiGai Kohei @ 2005-03-13 16:36 UTC (permalink / raw)
  To: SELinux Mail List; +Cc: kaigai

[-- Attachment #1: Type: text/plain, Size: 5276 bytes --]

Hello,
This attached patch provids a new syntax extension to checkpolicy.
This makes it possible to describe a definition of type which inherit
access vectors of parent's types/attributes.

Syntax:
TYPE <type> [ALIAS <aliases>] EXTENDS <type/attr>, <type/attr>, ... ;

The basical idea is like attribute, but 'EXTENDS' has those differences as follows:
- It can inherit other types, not only attribute.
- It can describe multi-layer inheritance tree of type.

Currently, when we try to define a type like another type, we must describe a new
type from a scratch for tiny difference.  For example, if we want a new type
'ext_user_t' which is permitted all access vectors for user_t and a tiny additional
access vectors, we must describe all of the user_t's access vectors and some of
original allow-statements.

When you use EXTENDS extension, only what you describe are a type definition
with EXTENDS statement and some original allow-statements.

[Simple Example]
type subject_t;
type parent_t;
type child_t extends parent_t;
type grandchild_t extends child_t;
type stranger_t;

In this case, there are five types for explanation.
- "allow subject_t child_t:XXX XXX;" means "allow subject_t {child_t grandchild_t}:XXX XXX".
- "allow parent_t child_t:XXX XXX;" means "allow {parent_t child_t grandchild_t} {child_t grandchild_t}:XXX XXX"
- "allow subject_t ~parent_t:XXX XXX" means "allow subject_t stranger_t:XXX XXX".
  child_t and grandchild_t are not included in ~parent_t, because its ancestor is parent_t.
- "allow child_t self:XXX XXX" means "allow child_t child_t:XXX XXX",
  "allow child_t grandchild_t:XXX XXX" and "allow grandchild_t grandchild_t:XXX XXX".

An access vector granted to parent-type is inherited to child and grandchild.
We must pay attention to '~' and 'self'.
When we use '~', that means the reverse of the type and its children.
When we use 'self', that means the type and its children.

Thanks, any comments please.
# This is a personal work, but would you Cc: 'kaigai@ak.jp.nec.com' for useful ?

--------------------------------------------------------------------
When we don't use EXTENDS statement, checkpolicy works compatibly.
I tried to test checkpolicy-1.20 with EXTENDS patch by Tresys's sediff and policy-1.20.

Test 1: compatibility of the checkpolicy
[kaigai@ayu ~]$ sediff polbin.org polbin.std
Difference between policy 1 and policy 2:
   p1 (binary, ver: 18): polbin.org ... generated by standard checkpolicy
   p2 (binary, ver: 18): polbin.std ... generated by extended checkpolicy

Types (0 Added, 0 Removed, 0 Changed)
        Added Types: 0
        Removed Types: 0
        Changed Types: 0

Roles (0 Added, 0 Removed, 0 Changed)
        Added Roles: 0
        Removed Roles: 0
        Changed Roles: 0

Users (0 Added, 0 Removed, 0 Changed)
        Added Users: 0
        Removed Users: 0
        Changed Users: 0

Booleans (0 Added, 0 Removed, 0 Changed)
        Added Booleans: 0
        Removed Booleans: 0
        Changed Booleans: 0

Classes (0 Added, 0 Removed, 0 Changed)
        Added Classes: 0
        Removed Classes: 0
        Changed Classes: 0

Permissions (0 Added, 0 Removed)
        Added Permissions: 0
        Removed Permissions: 0

Common Permissions (0 Added, 0 Removed, 0 Changed)
        Added Common Permissions: 0
        Removed Common Permissions: 0
        Changed Common Permissions: 0

Conditionals are not currently supported.
Role Allows (0 Added, 0 Removed, 0 Changed)
        Added Role Allows: 0
        Removed Role Allows: 0
        Changed Role Allows: 0

TE Rules (0 Added, 0 Removed, 0 Changed)
        Added TE Rules 0:
        Removed TE Rules 0:
        Changed TE Rules 0:

Total Differences:
        Classes & Permissions 0
        Types 0
        Attributes 0
        Roles 0
        Users 0
        Booleans 0
        Rbac 0
        TE Rules 0

--------------------------------------------------------------------------
Test 2: The advantage of EXTENDS statement.
        I added a line 'type user_ext_t extends user_t;' into policy.conf.
[kaigai@ayu ~]$ sediff polbin.std polbin.ext
Difference between policy 1 and policy 2:
   p1 (binary, ver: 18): polbin.std ... original policy-1.20
   p2 (binary, ver: 18): polbin.ext ... I added a type definition.

Types (1 Added, 0 Removed, 0 Changed)
        Added Types: 1
                + user_ext_t
        Removed Types: 0
        Changed Types: 0

Roles (0 Added, 0 Removed, 1 Changed)
        Added Roles: 0
        Removed Roles: 0
        Changed Roles: 1
                * user_r (1 Added Types)
                        + user_ext_t

Users (0 Added, 0 Removed, 0 Changed)
                      :
                  <Omitted>
                      :
TE Rules (1766 Added, 0 Removed, 0 Changed)
        Added TE Rules 1766:
                + allow load_policy_t user_ext_t : fd { use };
                      :
                  <Omitted>
                      :
                + allow ifconfig_t user_ext_t : fd { use };
        Removed TE Rules 0:
        Changed TE Rules 0:

Total Differences:
        Classes & Permissions 0
        Types 1
        Attributes 0
        Roles 1
        Users 0
        Booleans 0
        Rbac 0
        TE Rules 1766

-- 
DO NOTHING IS THE WORST POLICY.
KaiGai Kohei <kaigai@kaigai.gr.jp>

[-- Attachment #2: checkpolicy-1.20-type_extends.patch --]
[-- Type: text/plain, Size: 12933 bytes --]

--- checkpolicy-1.20/policy_scan.l	2004-12-13 16:29:49.000000000 -0500
+++ checkpolicy-1.20.extends/policy_scan.l	2005-03-12 20:43:13.000000000 -0500
@@ -75,8 +75,10 @@
 ELSE |
 else                         { return(ELSE); }
 ALIAS |
 alias				{ return(ALIAS); }
+EXTENDS |
+extends				{ return(EXTENDS); }
 ATTRIBUTE |
 attribute			{ return(ATTRIBUTE); }
 TYPE_TRANSITION |
 type_transition			{ return(TYPE_TRANSITION); }
--- checkpolicy-1.20/checkpolicy.h	2004-08-11 09:38:55.000000000 -0400
+++ checkpolicy-1.20.extends/checkpolicy.h	2005-03-13 22:32:07.000000000 -0500
@@ -15,6 +15,17 @@
 
 te_assert_t *te_assertions;
 
 extern unsigned int policyvers;
+/* type was not indexed in policydb,
+   but it's necessary for extends support. */
+extern type_datum_t **type_val_to_struct;
+extern int num_type_val_to_struct;
+extern void get_child_types(ebitmap_t *set, type_datum_t *t, int depth);
+
+static inline type_datum_t *get_type(int typeval) {
+	if (!type_val_to_struct || typeval<1 || typeval>num_type_val_to_struct)
+		return NULL;
+	return type_val_to_struct[typeval-1];
+}
 
 #endif
--- checkpolicy-1.20/checkpolicy.c	2004-08-11 10:03:19.000000000 -0400
+++ checkpolicy-1.20.extends/checkpolicy.c	2005-03-14 00:48:45.000000000 -0500
@@ -336,8 +336,10 @@
 }
 
 void check_assertions(void) 
 {
+	ebitmap_t temp;
+	type_datum_t *typedatum;
 	te_assert_t *a, *tmp;
 	unsigned int i, j;
 
 	a = te_assertions;
@@ -345,9 +347,21 @@
 		for (i = ebitmap_startbit(&a->stypes); i < ebitmap_length(&a->stypes); i++) {
 			if (!ebitmap_get_bit(&a->stypes, i))
 				continue;
 			if (a->self) {
-				check_assertion_helper(i, i, &a->tclasses, a->avp, a->line);
+				typedatum = type_val_to_struct[i];
+				if (!typedatum) {
+					fprintf(stderr, "BUG: check_assetion for undefined type.\n");
+					exit(1);
+				}
+				ebitmap_init(&temp);
+				get_child_types(&temp, typedatum, 0);
+				for (j = ebitmap_startbit(&temp); j < ebitmap_length(&temp); j++) {
+					if (!ebitmap_get_bit(&temp, j))
+						continue;
+					check_assertion_helper(i, j, &a->tclasses, a->avp, a->line);
+				}
+				ebitmap_destroy(&temp);
 			}
 			for (j = ebitmap_startbit(&a->ttypes); j < ebitmap_length(&a->ttypes); j++) {
 				if (!ebitmap_get_bit(&a->ttypes, j)) 
 					continue;
@@ -434,8 +448,43 @@
 	evaluate_conds(policydbp);
 	return 0;
 }
 
+type_datum_t **type_val_to_struct = NULL;
+int num_type_val_to_struct = -1;
+
+static int type_val_to_struct_helper(hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+	type_datum_t *t = (type_datum_t *)d;
+	if (!t->isattr && t->primary)
+		type_val_to_struct[t->value-1] = t;
+	return 0; /* always success */
+}
+
+void get_child_types(ebitmap_t *set, type_datum_t *td, int depth)
+{
+	type_datum_t *child;
+	int i;
+
+	if (td->isattr && depth>0) {
+		fprintf(stderr, "BUG: an attribute must not inherit anyone.\n");
+		exit(1);
+	}
+
+	if (!td->isattr && !td->primary)
+		td = get_type(td->value);
+
+	if (!td->isattr)
+		ebitmap_set_bit(set, td->value - 1, 1);
+
+	for (i = ebitmap_startbit(&td->types); i < ebitmap_length(&td->types); i++) {
+		if (ebitmap_get_bit(&td->types, i)) {
+			child = type_val_to_struct[i];
+			get_child_types(set, child, depth + 1);
+		}
+	}
+}
+
 int main(int argc, char **argv)
 {
 	security_class_t tclass;
 	security_id_t ssid, tsid, *sids;
@@ -448,9 +497,9 @@
 	unsigned int protocol, port;
 	unsigned int binary = 0, debug = 0;
 	struct val_to_name v;
 	int ret, ch, fd;
-	unsigned int nel;
+	unsigned int nel, len;
 	struct stat sb;
 	void *map;
 	FILE *outfp = NULL;
 	char *name;
@@ -568,8 +617,20 @@
 		if (yyparse() || policydb_errors) {
 			fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 			exit(1);
 		}
+
+		/* construction of type_val_to_struct */
+		num_type_val_to_struct = policydbp->p_types.nprim;
+		len = sizeof(type_datum_t *) * num_type_val_to_struct;
+		type_val_to_struct = (type_datum_t **)malloc(len);
+		if (!type_val_to_struct) {
+			fprintf(stderr, "type_val_to_struct: out of memory\n");
+			exit(1);
+		}
+		memset(type_val_to_struct, 0, len);
+		hashtab_map(policydbp->p_types.table, type_val_to_struct_helper, NULL);
+
 		rewind(yyin);
 		policydb_lineno = 1;
 		source_file[0] = '\0';
 		source_lineno = 1;
--- checkpolicy-1.20/policy_parse.y	2004-12-13 16:29:49.000000000 -0500
+++ checkpolicy-1.20.extends/policy_parse.y	2005-03-14 00:49:23.000000000 -0500
@@ -12,8 +12,13 @@
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
  */
 
+/* Updated: KaiGai Kohei, <kaigai@kaigai.gr.jp>
+ *      Added inherited type extensions. (2005/03/13)
+ */
+
+
 /* FLASK */
 
 %{
 #include <sys/types.h>
@@ -68,9 +73,9 @@
 static int define_av_base(void);
 static int define_attrib(void);
 static int define_typealias(void);
 static int define_typeattribute(void);
-static int define_type(int alias);
+static int define_type(int alias, int extends);
 static int define_compute_type(int which);
 static int define_te_avtab(int which);
 static int define_role_types(void);
 static role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2);
@@ -125,8 +130,9 @@
 %token TYPEATTRIBUTE
 %token TYPE
 %token TYPES
 %token ALIAS
+%token EXTENDS
 %token ATTRIBUTE
 %token BOOL
 %token IF
 %token ELSE
@@ -298,11 +304,15 @@
 attribute_def           : ATTRIBUTE identifier ';'
                         { if (define_attrib()) return -1;}
                         ;
 type_def		: TYPE identifier alias_def opt_attr_list ';'
-                        {if (define_type(1)) return -1;}
+                        {if (define_type(1, 0)) return -1;}
 	                | TYPE identifier opt_attr_list ';'
-                        {if (define_type(0)) return -1;}
+                        {if (define_type(0, 0)) return -1;}
+			| TYPE identifier alias_def opt_extends_list ';'
+			{if (define_type(1, 1)) return -1;}
+			| TYPE identifier opt_extends_list ';'
+			{if (define_type(0, 1)) return -1;}
     			;
 typealias_def           : TYPEALIAS identifier alias_def ';'
 			{if (define_typealias()) return -1;}
 			;
@@ -311,8 +321,10 @@
 			;
 opt_attr_list           : ',' id_comma_list
 			| 
 			;
+opt_extends_list	: EXTENDS id_comma_list
+			;
 bool_def                : BOOL identifier bool_val ';'
                         {if (define_bool()) return -1;}
                         ;
 bool_val                : CTRUE
@@ -1676,15 +1688,13 @@
 
 		if (ret == HASHTAB_PRESENT) {
 			sprintf(errormsg, "name conflict for type alias %s", id);
 			yyerror(errormsg);
-			free(aliasdatum);
 			free(id);
 			return -1;
 		}
 		if (ret == HASHTAB_OVERFLOW) {
 			yyerror("hash table overflow");
-			free(aliasdatum);
 			free(id);
 			return -1;
 		}
 	}
@@ -1770,12 +1780,12 @@
 
 	return 0;
 }
 
-static int define_type(int alias)
+static int define_type(int alias, int extends)
 {
 	char *id;
-	type_datum_t *datum, *aliasdatum, *attr;
+	type_datum_t *datum, *aliasdatum, *inherit;
 	int ret, newattr = 0;
 
 
 	if (pass == 2) {
@@ -1837,15 +1847,13 @@
 
 			if (ret == HASHTAB_PRESENT) {
 				sprintf(errormsg, "name conflict for type alias %s", id);
 				yyerror(errormsg);
-				free(aliasdatum);
 				free(id);
 				return -1;
 			}
 			if (ret == HASHTAB_OVERFLOW) {
 				yyerror("hash table overflow");
-				free(aliasdatum);
 				free(id);
 				return -1;
 			}
 		}
@@ -1856,11 +1864,12 @@
 			yyerror("out of memory");
 			free(id);
 			return -1;
 		}
-		attr = hashtab_search(policydbp->p_types.table, id);
-		if (!attr) {
-			sprintf(errormsg, "attribute %s is not declared", id);
+		inherit = hashtab_search(policydbp->p_types.table, id);
+		if (!inherit) {
+			sprintf(errormsg, "%sattribute %s is not declared",
+			       (extends)?"type/":"", id);
 #if 1
 			/* treat it as a fatal error */
 			yyerror(errormsg);
 			return -1;
@@ -1887,18 +1896,18 @@
 		} else {
 			newattr = 0;
 		}
 
-		if (!attr->isattr) {
+		if (!extends && !inherit->isattr) {
 			sprintf(errormsg, "%s is a type, not an attribute", id);
 			yyerror(errormsg);
 			return -1;
 		}
 
 		if (!newattr)
 			free(id);
 
-		ebitmap_set_bit(&attr->types, datum->value - 1, TRUE);
+		ebitmap_set_bit(&inherit->types, datum->value - 1, TRUE);
 	}
 
 	return 0;
 }
@@ -1935,16 +1944,16 @@
 		return v.name;
 	return NULL;
 }
 
-
 static int set_types(ebitmap_t *set,
 		     ebitmap_t *negset,
 		     char *id,
 		     int *add)
 {
 	type_datum_t *t;
 	unsigned int i;
+	ebitmap_t temp;
 
 	if (strcmp(id, "*") == 0) {
 		/* set all types not in negset */
 		for (i = 0; i < policydbp->p_types.nprim; i++) {
@@ -1980,43 +1989,27 @@
 		free(id);
 		return -1;
 	}
 
-	if (t->isattr) {
-		/* set or clear all types with this attribute,
-		   but do not set anything explicitly cleared previously */
-		for (i = ebitmap_startbit(&t->types); i < ebitmap_length(&t->types); i++) {
-			if (!ebitmap_get_bit(&t->types, i)) 
-				continue;		
-			if (!(*add)) {
-				ebitmap_set_bit(set, i, FALSE);
-				ebitmap_set_bit(negset, i, TRUE);
-			} else if (!ebitmap_get_bit(negset, i)) {
-				ebitmap_set_bit(set, i, TRUE);
-#if VERBOSE
-			} else {
-				char *name = type_val_to_name(i+1);
-				sprintf(errormsg, "ignoring %s due to prior -%s", name, name);
-				yywarn(errormsg);
-#endif
-			}
-		}
-	} else {
-		/* set or clear one type, but do not set anything
-		   explicitly cleared previously */	
+	ebitmap_init(&temp);
+	get_child_types(&temp, t, 0);
+	for (i = ebitmap_startbit(&temp); i < ebitmap_length(&temp); i++) {
+		if (!ebitmap_get_bit(&temp, i))
+			continue;
 		if (!(*add)) {
-			ebitmap_set_bit(set, t->value - 1, FALSE);
-			ebitmap_set_bit(negset, t->value - 1, TRUE);
-		} else if (!ebitmap_get_bit(negset, t->value - 1)) {
-			ebitmap_set_bit(set, t->value - 1, TRUE);
+			ebitmap_set_bit(set, i, FALSE);
+			ebitmap_set_bit(negset, i, TRUE);
+		} else if (!ebitmap_get_bit(negset, i)) {
+			ebitmap_set_bit(set, i, TRUE);
 #if VERBOSE
 		} else {
-			sprintf(errormsg, "ignoring %s due to prior -%s", id, id);
+			char *name = type_val_to_name(i+1);
+			sprintf(errormsg, "ignoring %s due to prior -%s", name, name);
 			yywarn(errormsg);
 #endif
 		}
 	}
-
+	ebitmap_destroy(&temp);
 	free(id);
 	*add = 1;
 	return 0;
 }
@@ -2598,9 +2591,10 @@
 	char *id;
 	cond_av_list_t *sub_list, *final_list, *tail;
 	class_datum_t *cladatum;
 	perm_datum_t *perdatum;
-	ebitmap_t stypes, ttypes, tclasses, negset;
+	type_datum_t *typedatum;
+	ebitmap_t stypes, ttypes, tclasses, temp, negset;
 	access_vector_t *avp;
 	int i, j, hiclass, self = 0, add = 1;
 	int suppress = 0;
 
@@ -2722,20 +2716,33 @@
 		for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
 			if (!ebitmap_get_bit(&stypes, i)) 
 				continue;
 			if (self) {
-				if ((sub_list = cond_te_avtab_helper(which, i, i, &tclasses, avp )) == COND_ERR)
+				typedatum = get_type(i+1);
+				if (!typedatum)
 					return COND_ERR;
-				if (final_list) {
-					tail->next = sub_list;
-					while (tail->next != NULL)
-						tail = tail->next;
-				} else {
-					final_list = sub_list;
-					tail = final_list;
-					while (tail->next != NULL)
-						tail = tail->next;
+				ebitmap_init(&temp);
+				get_child_types(&temp, typedatum, 0);
+				for (j = ebitmap_startbit(&temp); j < ebitmap_length(&temp); j++) {
+					if(!ebitmap_get_bit(&temp, j))
+						continue;
+					sub_list = cond_te_avtab_helper(which, i, j, &tclasses, avp );
+					if (sub_list==COND_ERR) {
+						ebitmap_destroy(&temp);
+						return COND_ERR;
+					}
+					if (final_list) {
+						tail->next = sub_list;
+						while (tail->next != NULL)
+							tail = tail->next;
+					} else {
+						final_list = sub_list;
+						tail = final_list;
+						while (tail->next != NULL)
+							tail = tail->next;
+					}
 				}
+				ebitmap_destroy(&temp);
 			}
 		}
 	}
 	for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
@@ -2774,9 +2781,10 @@
 {
 	char *id;
 	class_datum_t *cladatum;
 	perm_datum_t *perdatum;
-	ebitmap_t stypes, ttypes, tclasses, negset;
+	type_datum_t *typedatum;
+	ebitmap_t stypes, ttypes, tclasses, temp, negset;
 	access_vector_t *avp;
 	unsigned int i, j, hiclass;
 	int self = 0, add = 1;
 	te_assert_t *newassert;
@@ -2914,10 +2922,22 @@
 	for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) {
 		if (!ebitmap_get_bit(&stypes, i)) 
 			continue;
 		if (self) {
-			if (te_avtab_helper(which, i, i, &tclasses, avp))
+			typedatum = get_type(i+1);
+			if (!typedatum)
 				return -1;
+			ebitmap_init(&temp);
+			get_child_types(&temp, typedatum, 0);
+			for (j = ebitmap_startbit(&temp); j < ebitmap_length(&temp); j++) {
+				if (!ebitmap_get_bit(&temp, j))
+					continue;
+				if (te_avtab_helper(which, i, j, &tclasses, avp)) {
+					ebitmap_destroy(&temp);
+					return -1;
+				}
+			}
+			ebitmap_destroy(&temp);
 		}
 		for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) {
 			if (!ebitmap_get_bit(&ttypes, j)) 
 				continue;

^ permalink raw reply	[flat|nested] 58+ messages in thread

end of thread, other threads:[~2005-04-18 16:57 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-13 16:36 [RFC & PATCH] inherited type definition KaiGai Kohei
2005-03-14 13:17 ` KaiGai Kohei
2005-03-14 13:50 ` Stephen Smalley
2005-03-14 15:13   ` Luke Kenneth Casson Leighton
2005-03-14 15:22     ` Stephen Smalley
2005-03-14 16:01       ` Luke Kenneth Casson Leighton
2005-03-14 19:27         ` Valdis.Kletnieks
2005-03-14 20:10         ` Stephen Smalley
2005-03-14 17:26   ` KaiGai Kohei
2005-03-14 18:10     ` Luke Kenneth Casson Leighton
2005-03-14 18:25     ` Stephen Smalley
2005-03-15 11:50       ` KaiGai Kohei
2005-03-15 14:42         ` Stephen Smalley
2005-03-16  4:42           ` Kaigai Kohei
2005-03-16 10:00             ` Luke Kenneth Casson Leighton
2005-03-16 14:05             ` Stephen Smalley
2005-03-17  9:32               ` Kaigai Kohei
2005-03-17 13:55                 ` Stephen Smalley
2005-03-17 14:57                   ` KaiGai Kohei
2005-03-21 10:07                     ` KaiGai Kohei
2005-03-21 15:59                       ` Stephen Smalley
2005-03-23  8:17                         ` Kaigai Kohei
2005-03-23 13:56                           ` Stephen Smalley
2005-04-16  7:31                             ` KaiGai Kohei
2005-04-18 12:25                               ` Stephen Smalley
2005-04-18 16:57                                 ` KaiGai Kohei
2005-03-24 11:06                           ` Luke Kenneth Casson Leighton
2005-03-24 12:34                             ` Kaigai Kohei
2005-04-06 12:49         ` Russell Coker
2005-04-06 14:50           ` KaiGai Kohei
2005-04-06 15:30             ` Russell Coker
2005-04-06 18:23               ` Jim McCullough
2005-04-07  2:16               ` Kaigai Kohei
2005-04-06 17:55             ` Luke Kenneth Casson Leighton
2005-03-14 16:38 ` Karl MacMillan
2005-03-15 11:47   ` KaiGai Kohei
2005-03-15 14:00     ` Karl MacMillan
2005-03-16  4:35       ` Kaigai Kohei
2005-03-16 10:13         ` Luke Kenneth Casson Leighton
2005-03-16 21:46           ` Karl MacMillan
2005-03-16 21:31         ` Karl MacMillan
2005-03-17 13:05           ` Kaigai Kohei
2005-03-17 19:15             ` Karl MacMillan
2005-03-17 20:07               ` Stephen Smalley
2005-03-17 21:41                 ` Karl MacMillan
2005-03-18 13:13                   ` Stephen Smalley
2005-03-18 13:56                     ` Stephen Smalley
2005-03-18 22:28                     ` Karl MacMillan
2005-03-18 23:03                       ` Luke Kenneth Casson Leighton
2005-03-20 23:20                         ` Karl MacMillan
2005-03-21  0:17                           ` Luke Kenneth Casson Leighton
2005-03-21 13:39                             ` Karl MacMillan
2005-03-22  0:14                               ` Luke Kenneth Casson Leighton
2005-03-22 13:53                                 ` Karl MacMillan
2005-03-24 11:04                                   ` Luke Kenneth Casson Leighton
2005-03-24 12:31                                     ` Kaigai Kohei
2005-03-24 22:19                                       ` Luke Kenneth Casson Leighton
2005-03-24 22:27                                     ` Luke Kenneth Casson Leighton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.