All of lore.kernel.org
 help / color / mirror / Atom feed
* 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: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

* 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 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
       [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

* 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

* 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

* 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: 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: 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: 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: 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-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 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-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 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-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

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.