* SELinux userspace infrastructure language @ 2007-05-31 17:35 Joshua Brindle 2007-05-31 17:47 ` Karl MacMillan 0 siblings, 1 reply; 35+ messages in thread From: Joshua Brindle @ 2007-05-31 17:35 UTC (permalink / raw) To: selinux; +Cc: Karl MacMillan, Stephen Smalley Some discussion has started off-list about what language to use for the implementation of the new policy intermediary format and we'd like to bring this discussion into the community to get feedback from users and other developers. In the policyrep branch we've basically started taking OOisms and pythonisms and reimplementing them in C which is non-ideal. There is also madness behind the string handling in some newer work we are doing. We discussed the possibility of using python or C++ for our libraries so that they are more represenative of the datastructures that are being created elsewhere and being reimplemented in C. Libsemanage could easily be implemented in pure python, it doesn't do much hard work, libsepol, on the other hand, is used by a lot of external stuff so it's a more difficult sell. It would be nice to potentially use the STL for a lot of the stuff we are doing in libsepol. Libsemanage need not be rewritten immediately (or at all if not considered a necessity) but the new policy representation work will be happening in the near term so the language chosen for it will immediately be used. This language would be required for any systems with managed policies (eg., using policy modules and semanage) so that is something to be considered. What are some opinions from users and other people developing systems with SELinux? -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-05-31 17:35 SELinux userspace infrastructure language Joshua Brindle @ 2007-05-31 17:47 ` Karl MacMillan 2007-05-31 17:54 ` Joshua Brindle 2007-05-31 18:00 ` SELinux userspace infrastructure language Chad Sellers 0 siblings, 2 replies; 35+ messages in thread From: Karl MacMillan @ 2007-05-31 17:47 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley On Thu, 2007-05-31 at 13:35 -0400, Joshua Brindle wrote: > Some discussion has started off-list about what language to use for the > implementation of the new policy intermediary format and we'd like to > bring this discussion into the community to get feedback from users and > other developers. > > In the policyrep branch we've basically started taking OOisms and > pythonisms and reimplementing them in C which is non-ideal. No pythonisms that I am aware of (and I have avoided them). > There is > also madness behind the string handling in some newer work we are doing. > We discussed the possibility of using python or C++ for our libraries so > that they are more represenative of the datastructures that are being > created elsewhere and being reimplemented in C. > > Libsemanage could easily be implemented in pure python, it doesn't do > much hard work, libsepol, on the other hand, is used by a lot of > external stuff so it's a more difficult sell. It would be nice to > potentially use the STL for a lot of the stuff we are doing in libsepol. > > Libsemanage need not be rewritten immediately (or at all if not > considered a necessity) but the new policy representation work will be > happening in the near term so the language chosen for it will > immediately be used. This language would be required for any systems > with managed policies (eg., using policy modules and semanage) so that > is something to be considered. > To make this more concrete, there are two basic options (as I see it): 1) adopt sepolgen as the new policyrep and implement the policy compilers on top of that. The policyrep branch is in some senses a port of part of sepolgen. 2) Keep going with policyrep, but in C++. 1 is less work but harder for cross-language development. 2 is much more work, potentially forever. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-05-31 17:47 ` Karl MacMillan @ 2007-05-31 17:54 ` Joshua Brindle 2007-05-31 19:31 ` Karl MacMillan 2007-05-31 19:45 ` Stephen Bennett 2007-05-31 18:00 ` SELinux userspace infrastructure language Chad Sellers 1 sibling, 2 replies; 35+ messages in thread From: Joshua Brindle @ 2007-05-31 17:54 UTC (permalink / raw) To: Karl MacMillan; +Cc: selinux, Stephen Smalley Karl MacMillan wrote: > On Thu, 2007-05-31 at 13:35 -0400, Joshua Brindle wrote: >> Some discussion has started off-list about what language to use for >> the implementation of the new policy intermediary format and we'd >> like to bring this discussion into the community to get feedback >> from users and other developers. >> >> In the policyrep branch we've basically started taking OOisms and >> pythonisms and reimplementing them in C which is non-ideal. > > No pythonisms that I am aware of (and I have avoided them). Fine, more OOisms though. > >> There is >> also madness behind the string handling in some newer work we are >> doing. We discussed the possibility of using python or C++ for our >> libraries so that they are more represenative of the datastructures >> that are being created elsewhere and being reimplemented in C. >> >> Libsemanage could easily be implemented in pure python, it doesn't do >> much hard work, libsepol, on the other hand, is used by a lot of >> external stuff so it's a more difficult sell. It would be nice to >> potentially use the STL for a lot of the stuff we are doing in >> libsepol. >> >> Libsemanage need not be rewritten immediately (or at all if not >> considered a necessity) but the new policy representation work will >> be happening in the near term so the language chosen for it will >> immediately be used. This language would be required for any systems >> with managed policies (eg., using policy modules and semanage) so >> that is something to be considered. >> > > To make this more concrete, there are two basic options (as I see it): > Agreed. > 1) adopt sepolgen as the new policyrep and implement the > policy compilers on top of that. The policyrep branch is in > some senses a port of part of sepolgen. > 2) Keep going with policyrep, but in C++. > > 1 is less work but harder for cross-language development. 2 > is much more work, potentially forever. > So, the new representation should make it much easier to interact with parts of policy and hopefully users will come (and continue) to do policy analysis, generation, writing, etc using these representations that we are making. My main concern is that us doing it in python basically puts a huge damper on what our users will do (eg., who are we to say someone writing an analysis tool can't use haskell if they want ;) ). SLIDE, which will become increasingly important IMO, is in java which /can/ use python (using jython) but I am under the impression there are risks of incompatibilities and a huge lag in support. Setools also wants to use the new representation to do analysis of the policy (and SLIDE wants to integrate with setools for debugging assistance), all of this is made possible by the new representation but using python inherently limits what they can do. Given all this I think C++ is the best bet, though I'm not adverse to most of the frontends being written in python, it would just be nice if the actual policy representation and accessors are available from a shared library API that most languages can use. -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-05-31 17:54 ` Joshua Brindle @ 2007-05-31 19:31 ` Karl MacMillan 2007-06-04 22:24 ` Karl MacMillan 2007-05-31 19:45 ` Stephen Bennett 1 sibling, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-05-31 19:31 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley On Thu, 2007-05-31 at 13:54 -0400, Joshua Brindle wrote: > Karl MacMillan wrote: > > On Thu, 2007-05-31 at 13:35 -0400, Joshua Brindle wrote: > >> Some discussion has started off-list about what language to use for > >> the implementation of the new policy intermediary format and we'd > >> like to bring this discussion into the community to get feedback > >> from users and other developers. > >> > >> In the policyrep branch we've basically started taking OOisms and > >> pythonisms and reimplementing them in C which is non-ideal. > > > > No pythonisms that I am aware of (and I have avoided them). > > Fine, more OOisms though. > > > > >> There is > >> also madness behind the string handling in some newer work we are > >> doing. We discussed the possibility of using python or C++ for our > >> libraries so that they are more represenative of the datastructures > >> that are being created elsewhere and being reimplemented in C. > >> > >> Libsemanage could easily be implemented in pure python, it doesn't do > >> much hard work, libsepol, on the other hand, is used by a lot of > >> external stuff so it's a more difficult sell. It would be nice to > >> potentially use the STL for a lot of the stuff we are doing in > >> libsepol. > >> > >> Libsemanage need not be rewritten immediately (or at all if not > >> considered a necessity) but the new policy representation work will > >> be happening in the near term so the language chosen for it will > >> immediately be used. This language would be required for any systems > >> with managed policies (eg., using policy modules and semanage) so > >> that is something to be considered. > >> > > > > To make this more concrete, there are two basic options (as I see it): > > > > Agreed. > > > 1) adopt sepolgen as the new policyrep and implement the > > policy compilers on top of that. The policyrep branch is in > > some senses a port of part of sepolgen. > > 2) Keep going with policyrep, but in C++. > > > > 1 is less work but harder for cross-language development. 2 > > is much more work, potentially forever. > > > > So, the new representation should make it much easier to interact with > parts of policy and hopefully users will come (and continue) to do > policy analysis, generation, writing, etc using these representations > that we are making. My main concern is that us doing it in python > basically puts a huge damper on what our users will do (eg., who are we > to say someone writing an analysis tool can't use haskell if they want > ;) ). SLIDE, which will become increasingly important IMO, is in java > which /can/ use python (using jython) but I am under the impression > there are risks of incompatibilities and a huge lag in support. > > Setools also wants to use the new representation to do analysis of the > policy (and SLIDE wants to integrate with setools for debugging > assistance), all of this is made possible by the new representation but > using python inherently limits what they can do. > > Given all this I think C++ is the best bet, though I'm not adverse to > most of the frontends being written in python, it would just be nice if > the actual policy representation and accessors are available from a > shared library API that most languages can use. > I'm basically OK with this approach with some caveats / concerns: 1) We need to allow the use of the boost libraries, particularly boost::python. Wrapping C++ with boost::python gets you a lot for very little code (and a fair amount of CPU usage during compile). I think it is _much_ better than swig for creating idiomatic bindings. Many of the other libraries are excellent and, in my opinion, indispensable for C++ work. 2) How are we going to proceed with the development? Create a brand new library in C++ and pull in parts of libsepol as needed? I guess we would simultaneously rip out parts of the current libsepol that are no longer needed. 3) We should adopt some C++ coding standards before development starts to avoid really bad C++. I still think we should consider sepolgen, but C++ may be the best choice. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-05-31 19:31 ` Karl MacMillan @ 2007-06-04 22:24 ` Karl MacMillan 2007-06-05 0:52 ` Joshua Brindle 0 siblings, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-06-04 22:24 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley On Thu, 2007-05-31 at 15:31 -0400, Karl MacMillan wrote: > On Thu, 2007-05-31 at 13:54 -0400, Joshua Brindle wrote: > > Karl MacMillan wrote: [...] > > > > > 1) adopt sepolgen as the new policyrep and implement the > > > policy compilers on top of that. The policyrep branch is in > > > some senses a port of part of sepolgen. > > > 2) Keep going with policyrep, but in C++. > > > > > > 1 is less work but harder for cross-language development. 2 > > > is much more work, potentially forever. > > > > > > > So, the new representation should make it much easier to interact with > > parts of policy and hopefully users will come (and continue) to do > > policy analysis, generation, writing, etc using these representations > > that we are making. My main concern is that us doing it in python > > basically puts a huge damper on what our users will do (eg., who are we > > to say someone writing an analysis tool can't use haskell if they want > > ;) ). SLIDE, which will become increasingly important IMO, is in java > > which /can/ use python (using jython) but I am under the impression > > there are risks of incompatibilities and a huge lag in support. > > > > Setools also wants to use the new representation to do analysis of the > > policy (and SLIDE wants to integrate with setools for debugging > > assistance), all of this is made possible by the new representation but > > using python inherently limits what they can do. > > > > Given all this I think C++ is the best bet, though I'm not adverse to > > most of the frontends being written in python, it would just be nice if > > the actual policy representation and accessors are available from a > > shared library API that most languages can use. > > > > I'm basically OK with this approach with some caveats / concerns: > > 1) We need to allow the use of the boost libraries, particularly > boost::python. Wrapping C++ with boost::python gets you a lot for very > little code (and a fair amount of CPU usage during compile). I think it > is _much_ better than swig for creating idiomatic bindings. Many of the > other libraries are excellent and, in my opinion, indispensable for C++ > work. > > 2) How are we going to proceed with the development? Create a brand new > library in C++ and pull in parts of libsepol as needed? I guess we would > simultaneously rip out parts of the current libsepol that are no longer > needed. > > 3) We should adopt some C++ coding standards before development starts > to avoid really bad C++. > > I still think we should consider sepolgen, but C++ may be the best > choice. > To explore this, I coded up some basic ideas in C++ to get a feel for the time savings (patch below). What I came up with allows you to do this: int main(int argc, char **arv) { shared_ptr<Policy> pol(new Policy()); shared_ptr<Module> mod(new Module("foo", "1.0")); pol->append_child(mod); shared_ptr<Type> type(new Type("foo")); type->aliases().insert("bar"); type->aliases().insert("baz"); type->aliases().insert("bar"); // duplicate - will be ingored type->attributes().insert("domain"); type->attributes().insert("userdomain"); mod->append_child(type); output_tree(std::cout, *pol); } Which outputs: module foo 1.0; type foo alias { bar baz }, domain, userdomain; Notes: * This took the better part of two days, though a fair amount of that time was spent remembering how C++ worked and looking at new boost libraries. * The shared_ptr business gives us reference counting, so that when the top-level node (pol in this example) is deleted / goes out of scope the rest of the tree is destroyed. This is a very standard technique, but I can remove it if it is too strange for people. On the other hand I had no memory leaks in the initial version. * This is basically equivalent to where the policyrep branch is today - so there is a huge savings in development time with C++. Having lists, vectors, sets, etc. all int the stl helps immensely. * Parts of this are _much_ better than the C equivalent in ways that are very hard to duplicate. The output, for example, is simple and shared for file, stream, and string output. * Most of this is pretty standard - any C++ coder would be able to get up to speed quickly. * The biggest drawback is, as usual, that some problems caused long and mysterious compiler errors (including nested template insanity out of some of the boost libraries). I'm pretty used to this but non-C++ programmers might be put off by this. I also did serialization using the boost serialization library. This allows us to do: [...] save_policy(*pol, "archive"); shared_ptr<Policy> newpol(new Policy()); load_policy(*newpol, "archive"); output_tree(std::cout, *newpol, DEBUG_OUTPUT); The serialization is pretty easy - for example, serializing "Type" is done with (this works for both saving and loading): template<class Archive> void Type::serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object<Node>(*this); ar & m_name; ar & m_attributes; ar & m_aliases; } Finally, I made Python bindings using Boost::Python. The result is Python bindings that are _easy_ to make and very idiomatic. For example, Type needs (plus a few simple helpers and the wrapping for Node): class_<StringSet>("StringSet") .def("add", &set_insert) .def("discard", &set_erase) .def("__str__", &set_to_string) .def("__repr__", &set_to_string) .def("__iter__", range(&StringSet::begin, &StringSet::end)) ; class_<Type, bases<Node> >("Type") .add_property("name", &Type::get_name, &Type::set_name) .add_property("aliases" , make_function( &Type::aliases, return_value_policy<reference_existing_object>() )) .add_property("attributes" , make_function( &Type::attributes, return_value_policy<reference_existing_object>() )) ; Which yields bindings that allow you to do: import policyrep t = policyrep.Type() t.name = "user_t" t.aliases.add("foo") t.aliases.add("bar") for a in t.aliases: print a These bindings are much better than what you can get out of swig with much less work. The tradeoff is that they use deep and mysterious C++ magic, which sometimes makes the compiler very unhappy. This has basically convinced me that C++ is the way to go (or to put it another way - please, oh, please don't make me write any more C code). Thoughts? Karl ----- Makefile | 2 libpolicyrep/Makefile | 22 + libpolicyrep/include/Makefile | 10 libpolicyrep/include/policyrep/policy.hpp | 175 ++++++++++++ libpolicyrep/src/Makefile | 66 ++++ libpolicyrep/src/policy.cpp | 422 ++++++++++++++++++++++++++++++ libpolicyrep/src/policyrep_python.cpp | 75 +++++ libpolicyrep/tests/Makefile | 24 + libpolicyrep/tests/libpolicyrep-test.cpp | 38 ++ 9 files changed, 833 insertions(+), 1 deletion(-) diff -r 83885c13a34d Makefile --- a/Makefile Mon Jun 04 13:24:11 2007 -0400 +++ b/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ -1,4 +1,4 @@ SUBDIRS=libsepol libselinux libsemanage -SUBDIRS=libsepol libselinux libsemanage sepolgen checkpolicy policycoreutils # policy +SUBDIRS=libsepol libselinux libsemanage libpolicyrep sepolgen checkpolicy policycoreutils # policy PYSUBDIRS=libselinux libsemanage ifeq ($(DEBUG),1) diff -r 83885c13a34d libpolicyrep/Makefile --- a/libpolicyrep/Makefile Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ -0,0 +1,22 @@ +all: + $(MAKE) -C src + +install: + $(MAKE) -C include install + $(MAKE) -C src install + +relabel: + $(MAKE) -C src relabel + +clean: + $(MAKE) -C src clean + $(MAKE) -C tests clean + +indent: + $(MAKE) -C src $@ + $(MAKE) -C include $@ + $(MAKE) -C utils $@ + +test: + $(MAKE) -C tests test + diff -r 83885c13a34d libpolicyrep/include/Makefile --- a/libpolicyrep/include/Makefile Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/include/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ -0,0 +1,10 @@ +# Installation directories. +PREFIX ?= $(DESTDIR)/usr +INCDIR ?= $(PREFIX)/include/policyrep + +install: + test -d $(INCDIR) || install -m 755 -d $(INCDIR) + install -m 644 $(wildcard policyrep/*.hpp) $(INCDIR) + +indent: + ../../scripts/Lindent $(wildcard policyrep/*.hpp) diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 16:25:23 2007 -0400 @@ -0,0 +1,175 @@ +#include <vector> +#include <list> +#include <set> +#include <string> + +#include <boost/shared_ptr.hpp> + +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/serialization/vector.hpp> +#include <boost/serialization/list.hpp> +#include <boost/serialization/set.hpp> +#include <boost/serialization/shared_ptr.hpp> + +namespace policyrep { + + class Node; + class Parent; + + typedef boost::shared_ptr<Node> NodePtr; + + enum OutputStyle { DEFAULT_OUTPUT, DEBUG_OUTPUT }; + + class Node { + public: + Node(); + virtual ~Node() { }; + + void set_parent(Parent* p); + Parent* get_parent() const; + + bool get_visited() const; + void set_visited(bool val); + + friend std::ostream& operator<<(std::ostream& o, const Node& n); + virtual void output(std::ostream& o, enum OutputStyle style=DEFAULT_OUTPUT) const; + virtual void output_end(std::ostream& o, enum OutputStyle style=DEFAULT_OUTPUT) const; + virtual void output_end_brace(std::ostream& o, enum OutputStyle style=DEFAULT_OUTPUT) const; + std::string to_string() const; + std::string to_string_end() const; + protected: + Parent* m_parent; + int m_flags; + static const int VISITED = 1; + private: + friend class boost::serialization::access; + template<class Archive> + void serialize(Archive& ar, const unsigned int version); + }; + + typedef std::vector<NodePtr> NodeVector; + typedef std::set<std::string> StringSet; + + std::ostream& operator<<(std::ostream& o, const Node& n); + + class Output { + public: + Output(const Node &n, bool end=false, enum OutputStyle style=DEFAULT_OUTPUT); + friend std::ostream& operator<<(std::ostream& o, const Output& op); + private: + const Node& m_n; + bool m_end; + enum OutputStyle m_style; + }; + + void output_set_space(std::ostream& o, const StringSet& set); + void output_set_comma(std::ostream& o, const StringSet& set); + + class TreeIterator + : public boost::iterator_facade<TreeIterator, Node, + boost::forward_traversal_tag> + { + public: + enum Strategy { POSTORDER, PREORDER, HYBRID }; + TreeIterator(enum Strategy strategy=POSTORDER); + explicit TreeIterator(Node& n, enum Strategy strategy=POSTORDER); + + bool get_visited() const; + private: + friend class boost::iterator_core_access; + void increment(); + void increment_preorder(); + void increment_postorder(); + bool equal(const TreeIterator& other) const; + Node& dereference() const; + + int m_strategy; + std::list<Node*> m_stack; + Node* m_cur; + bool m_visited; + }; + + class Parent : public Node { + public: + typedef TreeIterator iterator; + virtual void append_child(NodePtr node); + virtual NodeVector& children(); + + iterator begin(enum TreeIterator::Strategy strategy=TreeIterator::POSTORDER); + iterator end(); + protected: + NodeVector m_children; + private: + friend class boost::serialization::access; + template<class Archive> + void serialize(Archive& ar, const unsigned int version); + }; + + void output_tree(std::ostream& o, Parent& p, + enum OutputStyle style=DEFAULT_OUTPUT); + + class Policy : public Parent { + public: + Policy(bool mls=false); + virtual ~Policy() { }; + + bool get_mls() const; + void set_mls(bool val); + virtual void output(std::ostream& o, enum OutputStyle style=DEFAULT_OUTPUT) const; + protected: + bool m_mls; + private: + friend class boost::serialization::access; + template<class Archive> + void serialize(Archive& ar, const unsigned int version); + }; + + class Module : public Parent { + public: + Module() { }; + Module(std::string name, std::string version); + virtual ~Module() { }; + + std::string get_name() const; + void set_name(std::string name); + std::string get_version() const; + void set_version(std::string version); + + virtual void output(std::ostream& o, enum OutputStyle style=DEFAULT_OUTPUT) const; + protected: + std::string m_name; + std::string m_version; + private: + friend class boost::serialization::access; + template<class Archive> + void serialize(Archive& ar, const unsigned int version); + }; + + void save_policy(const Policy& p, std::string filename); + void load_policy(Policy& p, std::string filename); + + class Type : public Node { + public: + Type() { }; + Type(std::string name); + + std::string get_name() const; + void set_name(std::string name); + + virtual ~Type() { }; + StringSet& aliases(); + StringSet& attributes(); + virtual void output(std::ostream& o, enum OutputStyle style=DEFAULT_OUTPUT) const; + protected: + std::string m_name; + StringSet m_attributes; + StringSet m_aliases; + private: + friend class boost::serialization::access; + template<class Archive> + void serialize(Archive& ar, const unsigned int version); + }; +} diff -r 83885c13a34d libpolicyrep/src/Makefile --- a/libpolicyrep/src/Makefile Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/src/Makefile Mon Jun 04 16:15:40 2007 -0400 @@ -0,0 +1,66 @@ +# Installation directories. +PREFIX ?= $(DESTDIR)/usr +LIBDIR ?= $(PREFIX)/lib +SHLIBDIR ?= $(DESTDIR)/lib + +PYLIBVER ?= $(shell python -c 'import sys;print "python%d.%d" % sys.version_info[0:2]') +PYINC ?= /usr/include/$(PYLIBVER) +PYLIB ?= /usr/lib/$(PYLIBVER) +PYTHONLIBDIR ?= $(LIBDIR)/$(PYLIBVER) +PYTHONCPP=policyrep_python.cpp +PYTHONLOBJ=policyrep_python.lo +PYTHONSO=policyrep.so + +LIBVERSION = 1 + +LIBA=libpolicyrep.a +TARGET=libpolicyrep.so +LIBSO=$(TARGET).$(LIBVERSION) +OBJS= $(patsubst %.cpp,%.o,$(filter-out $(PYTHONCPP), $(wildcard *.cpp))) +LOBJS= $(patsubst %.cpp,%.lo,$(filter-out $(PYTHONCPP), $(wildcard *.cpp))) +CFLAGS ?= -Wall -W -Wundef -Wmissing-format-attribute -Wno-unused-parameter +override CFLAGS += -I. -I../include -D_GNU_SOURCE +LDFLAGS += -lboost_serialization + +all: $(LIBA) $(LIBSO) $(PYTHONSO) + +$(LIBA): $(OBJS) + $(AR) rcs $@ $^ + ranlib $@ + +$(LIBSO): $(LOBJS) + g++ $(LDFLAGS) -shared -o $@ $^ -Wl,-soname,$(LIBSO) + ln -sf $@ $(TARGET) + +$(PYTHONSO): $(PYTHONLOBJ) + g++ $(LDFLAGS) -lboost_python -shared -o $@ $< $(LOBJS) -Wl,-soname,$@ + +$(PYTHONLOBJ): $(PYTHONCPP) + g++ $(CFLAGS) -I$(PYINC) -fPIC -DSHARED -c -o $@ $< + +%.o: %.cpp + g++ $(CFLAGS) -fPIC -c -o $@ $< + +%.lo: %.cpp + g++ $(CFLAGS) -fPIC -DSHARED -c -o $@ $< + +install: all install-pywrap + test -d $(LIBDIR) || install -m 755 -d $(LIBDIR) + install -m 644 $(LIBA) $(LIBDIR) + test -d $(SHLIBDIR) || install -m 755 -d $(SHLIBDIR) + install -m 755 $(LIBSO) $(SHLIBDIR) + cd $(LIBDIR) && ln -sf ../../`basename $(SHLIBDIR)`/$(LIBSO) $(TARGET) + +install-pywrap: + test -d $(PYTHONLIBDIR)/site-packages || install -m 755 -d $(PYTHONLIBDIR)/site-packages + install -m 755 $(PYTHONSO) $(PYTHONLIBDIR)/site-packages + +relabel: + /sbin/restorecon $(SHLIBDIR)/$(LIBSO) + +clean: + -rm -f $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(PYTHONSO) $(PYTHONLOBJ) + +indent: + ../../scripts/Lindent $(wildcard *.cpp) + diff -r 83885c13a34d libpolicyrep/src/policy.cpp --- a/libpolicyrep/src/policy.cpp Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/src/policy.cpp Mon Jun 04 16:25:11 2007 -0400 @@ -0,0 +1,422 @@ +#include <policyrep/policy.hpp> + +#include <iostream> +#include <algorithm> +#include <fstream> +#include <sstream> + +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> + +namespace policyrep { + +// +// Node +// + +Node::Node() +: m_flags(0) { } + +void Node::set_parent(Parent* parent) +{ + m_parent = parent; +} + +Parent* Node::get_parent() const +{ + return m_parent; +} + +bool Node::get_visited() const +{ + return m_flags & VISITED; +} + +void Node::set_visited(bool val) +{ + if (val) + m_flags |= VISITED; + else + m_flags &= ~VISITED; +} + +void Node::output(std::ostream& o, enum OutputStyle style) const +{ + if (style == DEBUG_OUTPUT) + o << "[Node " << this << "]"; +} + +void Node::output_end(std::ostream& o, enum OutputStyle style) const +{ + switch (style) { + case DEFAULT_OUTPUT: + break; + case DEBUG_OUTPUT: + o << "[END " << typeid(this).name() << " " << this << "]"; + }; +} + +void Node::output_end_brace(std::ostream& o, enum OutputStyle style) const +{ + switch (style) { + case DEFAULT_OUTPUT: + o << "}"; + break; + case DEBUG_OUTPUT: + o << "} [" << typeid(this).name() << " " << this << "]"; + }; +} + +std::string Node::to_string() const +{ + std::stringstream s; + s << *this; + return s.str(); +} + +std::string Node::to_string_end() const +{ + std::stringstream s; + s << Output(*this, true, DEFAULT_OUTPUT); + return s.str(); +} + +const int Node::VISITED; + +template<class Archive> +void Node::serialize(Archive& ar, const unsigned int version) +{ + //if (m_parent) + // ar & m_parent; + ar & m_flags; +} + +std::ostream& operator<<(std::ostream& o, const Node& n) +{ + n.output(o); + return o; +} + +Output::Output(const Node &n, bool end, enum OutputStyle style) +: m_n(n), m_end(end), m_style(style) { } + +std::ostream& operator<<(std::ostream& o, const Output& op) +{ + if (op.m_end) + op.m_n.output_end(o, op.m_style); + else + op.m_n.output(o, op.m_style); + return o; +} + +void output_set_space(std::ostream& o, const StringSet& set) +{ + if (set.size() > 1) + o << "{ "; + StringSet::const_iterator i; + bool first = true; + for (i = set.begin(); i != set.end(); ++i) { + if (first) + first = false; + else + o << " "; + o << *i; + } + if (set.size() > 1) + o << " }"; +} + +void output_set_comma(std::ostream& o, const StringSet& set) +{ + StringSet::const_iterator i; + bool first = true; + for (i = set.begin(); i != set.end(); ++i) { + if (first) + first = false; + else + o << ", "; + o << *i; + } +} + +// +// TreeIterator +// + +TreeIterator::TreeIterator(enum Strategy strategy) +: m_strategy(strategy), m_cur(0) { } + +TreeIterator::TreeIterator(Node& n, enum Strategy strategy) +: m_strategy(strategy), m_cur(&n) +{ + n.set_visited(false); + m_stack.push_back(&n); + increment(); +} + +bool TreeIterator::get_visited() const +{ + return m_visited; +} + +void TreeIterator::increment() +{ + switch (m_strategy) { + case POSTORDER: + this->increment_postorder(); + break; + case PREORDER: + case HYBRID: + this->increment_preorder(); + break; + }; +} + +void TreeIterator::increment_preorder() +{ + if (m_stack.empty()) { + m_cur = NULL; + return; + } + m_cur = m_stack.back(); + m_visited = m_cur->get_visited(); + m_stack.pop_back(); + + Parent* p = dynamic_cast<Parent*>(m_cur); + if (p and !p->get_visited()) { + if (m_strategy == HYBRID) { + p->set_visited(true); + m_stack.push_back(m_cur); + } + NodeVector::reverse_iterator i; + for (i = p->children().rbegin(); i != p->children().rend(); ++i) { + (*i)->set_visited(false); + m_stack.push_back(i->get()); + } + } +} + +void TreeIterator::increment_postorder() +{ + while (1) { + if (m_stack.empty()) { + m_cur = NULL; + return; + } + Node* n = m_stack.back(); + m_stack.pop_back(); + + Parent* p = dynamic_cast<Parent*>(n); + if (n->get_visited() || p == 0) { + m_cur = n; + break; + } else { + p->set_visited(true); + m_stack.push_back(n); + NodeVector::reverse_iterator i; + for (i = p->children().rbegin(); i != p->children().rend(); ++i) { + (*i)->set_visited(false); + m_stack.push_back(i->get()); + } + } + } +} + +bool TreeIterator::equal(const TreeIterator& other) const +{ + return m_cur == other.m_cur; +} + +Node& TreeIterator::dereference() const +{ + return *m_cur; +} + +// +// Parent +// + +void Parent::append_child(NodePtr node) +{ + m_children.push_back(node); + node->set_parent(this); +} + +NodeVector& Parent::children() +{ + return m_children; +} + +Parent::iterator Parent::begin(enum TreeIterator::Strategy strategy) +{ + return TreeIterator(*this, strategy); +} + +Parent::iterator Parent::end() +{ + return TreeIterator(); +} + +template<class Archive> +void Parent::serialize(Archive& ar, const unsigned int version) +{ + ar & boost::serialization::base_object<Node>(*this); + ar & m_children; +} + +void output_tree(std::ostream& o, Parent& p, + enum OutputStyle style) +{ + Parent::iterator i, end; + end = p.end(); + for (i = p.begin(TreeIterator::HYBRID); i != end; ++i) { + o << Output(*i, i.get_visited(), style) << "\n"; + } + o << std::flush; +} + +// +// Policy +// + +Policy::Policy(bool mls) +: m_mls(mls) { } + +bool Policy::get_mls() const +{ + return m_mls; +} + +void Policy::set_mls(bool val) +{ + m_mls = val; +} + +void Policy::output(std::ostream& o, enum OutputStyle style) const +{ + if (style == DEBUG_OUTPUT) + o << "[Policy " << this << "]"; +} + +template<class Archive> +void Policy::serialize(Archive& ar, const unsigned int version) +{ + ar.register_type(static_cast<Node*>(NULL)); + ar.register_type(static_cast<Parent*>(NULL)); + ar.register_type(static_cast<Module*>(NULL)); + ar.register_type(static_cast<Type*>(NULL)); + ar & boost::serialization::base_object<Parent>(*this); + ar & m_mls; +} + +void save_policy(const Policy& p, std::string filename) +{ + std::ofstream fout(filename.c_str()); + boost::archive::text_oarchive ar(fout); + ar << p; +} + +void load_policy(Policy& p, std::string filename) +{ + std::ifstream fin(filename.c_str(), std::ios::binary); + boost::archive::text_iarchive ia(fin); + ia >> p; +} + +// +// Module +// + +Module::Module(std::string name, std::string version) +: m_name(name), m_version(version) { } + +std::string Module::get_name() const +{ + return m_name; +} + +void Module::set_name(std::string name) +{ + m_name = name; +} + +std::string Module::get_version() const +{ + return m_version; +} + +void Module::set_version(std::string version) +{ + m_version = version; +} + +void Module::output(std::ostream& o, enum OutputStyle style) const +{ + if (style == DEBUG_OUTPUT) + o << "[MODULE " << this << "]"; + o << "module " << m_name << " " << m_version << ";"; +} + +template<class Archive> +void Module::serialize(Archive& ar, const unsigned int version) +{ + ar & boost::serialization::base_object<Parent>(*this); + ar & m_name; + ar & m_version; +} + +// +// Type +// + +Type::Type(std::string name) +: m_name(name) { } + +std::string Type::get_name() const +{ + return m_name; +} + +void Type::set_name(std::string name) +{ + m_name = name; +} + +StringSet& Type::aliases() +{ + return m_aliases; +} + +StringSet& Type::attributes() +{ + return m_attributes; +} + +void Type::output(std::ostream& o, enum OutputStyle style) const +{ + if (style == DEBUG_OUTPUT) + o << "[TYPE " << this << "]"; + + o << "type " << m_name; + if (!m_aliases.empty()) { + o << " alias "; + output_set_space(o, m_aliases); + } + if (!m_attributes.empty()) { + o << ", "; + output_set_comma(o, m_attributes); + } + o << ";"; +} + +template<class Archive> +void Type::serialize(Archive& ar, const unsigned int version) +{ + ar & boost::serialization::base_object<Node>(*this); + ar & m_name; + ar & m_attributes; + ar & m_aliases; +} + + +} // namespace policyrep diff -r 83885c13a34d libpolicyrep/src/policyrep_python.cpp --- a/libpolicyrep/src/policyrep_python.cpp Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/src/policyrep_python.cpp Mon Jun 04 18:11:20 2007 -0400 @@ -0,0 +1,75 @@ +#include <sstream> + +#include <policyrep/policy.hpp> +using namespace policyrep; + +#include <boost/python.hpp> +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +using namespace boost::python; + +void set_insert(StringSet &s, const char* c) { s.insert(c); } +void set_erase(StringSet &s, const char* c) { s.erase(c); } +std::string set_to_string(const StringSet &s) { + std::stringstream ss; + ss << "StringSet(["; + bool first = true; + for (StringSet::const_iterator i = s.begin(); i != s.end(); ++i) { + if (first) + first = false; + else + ss << ", "; + ss << "'" << *i << "'"; + } + ss << "])"; + return ss.str(); +} + +BOOST_PYTHON_MODULE(policyrep) +{ + class_<Node>("Node") + .def("get_parent", &Node::get_parent, return_value_policy<reference_existing_object>()) + .def("set_parent", &Node::set_parent)//, return_value_policy<reference_existing_object>()) + .add_property("visited", &Node::get_visited, &Node::set_visited) + .def("__str__", &Node::to_string) + .def("to_string_end", &Node::to_string_end) + ; + + class_<NodeVector>("NodeVector") + .def(vector_indexing_suite<NodeVector, true>()) + ; + + class_<Parent, bases<Node> >("Parent") + //.def("append_child", &Parent::append_child) + .def("children", &Parent::children, return_value_policy<reference_existing_object>()) + ; + + class_<Policy, bases<Parent> >("Policy") + .add_property("mls", &Policy::get_mls, &Policy::set_mls) + ; + + + class_<Module, bases<Parent> >("Module") + .add_property("name", &Module::get_name, &Module::set_name) + .add_property("version", &Module::get_version, &Module::set_version) + ; + + class_<StringSet>("StringSet") + .def("add", &set_insert) + .def("discard", &set_erase) + .def("__str__", &set_to_string) + .def("__repr__", &set_to_string) + .def("__iter__", range(&StringSet::begin, &StringSet::end)) + ; + + class_<Type, bases<Node> >("Type") + .add_property("name", &Type::get_name, &Type::set_name) + .add_property("aliases" + , make_function( + &Type::aliases, return_value_policy<reference_existing_object>() + )) + .add_property("attributes" + , make_function( + &Type::attributes, return_value_policy<reference_existing_object>() + )) + ; +} diff -r 83885c13a34d libpolicyrep/tests/Makefile --- a/libpolicyrep/tests/Makefile Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/tests/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ -0,0 +1,24 @@ +M4 ?= m4 +MKDIR ?= mkdir +EXE ?= libpolicyrep-test + +CFLAGS += -g3 -gdwarf-2 -o0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter -Werror -I../include + +LIBPOLICYREP := ../src/libpolicyrep.a + +# test program object files +objs := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) + +all: $(EXE) + +$(EXE): $(objs) $(LIBPOLICYREP) + g++ $(CFLAGS) $(objs) $(LIBPOLICYREP) -lboost_serialization -o $@ + +%.o: %.cpp + g++ $(CFLAGS) -fPIC -c -o $@ $< + +clean: + rm -f $(objs) $(EXE) + +test: $(EXE) + ./$(EXE) diff -r 83885c13a34d libpolicyrep/tests/libpolicyrep-test.cpp --- a/libpolicyrep/tests/libpolicyrep-test.cpp Mon Jun 04 13:24:11 2007 -0400 +++ b/libpolicyrep/tests/libpolicyrep-test.cpp Mon Jun 04 15:58:15 2007 -0400 @@ -0,0 +1,38 @@ +#include <policyrep/policy.hpp> + +#include <iostream> +#include <sstream> + +using namespace policyrep; +using boost::shared_ptr; + +int main(int argc, char **argv) +{ + shared_ptr<Policy> pol(new Policy()); + shared_ptr<Module> mod(new Module("foo", "1.0")); + pol->append_child(mod); + shared_ptr<Type> type(new Type("foo")); + type->aliases().insert("bar"); + type->aliases().insert("baz"); + type->aliases().insert("bar"); // duplicate - will be ingored + type->attributes().insert("domain"); + type->attributes().insert("userdomain"); + + mod->append_child(type); + + output_tree(std::cout, *pol); + + std::stringstream s; + output_tree(s, *pol, DEBUG_OUTPUT); + std::cout << s.str() << std::endl; + + std::cout << "saving" << std::endl; + save_policy(*pol, "archive"); + + shared_ptr<Policy> newpol(new Policy()); + std::cout << "loading" << std::endl; + load_policy(*newpol, "archive"); + output_tree(std::cout, *newpol, DEBUG_OUTPUT); + + return 0; +} -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-04 22:24 ` Karl MacMillan @ 2007-06-05 0:52 ` Joshua Brindle 2007-06-04 16:49 ` Karl MacMillan 0 siblings, 1 reply; 35+ messages in thread From: Joshua Brindle @ 2007-06-05 0:52 UTC (permalink / raw) To: Karl MacMillan; +Cc: selinux, Stephen Smalley Karl MacMillan wrote: <snip> > > To explore this, I coded up some basic ideas in C++ to get a > feel for the time savings (patch below). What I came up with > allows you to do > this: > > int main(int argc, char **arv) > { > shared_ptr<Policy> pol(new Policy()); > shared_ptr<Module> mod(new Module("foo", "1.0")); > pol->append_child(mod); > shared_ptr<Type> type(new Type("foo")); > type->aliases().insert("bar"); > type->aliases().insert("baz"); > type->aliases().insert("bar"); // duplicate - will be ingored > type->attributes().insert("domain"); > type->attributes().insert("userdomain"); > Interesting, you didn't create attributes/aliases as a proper type? They are just strings associated with types? I'm not adverse to this, I'm just noting that it's a large difference from what we are doing now. > mod->append_child(type); > > output_tree(std::cout, *pol); > } > > Which outputs: > > module foo 1.0; > type foo alias { bar baz }, domain, userdomain; > > Notes: > > * This took the better part of two days, though a fair amount > of that time was spent remembering how C++ worked and looking > at new boost libraries. > > * The shared_ptr business gives us reference counting, so > that when the top-level node (pol in this example) is deleted > / goes out of scope the rest of the tree is destroyed. This > is a very standard technique, but I can remove it if it is > too strange for people. On the other hand I had no memory > leaks in the initial version. > > * This is basically equivalent to where the policyrep branch > is today - so there is a huge savings in development time > with C++. Having lists, vectors, sets, etc. all int the stl > helps immensely. > Sounds good > * Parts of this are _much_ better than the C equivalent in > ways that are very hard to duplicate. The output, for > example, is simple and shared for file, stream, and string output. > > * Most of this is pretty standard - any C++ coder would be > able to get up to speed quickly. > > * The biggest drawback is, as usual, that some problems > caused long and mysterious compiler errors (including nested > template insanity out of some of the boost libraries). I'm > pretty used to this but non-C++ programmers might be put off by this. > > I also did serialization using the boost serialization > library. This allows us to do: > Does this mean binary serialization? Is the serialization stable (between versions of boost, even major versions?) Will we be able to use this serialization for everything including reading/writing binary modules, reading/writing to sockets? > [...] > save_policy(*pol, "archive"); > > shared_ptr<Policy> newpol(new Policy()); > load_policy(*newpol, "archive"); > output_tree(std::cout, *newpol, DEBUG_OUTPUT); > > The serialization is pretty easy - for example, serializing > "Type" is done with (this works for both saving and loading): > > template<class Archive> > void Type::serialize(Archive& ar, const unsigned int version) { > ar & boost::serialization::base_object<Node>(*this); ar & m_name; > ar & m_attributes; > ar & m_aliases; > } > > Finally, I made Python bindings using Boost::Python. The > result is Python bindings that are _easy_ to make and very > idiomatic. For example, Type needs (plus a few simple helpers > and the wrapping for Node): > > class_<StringSet>("StringSet") > .def("add", &set_insert) > .def("discard", &set_erase) > .def("__str__", &set_to_string) > .def("__repr__", &set_to_string) > .def("__iter__", range(&StringSet::begin, &StringSet::end)) Are those last 3 special functions that are expected to be there by boost? Do we really have to implement our own stringset class? There is nothing in boost or elsewhere that does this really basic stuff? > ; > > class_<Type, bases<Node> >("Type") > .add_property("name", &Type::get_name, &Type::set_name) > .add_property("aliases" > , make_function( > &Type::aliases, > return_value_policy<reference_existing_object>() > )) > .add_property("attributes" > , make_function( > &Type::attributes, > return_value_policy<reference_existing_object>() > )) > ; > > Which yields bindings that allow you to do: > > import policyrep > > t = policyrep.Type() > t.name = "user_t" > t.aliases.add("foo") > t.aliases.add("bar") > > for a in t.aliases: > print a > > These bindings are much better than what you can get out of > swig with much less work. The tradeoff is that they use deep > and mysterious C++ magic, which sometimes makes the compiler > very unhappy. > They do look much better, what do you mean unhappy? > This has basically convinced me that C++ is the way to go (or > to put it another way - please, oh, please don't make me > write any more C code). > Thoughts? > Great news :) > Karl > > ----- > > Makefile | 2 > libpolicyrep/Makefile | 22 + > libpolicyrep/include/Makefile | 10 > libpolicyrep/include/policyrep/policy.hpp | 175 ++++++++++++ > libpolicyrep/src/Makefile | 66 ++++ > libpolicyrep/src/policy.cpp | 422 > ++++++++++++++++++++++++++++++ > libpolicyrep/src/policyrep_python.cpp | 75 +++++ > libpolicyrep/tests/Makefile | 24 + > libpolicyrep/tests/libpolicyrep-test.cpp | 38 ++ > 9 files changed, 833 insertions(+), 1 deletion(-) > > > diff -r 83885c13a34d Makefile > --- a/Makefile Mon Jun 04 13:24:11 2007 -0400 > +++ b/Makefile Mon Jun 04 13:24:13 2007 -0400 > @@ -1,4 +1,4 @@ SUBDIRS=libsepol libselinux libsemanage > -SUBDIRS=libsepol libselinux libsemanage sepolgen checkpolicy > policycoreutils # policy +SUBDIRS=libsepol libselinux libsemanage > libpolicyrep sepolgen +checkpolicy policycoreutils # policy > PYSUBDIRS=libselinux libsemanage > > ifeq ($(DEBUG),1) > diff -r 83885c13a34d libpolicyrep/Makefile > --- a/libpolicyrep/Makefile Mon Jun 04 13:24:11 2007 -0400 > +++ b/libpolicyrep/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ -0,0 > +1,22 @@ +all: > + $(MAKE) -C src > + > +install: > + $(MAKE) -C include install > + $(MAKE) -C src install > + > +relabel: > + $(MAKE) -C src relabel > + > +clean: > + $(MAKE) -C src clean > + $(MAKE) -C tests clean > + > +indent: > + $(MAKE) -C src $@ > + $(MAKE) -C include $@ > + $(MAKE) -C utils $@ > + > +test: > + $(MAKE) -C tests test > + > diff -r 83885c13a34d libpolicyrep/include/Makefile > --- a/libpolicyrep/include/Makefile Mon Jun 04 13:24:11 2007 -0400 > +++ b/libpolicyrep/include/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ > -0,0 +1,10 @@ +# Installation directories. > +PREFIX ?= $(DESTDIR)/usr > +INCDIR ?= $(PREFIX)/include/policyrep > + > +install: > + test -d $(INCDIR) || install -m 755 -d $(INCDIR) > + install -m 644 $(wildcard policyrep/*.hpp) $(INCDIR) + > +indent: > + ../../scripts/Lindent $(wildcard policyrep/*.hpp) > diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp > --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 13:24:11 > 2007 -0400 +++ b/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 So this is exported and stable? We never previously exported the policydb, is this intentional? > 16:25:23 2007 -0400 @@ -0,0 +1,175 @@ > +#include <vector> > +#include <list> > +#include <set> > +#include <string> > + > +#include <boost/shared_ptr.hpp> > + > +#include <boost/iterator/iterator_facade.hpp> > + > +#include <boost/archive/text_oarchive.hpp> #include > +<boost/archive/text_iarchive.hpp> > +#include <boost/serialization/vector.hpp> #include > +<boost/serialization/list.hpp> #include > <boost/serialization/set.hpp> > +#include <boost/serialization/shared_ptr.hpp> > + > +namespace policyrep { > + > + class Node; > + class Parent; > + > + typedef boost::shared_ptr<Node> NodePtr; > + > + enum OutputStyle { DEFAULT_OUTPUT, DEBUG_OUTPUT }; + > + class Node { > + public: > + Node(); > + virtual ~Node() { }; > + > + void set_parent(Parent* p); > + Parent* get_parent() const; > + > + bool get_visited() const; > + void set_visited(bool val); > + > + friend std::ostream& Oh, this is going to be fun to learn :) > operator<<(std::ostream& o, const Node& n); > + virtual void output(std::ostream& o, enum > OutputStyle style=DEFAULT_OUTPUT) const; Yep.. Fun > + virtual void output_end(std::ostream& o, > enum OutputStyle style=DEFAULT_OUTPUT) const; > + virtual void output_end_brace(std::ostream& > o, enum OutputStyle style=DEFAULT_OUTPUT) const; > + std::string to_string() const; > + std::string to_string_end() const; + > protected: + Parent* m_parent; > + int m_flags; > + static const int VISITED = 1; > + private: > + friend class boost::serialization::access; > + template<class Archive> > + void serialize(Archive& ar, const unsigned int version); + > }; + > + typedef std::vector<NodePtr> NodeVector; > + typedef std::set<std::string> StringSet; > + > + std::ostream& operator<<(std::ostream& o, const Node& n); + Are you overloading the << operator? I thought we weren't going to overload operators. > + class Output { > + public: > + Output(const Node &n, bool end=false, enum > OutputStyle style=DEFAULT_OUTPUT); > + friend std::ostream& > operator<<(std::ostream& o, const Output& op); > + private: > + const Node& m_n; > + bool m_end; > + enum OutputStyle m_style; > + }; > + > + void output_set_space(std::ostream& o, const StringSet& set); > + void output_set_comma(std::ostream& o, const StringSet& > set); + + class TreeIterator > + : public boost::iterator_facade<TreeIterator, Node, + > boost::forward_traversal_tag> > + { > + public: > + enum Strategy { POSTORDER, PREORDER, HYBRID }; > + TreeIterator(enum Strategy strategy=POSTORDER); > + explicit TreeIterator(Node& n, enum Strategy + > strategy=POSTORDER); + > + bool get_visited() const; > + private: > + friend class boost::iterator_core_access; > + void increment(); > + void increment_preorder(); > + void increment_postorder(); > + bool equal(const TreeIterator& other) const; > + Node& dereference() const; > + > + int m_strategy; > + std::list<Node*> m_stack; > + Node* m_cur; > + bool m_visited; > + }; > + > + class Parent : public Node { > + public: > + typedef TreeIterator iterator; > + virtual void append_child(NodePtr node); > + virtual NodeVector& children(); > + > + iterator begin(enum TreeIterator::Strategy > strategy=TreeIterator::POSTORDER); > + iterator end(); > + protected: > + NodeVector m_children; > + private: > + friend class boost::serialization::access; > + template<class Archive> > + void serialize(Archive& ar, const unsigned int > version); > + }; > + > + void output_tree(std::ostream& o, Parent& p, > + enum OutputStyle style=DEFAULT_OUTPUT); > + > + class Policy : public Parent { > + public: > + Policy(bool mls=false); > + virtual ~Policy() { }; > + > + bool get_mls() const; > + void set_mls(bool val); > + virtual void output(std::ostream& o, enum > OutputStyle style=DEFAULT_OUTPUT) const; > + protected: > + bool m_mls; > + private: > + friend class boost::serialization::access; > + template<class Archive> > + void serialize(Archive& ar, const unsigned int version); + }; > + > + class Module : public Parent { > + public: > + Module() { }; > + Module(std::string name, std::string version); > + virtual ~Module() { }; > + > + std::string get_name() const; > + void set_name(std::string name); > + std::string get_version() const; > + void set_version(std::string version); + > + virtual void output(std::ostream& o, enum > OutputStyle style=DEFAULT_OUTPUT) const; > + protected: > + std::string m_name; > + std::string m_version; > + private: > + friend class boost::serialization::access; > + template<class Archive> > + void serialize(Archive& ar, const unsigned int version); + > }; + > + void save_policy(const Policy& p, std::string filename); > + void load_policy(Policy& p, std::string filename); + > + class Type : public Node { > + public: > + Type() { }; > + Type(std::string name); > + > + std::string get_name() const; > + void set_name(std::string name); > + > + virtual ~Type() { }; > + StringSet& aliases(); > + StringSet& attributes(); > + virtual void output(std::ostream& o, enum > OutputStyle style=DEFAULT_OUTPUT) const; > + protected: > + std::string m_name; > + StringSet m_attributes; > + StringSet m_aliases; > + private: > + friend class boost::serialization::access; > + template<class Archive> > + void serialize(Archive& ar, const unsigned int version); + > }; +} > diff -r 83885c13a34d libpolicyrep/src/Makefile > --- a/libpolicyrep/src/Makefile Mon Jun 04 13:24:11 2007 -0400 > +++ b/libpolicyrep/src/Makefile Mon Jun 04 16:15:40 2007 -0400 @@ > -0,0 +1,66 @@ +# Installation directories. > +PREFIX ?= $(DESTDIR)/usr > +LIBDIR ?= $(PREFIX)/lib > +SHLIBDIR ?= $(DESTDIR)/lib > + > +PYLIBVER ?= $(shell python -c 'import sys;print "python%d.%d" % > +sys.version_info[0:2]') PYINC ?= /usr/include/$(PYLIBVER) PYLIB ?= > +/usr/lib/$(PYLIBVER) PYTHONLIBDIR ?= $(LIBDIR)/$(PYLIBVER) > +PYTHONCPP=policyrep_python.cpp PYTHONLOBJ=policyrep_python.lo > +PYTHONSO=policyrep.so + > +LIBVERSION = 1 > + > +LIBA=libpolicyrep.a > +TARGET=libpolicyrep.so > +LIBSO=$(TARGET).$(LIBVERSION) > +OBJS= $(patsubst %.cpp,%.o,$(filter-out $(PYTHONCPP), $(wildcard > +*.cpp))) LOBJS= $(patsubst %.cpp,%.lo,$(filter-out $(PYTHONCPP), > +$(wildcard *.cpp))) CFLAGS ?= -Wall -W -Wundef > +-Wmissing-format-attribute -Wno-unused-parameter override > CFLAGS += -I. > +-I../include -D_GNU_SOURCE LDFLAGS += -lboost_serialization + > +all: $(LIBA) $(LIBSO) $(PYTHONSO) > + > +$(LIBA): $(OBJS) > + $(AR) rcs $@ $^ > + ranlib $@ > + > +$(LIBSO): $(LOBJS) > + g++ $(LDFLAGS) -shared -o $@ $^ -Wl,-soname,$(LIBSO) + ln -sf $@ > $(TARGET) + > +$(PYTHONSO): $(PYTHONLOBJ) > + g++ $(LDFLAGS) -lboost_python -shared -o $@ $< $(LOBJS) > -Wl,-soname,$@ + > +$(PYTHONLOBJ): $(PYTHONCPP) > + g++ $(CFLAGS) -I$(PYINC) -fPIC -DSHARED -c -o $@ $< + > +%.o: %.cpp > + g++ $(CFLAGS) -fPIC -c -o $@ $< > + > +%.lo: %.cpp > + g++ $(CFLAGS) -fPIC -DSHARED -c -o $@ $< > + > +install: all install-pywrap > + test -d $(LIBDIR) || install -m 755 -d $(LIBDIR) > + install -m 644 $(LIBA) $(LIBDIR) > + test -d $(SHLIBDIR) || install -m 755 -d $(SHLIBDIR) > + install -m 755 $(LIBSO) $(SHLIBDIR) > + cd $(LIBDIR) && ln -sf ../../`basename > $(SHLIBDIR)`/$(LIBSO) $(TARGET) > + > +install-pywrap: > + test -d $(PYTHONLIBDIR)/site-packages || install -m 755 > -d $(PYTHONLIBDIR)/site-packages > + install -m 755 $(PYTHONSO) $(PYTHONLIBDIR)/site-packages + > +relabel: > + /sbin/restorecon $(SHLIBDIR)/$(LIBSO) > + > +clean: > + -rm -f $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(PYTHONSO) > +$(PYTHONLOBJ) + > +indent: > + ../../scripts/Lindent $(wildcard *.cpp) > + > diff -r 83885c13a34d libpolicyrep/src/policy.cpp > --- a/libpolicyrep/src/policy.cpp Mon Jun 04 13:24:11 2007 -0400 > +++ b/libpolicyrep/src/policy.cpp Mon Jun 04 16:25:11 2007 -0400 @@ > -0,0 +1,422 @@ +#include <policyrep/policy.hpp> > + > +#include <iostream> > +#include <algorithm> > +#include <fstream> > +#include <sstream> > + > +#include <boost/archive/text_oarchive.hpp> #include > +<boost/archive/text_iarchive.hpp> > + > +namespace policyrep { > + > +// > +// Node > +// > + > +Node::Node() > +: m_flags(0) { } > + > +void Node::set_parent(Parent* parent) > +{ > + m_parent = parent; > +} > + > +Parent* Node::get_parent() const > +{ > + return m_parent; > +} > + > +bool Node::get_visited() const > +{ > + return m_flags & VISITED; > +} > + > +void Node::set_visited(bool val) > +{ > + if (val) > + m_flags |= VISITED; > + else > + m_flags &= ~VISITED; > +} > + > +void Node::output(std::ostream& o, enum OutputStyle style) const { > + if (style == DEBUG_OUTPUT) + o << "[Node " << this << "]"; > +} > + > +void Node::output_end(std::ostream& o, enum OutputStyle > style) const { > + switch (style) { > + case DEFAULT_OUTPUT: > + break; > + case DEBUG_OUTPUT: > + o << "[END " << typeid(this).name() << " " << this > << "]"; + }; > +} > + > +void Node::output_end_brace(std::ostream& o, enum OutputStyle style) > +const { + switch (style) { > + case DEFAULT_OUTPUT: > + o << "}"; > + break; > + case DEBUG_OUTPUT: > + o << "} [" << typeid(this).name() << " " << > this << "]"; > + }; > +} > + > +std::string Node::to_string() const > +{ > + std::stringstream s; > + s << *this; > + return s.str(); > +} > + > +std::string Node::to_string_end() const { > + std::stringstream s; > + s << Output(*this, true, DEFAULT_OUTPUT); > + return s.str(); > +} > + > +const int Node::VISITED; > + > +template<class Archive> > +void Node::serialize(Archive& ar, const unsigned int version) { + > //if (m_parent) + // ar & m_parent; > + ar & m_flags; > +} > + > +std::ostream& operator<<(std::ostream& o, const Node& n) { + > n.output(o); + return o; > +} > + > +Output::Output(const Node &n, bool end, enum OutputStyle style) > +: m_n(n), m_end(end), m_style(style) { } > + > +std::ostream& operator<<(std::ostream& o, const Output& op) { + > if (op.m_end) + op.m_n.output_end(o, op.m_style); > + else > + op.m_n.output(o, op.m_style); > + return o; > +} > + > +void output_set_space(std::ostream& o, const StringSet& set) { + > if (set.size() > 1) + o << "{ "; > + StringSet::const_iterator i; > + bool first = true; > + for (i = set.begin(); i != set.end(); ++i) { + > if (first) + first = false; > + else > + o << " "; > + o << *i; > + } > + if (set.size() > 1) > + o << " }"; > +} > + > +void output_set_comma(std::ostream& o, const StringSet& set) { > + StringSet::const_iterator i; > + bool first = true; > + for (i = set.begin(); i != set.end(); ++i) { + > if (first) + first = false; > + else > + o << ", "; > + o << *i; > + } > +} > + > +// > +// TreeIterator > +// > + > +TreeIterator::TreeIterator(enum Strategy strategy) > +: m_strategy(strategy), m_cur(0) { } > + > +TreeIterator::TreeIterator(Node& n, enum Strategy strategy) > +: m_strategy(strategy), m_cur(&n) > +{ > + n.set_visited(false); > + m_stack.push_back(&n); > + increment(); > +} > + > +bool TreeIterator::get_visited() const > +{ > + return m_visited; > +} > + > +void TreeIterator::increment() > +{ > + switch (m_strategy) { > + case POSTORDER: > + this->increment_postorder(); > + break; > + case PREORDER: > + case HYBRID: > + this->increment_preorder(); > + break; > + }; > +} > + > +void TreeIterator::increment_preorder() > +{ > + if (m_stack.empty()) { > + m_cur = NULL; > + return; > + } > + m_cur = m_stack.back(); > + m_visited = m_cur->get_visited(); > + m_stack.pop_back(); > + > + Parent* p = dynamic_cast<Parent*>(m_cur); > + if (p and !p->get_visited()) { > + if (m_strategy == HYBRID) { > + p->set_visited(true); > + m_stack.push_back(m_cur); > + } > + NodeVector::reverse_iterator i; > + for (i = p->children().rbegin(); i != > p->children().rend(); ++i) { + > (*i)->set_visited(false); + > m_stack.push_back(i->get()); + } + } > +} > + > +void TreeIterator::increment_postorder() > +{ > + while (1) { > + if (m_stack.empty()) { > + m_cur = NULL; > + return; > + } > + Node* n = m_stack.back(); > + m_stack.pop_back(); > + > + Parent* p = dynamic_cast<Parent*>(n); > + if (n->get_visited() || p == 0) { > + m_cur = n; > + break; > + } else { > + p->set_visited(true); > + m_stack.push_back(n); > + NodeVector::reverse_iterator i; > + for (i = p->children().rbegin(); i > != p->children().rend(); ++i) { > + (*i)->set_visited(false); > + m_stack.push_back(i->get()); + > } + } > + } > +} > + > +bool TreeIterator::equal(const TreeIterator& other) const { > + return m_cur == other.m_cur; > +} > + > +Node& TreeIterator::dereference() const { > + return *m_cur; > +} > + > +// > +// Parent > +// > + > +void Parent::append_child(NodePtr node) { > + m_children.push_back(node); > + node->set_parent(this); > +} > + > +NodeVector& Parent::children() > +{ > + return m_children; > +} > + > +Parent::iterator Parent::begin(enum TreeIterator::Strategy > strategy) { > + return TreeIterator(*this, strategy); } > + > +Parent::iterator Parent::end() > +{ > + return TreeIterator(); > +} > + > +template<class Archive> > +void Parent::serialize(Archive& ar, const unsigned int version) { > + ar & boost::serialization::base_object<Node>(*this); + ar & > m_children; +} > + > +void output_tree(std::ostream& o, Parent& p, > + enum OutputStyle style) > +{ > + Parent::iterator i, end; > + end = p.end(); > + for (i = p.begin(TreeIterator::HYBRID); i != end; ++i) { > + o << Output(*i, i.get_visited(), style) << "\n"; + > } + o << std::flush; > +} > + > +// > +// Policy > +// > + > +Policy::Policy(bool mls) > +: m_mls(mls) { } > + > +bool Policy::get_mls() const > +{ > + return m_mls; > +} > + > +void Policy::set_mls(bool val) > +{ > + m_mls = val; > +} > + > +void Policy::output(std::ostream& o, enum OutputStyle style) const { > + if (style == DEBUG_OUTPUT) + o << "[Policy " << this << "]"; > +} > + > +template<class Archive> > +void Policy::serialize(Archive& ar, const unsigned int version) { > + ar.register_type(static_cast<Node*>(NULL)); > + ar.register_type(static_cast<Parent*>(NULL)); > + ar.register_type(static_cast<Module*>(NULL)); > + ar.register_type(static_cast<Type*>(NULL)); > + ar & boost::serialization::base_object<Parent>(*this); + ar & m_mls; > +} > + > +void save_policy(const Policy& p, std::string filename) { > + std::ofstream fout(filename.c_str()); > + boost::archive::text_oarchive ar(fout); > + ar << p; > +} > + > +void load_policy(Policy& p, std::string filename) { > + std::ifstream fin(filename.c_str(), std::ios::binary); > + boost::archive::text_iarchive ia(fin); > + ia >> p; > +} > + > +// > +// Module > +// > + > +Module::Module(std::string name, std::string version) > +: m_name(name), m_version(version) { } > + > +std::string Module::get_name() const > +{ > + return m_name; > +} > + > +void Module::set_name(std::string name) { > + m_name = name; > +} > + > +std::string Module::get_version() const { > + return m_version; > +} > + > +void Module::set_version(std::string version) { > + m_version = version; > +} > + > +void Module::output(std::ostream& o, enum OutputStyle style) const { > + if (style == DEBUG_OUTPUT) + o << "[MODULE " << this << "]"; > + o << "module " << m_name << " " << m_version << ";"; } + > +template<class Archive> > +void Module::serialize(Archive& ar, const unsigned int version) { > + ar & boost::serialization::base_object<Parent>(*this); + ar & > m_name; + ar & m_version; > +} > + > +// > +// Type > +// > + > +Type::Type(std::string name) > +: m_name(name) { } > + > +std::string Type::get_name() const > +{ > + return m_name; > +} > + > +void Type::set_name(std::string name) > +{ > + m_name = name; > +} > + > +StringSet& Type::aliases() > +{ > + return m_aliases; > +} > + > +StringSet& Type::attributes() > +{ > + return m_attributes; > +} > + > +void Type::output(std::ostream& o, enum OutputStyle style) const { > + if (style == DEBUG_OUTPUT) + o << "[TYPE " << this << "]"; > + > + o << "type " << m_name; > + if (!m_aliases.empty()) { > + o << " alias "; > + output_set_space(o, m_aliases); > + } > + if (!m_attributes.empty()) { > + o << ", "; > + output_set_comma(o, m_attributes); + } > + o << ";"; > +} > + > +template<class Archive> > +void Type::serialize(Archive& ar, const unsigned int version) { > + ar & boost::serialization::base_object<Node>(*this); + ar & m_name; > + ar & m_attributes; > + ar & m_aliases; > +} > + > + > +} // namespace policyrep > diff -r 83885c13a34d libpolicyrep/src/policyrep_python.cpp > --- a/libpolicyrep/src/policyrep_python.cpp Mon Jun 04 13:24:11 2007 > -0400 +++ b/libpolicyrep/src/policyrep_python.cpp Mon Jun 04 18:11:20 > 2007 -0400 @@ -0,0 +1,75 @@ > +#include <sstream> > + > +#include <policyrep/policy.hpp> > +using namespace policyrep; > + > +#include <boost/python.hpp> > +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> > +using namespace boost::python; > + > +void set_insert(StringSet &s, const char* c) { s.insert(c); } void > +set_erase(StringSet &s, const char* c) { s.erase(c); } std::string > +set_to_string(const StringSet &s) { > + std::stringstream ss; > + ss << "StringSet(["; > + bool first = true; > + for (StringSet::const_iterator i = s.begin(); i != > s.end(); ++i) { > + if (first) > + first = false; > + else > + ss << ", "; > + ss << "'" << *i << "'"; > + } > + ss << "])"; > + return ss.str(); > +} > + > +BOOST_PYTHON_MODULE(policyrep) > +{ > + class_<Node>("Node") > + .def("get_parent", &Node::get_parent, > return_value_policy<reference_existing_object>()) > + .def("set_parent", &Node::set_parent)//, > return_value_policy<reference_existing_object>()) > + .add_property("visited", &Node::get_visited, > &Node::set_visited) + .def("__str__", &Node::to_string) > + .def("to_string_end", &Node::to_string_end) + > ; + > + class_<NodeVector>("NodeVector") > + .def(vector_indexing_suite<NodeVector, true>()) + > ; + > + class_<Parent, bases<Node> >("Parent") > + //.def("append_child", &Parent::append_child) > + .def("children", &Parent::children, > return_value_policy<reference_existing_object>()) > + ; > + > + class_<Policy, bases<Parent> >("Policy") > + .add_property("mls", &Policy::get_mls, > &Policy::set_mls) + ; > + > + > + class_<Module, bases<Parent> >("Module") > + .add_property("name", &Module::get_name, > &Module::set_name) + .add_property("version", > &Module::get_version, &Module::set_version) > + ; > + > + class_<StringSet>("StringSet") > + .def("add", &set_insert) > + .def("discard", &set_erase) > + .def("__str__", &set_to_string) > + .def("__repr__", &set_to_string) > + .def("__iter__", range(&StringSet::begin, > &StringSet::end)) + ; > + > + class_<Type, bases<Node> >("Type") > + .add_property("name", &Type::get_name, > &Type::set_name) + .add_property("aliases" > + , make_function( > + &Type::aliases, > return_value_policy<reference_existing_object>() > + )) > + .add_property("attributes" > + , make_function( > + &Type::attributes, > return_value_policy<reference_existing_object>() > + )) > + ; > +} > diff -r 83885c13a34d libpolicyrep/tests/Makefile > --- a/libpolicyrep/tests/Makefile Mon Jun 04 13:24:11 2007 -0400 > +++ b/libpolicyrep/tests/Makefile Mon Jun 04 13:24:13 2007 -0400 @@ > -0,0 +1,24 @@ +M4 ?= m4 > +MKDIR ?= mkdir > +EXE ?= libpolicyrep-test > + > +CFLAGS += -g3 -gdwarf-2 -o0 -Wall -W -Wundef -Wmissing-noreturn > +-Wmissing-format-attribute -Wno-unused-parameter -Werror > -I../include + +LIBPOLICYREP := ../src/libpolicyrep.a > + > +# test program object files > +objs := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) > + > +all: $(EXE) > + > +$(EXE): $(objs) $(LIBPOLICYREP) > + g++ $(CFLAGS) $(objs) $(LIBPOLICYREP) > -lboost_serialization -o $@ > + > +%.o: %.cpp > + g++ $(CFLAGS) -fPIC -c -o $@ $< > + > +clean: > + rm -f $(objs) $(EXE) > + > +test: $(EXE) > + ./$(EXE) > diff -r 83885c13a34d libpolicyrep/tests/libpolicyrep-test.cpp > --- a/libpolicyrep/tests/libpolicyrep-test.cpp Mon Jun 04 13:24:11 > 2007 -0400 +++ b/libpolicyrep/tests/libpolicyrep-test.cpp Mon Jun 04 > 15:58:15 2007 -0400 @@ -0,0 +1,38 @@ > +#include <policyrep/policy.hpp> > + > +#include <iostream> > +#include <sstream> > + > +using namespace policyrep; > +using boost::shared_ptr; > + > +int main(int argc, char **argv) > +{ > + shared_ptr<Policy> pol(new Policy()); > + shared_ptr<Module> mod(new Module("foo", "1.0")); > + pol->append_child(mod); > + shared_ptr<Type> type(new Type("foo")); > + type->aliases().insert("bar"); > + type->aliases().insert("baz"); > + type->aliases().insert("bar"); // duplicate - will be ingored > + type->attributes().insert("domain"); > + type->attributes().insert("userdomain"); > + > + mod->append_child(type); > + > + output_tree(std::cout, *pol); > + > + std::stringstream s; > + output_tree(s, *pol, DEBUG_OUTPUT); > + std::cout << s.str() << std::endl; > + > + std::cout << "saving" << std::endl; > + save_policy(*pol, "archive"); > + > + shared_ptr<Policy> newpol(new Policy()); > + std::cout << "loading" << std::endl; > + load_policy(*newpol, "archive"); > + output_tree(std::cout, *newpol, DEBUG_OUTPUT); + > + return 0; > +} -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-05 0:52 ` Joshua Brindle @ 2007-06-04 16:49 ` Karl MacMillan 2007-06-05 14:19 ` Stephen Smalley 2007-06-05 23:18 ` Joshua Brindle 0 siblings, 2 replies; 35+ messages in thread From: Karl MacMillan @ 2007-06-04 16:49 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > Karl MacMillan wrote: > <snip> > > > > To explore this, I coded up some basic ideas in C++ to get a > > feel for the time savings (patch below). What I came up with > > allows you to do > > this: > > > > int main(int argc, char **arv) > > { > > shared_ptr<Policy> pol(new Policy()); > > shared_ptr<Module> mod(new Module("foo", "1.0")); > > pol->append_child(mod); > > shared_ptr<Type> type(new Type("foo")); > > type->aliases().insert("bar"); > > type->aliases().insert("baz"); > > type->aliases().insert("bar"); // duplicate - will be ingored > > type->attributes().insert("domain"); > > type->attributes().insert("userdomain"); > > > > Interesting, you didn't create attributes/aliases as a proper type? They > are just strings associated with types? I'm not adverse to this, I'm > just noting that it's a large difference from what we are doing now. > It's what I do in sepolgen and what I've done in all of the policyrep patches so far. Note that there will be types for attribute, typealias, and typeattribute statements - my goal is to represent the policy language fairly directly. So far it works well - it makes programmatically manipulating policies really simple. [...] > > > * Parts of this are _much_ better than the C equivalent in > > ways that are very hard to duplicate. The output, for > > example, is simple and shared for file, stream, and string output. > > > > * Most of this is pretty standard - any C++ coder would be > > able to get up to speed quickly. > > > > * The biggest drawback is, as usual, that some problems > > caused long and mysterious compiler errors (including nested > > template insanity out of some of the boost libraries). I'm > > pretty used to this but non-C++ programmers might be put off by this. > > > > I also did serialization using the boost serialization > > library. This allows us to do: > > > > Does this mean binary serialization? Whatever you want - there is binary, text, XML, and you can implement arbitrary formats. The custom format thing is nice - you just need to implement support for built-in types (plus some other low-level stuff) and the library takes care of using that to serialize higher-level types. > Is the serialization stable > (between versions of boost, even major versions?) > I'm still looking into this, but it seems that is the case. > Will we be able to use this serialization for everything including > reading/writing binary modules, reading/writing to sockets? > Yes - should be able to serialize to any stream. You can also start the serialization from any point in the tree (though I believe you have to know the starting type for de-serialization). > > [...] > > save_policy(*pol, "archive"); > > > > shared_ptr<Policy> newpol(new Policy()); > > load_policy(*newpol, "archive"); > > output_tree(std::cout, *newpol, DEBUG_OUTPUT); > > > > The serialization is pretty easy - for example, serializing > > "Type" is done with (this works for both saving and loading): > > > > template<class Archive> > > void Type::serialize(Archive& ar, const unsigned int version) { > > ar & boost::serialization::base_object<Node>(*this); ar & > m_name; > > ar & m_attributes; > > ar & m_aliases; > > } > > > > Finally, I made Python bindings using Boost::Python. The > > result is Python bindings that are _easy_ to make and very > > idiomatic. For example, Type needs (plus a few simple helpers > > and the wrapping for Node): > > > > class_<StringSet>("StringSet") > > .def("add", &set_insert) > > .def("discard", &set_erase) > > .def("__str__", &set_to_string) > > .def("__repr__", &set_to_string) > > .def("__iter__", range(&StringSet::begin, &StringSet::end)) > > Are those last 3 special functions that are expected to be there by > boost? Boost doesn't care - they just make the type behave like a regular python class. > Do we really have to implement our own stringset class? There is > nothing in boost or elsewhere that does this really basic stuff? > I am just wrapping std::set<std::string> which is typedef'd to StringSet, so I didn't implement anything. What is above is pretty fantastic if you ask me (just the iterator mapping is a huge win). But yes, there are easy ways to export container types (through "indexing suites"). For example, a vector of nodes is exported via: class_<NodeVector>("NodeVector") .def(vector_indexing_suite<NodeVector, true>()); That gives you all of special functions that you would expect (and conversion to/from python lists). Unfortunately, there seems to only be support for map and vector types - sets aren't supported, probably because they are less commonly used. > > ; > > > > class_<Type, bases<Node> >("Type") > > .add_property("name", &Type::get_name, &Type::set_name) > > .add_property("aliases" > > , make_function( > > &Type::aliases, > > return_value_policy<reference_existing_object>() > > )) > > .add_property("attributes" > > , make_function( > > &Type::attributes, > > return_value_policy<reference_existing_object>() > > )) > > ; > > > > Which yields bindings that allow you to do: > > > > import policyrep > > > > t = policyrep.Type() > > t.name = "user_t" > > t.aliases.add("foo") > > t.aliases.add("bar") > > > > for a in t.aliases: > > print a > > > > These bindings are much better than what you can get out of > > swig with much less work. The tradeoff is that they use deep > > and mysterious C++ magic, which sometimes makes the compiler > > very unhappy. > > > > They do look much better, And there are some advantages that aren't readily visible - like there are none of those odd swig shadow types. This creates real new-style python classes directly. > what do you mean unhappy? > Ummm - you just have to see it to believe it :) For example, changing true to false in the vector example above causes the error message at the bottom of this email. The good news, though, is that once you get things right everything works well. Part of the advantage to boost::python is that it is uses the C++ compiler to introspect the classes / functions at compile time to generate the bindings. That means that all of the C++ type information is available (unlike swig - which can't fully parse and understand the semantics of C or C++). The downside is that the compilation can consume huge amounts of cpu / memory and generate bizarre errors if the code is wrong. > > This has basically convinced me that C++ is the way to go (or > > to put it another way - please, oh, please don't make me > > write any more C code). > > Thoughts? > > > > Great news :) > I assume that means you think this is the way to go? Steve - any thoughts? [...] > > diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp > > --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 > 13:24:11 > > 2007 -0400 +++ b/libpolicyrep/include/policyrep/policy.hpp Mon > Jun > 04 > > So this is exported and stable? We never previously exported the > policydb, is this intentional? > Not yet - but I intend this to be stable. That is one of the things we need to consider - C++ is not the best for ABI compatibility. I think we can make reasonable API/ABI guarantees for stable versions while still making more changes than we make to libselinux/libsepol (since it will be selinux tools linking to this library I think they will be more tolerant to changes). [...] > > + std::ostream& operator<<(std::ostream& o, const Node& n); + > > Are you overloading the << operator? I thought we weren't going to > overload operators. > Overloading << is pretty much required for efficient use of streams. It allows you to do: policyrep::Type t; std::cout << t << std::endl; I'm not really a fan of operator overloading in general, but in this case I think it is worthwhile. And because of the friend function hack in the base class we only need to do it in on place - the subclasses simply override the virtual function "output". Karl Error message from example above: g++ -Wall -W -Wundef -Wmissing-format-attribute -Wno-unused-parameter -I. -I../include -D_GNU_SOURCE -I/usr/include/python2.4 -fPIC -DSHARED -c -o policyrep_python.lo policyrep_python.cpp /usr/include/boost/python/with_custodian_and_ward.hpp: In static member function ‘static PyObject* boost::python::with_custodian_and_ward_postcall<custodian, ward, BasePolicy_>::postcall(const ArgumentPackage&, PyObject*) [with ArgumentPackage = PyObject*, long unsigned int custodian = 0ul, long unsigned int ward = 1ul, BasePolicy_ = boost::python::default_call_policies]’: /usr/include/boost/python/detail/caller.hpp:201: instantiated from ‘PyObject* boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = boost::python::objects::iterator_range<boost::python::return_internal_reference<1ul, boost::python::default_call_policies>, __gnu_cxx::__normal_iterator<boost::shared_ptr<policyrep::Node>*, std::vector<boost::shared_ptr<policyrep::Node>, std::allocator<boost::shared_ptr<policyrep::Node> > > > >::next, Policies = boost::python::return_internal_reference<1ul, boost::python::default_call_policies>, Sig = boost::mpl::vector2<boost::shared_ptr<policyrep::Node>&, boost::python::objects::iterator_range<boost::python::return_internal_reference<1ul, boost::python::default_call_policies>, __gnu_cxx::__normal_iterator<boost::shared_ptr<policyrep::Node>*, std::vector<boost::shared_ptr<policyrep::Node>, std::allocator<boost::shared_ptr<policyrep::Node> > > > >&>]’ /usr/include/boost/python/object/py_function.hpp:38: instantiated from ‘PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<boost::python::objects::iterator_range<boost::python::return_internal_reference<1ul, boost::python::default_call_policies>, __gnu_cxx::__normal_iterator<boost::shared_ptr<policyrep::Node>*, std::vector<boost::shared_ptr<policyrep::Node>, std::allocator<boost::shared_ptr<policyrep::Node> > > > >::next, boost::python::return_internal_reference<1ul, boost::python::default_call_policies>, boost::mpl::vector2<boost::shared_ptr<policyrep::Node>&, boost::python::objects::iterator_range<boost::python::return_internal_reference<1ul, boost::python::default_call_policies>, __gnu_cxx::__normal_iterator<boost::shared_ptr<policyrep::Node>*, std::vector<boost::shared_ptr<policyrep::Node>, std::allocator<boost::shared_ptr<policyrep::Node> > > > >&> >]’ policyrep_python.cpp:74: instantiated from here /usr/include/boost/python/with_custodian_and_ward.hpp:87: warning: comparison of unsigned expression < 0 is always false -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-04 16:49 ` Karl MacMillan @ 2007-06-05 14:19 ` Stephen Smalley 2007-06-05 15:13 ` Karl MacMillan 2007-06-05 23:18 ` Joshua Brindle 1 sibling, 1 reply; 35+ messages in thread From: Stephen Smalley @ 2007-06-05 14:19 UTC (permalink / raw) To: Karl MacMillan; +Cc: Joshua Brindle, selinux On Mon, 2007-06-04 at 12:49 -0400, Karl MacMillan wrote: > On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > > Karl MacMillan wrote: > > > This has basically convinced me that C++ is the way to go (or > > > to put it another way - please, oh, please don't make me > > > write any more C code). > > > Thoughts? > > > > > > > Great news :) > > > > I assume that means you think this is the way to go? Steve - any > thoughts? I'm open to trying it. Time to create a new branch for it? So you would introduce this new library, and prune libsepol down to only dealing with the kernel policy representation? Meanwhile, I suppose I should create a separate branch and replay the setlocaldefs/preservebools changes into it, and we can do the namespace work in that separate branch as well, separately from the policyrep work. -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-05 14:19 ` Stephen Smalley @ 2007-06-05 15:13 ` Karl MacMillan 2007-06-06 12:42 ` Stephen Smalley 0 siblings, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-06-05 15:13 UTC (permalink / raw) To: Stephen Smalley; +Cc: Joshua Brindle, selinux On Tue, 2007-06-05 at 10:19 -0400, Stephen Smalley wrote: > On Mon, 2007-06-04 at 12:49 -0400, Karl MacMillan wrote: > > On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > > > Karl MacMillan wrote: > > > > This has basically convinced me that C++ is the way to go (or > > > > to put it another way - please, oh, please don't make me > > > > write any more C code). > > > > Thoughts? > > > > > > > > > > Great news :) > > > > > > > I assume that means you think this is the way to go? Steve - any > > thoughts? > > I'm open to trying it. Time to create a new branch for it? So you > would introduce this new library, and prune libsepol down to only > dealing with the kernel policy representation? > I think we could continue on the policyrep branch, just pruning libsepol there. > Meanwhile, I suppose I should create a separate branch and replay the > setlocaldefs/preservebools changes into it, and we can do the namespace > work in that separate branch as well, separately from the policyrep > work. > That's fine with me, though I guess it results in two ABI bumps for libsepol. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-05 15:13 ` Karl MacMillan @ 2007-06-06 12:42 ` Stephen Smalley 2007-06-06 14:51 ` Karl MacMillan 0 siblings, 1 reply; 35+ messages in thread From: Stephen Smalley @ 2007-06-06 12:42 UTC (permalink / raw) To: Karl MacMillan; +Cc: Joshua Brindle, selinux On Tue, 2007-06-05 at 11:13 -0400, Karl MacMillan wrote: > On Tue, 2007-06-05 at 10:19 -0400, Stephen Smalley wrote: > > On Mon, 2007-06-04 at 12:49 -0400, Karl MacMillan wrote: > > > On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > > > > Karl MacMillan wrote: > > > > > This has basically convinced me that C++ is the way to go (or > > > > > to put it another way - please, oh, please don't make me > > > > > write any more C code). > > > > > Thoughts? > > > > > > > > > > > > > Great news :) > > > > > > > > > > I assume that means you think this is the way to go? Steve - any > > > thoughts? > > > > I'm open to trying it. Time to create a new branch for it? So you > > would introduce this new library, and prune libsepol down to only > > dealing with the kernel policy representation? > > > > I think we could continue on the policyrep branch, just pruning libsepol > there. Actually, I think I'd rather have a clean slate unless you think you'd be preserving any of the changes you've made to date in policyrep (vs. just reverting/removing all of that code from libsepol). So I'd favor making a clean copy of trunk to a new branch for your new work, and another clean copy of trunk to a separate branch for the other changes. > > Meanwhile, I suppose I should create a separate branch and replay the > > setlocaldefs/preservebools changes into it, and we can do the namespace > > work in that separate branch as well, separately from the policyrep > > work. > > > > That's fine with me, though I guess it results in two ABI bumps for > libsepol. Not necessarily; it depends on how/when we merge to trunk. If the two development efforts turn out to "complete" in the same timeframe or we choose to hold merging of either until the other is "complete", then we can just merge the one branch to the other, and then merge the union to the trunk, only requiring a single ABI bump for the library. -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-06 12:42 ` Stephen Smalley @ 2007-06-06 14:51 ` Karl MacMillan 0 siblings, 0 replies; 35+ messages in thread From: Karl MacMillan @ 2007-06-06 14:51 UTC (permalink / raw) To: Stephen Smalley; +Cc: Joshua Brindle, selinux On Wed, 2007-06-06 at 08:42 -0400, Stephen Smalley wrote: > On Tue, 2007-06-05 at 11:13 -0400, Karl MacMillan wrote: > > On Tue, 2007-06-05 at 10:19 -0400, Stephen Smalley wrote: > > > On Mon, 2007-06-04 at 12:49 -0400, Karl MacMillan wrote: > > > > On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > > > > > Karl MacMillan wrote: > > > > > > This has basically convinced me that C++ is the way to go (or > > > > > > to put it another way - please, oh, please don't make me > > > > > > write any more C code). > > > > > > Thoughts? > > > > > > > > > > > > > > > > Great news :) > > > > > > > > > > > > > I assume that means you think this is the way to go? Steve - any > > > > thoughts? > > > > > > I'm open to trying it. Time to create a new branch for it? So you > > > would introduce this new library, and prune libsepol down to only > > > dealing with the kernel policy representation? > > > > > > > I think we could continue on the policyrep branch, just pruning libsepol > > there. > > Actually, I think I'd rather have a clean slate unless you think you'd > be preserving any of the changes you've made to date in policyrep (vs. > just reverting/removing all of that code from libsepol). So I'd favor > making a clean copy of trunk to a new branch for your new work, and > another clean copy of trunk to a separate branch for the other changes. > Unfortunately, I don't think any of the changes are needed - *sigh*. We can do this when the first set of patches is ready. > > > Meanwhile, I suppose I should create a separate branch and replay the > > > setlocaldefs/preservebools changes into it, and we can do the namespace > > > work in that separate branch as well, separately from the policyrep > > > work. > > > > > > > That's fine with me, though I guess it results in two ABI bumps for > > libsepol. > > Not necessarily; it depends on how/when we merge to trunk. If the two > development efforts turn out to "complete" in the same timeframe or we > choose to hold merging of either until the other is "complete", then we > can just merge the one branch to the other, and then merge the union to > the trunk, only requiring a single ABI bump for the library. > Sounds good - that way if this stupid policyrep work ends up on a debian like release schedule we can still release something in a reasonable time frame. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-04 16:49 ` Karl MacMillan 2007-06-05 14:19 ` Stephen Smalley @ 2007-06-05 23:18 ` Joshua Brindle 2007-06-06 14:48 ` Karl MacMillan 1 sibling, 1 reply; 35+ messages in thread From: Joshua Brindle @ 2007-06-05 23:18 UTC (permalink / raw) To: Karl MacMillan; +Cc: selinux, Stephen Smalley Karl MacMillan wrote: > On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: >> Karl MacMillan wrote: >> <snip> > [...] > >>> diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp >>> --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 >>> 13:24:11 2007 -0400 +++ b/libpolicyrep/include/policyrep/policy.hpp >>> Mon >> Jun >> 04 >> One thing is that I thought you going to separate classes of object into their own files (eg., types.cpp, users.cpp, etc) since you had always complained about them being munged together in libsepol. >> So this is exported and stable? We never previously exported the >> policydb, is this intentional? >> > > Not yet - but I intend this to be stable. That is one of the > things we need to consider - C++ is not the best for ABI > compatibility. I think we can make reasonable API/ABI > guarantees for stable versions while still making more > changes than we make to libselinux/libsepol (since it will be > selinux tools linking to this library I think they will be > more tolerant to changes). > I worry about making the whole policy structure public instead of just the public parts, maybe this isn't something you can do in c++? > [...] > > >>> + std::ostream& operator<<(std::ostream& o, const Node& n); + >> >> Are you overloading the << operator? I thought we weren't going to >> overload operators. >> > > Overloading << is pretty much required for efficient use of > streams. It allows you to do: > > policyrep::Type t; > std::cout << t << std::endl; > > I'm not really a fan of operator overloading in general, but > in this case I think it is worthwhile. And because of the > friend function hack in the base class we only need to do it > in on place - the subclasses simply override the virtual > function "output". > Hrm, so these aren't included in the elusive "stuff we shouldn't do in c++" list? > <snip> > comparison of unsigned expression < 0 is always false Ew. -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-05 23:18 ` Joshua Brindle @ 2007-06-06 14:48 ` Karl MacMillan 2007-06-06 14:59 ` Joshua Brindle 0 siblings, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-06-06 14:48 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley On Tue, 2007-06-05 at 19:18 -0400, Joshua Brindle wrote: > Karl MacMillan wrote: > > On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > >> Karl MacMillan wrote: > >> <snip> > > > [...] > > > >>> diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp > >>> --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 > >>> 13:24:11 2007 -0400 +++ b/libpolicyrep/include/policyrep/policy.hpp > >>> Mon > >> Jun > >> 04 > >> > > One thing is that I thought you going to separate classes of object into > their own files (eg., types.cpp, users.cpp, etc) since you had always > complained about them being munged together in libsepol. > You've got that backwards - I've always complained about too many headers in libsepol (two per object). > >> So this is exported and stable? We never previously exported the > >> policydb, is this intentional? > >> > > > > Not yet - but I intend this to be stable. That is one of the > > things we need to consider - C++ is not the best for ABI > > compatibility. I think we can make reasonable API/ABI > > guarantees for stable versions while still making more > > changes than we make to libselinux/libsepol (since it will be > > selinux tools linking to this library I think they will be > > more tolerant to changes). > > > > I worry about making the whole policy structure public instead of just > the public parts, maybe this isn't something you can do in c++? > Not certain what you mean - you mean the private variables? You can use the PIMPL idiom - http://www.codepedia.com/1/CppPimpl - but I'm not convinced it's worth the pain. After the care we took to hide implementation in libsepol we didn't really make changes that would have broken in the ABI. > > [...] > > > > > >>> + std::ostream& operator<<(std::ostream& o, const Node& n); + > >> > >> Are you overloading the << operator? I thought we weren't going to > >> overload operators. > >> > > > > Overloading << is pretty much required for efficient use of > > streams. It allows you to do: > > > > policyrep::Type t; > > std::cout << t << std::endl; > > > > I'm not really a fan of operator overloading in general, but > > in this case I think it is worthwhile. And because of the > > friend function hack in the base class we only need to do it > > in on place - the subclasses simply override the virtual > > function "output". > > > > Hrm, so these aren't included in the elusive "stuff we shouldn't do in > c++" list? > Nope - this is _very_ standard for C++. Not doing this would be like avoiding printf. > > <snip> > > comparison of unsigned expression < 0 is always false > > Ew. Yep. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-06 14:48 ` Karl MacMillan @ 2007-06-06 14:59 ` Joshua Brindle 2007-06-06 15:18 ` Karl MacMillan 0 siblings, 1 reply; 35+ messages in thread From: Joshua Brindle @ 2007-06-06 14:59 UTC (permalink / raw) To: Karl MacMillan; +Cc: selinux, Stephen Smalley Karl MacMillan wrote: > On Tue, 2007-06-05 at 19:18 -0400, Joshua Brindle wrote: >> Karl MacMillan wrote: >>> On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: >>>> Karl MacMillan wrote: >>>> <snip> >> >>> [...] >>> >>>>> diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp >>>>> --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 >>>>> 13:24:11 2007 -0400 +++ >>>>> b/libpolicyrep/include/policyrep/policy.hpp >>>>> Mon >>>> Jun >>>> 04 >>>> >> >> One thing is that I thought you going to separate classes of object >> into their own files (eg., types.cpp, users.cpp, etc) since you had >> always complained about them being munged together in libsepol. >> > > You've got that backwards - I've always complained about too > many headers in libsepol (two per object). > Nuh uh.. You always said you wanted functions for each object separated out of policydb.c, write.c and so on. You even started this when you did the conditional work and put it in booleans.c instead of policydb.c. Not sure why I'm surprised though, you change your mind more often than anyone I know :) >>>> So this is exported and stable? We never previously exported the >>>> policydb, is this intentional? >>>> >>> >>> Not yet - but I intend this to be stable. That is one of the things >>> we need to consider - C++ is not the best for ABI compatibility. I >>> think we can make reasonable API/ABI guarantees for stable versions >>> while still making more changes than we make to libselinux/libsepol >>> (since it will be selinux tools linking to this library I think they >>> will be more tolerant to changes). >>> >> >> I worry about making the whole policy structure public instead of >> just the public parts, maybe this isn't something you can do in c++? >> > > Not certain what you mean - you mean the private variables? You can > use the PIMPL idiom - http://www.codepedia.com/1/CppPimpl - but I'm > not convinced it's worth the pain. After the care we took to hide > implementation in libsepol we didn't really make changes that would > have broken in the ABI. > Ok, I guess the fact that the variables are all going to be in the private section is good enough since the compiler won't let you directly access them anyway (correct?) >>> [...] >>> >>> >>>>> + std::ostream& operator<<(std::ostream& o, const Node& n); >>>>> + + >>>> >>>> Are you overloading the << operator? I thought we weren't going to >>>> overload operators. >>>> >>> >>> Overloading << is pretty much required for efficient use of >>> streams. It allows you to do: >>> >>> policyrep::Type t; >>> std::cout << t << std::endl; >>> >>> I'm not really a fan of operator overloading in general, but in this >>> case I think it is worthwhile. And because of the friend function >>> hack in the base class we only need to do it in on place - the >>> subclasses simply override the virtual function "output". >>> >> >> Hrm, so these aren't included in the elusive "stuff we shouldn't do >> in c++" list? >> > > Nope - this is _very_ standard for C++. Not doing this would be like > avoiding printf. > Ok, I understand. We are assuming here that all these objects can indeed be printed as a string (which is fair). How does this work with a policy tree, is this essentially how dumping it out as a source policy would work? How are we going to differenciate serializing to strings and serializing to a binary module? Also, how cheap is the binary serializing/unserializing going to be? We don't want it to be equivalent to re-parsing from source (or else there is no reason to have a binary format). Are we going to build compression of the modules in from the get-go to avoid the complaints about oversized modules that we had before? -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-06 14:59 ` Joshua Brindle @ 2007-06-06 15:18 ` Karl MacMillan 2007-06-06 15:28 ` Joshua Brindle 0 siblings, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-06-06 15:18 UTC (permalink / raw) To: Joshua Brindle; +Cc: selinux, Stephen Smalley On Wed, 2007-06-06 at 10:59 -0400, Joshua Brindle wrote: > Karl MacMillan wrote: > > On Tue, 2007-06-05 at 19:18 -0400, Joshua Brindle wrote: > >> Karl MacMillan wrote: > >>> On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: > >>>> Karl MacMillan wrote: > >>>> <snip> > >> > >>> [...] > >>> > >>>>> diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp > >>>>> --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 > >>>>> 13:24:11 2007 -0400 +++ > >>>>> b/libpolicyrep/include/policyrep/policy.hpp > >>>>> Mon > >>>> Jun > >>>> 04 > >>>> > >> > >> One thing is that I thought you going to separate classes of object > >> into their own files (eg., types.cpp, users.cpp, etc) since you had > >> always complained about them being munged together in libsepol. > >> > > > > You've got that backwards - I've always complained about too > > many headers in libsepol (two per object). > > > > Nuh uh.. You always said you wanted functions for each object separated > out of policydb.c, write.c and so on. You even started this when you did > the conditional work and put it in booleans.c instead of policydb.c. > Oh - that. I wanted the functions related to each "object" grouped together rather than spread through separate files. Multiple objects in the same file is preferable unless the file gets too big. > Not sure why I'm surprised though, you change your mind more often than > anyone I know :) > I thought about arguing with you but then I changed my mind. > >>>> So this is exported and stable? We never previously exported the > >>>> policydb, is this intentional? > >>>> > >>> > >>> Not yet - but I intend this to be stable. That is one of the things > >>> we need to consider - C++ is not the best for ABI compatibility. I > >>> think we can make reasonable API/ABI guarantees for stable versions > >>> while still making more changes than we make to libselinux/libsepol > >>> (since it will be selinux tools linking to this library I think they > >>> will be more tolerant to changes). > >>> > >> > >> I worry about making the whole policy structure public instead of > >> just the public parts, maybe this isn't something you can do in c++? > >> > > > > Not certain what you mean - you mean the private variables? You can > > use the PIMPL idiom - http://www.codepedia.com/1/CppPimpl - but I'm > > not convinced it's worth the pain. After the care we took to hide > > implementation in libsepol we didn't really make changes that would > > have broken in the ABI. > > > > Ok, I guess the fact that the variables are all going to be in the > private section is good enough since the compiler won't let you directly > access them anyway (correct?) > It won't (though you can do nasty things to get access if you want). The variables do become part of the ABI though (since classes are glorified structs and access is still based on offset like in C). > >>> [...] > >>> > >>> > >>>>> + std::ostream& operator<<(std::ostream& o, const Node& n); > >>>>> + + > >>>> > >>>> Are you overloading the << operator? I thought we weren't going to > >>>> overload operators. > >>>> > >>> > >>> Overloading << is pretty much required for efficient use of > >>> streams. It allows you to do: > >>> > >>> policyrep::Type t; > >>> std::cout << t << std::endl; > >>> > >>> I'm not really a fan of operator overloading in general, but in this > >>> case I think it is worthwhile. And because of the friend function > >>> hack in the base class we only need to do it in on place - the > >>> subclasses simply override the virtual function "output". > >>> > >> > >> Hrm, so these aren't included in the elusive "stuff we shouldn't do > >> in c++" list? > >> > > > > Nope - this is _very_ standard for C++. Not doing this would be like > > avoiding printf. > > > > Ok, I understand. We are assuming here that all these objects can indeed > be printed as a string (which is fair). How does this work with a policy > tree, is this essentially how dumping it out as a source policy would > work? You have to iterate over the whole tree outputting as you go: void output_tree(std::ostream& o, Parent& p, enum OutputStyle style) { Parent::iterator i, end; end = p.end(); for (i = p.begin(TreeIterator::HYBRID); i != end; ++i) { o << Output(*i, i.get_visited(), style) << "\n"; } o << std::flush; } The Output thing is how you control the output options (I'm not entirely happy with that design, but it is similar to how output formatting is done with streams). It also takes into account whether this is the opening of a block ("if (foo) {") or the closing ("}"). This doesn't yet handle indentation. > How are we going to differenciate serializing to strings and > serializing to a binary module? > The serialization module handles that - it depends on the type on the left. std::cout << foo; // string std::ofstream fout("filename"); boost::archive::text_oarchive ar(fout); ar << p; // serialization - actually calls serialize method > Also, how cheap is the binary serializing/unserializing going to be? We > don't want it to be equivalent to re-parsing from source (or else there > is no reason to have a binary format). It will be pretty cheap - much better than parsing. It should also be a more compact form. > Are we going to build compression > of the modules in from the get-go to avoid the complaints about > oversized modules that we had before? I would like to, but I haven't looked much for compressed streams. Something like http://www.cs.unc.edu/Research/compgeom/gzstream/ might work. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-06 15:18 ` Karl MacMillan @ 2007-06-06 15:28 ` Joshua Brindle 2007-06-06 16:19 ` Stephen Bennett 0 siblings, 1 reply; 35+ messages in thread From: Joshua Brindle @ 2007-06-06 15:28 UTC (permalink / raw) To: Karl MacMillan; +Cc: selinux, Stephen Smalley Karl MacMillan wrote: > On Wed, 2007-06-06 at 10:59 -0400, Joshua Brindle wrote: >> Karl MacMillan wrote: >>> On Tue, 2007-06-05 at 19:18 -0400, Joshua Brindle wrote: >>>> Karl MacMillan wrote: >>>>> On Mon, 2007-06-04 at 20:52 -0400, Joshua Brindle wrote: >>>>>> Karl MacMillan wrote: >>>>>> <snip> >>>> >>>>> [...] >>>>> >>>>>>> diff -r 83885c13a34d libpolicyrep/include/policyrep/policy.hpp >>>>>>> --- a/libpolicyrep/include/policyrep/policy.hpp Mon Jun 04 >>>>>>> 13:24:11 2007 -0400 +++ >>>>>>> b/libpolicyrep/include/policyrep/policy.hpp >>>>>>> Mon >>>>>> Jun >>>>>> 04 >>>>>> >>>> >>>> One thing is that I thought you going to separate classes of object >>>> into their own files (eg., types.cpp, users.cpp, etc) since you had >>>> always complained about them being munged together in libsepol. >>>> >>> >>> You've got that backwards - I've always complained about too many >>> headers in libsepol (two per object). >>> >> >> Nuh uh.. You always said you wanted functions for each object >> separated out of policydb.c, write.c and so on. You even started this >> when you did the conditional work and put it in booleans.c instead >> of policydb.c. >> > > Oh - that. I wanted the functions related to each "object" > grouped together rather than spread through separate files. > Multiple objects in the same file is preferable unless the > file gets too big. > >> Not sure why I'm surprised though, you change your mind more often >> than anyone I know :) >> > > I thought about arguing with you but then I changed my mind. > Touche. >>>>>> So this is exported and stable? We never previously exported the >>>>>> policydb, is this intentional? >>>>>> >>>>> >>>>> Not yet - but I intend this to be stable. That is one of the >>>>> things we need to consider - C++ is not the best for ABI >>>>> compatibility. I think we can make reasonable API/ABI guarantees >>>>> for stable versions while still making more changes than we make >>>>> to libselinux/libsepol (since it will be selinux tools linking to >>>>> this library I think they will be more tolerant to changes). >>>>> >>>> >>>> I worry about making the whole policy structure public instead of >>>> just the public parts, maybe this isn't something you can do in >>>> c++? >>>> >>> >>> Not certain what you mean - you mean the private variables? You can >>> use the PIMPL idiom - http://www.codepedia.com/1/CppPimpl - but I'm >>> not convinced it's worth the pain. After the care we took to hide >>> implementation in libsepol we didn't really make changes that would >>> have broken in the ABI. >>> >> How painful is it? The examples on that page don't look too bad, and they claim it reduces compile time (something you've already griped about) >> Ok, I guess the fact that the variables are all going to be in the >> private section is good enough since the compiler won't let you >> directly access them anyway (correct?) >> > > It won't (though you can do nasty things to get access if you > want). The variables do become part of the ABI though (since > classes are glorified structs and access is still based on > offset like in C). > So are we going to have to pad it to be able to add stuff later on? Would adding something in the public part shift the private part down in a way that would break the ABI? This worries me a bit, I know QT does padding to handle this but I haven't looked at what they do specifically. >>>>> [...] >>>>> >>>>> >>>>>>> + std::ostream& operator<<(std::ostream& o, const Node& >>>>>>> + n); + + >>>>>> >>>>>> Are you overloading the << operator? I thought we weren't going >>>>>> to overload operators. >>>>>> >>>>> >>>>> Overloading << is pretty much required for efficient use of >>>>> streams. It allows you to do: >>>>> >>>>> policyrep::Type t; >>>>> std::cout << t << std::endl; >>>>> >>>>> I'm not really a fan of operator overloading in general, but in >>>>> this case I think it is worthwhile. And because of the friend >>>>> function hack in the base class we only need to do it in on place >>>>> - the subclasses simply override the virtual function "output". >>>>> >>>> >>>> Hrm, so these aren't included in the elusive "stuff we shouldn't >>>> do in c++" list? >>>> >>> >>> Nope - this is _very_ standard for C++. Not doing this would be >>> like avoiding printf. >>> >> >> Ok, I understand. We are assuming here that all these objects can >> indeed be printed as a string (which is fair). How does this work >> with a policy tree, is this essentially how dumping it out as a >> source policy would work? > > You have to iterate over the whole tree outputting as you go: > > void output_tree(std::ostream& o, Parent& p, enum OutputStyle style) { > Parent::iterator i, end; > end = p.end(); > for (i = p.begin(TreeIterator::HYBRID); i != end; ++i) { > o << Output(*i, i.get_visited(), style) << "\n"; > } o << std::flush; > } > > The Output thing is how you control the output options (I'm > not entirely happy with that design, but it is similar to how > output formatting is done with streams). It also takes into > account whether this is the opening of a block ("if (foo) {") > or the closing ("}"). This doesn't yet handle indentation. > >> How are we going to differenciate serializing to strings and >> serializing to a binary module? >> > > The serialization module handles that - it depends on the > type on the left. > Ah, that's pretty neat. Should we, then, have output_tree as a template that takes the type being serialized to and does the serialization to whatever type you pass in? > std::cout << foo; // string > > std::ofstream fout("filename"); > boost::archive::text_oarchive ar(fout); > ar << p; // serialization - actually calls serialize method > >> Also, how cheap is the binary serializing/unserializing going to be? >> We don't want it to be equivalent to re-parsing from source (or else >> there is no reason to have a binary format). > > It will be pretty cheap - much better than parsing. It should > also be a more compact form. > >> Are we going to build compression >> of the modules in from the get-go to avoid the complaints about >> oversized modules that we had before? > > I would like to, but I haven't looked much for compressed streams. > Something like http://www.cs.unc.edu/Research/compgeom/gzstream/ > might work. > I might be getting ahead of myself here but does it create a different kind of stream object so that either compressed or non-compressed will act basically the same (and can be used from the same output_tree template I mention above?) Also, I don't see this library in yum, would we just package it with our stuff and statically link or am I missing it somewhere? -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-06-06 15:28 ` Joshua Brindle @ 2007-06-06 16:19 ` Stephen Bennett 2007-06-06 16:30 ` Karl MacMillan 0 siblings, 1 reply; 35+ messages in thread From: Stephen Bennett @ 2007-06-06 16:19 UTC (permalink / raw) To: Joshua Brindle; +Cc: Karl MacMillan, selinux, Stephen Smalley On Wed, 6 Jun 2007 11:28:04 -0400 "Joshua Brindle" <jbrindle@tresys.com> wrote: > >>> Not certain what you mean - you mean the private variables? You > >>> can use the PIMPL idiom - http://www.codepedia.com/1/CppPimpl - > >>> but I'm not convinced it's worth the pain. After the care we took > >>> to hide implementation in libsepol we didn't really make changes > >>> that would have broken in the ABI. > >>> > >> > > How painful is it? The examples on that page don't look too bad, and > they claim it reduces compile time (something you've already griped > about) It's not painful really, even for very small or very large classes. If you're using it a lot in a given library it's not too hard to add a few templated utility classes to make life somewhat easier either. > So are we going to have to pad it to be able to add stuff later on? > Would adding something in the public part shift the private part down > in a way that would break the ABI? This worries me a bit, I know QT > does padding to handle this but I haven't looked at what they do > specifically. The public part should consist solely of one or two pointers --one to the private implementation part, and possibly one to the vtable if it has virtual functions. That sort of ABI is extremely resilient, and members (both data and functions) can be added without breaking it. -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-06-06 16:19 ` Stephen Bennett @ 2007-06-06 16:30 ` Karl MacMillan 2007-06-06 17:07 ` Stephen Bennett 0 siblings, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-06-06 16:30 UTC (permalink / raw) To: Stephen Bennett; +Cc: Joshua Brindle, selinux, Stephen Smalley On Wed, 2007-06-06 at 17:19 +0100, Stephen Bennett wrote: > On Wed, 6 Jun 2007 11:28:04 -0400 > "Joshua Brindle" <jbrindle@tresys.com> wrote: > > > >>> Not certain what you mean - you mean the private variables? You > > >>> can use the PIMPL idiom - http://www.codepedia.com/1/CppPimpl - > > >>> but I'm not convinced it's worth the pain. After the care we took > > >>> to hide implementation in libsepol we didn't really make changes > > >>> that would have broken in the ABI. > > >>> > > >> > > > > How painful is it? The examples on that page don't look too bad, and > > they claim it reduces compile time (something you've already griped > > about) > > It's not painful really, even for very small or very large classes. If > you're using it a lot in a given library it's not too hard to add a few > templated utility classes to make life somewhat easier either. > Can you give an example of what those templated classes do? > > So are we going to have to pad it to be able to add stuff later on? > > Would adding something in the public part shift the private part down > > in a way that would break the ABI? This worries me a bit, I know QT > > does padding to handle this but I haven't looked at what they do > > specifically. > > The public part should consist solely of one or two pointers --one to > the private implementation part, and possibly one to the vtable if it > has virtual functions. That sort of ABI is extremely resilient, and > members (both data and functions) can be added without breaking it. Hmm - I thought that adding a member function (virtual or non-virtual) changed the ABI. Is there some technique for addressing that problem? Karl -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-06-06 16:30 ` Karl MacMillan @ 2007-06-06 17:07 ` Stephen Bennett 0 siblings, 0 replies; 35+ messages in thread From: Stephen Bennett @ 2007-06-06 17:07 UTC (permalink / raw) To: Karl MacMillan; +Cc: Joshua Brindle, selinux, Stephen Smalley On Wed, 06 Jun 2007 12:30:01 -0400 Karl MacMillan <kmacmillan@mentalrootkit.com> wrote: > > It's not painful really, even for very small or very large classes. > > If you're using it a lot in a given library it's not too hard to > > add a few templated utility classes to make life somewhat easier > > either. > > > > Can you give an example of what those templated classes do? The one I've been using recently is found at http://paludis.pioto.org/trac/browser/trunk/paludis/util/private_implementation_pattern.hh and http://paludis.pioto.org/trac/browser/trunk/paludis/util/private_implementation_pattern-impl.hh (apologies for long URLs). Usage is fairly simple: in a class Foo, simply inherit from PrivateImplementationPatter<Foo>, and then initialise _imp with 'new Implementation<Foo>(args here)'. The entirety of Implementation<Foo> can then be hidden away in the .cc file, inaccessible to the outside world. > Hmm - I thought that adding a member function (virtual or non-virtual) > changed the ABI. Is there some technique for addressing that problem? Not as far as I'm aware .. adding a new virtual method will break the ABI if it's placed before any existing ones, but non-virtual methods and virtual methods added to the end shouldn't cause problems. -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-05-31 17:54 ` Joshua Brindle 2007-05-31 19:31 ` Karl MacMillan @ 2007-05-31 19:45 ` Stephen Bennett 2007-06-01 4:10 ` James Antill 2007-06-04 21:30 ` Help with semanage Hasan Rezaul-CHR010 1 sibling, 2 replies; 35+ messages in thread From: Stephen Bennett @ 2007-05-31 19:45 UTC (permalink / raw) To: Joshua Brindle; +Cc: Karl MacMillan, selinux, Stephen Smalley On Thu, 31 May 2007 13:54:23 -0400 "Joshua Brindle" <jbrindle@tresys.com> wrote: > Given all this I think C++ is the best bet, though I'm not adverse to > most of the frontends being written in python, it would just be nice > if the actual policy representation and accessors are available from a > shared library API that most languages can use. >From the library side, C++ has the advantage that it can produce bindings for any language that C can. Writing a library in python pretty much guarantees that noone will write anything using it in anything but python, and on smaller systems the python interpreter can get to be a lot of overhead. Python for the frontend apps though is entirely reasonable -- it's probably quicker to write, and people are unlikely to want to import it into another application. -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-05-31 19:45 ` Stephen Bennett @ 2007-06-01 4:10 ` James Antill 2007-06-01 11:40 ` Stephen Bennett 2007-06-01 14:49 ` Karl MacMillan 2007-06-04 21:30 ` Help with semanage Hasan Rezaul-CHR010 1 sibling, 2 replies; 35+ messages in thread From: James Antill @ 2007-06-01 4:10 UTC (permalink / raw) To: Stephen Bennett; +Cc: Joshua Brindle, Karl MacMillan, selinux, Stephen Smalley [-- Attachment #1: Type: text/plain, Size: 1702 bytes --] On Thu, 2007-05-31 at 20:45 +0100, Stephen Bennett wrote: > On Thu, 31 May 2007 13:54:23 -0400 > "Joshua Brindle" <jbrindle@tresys.com> wrote: > > > Given all this I think C++ is the best bet, though I'm not adverse to > > most of the frontends being written in python, it would just be nice > > if the actual policy representation and accessors are available from a > > shared library API that most languages can use. > > From the library side, C++ has the advantage that it can produce > bindings for any language that C can. Do you have a examples of this? From what little I know it's _much_ harder to produce usable bindings from C++, the Qt/KDE bindings seem to have been in the works for years now and AIUI only very recently[1] got into KDE's stable branch. With the first non-C++ application being written in ... python. Even assuming everyone could cooperatively write good C++ code from scratch using just the right C++ features, which is a huge assumption[2], it then has to be debugged and then after all that work all you'll gain is that you can then bind to python (and maybe, Java/ruby) as well? Is anyone writing anything in a language other than C or Python? > Writing a library in python > pretty much guarantees that noone will write anything using it in > anything but python, and on smaller systems the python interpreter can > get to be a lot of overhead. True, but you can still import C etc. into it if you really need the space savings. Just my 2¢ [1] http://dot.kde.org/1176941846/ [2] A _Much_ bigger assumption than getting python correct, or C string handling for that matter. -- James Antill <jantill@redhat.com> [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-06-01 4:10 ` James Antill @ 2007-06-01 11:40 ` Stephen Bennett 2007-06-01 11:47 ` Stephen Bennett 2007-06-01 14:49 ` Karl MacMillan 1 sibling, 1 reply; 35+ messages in thread From: Stephen Bennett @ 2007-06-01 11:40 UTC (permalink / raw) To: James Antill; +Cc: Joshua Brindle, Karl MacMillan, selinux, Stephen Smalley On Fri, 01 Jun 2007 00:10:15 -0400 James Antill <jantill@redhat.com> wrote: > > From the library side, C++ has the advantage that it can produce > > bindings for any language that C can. > > Do you have a examples of this? From what little I know it's _much_ > harder to produce usable bindings from C++, the Qt/KDE bindings seem > to have been in the works for years now and AIUI only very > recently[1] got into KDE's stable branch. With the first non-C++ > application being written in ... python. I know from recent experience that Ruby and Python can be done directly without too much trouble. If anything else is needed that particularly defies bindings in C++, one can (in principle, and if you haven't relied upon too many of the more advanced language features) create a C API by turning all object pointers into opaque types and wrapping methods in regular function calls, then go from that. -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-06-01 11:40 ` Stephen Bennett @ 2007-06-01 11:47 ` Stephen Bennett 0 siblings, 0 replies; 35+ messages in thread From: Stephen Bennett @ 2007-06-01 11:47 UTC (permalink / raw) To: James Antill; +Cc: Joshua Brindle, Karl MacMillan, selinux, Stephen Smalley On Fri, 1 Jun 2007 12:40:53 +0100 Stephen Bennett <spb@gentoo.org> wrote: > On Fri, 01 Jun 2007 00:10:15 -0400 > James Antill <jantill@redhat.com> wrote: > > > > From the library side, C++ has the advantage that it can produce > > > bindings for any language that C can. > > > > Do you have a examples of this? From what little I know it's _much_ > > harder to produce usable bindings from C++, the Qt/KDE bindings seem > > to have been in the works for years now and AIUI only very > > recently[1] got into KDE's stable branch. With the first non-C++ > > application being written in ... python. > > I know from recent experience that Ruby and Python can be done > directly without too much trouble. If anything else is needed that > particularly defies bindings in C++, one can (in principle, and if > you haven't relied upon too many of the more advanced language > features) create a C API by turning all object pointers into opaque > types and wrapping methods in regular function calls, then go from > that. The example I had in mind being http://paludis.pioto.org/trac/browser/trunk -- the ruby/ and python/ directories contain the bindings for those languages. The library itself is a lot of pretty 'heavy' C++. The Python interface uses the Boost library for convenience, whereas Ruby uses the Ruby/C API directly. -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-06-01 4:10 ` James Antill 2007-06-01 11:40 ` Stephen Bennett @ 2007-06-01 14:49 ` Karl MacMillan 2007-06-01 15:17 ` Joshua Brindle 1 sibling, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-06-01 14:49 UTC (permalink / raw) To: James Antill; +Cc: Stephen Bennett, Joshua Brindle, selinux, Stephen Smalley On Fri, 2007-06-01 at 00:10 -0400, James Antill wrote: > On Thu, 2007-05-31 at 20:45 +0100, Stephen Bennett wrote: > > On Thu, 31 May 2007 13:54:23 -0400 > > "Joshua Brindle" <jbrindle@tresys.com> wrote: > > > > > Given all this I think C++ is the best bet, though I'm not adverse to > > > most of the frontends being written in python, it would just be nice > > > if the actual policy representation and accessors are available from a > > > shared library API that most languages can use. > > > > From the library side, C++ has the advantage that it can produce > > bindings for any language that C can. > > Do you have a examples of this? From what little I know it's _much_ > harder to produce usable bindings from C++, the Qt/KDE bindings seem to > have been in the works for years now and AIUI only very recently[1] got > into KDE's stable branch. With the first non-C++ application being > written in ... python. It's a matter of how idiomatic you want the bindings and what the C++ code looks like. If you stick to fairly straightforward C++ code then the bindings are pretty simple. If you use lots of advanced features then things can be strange. > Even assuming everyone could cooperatively write good C++ code from > scratch using just the right C++ features, which is a huge > assumption[2], it then has to be debugged and then after all that work > all you'll gain is that you can then bind to python (and maybe, > Java/ruby) as well? > Is anyone writing anything in a language other than C or Python? > In the selinux world? Some people have, but not recently. > > Writing a library in python > > pretty much guarantees that noone will write anything using it in > > anything but python, and on smaller systems the python interpreter can > > get to be a lot of overhead. > > True, but you can still import C etc. into it if you really need the > space savings. > > Just my 2¢ > > [1] http://dot.kde.org/1176941846/ > > [2] A _Much_ bigger assumption than getting python correct, or C string > handling for that matter. > That's just FUD if you ask me. It is not that hard to write good C++ if you are conservative and show some restraint. The problem is that C++ people seem to feel the need to use every feature and litter their code with C++ 'magic', which is where I think a lot of the bad image comes from. It's kind of like the pathological need of Java developers to create "frameworks" that are "pluggable" and use XML - you don't have to do this with Java, but too many people do. Karl -- 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] 35+ messages in thread
* RE: SELinux userspace infrastructure language 2007-06-01 14:49 ` Karl MacMillan @ 2007-06-01 15:17 ` Joshua Brindle 0 siblings, 0 replies; 35+ messages in thread From: Joshua Brindle @ 2007-06-01 15:17 UTC (permalink / raw) To: Karl MacMillan, James Antill; +Cc: Stephen Bennett, selinux, Stephen Smalley Karl MacMillan wrote: > On Fri, 2007-06-01 at 00:10 -0400, James Antill wrote: >> On Thu, 2007-05-31 at 20:45 +0100, Stephen Bennett wrote: >>> On Thu, 31 May 2007 13:54:23 -0400 >>> "Joshua Brindle" <jbrindle@tresys.com> wrote: >>> >>>> Given all this I think C++ is the best bet, though I'm not adverse >>>> to most of the frontends being written in python, it would just be >>>> nice if the actual policy representation and accessors are >>>> available from a shared library API that most languages can use. >>> >>> From the library side, C++ has the advantage that it can produce >>> bindings for any language that C can. >> >> Do you have a examples of this? From what little I know it's _much_ >> harder to produce usable bindings from C++, the Qt/KDE bindings seem >> to have been in the works for years now and AIUI only very >> recently[1] got into KDE's stable branch. With the first non-C++ >> application being written in ... python. > > It's a matter of how idiomatic you want the bindings and what > the C++ code looks like. If you stick to fairly > straightforward C++ code then the bindings are pretty simple. > If you use lots of advanced features then things can be strange. > >> Even assuming everyone could cooperatively write good C++ code from >> scratch using just the right C++ features, which is a huge >> assumption[2], it then has to be debugged and then after all that >> work all you'll gain is that you can then bind to python (and maybe, >> Java/ruby) as well? Is anyone writing anything in a language other >> than C or Python? >> > > In the selinux world? Some people have, but not recently. > SLIDE is in active development and is written in Java. -- 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] 35+ messages in thread
* Help with semanage... 2007-05-31 19:45 ` Stephen Bennett 2007-06-01 4:10 ` James Antill @ 2007-06-04 21:30 ` Hasan Rezaul-CHR010 2007-06-04 21:40 ` Stephen Smalley 1 sibling, 1 reply; 35+ messages in thread From: Hasan Rezaul-CHR010 @ 2007-06-04 21:30 UTC (permalink / raw) To: selinux, Stephen Smalley [-- Attachment #1: Type: text/plain, Size: 1604 bytes --] Hi All, I have a Linux machine (Machine_A) running a collection of *strict* SELinux policies. On Machine_A, I am able to further modify policies by using semanage, and also add/delete policy modules using semodule. I can make changes at will successfully as many times as I want. I tarred up the entire /etc/selinux/* directory from Machine_A, and I untarred the tar-ball on another Linux machine, Machine_B. On Machine_B, I also created and mounted the /selinux/ directory. With all selinux files/dirs in place, AFTER rebooting Machine_B, SELinux policies seem to be working as expected ! At this point, I am able to execute "semanage" ONLY ONE time successfully ! Any attempts to make any further changes after the first time fails with the error below... So for example, If I create a new user-mapping with: "semanage login -a -s staff_u Admin", this first command is successful ! But every semanage command run afterwards has this same error: semanage login -d Admin Libsemanage.semanage_make_sandbox: Could not copy files to sandbox /etc/selinux/strict/modules/tmp /usr/sbin/semanage: Could not start semanage transaction The error message in the /var/log/messages file is: Jun 4 21:10:11 unknown python: Failed: delete SELinux user mapping name=Admin Any ideas on why I can execute semanage only ONCE ? I have tried rebooting the machine several times, to see if it helps, but it doesn't ! Also, whats the significance of the /etc/selinux/strict/module/semanage.read.LOCK & semanage.trans.LOCK files ? Thanks in advance, - Rezaul. [-- Attachment #2: Type: text/html, Size: 4112 bytes --] ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Help with semanage... 2007-06-04 21:30 ` Help with semanage Hasan Rezaul-CHR010 @ 2007-06-04 21:40 ` Stephen Smalley 2007-06-04 22:12 ` Hasan Rezaul-CHR010 0 siblings, 1 reply; 35+ messages in thread From: Stephen Smalley @ 2007-06-04 21:40 UTC (permalink / raw) To: Hasan Rezaul-CHR010; +Cc: selinux On Mon, 2007-06-04 at 17:30 -0400, Hasan Rezaul-CHR010 wrote: > Hi All, > > I have a Linux machine (Machine_A) running a collection of *strict* > SELinux policies. On Machine_A, I am able to further modify policies > by using semanage, and also add/delete policy modules using semodule. > I can make changes at will successfully as many times as I want. > > I tarred up the entire /etc/selinux/* directory from Machine_A, and I > untarred the tar-ball on another Linux machine, Machine_B. On > Machine_B, I also created and mounted the /selinux/ directory. > > With all selinux files/dirs in place, AFTER rebooting Machine_B, > SELinux policies seem to be working as expected ! > > At this point, I am able to execute "semanage" ONLY ONE time > successfully ! Any attempts to make any further changes after the > first time fails with the error below... > > So for example, If I create a new user-mapping with: "semanage login > -a -s staff_u Admin", this first command is successful ! > > But every semanage command run afterwards has this same error: > > semanage login -d Admin > Libsemanage.semanage_make_sandbox: Could not copy files to > sandbox /etc/selinux/strict/modules/tmp > /usr/sbin/semanage: Could not start semanage transaction > > The error message in the /var/log/messages file is: > Jun 4 21:10:11 unknown python: Failed: delete SELinux user mapping > name=Admin > > Any ideas on why I can execute semanage only ONCE ? I have tried > rebooting the machine several times, to see if it helps, but it > doesn't ! > > Also, whats the significance of > the /etc/selinux/strict/module/semanage.read.LOCK & > semanage.trans.LOCK files ? Run restorecon on /etc/selinux, e.g. /sbin/restorecon -R /etc/selinux This usually happens when the file security contexts in /etc/selinux are incorrect and permission is then denied to write to those directories. That can happen if you e.g. run semanage or semodule without being in the right domain in the first place. -- 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] 35+ messages in thread
* RE: Help with semanage... 2007-06-04 21:40 ` Stephen Smalley @ 2007-06-04 22:12 ` Hasan Rezaul-CHR010 2007-06-05 13:07 ` Stephen Smalley 0 siblings, 1 reply; 35+ messages in thread From: Hasan Rezaul-CHR010 @ 2007-06-04 22:12 UTC (permalink / raw) To: Stephen Smalley; +Cc: selinux Interesting. I am logged in as Linux_User = root, and my SELinux role = sysadm_r, domain = sysadm_t. So Not sure how my security contexts could become incorrect ??? In any case, when I did "/sbin/restorecon -R /etc/selinux" it DINDT help :( Still got the same error. BUT, just for kicks, I tried deleting the contents of the /etc/selinux/strict/modules/previous/ directory, and then I was able to run an semanage command for ONE more time ! So If I remove contents of the .../previous/ directory, then I can execute one more semanage command successfully. So for successful semanage commands I have to keep emptying out .../previous/*. Very Strange ! 1. Is there anyway to run semanage or semodule commands such that a "previous" directory is NOT created ? 2. What is the significance of the semanage.read.LOCK and semanage.trans.LOCK files ? 3. The fact the /var/log/messages file has a "python" error, does that mean anything ? Jun 4 21:10:11 unknown python: Failed: delete SELinux user mapping name=Admin 4. Any foreseeable problems with getting rid of the /etc/selinux/strict/modules/active/base.linked file ? I need to save some space on my machine. Thanks, - Rezaul. -----Original Message----- From: Stephen Smalley [mailto:sds@tycho.nsa.gov] Sent: Monday, June 04, 2007 4:41 PM To: Hasan Rezaul-CHR010 Cc: selinux@tycho.nsa.gov Subject: Re: Help with semanage... On Mon, 2007-06-04 at 17:30 -0400, Hasan Rezaul-CHR010 wrote: > Hi All, > > I have a Linux machine (Machine_A) running a collection of *strict* > SELinux policies. On Machine_A, I am able to further modify policies > by using semanage, and also add/delete policy modules using semodule. > I can make changes at will successfully as many times as I want. > > I tarred up the entire /etc/selinux/* directory from Machine_A, and I > untarred the tar-ball on another Linux machine, Machine_B. On > Machine_B, I also created and mounted the /selinux/ directory. > > With all selinux files/dirs in place, AFTER rebooting Machine_B, > SELinux policies seem to be working as expected ! > > At this point, I am able to execute "semanage" ONLY ONE time > successfully ! Any attempts to make any further changes after the > first time fails with the error below... > > So for example, If I create a new user-mapping with: "semanage login > -a -s staff_u Admin", this first command is successful ! > > But every semanage command run afterwards has this same error: > > semanage login -d Admin > Libsemanage.semanage_make_sandbox: Could not copy files to > sandbox /etc/selinux/strict/modules/tmp > /usr/sbin/semanage: Could not start semanage transaction > > The error message in the /var/log/messages file is: > Jun 4 21:10:11 unknown python: Failed: delete SELinux user mapping > name=Admin > > Any ideas on why I can execute semanage only ONCE ? I have tried > rebooting the machine several times, to see if it helps, but it > doesn't ! > > Also, whats the significance of > the /etc/selinux/strict/module/semanage.read.LOCK & > semanage.trans.LOCK files ? Run restorecon on /etc/selinux, e.g. /sbin/restorecon -R /etc/selinux This usually happens when the file security contexts in /etc/selinux are incorrect and permission is then denied to write to those directories. That can happen if you e.g. run semanage or semodule without being in the right domain in the first place. -- 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] 35+ messages in thread
* RE: Help with semanage... 2007-06-04 22:12 ` Hasan Rezaul-CHR010 @ 2007-06-05 13:07 ` Stephen Smalley 2007-06-05 16:34 ` Hasan Rezaul-CHR010 0 siblings, 1 reply; 35+ messages in thread From: Stephen Smalley @ 2007-06-05 13:07 UTC (permalink / raw) To: Hasan Rezaul-CHR010; +Cc: selinux On Mon, 2007-06-04 at 18:12 -0400, Hasan Rezaul-CHR010 wrote: > Interesting. I am logged in as Linux_User = root, and my SELinux role = > sysadm_r, domain = sysadm_t. > > So Not sure how my security contexts could become incorrect ??? > > In any case, when I did "/sbin/restorecon -R /etc/selinux" it DINDT > help :( Still got the same error. And what avc messages are you getting in /var/log/messages or /var/log/audit/audit.log? > BUT, just for kicks, I tried deleting the contents of the > /etc/selinux/strict/modules/previous/ directory, and then I was able to > run an semanage command for ONE more time ! > > So If I remove contents of the .../previous/ directory, then I can > execute one more semanage command successfully. So for successful > semanage commands I have to keep emptying out .../previous/*. Very > Strange ! > > 1. Is there anyway to run semanage or semodule commands such that a > "previous" directory is NOT created ? Update libsemanage to a recent version. What version do you presently have? > 2. What is the significance of the semanage.read.LOCK and > semanage.trans.LOCK files ? libsemanage performs flock(3) calls on them to perform locking on the policy store. The mere existence of the files means nothing (i.e. their existence does not imply that anything is locked). > 3. The fact the /var/log/messages file has a "python" error, does that > mean anything ? That is just how log messages from a python script like semanage manifest, since the real program is the python interpreter. > Jun 4 21:10:11 unknown python: Failed: delete SELinux user mapping > name=Admin > > 4. Any foreseeable problems with getting rid of the > /etc/selinux/strict/modules/active/base.linked file ? I need to save > some space on my machine. If you update to a newer libsemanage, it shouldn't be left around anymore. -- 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] 35+ messages in thread
* RE: Help with semanage... 2007-06-05 13:07 ` Stephen Smalley @ 2007-06-05 16:34 ` Hasan Rezaul-CHR010 2007-06-05 17:36 ` Stephen Smalley 0 siblings, 1 reply; 35+ messages in thread From: Hasan Rezaul-CHR010 @ 2007-06-05 16:34 UTC (permalink / raw) To: Stephen Smalley; +Cc: selinux The version of libsemanage I have is: libsemanage-1.6.17-1 1. What specific version of libsemanage removes the use of the ..../previous/ directory, as well as the .../active/base.linked files ? 2. Would I need a newer version of some other library(ies) as well (like libselinux, etc), so that executing semodule commands doesn't create a .../previous/ directory ? Example commands: "semodule -i myPolicy.pp" -or- "semodule -r myPolicy" 3. Any explanations of why emptying out the .../previous/* directory allows me to execute another semanage command successfully ? Thanks, - Rezaul. -----Original Message----- From: Stephen Smalley [mailto:sds@tycho.nsa.gov] Sent: Tuesday, June 05, 2007 8:07 AM To: Hasan Rezaul-CHR010 Cc: selinux@tycho.nsa.gov Subject: RE: Help with semanage... On Mon, 2007-06-04 at 18:12 -0400, Hasan Rezaul-CHR010 wrote: > Interesting. I am logged in as Linux_User = root, and my SELinux role = > sysadm_r, domain = sysadm_t. > > So Not sure how my security contexts could become incorrect ??? > > In any case, when I did "/sbin/restorecon -R /etc/selinux" it DINDT > help :( Still got the same error. And what avc messages are you getting in /var/log/messages or /var/log/audit/audit.log? > BUT, just for kicks, I tried deleting the contents of the > /etc/selinux/strict/modules/previous/ directory, and then I was able to > run an semanage command for ONE more time ! > > So If I remove contents of the .../previous/ directory, then I can > execute one more semanage command successfully. So for successful > semanage commands I have to keep emptying out .../previous/*. Very > Strange ! > > 1. Is there anyway to run semanage or semodule commands such that a > "previous" directory is NOT created ? Update libsemanage to a recent version. What version do you presently have? > 2. What is the significance of the semanage.read.LOCK and > semanage.trans.LOCK files ? libsemanage performs flock(3) calls on them to perform locking on the policy store. The mere existence of the files means nothing (i.e. their existence does not imply that anything is locked). > 3. The fact the /var/log/messages file has a "python" error, does that > mean anything ? That is just how log messages from a python script like semanage manifest, since the real program is the python interpreter. > Jun 4 21:10:11 unknown python: Failed: delete SELinux user mapping > name=Admin > > 4. Any foreseeable problems with getting rid of the > /etc/selinux/strict/modules/active/base.linked file ? I need to save > some space on my machine. If you update to a newer libsemanage, it shouldn't be left around anymore. -- 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] 35+ messages in thread
* RE: Help with semanage... 2007-06-05 16:34 ` Hasan Rezaul-CHR010 @ 2007-06-05 17:36 ` Stephen Smalley 2007-06-05 17:51 ` Stephen Smalley 0 siblings, 1 reply; 35+ messages in thread From: Stephen Smalley @ 2007-06-05 17:36 UTC (permalink / raw) To: Hasan Rezaul-CHR010; +Cc: selinux On Tue, 2007-06-05 at 12:34 -0400, Hasan Rezaul-CHR010 wrote: > The version of libsemanage I have is: libsemanage-1.6.17-1 > > 1. What specific version of libsemanage removes the use of the > ..../previous/ directory, as well as the .../active/base.linked files > ? 1.9.2 or higher. > 2. Would I need a newer version of some other library(ies) as well (like > libselinux, etc), so that executing semodule commands doesn't create a > .../previous/ directory ? Example commands: > "semodule -i myPolicy.pp" -or- "semodule -r myPolicy" No, it is a shared library and the .so version has not changed, so you don't have to upgrade other components. However, common practice is to upgrade all of the selinux core userland together (checkpolicy, libsepol, libselinux, libsemanage, policycoreutils). > 3. Any explanations of why emptying out the .../previous/* directory > allows me to execute another semanage command successfully ? I assume that there is a permission denial on it; check for avc messages in your /var/log/messages or /var/log/audit/audit.log files. -- 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] 35+ messages in thread
* RE: Help with semanage... 2007-06-05 17:36 ` Stephen Smalley @ 2007-06-05 17:51 ` Stephen Smalley 0 siblings, 0 replies; 35+ messages in thread From: Stephen Smalley @ 2007-06-05 17:51 UTC (permalink / raw) To: Hasan Rezaul-CHR010; +Cc: selinux On Tue, 2007-06-05 at 13:36 -0400, Stephen Smalley wrote: > On Tue, 2007-06-05 at 12:34 -0400, Hasan Rezaul-CHR010 wrote: > > The version of libsemanage I have is: libsemanage-1.6.17-1 > > > > 1. What specific version of libsemanage removes the use of the > > ..../previous/ directory, as well as the .../active/base.linked files > > ? > > 1.9.2 or higher. > > > 2. Would I need a newer version of some other library(ies) as well (like > > libselinux, etc), so that executing semodule commands doesn't create a > > .../previous/ directory ? Example commands: > > "semodule -i myPolicy.pp" -or- "semodule -r myPolicy" > > No, it is a shared library and the .so version has not changed, so you > don't have to upgrade other components. However, common practice is to > upgrade all of the selinux core userland together (checkpolicy, > libsepol, libselinux, libsemanage, policycoreutils). BTW, you can checkout the latest versions of the stable branch via: $ svn co https://selinux.svn.sourceforge.net/svnroot/selinux/branches/stable/1_0 sel-stable You can then build and install the entire core selinux userland via: $ cd sel-stable $ su # make install install-pywrap relabel -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-05-31 17:47 ` Karl MacMillan 2007-05-31 17:54 ` Joshua Brindle @ 2007-05-31 18:00 ` Chad Sellers 2007-05-31 19:13 ` Karl MacMillan 1 sibling, 1 reply; 35+ messages in thread From: Chad Sellers @ 2007-05-31 18:00 UTC (permalink / raw) To: Karl MacMillan, Joshua Brindle; +Cc: selinux, Stephen Smalley On 5/31/07 1:47 PM, "Karl MacMillan" <kmacmill@redhat.com> wrote: > On Thu, 2007-05-31 at 13:35 -0400, Joshua Brindle wrote: >> Some discussion has started off-list about what language to use for the >> implementation of the new policy intermediary format and we'd like to >> bring this discussion into the community to get feedback from users and >> other developers. >> >> In the policyrep branch we've basically started taking OOisms and >> pythonisms and reimplementing them in C which is non-ideal. > > No pythonisms that I am aware of (and I have avoided them). > >> There is >> also madness behind the string handling in some newer work we are doing. >> We discussed the possibility of using python or C++ for our libraries so >> that they are more represenative of the datastructures that are being >> created elsewhere and being reimplemented in C. >> >> Libsemanage could easily be implemented in pure python, it doesn't do >> much hard work, libsepol, on the other hand, is used by a lot of >> external stuff so it's a more difficult sell. It would be nice to >> potentially use the STL for a lot of the stuff we are doing in libsepol. >> >> Libsemanage need not be rewritten immediately (or at all if not >> considered a necessity) but the new policy representation work will be >> happening in the near term so the language chosen for it will >> immediately be used. This language would be required for any systems >> with managed policies (eg., using policy modules and semanage) so that >> is something to be considered. >> > > To make this more concrete, there are two basic options (as I see it): > > 1) adopt sepolgen as the new policyrep and implement the policy > compilers on top of that. The policyrep branch is in some senses a port > of part of sepolgen. > 2) Keep going with policyrep, but in C++. > > 1 is less work but harder for cross-language development. 2 is much more > work, potentially forever. > And don't forget about option 3, which is continue down the C path. This is the most painful immediate option, but may have less ripple effect among the users of the library. Chad -- 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] 35+ messages in thread
* Re: SELinux userspace infrastructure language 2007-05-31 18:00 ` SELinux userspace infrastructure language Chad Sellers @ 2007-05-31 19:13 ` Karl MacMillan [not found] ` <20070531205635.3b85f72b@maya> 0 siblings, 1 reply; 35+ messages in thread From: Karl MacMillan @ 2007-05-31 19:13 UTC (permalink / raw) To: Chad Sellers; +Cc: Joshua Brindle, selinux, Stephen Smalley On Thu, 2007-05-31 at 14:00 -0400, Chad Sellers wrote: > On 5/31/07 1:47 PM, "Karl MacMillan" <kmacmill@redhat.com> wrote: > > > On Thu, 2007-05-31 at 13:35 -0400, Joshua Brindle wrote: > >> Some discussion has started off-list about what language to use for the > >> implementation of the new policy intermediary format and we'd like to > >> bring this discussion into the community to get feedback from users and > >> other developers. > >> > >> In the policyrep branch we've basically started taking OOisms and > >> pythonisms and reimplementing them in C which is non-ideal. > > > > No pythonisms that I am aware of (and I have avoided them). > > > >> There is > >> also madness behind the string handling in some newer work we are doing. > >> We discussed the possibility of using python or C++ for our libraries so > >> that they are more represenative of the datastructures that are being > >> created elsewhere and being reimplemented in C. > >> > >> Libsemanage could easily be implemented in pure python, it doesn't do > >> much hard work, libsepol, on the other hand, is used by a lot of > >> external stuff so it's a more difficult sell. It would be nice to > >> potentially use the STL for a lot of the stuff we are doing in libsepol. > >> > >> Libsemanage need not be rewritten immediately (or at all if not > >> considered a necessity) but the new policy representation work will be > >> happening in the near term so the language chosen for it will > >> immediately be used. This language would be required for any systems > >> with managed policies (eg., using policy modules and semanage) so that > >> is something to be considered. > >> > > > > To make this more concrete, there are two basic options (as I see it): > > > > 1) adopt sepolgen as the new policyrep and implement the policy > > compilers on top of that. The policyrep branch is in some senses a port > > of part of sepolgen. > > 2) Keep going with policyrep, but in C++. > > > > 1 is less work but harder for cross-language development. 2 is much more > > work, potentially forever. > > > And don't forget about option 3, which is continue down the C path. This is > the most painful immediate option, but may have less ripple effect among the > users of the library. > Good point. For what it's worth my preferences in order: 1) Use sepolgen - my experience creating this tells me that Python is massively more productive for these tasks. I do have some reluctance, though, mainly around the lack of static typing and cross-language support. 2) Switch to C++ plus extra libraries. I don't think C++ by itself is enough of a productivity win, we would need to add some libraries (e.g., http://boost.org/). My biggest concerns here are 1) general hatred of C ++ by many in the Linux world and 2) the need for restraint to keep the C++ readable (e.g., template meta-programming is probably a bad idea in this library). 3) Continue inventing type systems in C - yay! Karl > Chad > > > -- > 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. -- 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] 35+ messages in thread
[parent not found: <20070531205635.3b85f72b@maya>]
[parent not found: <1180641092.22021.30.camel@localhost.localdomain>]
[parent not found: <1180641428.22021.34.camel@localhost.localdomain>]
* Re: SELinux userspace infrastructure language [not found] ` <1180641428.22021.34.camel@localhost.localdomain> @ 2007-05-31 20:28 ` Stephen Bennett 0 siblings, 0 replies; 35+ messages in thread From: Stephen Bennett @ 2007-05-31 20:28 UTC (permalink / raw) To: Karl MacMillan; +Cc: Chad Sellers, Joshua Brindle, selinux, Stephen Smalley On Thu, 31 May 2007 15:57:08 -0400 Karl MacMillan <kmacmill@redhat.com> wrote: > > I think there are things that are very useful for us around config > > file parsing, general string handling, etc. Also the graph library > > would be great for some of the analysis tasks. This is true, though last time I looked at the boost parser libraries (admittedly quite a few years ago) they felt more like a nice demonstration of how to abuse certain language features in new and interesting ways than a practical way to get things done. The other parts I've not yet had a need to use. > > Last time I used it I kept a private copy and only linked in what I > > used. I guess we could limit the use to python, though, and only > > have it as a runtime requirement for the python bindings. Yeah, in many cases this is the only reasonable way to use it. Which is a shame, really, because some small parts can be nice to have but aren't worth depending on the entire thing for. > Most of boost is just headers, so it is just a compile time > dependency. Another good point, though my perception here is rather skewed towards Gentoo, where compile time dependencies are just as much of a pain, and boost is a really big compile time depend for just a couple of headers. That's fixed by importing small parts of it into the source tree, though, so it's not a massive problem. -- 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] 35+ messages in thread
end of thread, other threads:[~2007-06-06 17:07 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-31 17:35 SELinux userspace infrastructure language Joshua Brindle
2007-05-31 17:47 ` Karl MacMillan
2007-05-31 17:54 ` Joshua Brindle
2007-05-31 19:31 ` Karl MacMillan
2007-06-04 22:24 ` Karl MacMillan
2007-06-05 0:52 ` Joshua Brindle
2007-06-04 16:49 ` Karl MacMillan
2007-06-05 14:19 ` Stephen Smalley
2007-06-05 15:13 ` Karl MacMillan
2007-06-06 12:42 ` Stephen Smalley
2007-06-06 14:51 ` Karl MacMillan
2007-06-05 23:18 ` Joshua Brindle
2007-06-06 14:48 ` Karl MacMillan
2007-06-06 14:59 ` Joshua Brindle
2007-06-06 15:18 ` Karl MacMillan
2007-06-06 15:28 ` Joshua Brindle
2007-06-06 16:19 ` Stephen Bennett
2007-06-06 16:30 ` Karl MacMillan
2007-06-06 17:07 ` Stephen Bennett
2007-05-31 19:45 ` Stephen Bennett
2007-06-01 4:10 ` James Antill
2007-06-01 11:40 ` Stephen Bennett
2007-06-01 11:47 ` Stephen Bennett
2007-06-01 14:49 ` Karl MacMillan
2007-06-01 15:17 ` Joshua Brindle
2007-06-04 21:30 ` Help with semanage Hasan Rezaul-CHR010
2007-06-04 21:40 ` Stephen Smalley
2007-06-04 22:12 ` Hasan Rezaul-CHR010
2007-06-05 13:07 ` Stephen Smalley
2007-06-05 16:34 ` Hasan Rezaul-CHR010
2007-06-05 17:36 ` Stephen Smalley
2007-06-05 17:51 ` Stephen Smalley
2007-05-31 18:00 ` SELinux userspace infrastructure language Chad Sellers
2007-05-31 19:13 ` Karl MacMillan
[not found] ` <20070531205635.3b85f72b@maya>
[not found] ` <1180641092.22021.30.camel@localhost.localdomain>
[not found] ` <1180641428.22021.34.camel@localhost.localdomain>
2007-05-31 20:28 ` Stephen Bennett
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.