* [ SEMANAGE ] Add a few direct dbases to handle
@ 2005-10-14 18:16 Ivan Gyurdiev
2005-10-14 18:39 ` [ SEMANAGE ] Bugfix previous patches Ivan Gyurdiev
2005-10-14 20:20 ` [ SEMANAGE ] Add a few direct dbases to handle Joshua Brindle
0 siblings, 2 replies; 12+ messages in thread
From: Ivan Gyurdiev @ 2005-10-14 18:16 UTC (permalink / raw)
To: selinux; +Cc: Stephen Smalley
[-- Attachment #1: Type: text/plain, Size: 148 bytes --]
Adds a few direct databases to the handle.
There's still no dangerous code in the main commit path...
This is just the equivalent to file init.
[-- Attachment #2: libsemanage.direct_dbase.diff --]
[-- Type: text/x-patch, Size: 3626 bytes --]
diff -Naur libsemanage/src/direct_api.c libsemanage.new/src/direct_api.c
--- libsemanage/src/direct_api.c 2005-10-13 15:23:31.000000000 -0400
+++ libsemanage.new/src/direct_api.c 2005-10-14 14:08:44.000000000 -0400
@@ -272,7 +272,7 @@
#if 0
/* Link components into base policy */
- if (semanage_base_merge_components(sh, NULL /* FIXME */) < 0)
+ if (semanage_base_merge_components(sh) < 0)
goto cleanup;
/* Commit changes to components */
diff -Naur libsemanage/src/handle.c libsemanage.new/src/handle.c
--- libsemanage/src/handle.c 2005-10-14 14:10:54.000000000 -0400
+++ libsemanage.new/src/handle.c 2005-10-14 14:07:52.000000000 -0400
@@ -39,6 +39,8 @@
#include "interfaces_file.h"
#include "booleans_file.h"
#include "seusers_file.h"
+#include "users_direct.h"
+#include "ports_direct.h"
#include "database.h"
#define SEMANAGE_COMMIT_READ_WAIT 5
@@ -90,6 +92,12 @@
if (seuser_file_dbase_init(&sh->dbase[DBASE_SEUSERS]) < 0)
goto err;
+ if (user_direct_dbase_init("base.pp", &sh->dbase[DBASE_BASE_USERS]) < 0)
+ goto err;
+
+ if (port_direct_dbase_init("base.pp", &sh->dbase[DBASE_BASE_PORTS]) < 0)
+ goto err;
+
return sh;
omem:
diff -Naur libsemanage/src/handle.h libsemanage.new/src/handle.h
--- libsemanage/src/handle.h 2005-10-14 14:10:54.000000000 -0400
+++ libsemanage.new/src/handle.h 2005-10-14 14:07:46.000000000 -0400
@@ -71,12 +71,20 @@
struct semanage_policy_table* funcs;
/* Object databases */
-#define DBASE_COUNT 5
+#define DBASE_COUNT 7
+
#define DBASE_USERS 0
#define DBASE_PORTS 1
#define DBASE_INTERFACES 2
#define DBASE_BOOLEANS 3
#define DBASE_SEUSERS 4
+
+#define DBASE_BASE_USERS 5
+#define DBASE_BASE_PORTS 6
+#if 0
+#define DBASE_BASE_INTERFACES 7
+#define DBASE_BASE_BOOLEANS 8
+#endif
dbase_config_t dbase[DBASE_COUNT];
};
@@ -105,5 +113,27 @@
return &handle->dbase[DBASE_SEUSERS];
}
+static inline
+dbase_config_t* semanage_base_user_dbase(semanage_handle_t* handle) {
+ return &handle->dbase[DBASE_BASE_USERS];
+}
+
+static inline
+dbase_config_t* semanage_base_port_dbase(semanage_handle_t* handle) {
+ return &handle->dbase[DBASE_BASE_PORTS];
+}
+
+#if 0
+static inline
+dbase_config_t* semanage_base_iface_dbase(semanage_handle_t* handle) {
+ return &handle->dbase[DBASE_BASE_INTERFACES];
+}
+
+static inline
+dbase_config_t* semanage_base_bool_dbase(semanage_handle_t* handle) {
+ return &handle->dbase[DBASE_BASE_BOOLEANS];
+}
+#endif
+
#endif
diff -Naur libsemanage/src/policy_components.c libsemanage.new/src/policy_components.c
--- libsemanage/src/policy_components.c 2005-10-14 13:19:51.000000000 -0400
+++ libsemanage.new/src/policy_components.c 2005-10-14 14:09:35.000000000 -0400
@@ -5,8 +5,7 @@
#include "debug.h"
int semanage_base_merge_components(
- semanage_handle_t* handle,
- semanage_module_info_t* base) {
+ semanage_handle_t* handle) {
//dbase_config_t* modules = dbase_modules_dbase(handle);
dbase_config_t* interfaces = semanage_iface_dbase(handle);
@@ -36,7 +35,6 @@
ports->dbase, NULL, NULL /* FIXME */) < 0)
goto err;
- base = NULL;
return STATUS_SUCCESS;
err:
diff -Naur libsemanage/src/policy.h libsemanage.new/src/policy.h
--- libsemanage/src/policy.h 2005-10-13 13:08:35.000000000 -0400
+++ libsemanage.new/src/policy.h 2005-10-14 14:09:44.000000000 -0400
@@ -66,8 +66,7 @@
/* Should be backend independent */
extern int semanage_base_merge_components(
- struct semanage_handle* handle,
- semanage_module_info_t* base);
+ struct semanage_handle* handle);
extern int semanage_commit_components(
struct semanage_handle* handle);
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [ SEMANAGE ] Bugfix previous patches 2005-10-14 18:16 [ SEMANAGE ] Add a few direct dbases to handle Ivan Gyurdiev @ 2005-10-14 18:39 ` Ivan Gyurdiev 2005-10-14 20:08 ` Stephen Smalley 2005-10-14 20:20 ` [ SEMANAGE ] Add a few direct dbases to handle Joshua Brindle 1 sibling, 1 reply; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-14 18:39 UTC (permalink / raw) To: selinux; +Cc: Stephen Smalley [-- Attachment #1: Type: text/plain, Size: 950 bytes --] Ivan Gyurdiev wrote: > Adds a few direct databases to the handle. > There's still no dangerous code in the main commit path... > This is just the equivalent to file init. Attached patch includes bugfixes for previous submissions (applies on top). Specifically: - direct code should be in direct_api.c (connect/disconnect), not in the create/destroy for the handle. - removes suffix parameter from direct init functions - I don't think I'll be implementing per module databases at this time (maybe some other day) - set correct suffix to policy.kern, not base.pp - we want to operate on the expanded policy, with the modules merged. Actually, with this fix, there's now a slight chance the dbase_direct cache function might start to work (since we're no longer using the policy package, so it's just a standard policy database, I think).... but I'd need to test that further. - add release() calls for the boolean/interface/seuser databases. [-- Attachment #2: libsemanage.direct.bugfixes.diff --] [-- Type: text/x-patch, Size: 4894 bytes --] diff -Naur libsemanage/src/direct_api.c libsemanage.new/src/direct_api.c --- libsemanage/src/direct_api.c 2005-10-14 14:20:47.000000000 -0400 +++ libsemanage.new/src/direct_api.c 2005-10-14 14:31:34.000000000 -0400 @@ -28,6 +28,13 @@ #include <sys/stat.h> #include <sys/types.h> +#include "users_direct.h" +#include "ports_direct.h" +#if 0 +#include "interfaces_direct.h" +#include "booleans_direct.h" +#endif + #include "debug.h" #include "handle.h" #include "modules.h" @@ -64,9 +71,8 @@ /* Check that the module store exists, creating it if necessary. */ int semanage_direct_connect(semanage_handle_t *sh) { - if (semanage_create_store(sh, 1) < 0) { - return -1; - } + if (semanage_create_store(sh, 1) < 0) + goto err; sh->conn.module.translock_file_fd = -1; sh->conn.module.readlock_file_fd = -1; @@ -74,9 +80,25 @@ /* set up function pointers */ sh->funcs = &direct_funcs; - /* FIXME: configure policy query databases */ + if (user_direct_dbase_init(&sh->dbase[DBASE_BASE_USERS]) < 0) + goto err; - return 0; + if (port_direct_dbase_init(&sh->dbase[DBASE_BASE_PORTS]) < 0) + goto err; + +#if 0 + if (iface_direct_dbase_init(&sh->dbase[DBASE_BASE_INTERFACES]) < 0) + goto err; + + if (bool_direct_dbase_init(&sh->dbase[DBASE_BASE_BOOLEANS]) < 0) + goto err; +#endif + + return STATUS_SUCCESS; + + err: + /* FIXME: handle error */ + return STATUS_ERR; } static void semanage_direct_destroy(semanage_handle_t *sh) { @@ -95,7 +117,13 @@ semanage_release_trans_lock(sh); } - /* FIXME: release policy query databases */ + /* Remove object databases */ + user_direct_dbase_release(sh, &sh->dbase[DBASE_BASE_USERS]); + port_direct_dbase_release(sh, &sh->dbase[DBASE_BASE_PORTS]); +#if 0 + iface_direct_dbase_release(sh, &sh->dbase[DBASE_BASE_INTERFACES]); + bool_direct_dbase_release(sh, &sh->dbase[DBASE_BASE_BOOLEANS]); +#endif return 0; } diff -Naur libsemanage/src/handle.c libsemanage.new/src/handle.c --- libsemanage/src/handle.c 2005-10-14 14:20:47.000000000 -0400 +++ libsemanage.new/src/handle.c 2005-10-14 14:32:22.000000000 -0400 @@ -29,9 +29,9 @@ #include <stdio.h> #include <sys/time.h> +#include "direct_api.h" #include "handle.h" #include "debug.h" -#include "direct_api.h" #include "semanage_conf.h" #include "semanage_store.h" #include "users_file.h" @@ -39,8 +39,6 @@ #include "interfaces_file.h" #include "booleans_file.h" #include "seusers_file.h" -#include "users_direct.h" -#include "ports_direct.h" #include "database.h" #define SEMANAGE_COMMIT_READ_WAIT 5 @@ -92,12 +90,6 @@ if (seuser_file_dbase_init(&sh->dbase[DBASE_SEUSERS]) < 0) goto err; - if (user_direct_dbase_init("base.pp", &sh->dbase[DBASE_BASE_USERS]) < 0) - goto err; - - if (port_direct_dbase_init("base.pp", &sh->dbase[DBASE_BASE_PORTS]) < 0) - goto err; - return sh; omem: @@ -150,6 +142,9 @@ /* Free object databases */ user_file_dbase_release(sh, &sh->dbase[DBASE_USERS]); port_file_dbase_release(sh, &sh->dbase[DBASE_PORTS]); + iface_file_dbase_release(sh, &sh->dbase[DBASE_INTERFACES]); + bool_file_dbase_release(sh, &sh->dbase[DBASE_BOOLEANS]); + seuser_file_dbase_release(sh, &sh->dbase[DBASE_SEUSERS]); free(sh); } diff -Naur libsemanage/src/ports_direct.c libsemanage.new/src/ports_direct.c --- libsemanage/src/ports_direct.c 2005-10-06 15:22:48.000000000 -0400 +++ libsemanage.new/src/ports_direct.c 2005-10-14 14:22:56.000000000 -0400 @@ -28,11 +28,10 @@ }; int port_direct_dbase_init( - const char* suffix, dbase_config_t* dconfig) { if (dbase_direct_init( - suffix, + "policy.kern", &SEPOL_PORT_RTABLE, &SEMANAGE_PORT_DIRECT_RTABLE, &dconfig->dbase) < 0) diff -Naur libsemanage/src/ports_direct.h libsemanage.new/src/ports_direct.h --- libsemanage/src/ports_direct.h 2005-10-06 15:22:48.000000000 -0400 +++ libsemanage.new/src/ports_direct.h 2005-10-14 14:29:37.000000000 -0400 @@ -5,7 +5,6 @@ #include "handle.h" int port_direct_dbase_init( - const char* suffix, dbase_config_t* dconfig); void port_direct_dbase_release( diff -Naur libsemanage/src/users_direct.c libsemanage.new/src/users_direct.c --- libsemanage/src/users_direct.c 2005-10-06 15:22:48.000000000 -0400 +++ libsemanage.new/src/users_direct.c 2005-10-14 14:23:00.000000000 -0400 @@ -28,11 +28,10 @@ }; int user_direct_dbase_init( - const char* suffix, dbase_config_t* dconfig) { if (dbase_direct_init( - suffix, + "policy.kern", &SEPOL_USER_RTABLE, &SEMANAGE_USER_DIRECT_RTABLE, &dconfig->dbase) < 0) diff -Naur libsemanage/src/users_direct.h libsemanage.new/src/users_direct.h --- libsemanage/src/users_direct.h 2005-10-06 15:22:48.000000000 -0400 +++ libsemanage.new/src/users_direct.h 2005-10-14 14:29:31.000000000 -0400 @@ -5,7 +5,6 @@ #include "handle.h" int user_direct_dbase_init( - const char* suffix, dbase_config_t* dconfig); void user_direct_dbase_release( ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Bugfix previous patches 2005-10-14 18:39 ` [ SEMANAGE ] Bugfix previous patches Ivan Gyurdiev @ 2005-10-14 20:08 ` Stephen Smalley 0 siblings, 0 replies; 12+ messages in thread From: Stephen Smalley @ 2005-10-14 20:08 UTC (permalink / raw) To: Ivan Gyurdiev; +Cc: selinux On Fri, 2005-10-14 at 14:39 -0400, Ivan Gyurdiev wrote: > Ivan Gyurdiev wrote: > > Adds a few direct databases to the handle. > > There's still no dangerous code in the main commit path... > > This is just the equivalent to file init. > Attached patch includes bugfixes for previous submissions (applies on top). All 5 patches merged, last one was libsemanage 1.3.18. -- Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 18:16 [ SEMANAGE ] Add a few direct dbases to handle Ivan Gyurdiev 2005-10-14 18:39 ` [ SEMANAGE ] Bugfix previous patches Ivan Gyurdiev @ 2005-10-14 20:20 ` Joshua Brindle 2005-10-14 20:40 ` Ivan Gyurdiev 1 sibling, 1 reply; 12+ messages in thread From: Joshua Brindle @ 2005-10-14 20:20 UTC (permalink / raw) To: Ivan Gyurdiev; +Cc: selinux, Stephen Smalley Ivan Gyurdiev wrote: > Adds a few direct databases to the handle. > There's still no dangerous code in the main commit path... > This is just the equivalent to file init. > > diff -Naur libsemanage/src/handle.h libsemanage.new/src/handle.h > --- libsemanage/src/handle.h 2005-10-14 14:10:54.000000000 -0400 > +++ libsemanage.new/src/handle.h 2005-10-14 14:07:46.000000000 -0400 > @@ -71,12 +71,20 @@ > struct semanage_policy_table* funcs; > > /* Object databases */ > -#define DBASE_COUNT 5 > +#define DBASE_COUNT 7 > + > #define DBASE_USERS 0 > #define DBASE_PORTS 1 > #define DBASE_INTERFACES 2 > #define DBASE_BOOLEANS 3 > #define DBASE_SEUSERS 4 > + > +#define DBASE_BASE_USERS 5 > +#define DBASE_BASE_PORTS 6 > +#if 0 > +#define DBASE_BASE_INTERFACES 7 > +#define DBASE_BASE_BOOLEANS 8 > +#endif > dbase_config_t dbase[DBASE_COUNT]; > }; > > @@ -105,5 +113,27 @@ > return &handle->dbase[DBASE_SEUSERS]; > } > I thought we agreed to have a direct only accessible part of the handle, such as struct semanage_direct_handle { semanage_handle_t *handle; /* direct stuff goes here */ }; So that this stuff is only exposed to direct api functions? The policy server shouldn't be filling out databases that are accessible to the user since it needs to mediate access. Joshua -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 20:20 ` [ SEMANAGE ] Add a few direct dbases to handle Joshua Brindle @ 2005-10-14 20:40 ` Ivan Gyurdiev 2005-10-14 20:45 ` Ivan Gyurdiev 0 siblings, 1 reply; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-14 20:40 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley > I thought we agreed to have a direct only accessible part of the > handle, such as > > struct semanage_direct_handle { > semanage_handle_t *handle; > /* direct stuff goes here */ > }; I'm a little confused... The dbase_config_t type is an a container for a database and its method table, which together form an interface. The interface does not specify implementation, so you can implement this database differently using the policy server. That patch also included code to init this database using the direct "constructor" - when you call <something>_direct_dbase_init(). That part was wrong, and if you look in the bugfix patch (#5), you will see that I moved the direct-specific part into direct_api.h, to be invoked on connect(), rather than create(). > So that this stuff is only exposed to direct api functions? The policy > server shouldn't be filling out databases that are accessible to the > user since it needs to mediate access. I'm not sure I understand this.. s/"are"/"aren't"? Note that those databases are needed regardless of backend - they're specified using an interface. -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 20:40 ` Ivan Gyurdiev @ 2005-10-14 20:45 ` Ivan Gyurdiev 2005-10-14 20:39 ` Joshua Brindle 0 siblings, 1 reply; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-14 20:45 UTC (permalink / raw) To: Ivan Gyurdiev; +Cc: Joshua Brindle, selinux, Stephen Smalley > >> I thought we agreed to have a direct only accessible part of the >> handle, such as >> >> struct semanage_direct_handle { >> semanage_handle_t *handle; >> /* direct stuff goes here */ >> }; To put it another way.. this "direct-only" part does exist, but it's hidden away. (into dbase_config_t -> dbase), which is an interface type. Then the method table (dbase_config_t->dtable) specifies how to access it, which is equivalent to your function table for modules. In fact, I want to convert your modules functions into a database too, but I haven't gotten to it yet, and this isn't high priority. So...basically I have multiple backend-specific portions, distributed by functionality, rather than putting it all into one big table of function pointers that aren't related. -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 20:45 ` Ivan Gyurdiev @ 2005-10-14 20:39 ` Joshua Brindle 2005-10-14 20:59 ` Ivan Gyurdiev 0 siblings, 1 reply; 12+ messages in thread From: Joshua Brindle @ 2005-10-14 20:39 UTC (permalink / raw) To: Ivan Gyurdiev; +Cc: selinux, Stephen Smalley Ivan Gyurdiev wrote: >> >>> I thought we agreed to have a direct only accessible part of the >>> handle, such as >>> >>> struct semanage_direct_handle { >>> semanage_handle_t *handle; >>> /* direct stuff goes here */ >>> }; > > To put it another way.. this "direct-only" part does exist, but it's > hidden away. > (into dbase_config_t -> dbase), which is an interface type. Then the > method table > (dbase_config_t->dtable) specifies how to access it, which is equivalent > to your > function table for modules. The direct-only part needs to exist. The handle is becoming very cluttered with stuff that should not be there. > > In fact, I want to convert your modules functions into a database too, but > I haven't gotten to it yet, and this isn't high priority. > Why? This doesn't solve any problem. > So...basically I have multiple backend-specific portions, distributed by > functionality, > rather than putting it all into one big table of function pointers that > aren't related. the backend-specific portions should be hidden in a backend specific handle. This means that semanage_handle_t does *not* contain *any* backend specific information, all backend specific information would be in semanage_direct_handle, semanage_ps_handle, and so on. Joshua -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 20:39 ` Joshua Brindle @ 2005-10-14 20:59 ` Ivan Gyurdiev 2005-10-14 21:06 ` Joshua Brindle 0 siblings, 1 reply; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-14 20:59 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley >> To put it another way.. this "direct-only" part does exist, but it's >> hidden away. >> (into dbase_config_t -> dbase), which is an interface type. Then the >> method table >> (dbase_config_t->dtable) specifies how to access it, which is >> equivalent to your >> function table for modules. > > The direct-only part needs to exist. The handle is becoming very > cluttered with stuff that should not be there. You don't seem to realize that those databases need to exist, whether or not you're using the policy server, or the direct api. This is just another way to switch between the two. >> >> In fact, I want to convert your modules functions into a database >> too, but >> I haven't gotten to it yet, and this isn't high priority. >> > Why? This doesn't solve any problem. For consistency, if nothing else... I think there are benefits to hiding data collections under a uniform interface, but I don't want to get into that right now - I sent Karl a long email some time ago. I know he's not convinced, but it's just my pet project. Like I said, I won't be doing that yet. >> So...basically I have multiple backend-specific portions, distributed >> by functionality, >> rather than putting it all into one big table of function pointers >> that aren't related. > > the backend-specific portions should be hidden in a backend specific > handle. This means that semanage_handle_t does *not* contain *any* > backend specific information, all backend specific information would > be in semanage_direct_handle, semanage_ps_handle, and so on. The handle does not contain anything backend specific currently. Please give an example of something backend specific. -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 20:59 ` Ivan Gyurdiev @ 2005-10-14 21:06 ` Joshua Brindle 2005-10-14 21:40 ` Ivan Gyurdiev 0 siblings, 1 reply; 12+ messages in thread From: Joshua Brindle @ 2005-10-14 21:06 UTC (permalink / raw) To: Ivan Gyurdiev; +Cc: selinux, Stephen Smalley Ivan Gyurdiev wrote: > >>> To put it another way.. this "direct-only" part does exist, but it's >>> hidden away. >>> (into dbase_config_t -> dbase), which is an interface type. Then the >>> method table >>> (dbase_config_t->dtable) specifies how to access it, which is >>> equivalent to your >>> function table for modules. >> >> >> The direct-only part needs to exist. The handle is becoming very >> cluttered with stuff that should not be there. > > You don't seem to realize that those databases need to exist, whether or > not you're using the policy server, or the direct api. > This is just another way to switch between the two. > The policy server can't fill in these databases since there are permission checks it would need to do for the queries. >>> >>> In fact, I want to convert your modules functions into a database >>> too, but >>> I haven't gotten to it yet, and this isn't high priority. >>> >> Why? This doesn't solve any problem. > > For consistency, if nothing else... I think there are benefits to hiding > data collections under a uniform interface, but I don't want to get into > that right now - I sent Karl a long email some time ago. I know he's not > convinced, but it's just my pet project. > this is a library being used by many people, I don't know that adding things for the sake of adding them is appropriate. > Like I said, I won't be doing that yet. > >>> So...basically I have multiple backend-specific portions, distributed >>> by functionality, >>> rather than putting it all into one big table of function pointers >>> that aren't related. >> >> >> the backend-specific portions should be hidden in a backend specific >> handle. This means that semanage_handle_t does *not* contain *any* >> backend specific information, all backend specific information would >> be in semanage_direct_handle, semanage_ps_handle, and so on. > > The handle does not contain anything backend specific currently. Please > give an example of something backend specific. The subject of this email is "Add a few direct dbases to handle". Does direct mean something different from a direct connection? Also: + +#define DBASE_BASE_USERS 5 +#define DBASE_BASE_PORTS 6 +#if 0 +#define DBASE_BASE_INTERFACES 7 +#define DBASE_BASE_BOOLEANS 8 +#endif What are these? How are they different from the other user, ports, interfaces, booleans. Why isn't this described in the code or even email? -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 21:06 ` Joshua Brindle @ 2005-10-14 21:40 ` Ivan Gyurdiev 2005-10-15 11:34 ` Ivan Gyurdiev 0 siblings, 1 reply; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-14 21:40 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley >> >> You don't seem to realize that those databases need to exist, whether >> or not you're using the policy server, or the direct api. >> This is just another way to switch between the two. >> > The policy server can't fill in these databases since there are > permission checks it would need to do for the queries. That sounds like an implementation detail, and I don't understand why it's a problem. Maybe you can be more specific? I've defined a database-like interface for users and other objects for files. You can look at users.h or ports.h, to see an example. I would like to support the same interface for the same objects in policy. I plan on exposing at least the query part of it to libsemanage clients. I'm not sure whether the modification part of it should be exposed (since you want modules only...no primitive changes), but I think it should be implemented internally in any case. I can support the direct-case implementation. I am hoping you can support the policy server case, because otherwise this interface will not work for the server. If you dislike the interface, please give concrete reasons why, and I'll try to correct it. >>>> >>>> In fact, I want to convert your modules functions into a database >>>> too, but >>>> I haven't gotten to it yet, and this isn't high priority. >>>> >>> Why? This doesn't solve any problem. >> >> For consistency, if nothing else... I think there are benefits to >> hiding data collections under a uniform interface, but I don't want >> to get into that right now - I sent Karl a long email some time ago. >> I know he's not convinced, but it's just my pet project. >> > this is a library being used by many people, I don't know that adding > things for the sake of adding them is appropriate. I don't waste my time adding things "for the sake of adding them". I try to design things so that they are extensible. For example, one concrete reason why I want to see the modules look like a database, is that the dbase interface has more functions than you currently provide, and provides better encapsulation. I think that having a similar modules interface could be beneficial. That said, Dan Walsh has not specified this as part of my current project, so it's just something that I would like to do. The handle does not contain anything backend specific currently. Please give an example of something backend specific. > The subject of this email is "Add a few direct dbases to handle". Does > direct mean something different from a direct connection? You're right...the subject is misleading. It should say: "Add a few policy databases to the handle, and stub their direct implementations". > Also: > > + > +#define DBASE_BASE_USERS 5 > +#define DBASE_BASE_PORTS 6 > +#if 0 > +#define DBASE_BASE_INTERFACES 7 > +#define DBASE_BASE_BOOLEANS 8 > +#endif > > What are these? How are they different from the other user, ports, > interfaces, booleans. Why isn't this described in the code or even email? These are the users/ports/interfaces, and booleans that are currently part of the binary policy. This was described in an email, to which you replied IIRC. It has also been described multiple times when I submitted patches that talk about a "direct database" to the list. I agree that the code is not commented, but I've tried to at least name things proplerly. I can add more comments later on, since a lot of this functionality isn't quite working yet - this is work in-progress. -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-14 21:40 ` Ivan Gyurdiev @ 2005-10-15 11:34 ` Ivan Gyurdiev 2005-10-15 11:38 ` Ivan Gyurdiev 0 siblings, 1 reply; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-15 11:34 UTC (permalink / raw) To: selinux; +Cc: Karl MacMillan, Joshua Brindle, Stephen Smalley [-- Attachment #1: Type: text/plain, Size: 3808 bytes --] > >>>>> >>>>> In fact, I want to convert your modules functions into a database >>>>> too, but >>>>> I haven't gotten to it yet, and this isn't high priority. >>>>> >>>> Why? This doesn't solve any problem. >>> >>> For consistency, if nothing else... I think there are benefits to >>> hiding data collections under a uniform interface, but I don't want >>> to get into that right now - I sent Karl a long email some time ago. >>> I know he's not convinced, but it's just my pet project. >>> >> this is a library being used by many people, I don't know that adding >> things for the sake of adding them is appropriate. > I don't waste my time adding things "for the sake of adding them". I > try to design things so that they are extensible. For example, one > concrete reason why I want to see the modules look like a database, is > that the dbase interface has more functions than you currently > provide, and provides better encapsulation. I think that having a > similar modules interface could be beneficial. I don't understand why you don't see how this is useful. It separates backend logic from record logic, which is a good idea, because it makes the code clearer to understand - right now your backend logic is mixed with your record logic. Separation would also allow you to write backend-independent record code, and record-independent backend code. You don't have this right now - you have an interface of function pointers, but any code you implement has to be record-aware, and backend-aware. That's why Karl says "there's very little shared code". There could be more shared code, if you would allow for better abstractions, but you're dead set against those, for reasons I don't understand. By "backend-independent record code" I mean, being able to add a user, and not care where the user is stored.. being able to loop over the seuser mappings, and not care whether the data is coming from LDAP or the seusers file, because all I want to do is load it into policy. In the particular case of modules, I should be able to loop over all modules, and, say, search for a particular symbol... or do search and replace (if you'll allow modifications), or... list all the modules. I should be able to do this without caring how the module is stored - whether it's on a policy server, or whatever... You could achieve this with the proper interface, but if your code is modeled that way internally, then you can also share implementation of higher-level algorithms. By "record-independent backend code" I mean, things that are specific to the way a backend stores records, regardless of what kind of records they are. For example, all my flat files are handled the same way - loop over the file, read the records into a cache, operate, write the file out. If I want to change the format of the cache, or encrypt files, or do some sort of permission checks, or ... something.. I could wirte this code once, instead of per record. In the case of modules, I could use the "directory" backend for other purposes.... if I add a directory with some other kind of files tomorrow... maybe I can add a "file" database for each file in the directory, and implement a shared flush() method, that writes changes to each individual file that was modified (regardless of what's in the file, or how it's stored - I don't care - that's what the file database hides). So, I could say: flush all changes in this directory to disk on event x-y-z, regardless of what's in there, or how it's distributed... Here's a bunch of stubs that I wrote just now - they don't add anything right now, but they could become useful in the future, if this is done properly. I think it's a worthy goal to move towards a more object-based code, whether this is written in C or not. [-- Attachment #2: libsemanage.modules.diff --] [-- Type: text/x-patch, Size: 13293 bytes --] diff -Naur --exclude ChangeLog --exclude VERSION --exclude CVS libsemanage/include/semanage/module_record.h libsemanage.new/include/semanage/module_record.h --- libsemanage/include/semanage/module_record.h 1969-12-31 19:00:00.000000000 -0500 +++ libsemanage.new/include/semanage/module_record.h 2005-10-15 06:42:12.000000000 -0400 @@ -0,0 +1,63 @@ +#ifndef _SEMANAGE_MODULE_RECORD_H_ +#define _SEMANAGE_MODULE_RECORD_H_ + +#include <semanage/handle.h> + +struct semanage_module; +struct semanage_module_key; +typedef struct semanage_module semanage_module_t; +typedef struct semanage_module_key semanage_module_key_t; + +/* Key */ +extern int semanage_module_key_create( + semanage_handle_t* handle, + const char* name, + semanage_module_key_t** key); + +extern int semanage_module_key_extract( + semanage_handle_t* handle, + semanage_module_t* module, + semanage_module_key_t** key); + +extern void semanage_module_key_free( + semanage_module_key_t* key); + +extern int semanage_module_compare( + semanage_module_t* module, + semanage_module_key_t* key); + +/* Name */ +#if 0 /* FIXME: conflict with modules.h */ +extern const char* semanage_module_get_name( + semanage_module_t* module); + +extern int semanage_module_set_name( + semanage_handle_t* handle, + semanage_module_t* module, + const char* name); + +/* Module Version */ +extern const char* semanage_module_get_version( + semanage_module_t* module); + +extern int semanage_module_set_version( + semanage_handle_t* handle, + semanage_module_t* module, + const char* version); +#endif + +/* FIXME: Add data fields here */ + +/* Create/Clone/Destroy */ +extern int semanage_module_create( + semanage_handle_t* handle, + semanage_module_t** module_ptr); + +extern int semanage_module_clone( + semanage_handle_t* handle, + semanage_module_t* module, + semanage_module_t** module_ptr); + +extern void semanage_module_free( + semanage_module_t* module); +#endif diff -Naur --exclude ChangeLog --exclude VERSION --exclude CVS libsemanage/include/semanage/seuser_record.h libsemanage.new/include/semanage/seuser_record.h --- libsemanage/include/semanage/seuser_record.h 2005-10-14 13:26:14.000000000 -0400 +++ libsemanage.new/include/semanage/seuser_record.h 2005-10-15 06:28:40.000000000 -0400 @@ -1,7 +1,6 @@ #ifndef _SEMANAGE_SEUSER_RECORD_H_ #define _SEMANAGE_SEUSER_RECORD_H_ -#include <stddef.h> #include <semanage/handle.h> struct semanage_seuser; diff -Naur --exclude ChangeLog --exclude VERSION --exclude CVS libsemanage/src/database_directory.c libsemanage.new/src/database_directory.c --- libsemanage/src/database_directory.c 1969-12-31 19:00:00.000000000 -0500 +++ libsemanage.new/src/database_directory.c 2005-10-15 06:44:49.000000000 -0400 @@ -0,0 +1,319 @@ +struct dbase_dir; +typedef struct dbase_dir dbase_t; +#define DBASE_DEFINED + +#include <stdlib.h> +#include <string.h> +#include "debug.h" +#include "handle.h" +#include "database_directory.h" +#include "semanage_store.h" + +/* DIRECTORY dbase */ +struct dbase_dir { + + /* Backing directory suffix */ + const char* suffix; + + /* Base record table */ + record_table_t* rtable; +}; + +#if 0 +static int construct_filename( + semanage_handle_t* handle, + dbase_dir_t* dbase, + char** filename) { + + const char* path = (handle->is_in_transaction)? + semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL): + semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL); + size_t fname_length = strlen(path) + strlen(dbase->suffix) + 2; + + char* fname = malloc(fname_length); + if (!fname) { + /* FIXME: handle error */ + return STATUS_ERR; + } + snprintf(fname, fname_length, "%s/%s", path, dbase->suffix); + + *filename = fname; + return STATUS_SUCCESS; +} +#endif + +static void dbase_dir_drop_cache( + semanage_handle_t* handle, + dbase_dir_t* dbase) { + + /* Stub */ + handle = NULL; + dbase = NULL; +} + +/* Flush database to file */ +static int dbase_dir_flush( + semanage_handle_t* handle, + dbase_dir_t* dbase) { + + /* Stub */ + handle = NULL; + dbase = NULL; + return STATUS_SUCCESS; +} + +static int enter_ro( + semanage_handle_t* handle, + dbase_dir_t* dbase) { + + //if (semanage_handle_get_read_lock(handle) < 0) { + // /* FIXME: handle error */ + // return STATUS_ERR; + //} + + /* Stub */ + handle = NULL; + dbase = NULL; + return STATUS_SUCCESS; +} + +static inline void exit_ro( + semanage_handle_t* handle, + dbase_dir_t* dbase) { + + //semanage_release_read_lock(handle); + dbase_dir_drop_cache(handle, dbase); +} + +static int enter_rw( + semanage_handle_t* handle, + dbase_dir_t* dbase) { + + if (!handle->is_in_transaction) { + /* FIXME: handle error */ + return STATUS_ERR; + } + + /* Stub */ + dbase = NULL; + return STATUS_SUCCESS; +} + +int dbase_dir_init( + const char* suffix, + record_table_t* rtable, + dbase_dir_t** dbase) { + + dbase_dir_t* tmp_dbase = + (dbase_dir_t*) malloc(sizeof(dbase_dir_t)); + + if (!tmp_dbase) + goto omem; + + tmp_dbase->suffix = suffix; + tmp_dbase->rtable = rtable; + *dbase = tmp_dbase; + + return STATUS_SUCCESS; + + omem: + /* FIXME: handle error condition */ + free(tmp_dbase); + return STATUS_ERR; +} + +/* Release dbase resources */ +void dbase_dir_release( + semanage_handle_t* handle, + dbase_dir_t* dbase) { + + dbase_dir_drop_cache(handle, dbase); + free(dbase); +} + +static int dbase_dir_exists( + semanage_handle_t* handle, + dbase_dir_t* dbase, + record_key_t* key, + int* response) { + + if (enter_ro(handle, dbase) < 0) + goto err; + + /* Stub */ + key = NULL; + response = NULL; + + exit_ro(handle, dbase); + return STATUS_SUCCESS; + + err: + /* FIXME: handle error condition */ + exit_ro(handle, dbase); + return STATUS_ERR; +} + +static int dbase_dir_add( + semanage_handle_t* handle, + dbase_dir_t* dbase, + record_key_t* key, + record_t* data) { + + int exists; + + if (enter_rw(handle, dbase) < 0) + goto err; + + if (dbase_dir_exists(handle, dbase, key, &exists) < 0) + goto err; + + else if (exists) { + /* FIXME: handle error condition */ + goto err; + } + + /* Stub */ + data = NULL; + return STATUS_SUCCESS; + + err: + /* FIXME: handle error condition */ + return STATUS_ERR; +} + +static int dbase_dir_modify( + semanage_handle_t* handle, + dbase_dir_t* dbase, + record_key_t* key, + record_t* data) { + + if (enter_rw(handle, dbase) < 0) + goto err; + + /* Stub */ + key = NULL; + data = NULL; + return STATUS_SUCCESS; + + err: + /* FIXME: handle error condition */ + return STATUS_ERR; +} + +static int dbase_dir_count( + semanage_handle_t* handle, + dbase_dir_t* dbase, + int* response) { + + if (enter_ro(handle, dbase) < 0) + goto err; + + /* Stub */ + response = NULL; + + exit_ro(handle, dbase); + return STATUS_SUCCESS; + + err: + /* FIXME: Handle error condition */ + exit_ro(handle, dbase); + return STATUS_ERR; +} + +static int dbase_dir_query( + semanage_handle_t* handle, + dbase_dir_t* dbase, + record_key_t* key, + record_t** response) { + + if (enter_ro(handle, dbase) < 0) + goto err; + + /* Stub */ + key = NULL; + response = NULL; + + exit_ro(handle, dbase); + return STATUS_SUCCESS; + + err: + /* FIXME: Handle error condition */ + exit_ro(handle, dbase); + return STATUS_ERR; +} + +static int dbase_dir_iterate( + semanage_handle_t* handle, + dbase_dir_t* dbase, + int (*fn) (record_t* record, void* fn_arg), + void* arg) { + + if (enter_ro(handle, dbase) < 0) + goto err; + + /* Stub */ + fn = NULL; + arg = NULL; + + exit_ro(handle, dbase); + return STATUS_SUCCESS; + + err: + /* FIXME: Handle error condition */ + exit_ro(handle, dbase); + return STATUS_ERR; +} + +static int dbase_dir_del( + semanage_handle_t* handle, + dbase_dir_t* dbase, + record_key_t* key) { + + if (enter_rw(handle, dbase) < 0) + goto err; + + /* Stub */ + key = NULL; + return STATUS_SUCCESS; + + err: + /* FIXME: Handle error condition */ + return STATUS_ERR; +} + +static int dbase_dir_list( + semanage_handle_t* handle, + dbase_dir_t* dbase, + record_t*** records, + size_t* count) { + + if (enter_ro(handle, dbase) < 0) + goto err; + + /* Stub */ + records = NULL; + count = NULL; + + exit_ro(handle, dbase); + return STATUS_SUCCESS; + + err: + exit_ro(handle, dbase); + /* FIXME: handle error condition */ + return STATUS_ERR; +} + + +/* DIRECTORY dbase - method table implementation */ +dbase_table_t SEMANAGE_DIR_DTABLE = { + .drop_cache = dbase_dir_drop_cache, + .flush = dbase_dir_flush, + .iterate = dbase_dir_iterate, + .exists = dbase_dir_exists, + .list = dbase_dir_list, + .add = dbase_dir_add, + .del = dbase_dir_del, + .modify = dbase_dir_modify, + .query = dbase_dir_query, + .count = dbase_dir_count, +}; diff -Naur --exclude ChangeLog --exclude VERSION --exclude CVS libsemanage/src/database_directory.h libsemanage.new/src/database_directory.h --- libsemanage/src/database_directory.h 1969-12-31 19:00:00.000000000 -0500 +++ libsemanage.new/src/database_directory.h 2005-10-15 06:38:23.000000000 -0400 @@ -0,0 +1,25 @@ +#ifndef _SEMANAGE_DATABASE_DIRECTORY_INTERNAL_H_ +#define _SEMANAGE_DATABASE_DIRECTORY_INTERNAL_H_ + +#include <stdio.h> +#include "database.h" +#include "handle.h" + +struct dbase_dir; +typedef struct dbase_dir dbase_dir_t; + +/* DIRECTORY - initialization */ +extern int dbase_dir_init( + const char* suffix, + record_table_t* rtable, + dbase_dir_t** dbase); + +/* DIRECTORY - release */ +extern void dbase_dir_release( + semanage_handle_t* handle, + dbase_dir_t* dbase); + +/* DIRECTORY - method table implementation */ +extern dbase_table_t SEMANAGE_DIR_DTABLE; + +#endif diff -Naur --exclude ChangeLog --exclude VERSION --exclude CVS libsemanage/src/module_record.c libsemanage.new/src/module_record.c --- libsemanage/src/module_record.c 1969-12-31 19:00:00.000000000 -0500 +++ libsemanage.new/src/module_record.c 2005-10-15 06:44:25.000000000 -0400 @@ -0,0 +1,172 @@ +#include <stdlib.h> +#include <string.h> + +#include <semanage/module_record.h> +#include "debug.h" +#include "handle.h" + +struct semanage_module { + /* This module's name */ + char* name; + + /* This module's version */ + char* version; + + /* FIXME: Add data fields here */ +}; + +struct semanage_module_key { + /* This module's name */ + const char* name; +}; + +int semanage_module_key_create( + semanage_handle_t* handle, + const char* name, + semanage_module_key_t** key_ptr) { + + semanage_module_key_t* tmp_key = + (semanage_module_key_t*) + malloc(sizeof (semanage_module_key_t)); + + if (!tmp_key) { + ERR(handle, "out of memory, could not create module key"); + return STATUS_ERR; + } + tmp_key->name = name; + + *key_ptr = tmp_key; + return STATUS_SUCCESS; +} + +int semanage_module_key_extract( + semanage_handle_t* handle, + semanage_module_t* module, + semanage_module_key_t** key_ptr) { + + if (semanage_module_key_create(handle, module->name, key_ptr) < 0) { + ERR(handle, "could not extract key from module %s", + module->name); + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +void semanage_module_key_free(semanage_module_key_t* key) { + free(key); +} + +int semanage_module_compare( + semanage_module_t* module, + semanage_module_key_t* key) { + + if (!strcmp(module->name, key->name)) + return 0; + return 1; +} + +/* Name */ +#if 0 /* FIXME: conflict with modules.h */ +const char* semanage_module_get_name( + semanage_module_t* module) { + + return module->name; +} + +int semanage_module_set_name( + semanage_handle_t* handle, + semanage_module_t* module, + const char* name) { + + module->name = strdup(name); + if (!module->name) { + ERR(handle, "out of memory, could not set name"); + return STATUS_ERR; + } + return STATUS_SUCCESS; +} + +/* Version */ +const char* semanage_module_get_version( + semanage_module_t* module) { + + return module->version; +} + +int semanage_module_set_version( + semanage_handle_t* handle, + semanage_module_t* module, + const char* version) { + + module->version = strdup(version); + if (!module->version) { + ERR(handle, "out of memory, could not set version"); + return STATUS_ERR; + } + return STATUS_SUCCESS; +} +#endif + +/* Create */ +int semanage_module_create( + semanage_handle_t* handle, + semanage_module_t** module_ptr) { + + semanage_module_t* module = + (semanage_module_t*) malloc(sizeof (semanage_module_t)); + + if (!module) { + ERR(handle, "out of memory, " + "could not create module record"); + return STATUS_ERR; + } + + module->name = NULL; + module->version = NULL; + + *module_ptr = module; + return STATUS_SUCCESS; +} + +/* Deep copy clone */ +int semanage_module_clone( + semanage_handle_t* handle, + semanage_module_t* module, + semanage_module_t** module_ptr) { + + semanage_module_t* new_module = NULL; + + if (semanage_module_create(handle, &new_module) < 0) + goto err; + +#if 0 /* FIXME: conflict with modules.h */ + if (semanage_module_set_name(handle, new_module, module->name) < 0) + goto err; + + if (semanage_module_set_version(handle, new_module, + module->version) < 0) + goto err; +#endif + module = NULL; + + *module_ptr = new_module; + return STATUS_SUCCESS; + + err: + ERR(handle, "could not clone module record"); + semanage_module_free(new_module); + return STATUS_ERR; +} + +/* Destroy */ +void semanage_module_free( + semanage_module_t* module) { + + if (!module) + return; + + free(module->name); + free(module->version); + free(module); +} ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [ SEMANAGE ] Add a few direct dbases to handle 2005-10-15 11:34 ` Ivan Gyurdiev @ 2005-10-15 11:38 ` Ivan Gyurdiev 0 siblings, 0 replies; 12+ messages in thread From: Ivan Gyurdiev @ 2005-10-15 11:38 UTC (permalink / raw) To: Ivan Gyurdiev; +Cc: selinux, Karl MacMillan, Joshua Brindle, Stephen Smalley > > By "backend-independent record code" I mean, being able to add a user, > and not care where the user is stored.. being able to loop over the > seuser mappings, and not care whether the data is coming from LDAP or > the seusers file, because all I want to do is load it into policy. Well, we wouldn't be loading the seusers into policy, but that's not important - the point is... backend separation. An example that makes sense would be looping over the seusers to find the ones that would be affected, if, say, I revoked the staff_r role, or changed some other policy thing that would affect seusers. -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message. ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2005-10-15 11:38 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-10-14 18:16 [ SEMANAGE ] Add a few direct dbases to handle Ivan Gyurdiev 2005-10-14 18:39 ` [ SEMANAGE ] Bugfix previous patches Ivan Gyurdiev 2005-10-14 20:08 ` Stephen Smalley 2005-10-14 20:20 ` [ SEMANAGE ] Add a few direct dbases to handle Joshua Brindle 2005-10-14 20:40 ` Ivan Gyurdiev 2005-10-14 20:45 ` Ivan Gyurdiev 2005-10-14 20:39 ` Joshua Brindle 2005-10-14 20:59 ` Ivan Gyurdiev 2005-10-14 21:06 ` Joshua Brindle 2005-10-14 21:40 ` Ivan Gyurdiev 2005-10-15 11:34 ` Ivan Gyurdiev 2005-10-15 11:38 ` Ivan Gyurdiev
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.