diff mbox series

[04/10] CaitSith: Add header file.

Message ID 20221102171025.126961-4-penguin-kernel@I-love.SAKURA.ne.jp (mailing list archive)
State Rejected
Delegated to: Paul Moore
Headers show
Series [01/10] security: Export security_hook_heads | expand

Commit Message

Tetsuo Handa Nov. 2, 2022, 5:10 p.m. UTC
The main point of this submission is to demonstrate how an LSM module
which can be loaded using /sbin/insmod can work, and to provide
consideration points for making changes for LSM stacking in a way that
will not lock out LSM modules which can be loaded using /sbin/insmod .

CaitSith was developed as next version of TOMOYO. But since it became
too different to call as TOMOYO (this was a fundamental change as if
SELinux stops using filesystem's extended attributes), I gave this module
a new name. Background of developing this module is explained in
https://I-love.SAKURA.ne.jp/tomoyo/CaitSith-en.pdf .

This file defines constants, structures, and inline functions used by
CaitSith. Please ignore redundancy, for this submission is just an output
 from repository which supports 2.6.27+ kernels with LINUX_VERSION_CODE
removed.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/caitsith/caitsith.h | 919 +++++++++++++++++++++++++++++++++++
 1 file changed, 919 insertions(+)
 create mode 100644 security/caitsith/caitsith.h

Comments

Casey Schaufler Nov. 2, 2022, 5:57 p.m. UTC | #1
On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
> The main point of this submission is to demonstrate how an LSM module
> which can be loaded using /sbin/insmod can work, and to provide
> consideration points for making changes for LSM stacking in a way that
> will not lock out LSM modules which can be loaded using /sbin/insmod .

CaitSith could readily be done as an in-tree LSM. The implementation
of loadable module infrastructure is unnecessary.
Serge E. Hallyn Nov. 5, 2022, 2:43 a.m. UTC | #2
On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
> > The main point of this submission is to demonstrate how an LSM module
> > which can be loaded using /sbin/insmod can work, and to provide
> > consideration points for making changes for LSM stacking in a way that
> > will not lock out LSM modules which can be loaded using /sbin/insmod .
> 
> CaitSith could readily be done as an in-tree LSM. The implementation
> of loadable module infrastructure is unnecessary.

Sorry, I'm getting confused.  But in-tree and loadable are not related,
right?
Tetsuo Handa Nov. 5, 2022, 4:05 a.m. UTC | #3
On 2022/11/05 11:43, Serge E. Hallyn wrote:
> On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
>> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
>>> The main point of this submission is to demonstrate how an LSM module
>>> which can be loaded using /sbin/insmod can work, and to provide
>>> consideration points for making changes for LSM stacking in a way that
>>> will not lock out LSM modules which can be loaded using /sbin/insmod .
>>
>> CaitSith could readily be done as an in-tree LSM. The implementation
>> of loadable module infrastructure is unnecessary.
> 
> Sorry, I'm getting confused.  But in-tree and loadable are not related,
> right?

Very much related. My goal is to get CaitSith in-tree as a loadable LSM module
which can be loaded using /sbin/insmod .

Lessons I learned from TOMOYO are that:

  Most of Linux users, unlike Linux kernel developers, consider the Linux kernel
  as something black-box program. While the source code is open, they cannot
  afford understanding how updating the Linux kernel via "yum update" or
  "apt dist-upgrade" affects their systems.

  I can't force Linux users to replace their kernel packages in order to
  allow them to use TOMOYO, for replacing the kernel package makes their
  replaced kernel packages incompatible (kABI breakage) with other kernel
  modules (e.g. device drivers provided by hardware vendors) and/or makes
  their kernel completely unsupported. I can support TOMOYO part but I can't
  support the rest of the kernel, which makes it impossible for Linux users
  using supported kernels to try TOMOYO. Being in-tree helps catching up
  the upstream kernel changes, but being in-tree does not help allowing
  Linux distribution users to use TOMOYO.

  Linux distributors cannot afford enabling all LSM modules, due to the
  "enabled" == "supported" spell. There are out-of-tree kernel modules
  which are built as a loadable kernel module (i.e. not included into
  the main kernel package which is supported by Linux distributors), but
  the LSM framework does not legally allow use of LSM modules which are
  not built into the bzImage file.

If the LSM framework legally allows use of LSM modules which are not built
into the bzImage file, we can allow users to use whatever LSM modules they
want (and "support" is provided by the module authors rather than by Linux
distributors).

This submission is to ask LSM framework "please don't make it impossible to
allow users to use whatever LSM modules they want". That is more important
than "complete LSM stacking".

Casey's proposal towards "complete LSM stacking" is making it impossible to
allow users to use whatever LSM modules they want, due to the requirement of
having an LSM id integer value and using fixed sized array.
Serge E. Hallyn Nov. 5, 2022, 11:46 p.m. UTC | #4
On Sat, Nov 05, 2022 at 01:05:44PM +0900, Tetsuo Handa wrote:
> On 2022/11/05 11:43, Serge E. Hallyn wrote:
> > On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
> >> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
> >>> The main point of this submission is to demonstrate how an LSM module
> >>> which can be loaded using /sbin/insmod can work, and to provide
> >>> consideration points for making changes for LSM stacking in a way that
> >>> will not lock out LSM modules which can be loaded using /sbin/insmod .
> >>
> >> CaitSith could readily be done as an in-tree LSM. The implementation
> >> of loadable module infrastructure is unnecessary.
> > 
> > Sorry, I'm getting confused.  But in-tree and loadable are not related,
> > right?
> 
> Very much related. My goal is to get CaitSith in-tree as a loadable LSM module
> which can be loaded using /sbin/insmod .

Great.  I support that.  But the sentence

> >> CaitSith could readily be done as an in-tree LSM. The implementation
> >> of loadable module infrastructure is unnecessary.

suggests that because CaitSith could be done in-tree, it doesn't need
to be loadable.  I'm saying that is a non sequitur.  It sounded like
that setence was meant to say "Because CaitSith could be in-tree, it
doesn't need to be =m.  Only out of tree modules need to be loadable."

-serge
Tetsuo Handa Nov. 6, 2022, 12:56 a.m. UTC | #5
On 2022/11/06 8:46, Serge E. Hallyn wrote:
> On Sat, Nov 05, 2022 at 01:05:44PM +0900, Tetsuo Handa wrote:
>> On 2022/11/05 11:43, Serge E. Hallyn wrote:
>>> On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
>>>> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
>>>>> The main point of this submission is to demonstrate how an LSM module
>>>>> which can be loaded using /sbin/insmod can work, and to provide
>>>>> consideration points for making changes for LSM stacking in a way that
>>>>> will not lock out LSM modules which can be loaded using /sbin/insmod .
>>>>
>>>> CaitSith could readily be done as an in-tree LSM. The implementation
>>>> of loadable module infrastructure is unnecessary.
>>>
>>> Sorry, I'm getting confused.  But in-tree and loadable are not related,
>>> right?
>>
>> Very much related. My goal is to get CaitSith in-tree as a loadable LSM module
>> which can be loaded using /sbin/insmod .
> 
> Great.  I support that.  But the sentence

Thank you.

> 
>>>> CaitSith could readily be done as an in-tree LSM. The implementation
>>>> of loadable module infrastructure is unnecessary.
> 
> suggests that because CaitSith could be done in-tree, it doesn't need
> to be loadable.  I'm saying that is a non sequitur.  It sounded like
> that setence was meant to say "Because CaitSith could be in-tree, it
> doesn't need to be =m.  Only out of tree modules need to be loadable."

Unfortunately, I don't think that my intended Linux distributor (namely, Red Hat)
will support LSMs other than SELinux.

  https://bugzilla.redhat.com/show_bug.cgi?id=542986

Therefore, not only out of tree modules but also in-tree modules which cannot be
enabled by Linux distributors need to be implemented as loadable kernel modules.
Casey Schaufler Nov. 7, 2022, 6:59 p.m. UTC | #6
On 11/5/2022 5:56 PM, Tetsuo Handa wrote:
> On 2022/11/06 8:46, Serge E. Hallyn wrote:
>> On Sat, Nov 05, 2022 at 01:05:44PM +0900, Tetsuo Handa wrote:
>>> On 2022/11/05 11:43, Serge E. Hallyn wrote:
>>>> On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
>>>>> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
>>>>>> The main point of this submission is to demonstrate how an LSM module
>>>>>> which can be loaded using /sbin/insmod can work, and to provide
>>>>>> consideration points for making changes for LSM stacking in a way that
>>>>>> will not lock out LSM modules which can be loaded using /sbin/insmod .
>>>>> CaitSith could readily be done as an in-tree LSM. The implementation
>>>>> of loadable module infrastructure is unnecessary.
>>>> Sorry, I'm getting confused.  But in-tree and loadable are not related,
>>>> right?
>>> Very much related. My goal is to get CaitSith in-tree as a loadable LSM module
>>> which can be loaded using /sbin/insmod .
>> Great.  I support that.  But the sentence
> Thank you.
>
>>>>> CaitSith could readily be done as an in-tree LSM. The implementation
>>>>> of loadable module infrastructure is unnecessary.
>> suggests that because CaitSith could be done in-tree, it doesn't need
>> to be loadable.  I'm saying that is a non sequitur.  It sounded like
>> that setence was meant to say "Because CaitSith could be in-tree, it
>> doesn't need to be =m.  Only out of tree modules need to be loadable."
> Unfortunately, I don't think that my intended Linux distributor (namely, Red Hat)
> will support LSMs other than SELinux.

I also doubt that even if you came up with a 100% perfect implementation
of loadable module support it would be accepted upstream. If you somehow
got it upstream I really, really think it would be required to be optional.
There's no way Redhat would enable loadable module support if were available.
I am perfectly willing to be corrected if I've made a statement here that
isn't true, but I'll bet a refreshing beverage on it.

>
>   https://bugzilla.redhat.com/show_bug.cgi?id=542986
>
> Therefore, not only out of tree modules but also in-tree modules which cannot be
> enabled by Linux distributors need to be implemented as loadable kernel modules.

Today you cannot use SELinux and AppArmor together on Redhat. Someday
"soon ;)" you won't be allowed to run them together on Redhat. If there's
market demand (I'm not holding my breath) it could happen in the future.
But that's up to Redhat to decide. I don't see Redhat as the customer for
LSM improvements. They are happy with what they have.

You have to take a different approach. Find a distribution that does want
loadable modules. You'll need a viable implementation to convince them to
help with the effort. Even then, you'll have a tough row to hoe.
Paul Moore Nov. 7, 2022, 7:22 p.m. UTC | #7
On Sat, Nov 5, 2022 at 12:06 AM Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> On 2022/11/05 11:43, Serge E. Hallyn wrote:
> > On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
> >> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
> >>> The main point of this submission is to demonstrate how an LSM module
> >>> which can be loaded using /sbin/insmod can work, and to provide
> >>> consideration points for making changes for LSM stacking in a way that
> >>> will not lock out LSM modules which can be loaded using /sbin/insmod .
> >>
> >> CaitSith could readily be done as an in-tree LSM. The implementation
> >> of loadable module infrastructure is unnecessary.
> >
> > Sorry, I'm getting confused.  But in-tree and loadable are not related,
> > right?
>
> Very much related. My goal is to get CaitSith in-tree as a loadable LSM module
> which can be loaded using /sbin/insmod .

At this point in time I don't want to support dynamically loadable LSM modules.
Tetsuo Handa Nov. 8, 2022, 10:18 a.m. UTC | #8
On 2022/11/08 3:59, Casey Schaufler wrote:
> On 11/5/2022 5:56 PM, Tetsuo Handa wrote:
>> On 2022/11/06 8:46, Serge E. Hallyn wrote:
>>> On Sat, Nov 05, 2022 at 01:05:44PM +0900, Tetsuo Handa wrote:
>>>> On 2022/11/05 11:43, Serge E. Hallyn wrote:
>>>>> On Wed, Nov 02, 2022 at 10:57:48AM -0700, Casey Schaufler wrote:
>>>>>> On 11/2/2022 10:10 AM, Tetsuo Handa wrote:
>>>>>>> The main point of this submission is to demonstrate how an LSM module
>>>>>>> which can be loaded using /sbin/insmod can work, and to provide
>>>>>>> consideration points for making changes for LSM stacking in a way that
>>>>>>> will not lock out LSM modules which can be loaded using /sbin/insmod .
>>>>>> CaitSith could readily be done as an in-tree LSM. The implementation
>>>>>> of loadable module infrastructure is unnecessary.
>>>>> Sorry, I'm getting confused.  But in-tree and loadable are not related,
>>>>> right?
>>>> Very much related. My goal is to get CaitSith in-tree as a loadable LSM module
>>>> which can be loaded using /sbin/insmod .
>>> Great.  I support that.  But the sentence
>> Thank you.
>>
>>>>>> CaitSith could readily be done as an in-tree LSM. The implementation
>>>>>> of loadable module infrastructure is unnecessary.
>>> suggests that because CaitSith could be done in-tree, it doesn't need
>>> to be loadable.  I'm saying that is a non sequitur.  It sounded like
>>> that setence was meant to say "Because CaitSith could be in-tree, it
>>> doesn't need to be =m.  Only out of tree modules need to be loadable."
>> Unfortunately, I don't think that my intended Linux distributor (namely, Red Hat)
>> will support LSMs other than SELinux.
> 
> I also doubt that even if you came up with a 100% perfect implementation
> of loadable module support it would be accepted upstream. If you somehow
> got it upstream I really, really think it would be required to be optional.
> There's no way Redhat would enable loadable module support if were available.
> I am perfectly willing to be corrected if I've made a statement here that
> isn't true, but I'll bet a refreshing beverage on it.
> 
>>
>>   https://bugzilla.redhat.com/show_bug.cgi?id=542986
>>
>> Therefore, not only out of tree modules but also in-tree modules which cannot be
>> enabled by Linux distributors need to be implemented as loadable kernel modules.
> 
> Today you cannot use SELinux and AppArmor together on Redhat. Someday
> "soon ;)" you won't be allowed to run them together on Redhat. If there's
> market demand (I'm not holding my breath) it could happen in the future.
> But that's up to Redhat to decide. I don't see Redhat as the customer for
> LSM improvements. They are happy with what they have.
> 
> You have to take a different approach. Find a distribution that does want
> loadable modules. You'll need a viable implementation to convince them to
> help with the effort. Even then, you'll have a tough row to hoe.
> 

You are proving yourself that you are completely trapped into
"only in-tree and supported by distributors is correct" crap.

I am an individual who don't belong to specific distribution. Most of Linux users
in companies I relate with are using RHEL. Company's financial support for TOMOYO
terminated in March 2012 because I was not able to establish support/consult business
because I was not able to get TOMOYO enabled in RHEL (even in Fedora).

My support for TOMOYO is still continued, but unless loadable LSMs becomes legally
possible, I can't introduce TOMOYO/CaitSith to Linux users in companies I relate with.

Even if your LSM stacking work completes some day, I can imagine that there will be
no LSMs I can stack (unless loadable LSMs becomes legally possible).
Finding a distribution who want loadable LSMs does not help.
Only that loadable LSMs becomes legally possible without kernel config option helps.

What I'm asking you are that:

  Please don't lock out out-of-tree LSM modules (by requiring an LSM id integer value
  which are assigned to only in-tree LSM modules) because we can't accept whatever LSM
  modules as in-tree.

  Please don't lock out loadable LSM modules (by using fixed sized array) because
  locking out loadable LSM modules reduces the value of your LSM stacking work.

Quite simple.
Paul Moore Nov. 9, 2022, 2:20 a.m. UTC | #9
On Tue, Nov 8, 2022 at 5:20 AM Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> What I'm asking you are that:
>
>   Please don't lock out out-of-tree LSM modules (by requiring an LSM id integer value
>   which are assigned to only in-tree LSM modules) because we can't accept whatever LSM
>   modules as in-tree.
>
>   Please don't lock out loadable LSM modules (by using fixed sized array) because
>   locking out loadable LSM modules reduces the value of your LSM stacking work.
>
> Quite simple.

Tetsuo, at this point I think we all understand your concern and I
appreciate and respect the passion you have for your argument.
However, I think the rest of the developers, including myself, have
also made our points very clear.  While there may still be revisions
to the syscall patches, I believe identifying LSMs via a token value
as opposed to a string value is the better option for the upstream
Linux Kernel.  This alone should not prevent dynamically loadable LSMs
in the future, if we decide to pursue that, but I do recognize that it
will present more of a challenge for the long term maintenance of
out-of-tree LSMs.  I see no reason to trade off what I believe as a
better API choice (LSM ID tokens) for something that is explicitly not
supported by the Linux Kernel as a whole (out-of-tree kernel code).

Thank you for your comments, but I'm considering this settled.
Tetsuo Handa Nov. 9, 2022, 10:13 a.m. UTC | #10
On 2022/11/09 11:20, Paul Moore wrote:
> On Tue, Nov 8, 2022 at 5:20 AM Tetsuo Handa
> <penguin-kernel@i-love.sakura.ne.jp> wrote:
>> What I'm asking you are that:
>>
>>   Please don't lock out out-of-tree LSM modules (by requiring an LSM id integer value
>>   which are assigned to only in-tree LSM modules) because we can't accept whatever LSM
>>   modules as in-tree.
>>
>>   Please don't lock out loadable LSM modules (by using fixed sized array) because
>>   locking out loadable LSM modules reduces the value of your LSM stacking work.
>>
>> Quite simple.
> 
> Tetsuo, at this point I think we all understand your concern and I
> appreciate and respect the passion you have for your argument.
> However, I think the rest of the developers, including myself, have
> also made our points very clear.  While there may still be revisions
> to the syscall patches, I believe identifying LSMs via a token value
> as opposed to a string value is the better option for the upstream
> Linux Kernel.

I'm not opposing to identifying LSMs via a token value. I'm opposing to who can
obtain a token value, for I haven't heard a clear promise that we shall allow
whatever LSM modules to obtain a token value.

>                This alone should not prevent dynamically loadable LSMs
> in the future, if we decide to pursue that, but I do recognize that it
> will present more of a challenge for the long term maintenance of
> out-of-tree LSMs.

Who can obtain a token value affects both built-in LSM modules and dynamically
loadable LSM modules. A "code that is being developed in the open with the
*intention* to be submitted to be in-tree" has to be able to obtain a token
value as soon as starting development (which is much earlier stage than getting
that code in-tree).

Do you remember that you said

  >> Currently anyone can start writing new LSM modules using name as identifier. But
  >> you are trying to forbid using name as identifier, and trying to force using integer
  >> as identifier, but that integer will not be provided unless new LSM modules get
  >> upstream.
  > 
  > That is correct.  In order to have a LSM identifier token the LSM must
  > be upstream.

at https://lkml.kernel.org/r/CAHC9VhT2Azg1F-G3RQ4xL7JgA3OAtHafzS1_nvUyEUFsCJ9+SA@mail.gmail.com ?

If in-tree kernel refuses to assign a token value, no new LSM module would be developed
in the open, for not-yet-in-tree code (in whatever stage) cannot use a token value for
registering into the LSM framework.

>                    I see no reason to trade off what I believe as a
> better API choice (LSM ID tokens) for something that is explicitly not
> supported by the Linux Kernel as a whole (out-of-tree kernel code).

And even if a "code is being developed in the open with the intention to be
submitted to be in-tree, and actually submitted for in-tree", we know that we
cannot accept all submitted LSM modules. LSM modules which were not accepted for
in-tree have to remain out-of-tree.

We don't make patches for out-of-tree code in order to catch up to upstream kernel
changes. But we didn't and must not try to forbid out-of-tree code to exist.

Although I'm not a fan of proprietary / closed source code, I have to resist
Casey's attempt to lock out out-of-tree code and new code.

> 
> Thank you for your comments, but I'm considering this settled.
> 

Never settled, unless you all promise that we shall assign a token value to whatever
LSM modules (regardless of whether that LSM module is already in-tree or not).
Paul Moore Nov. 9, 2022, 2:48 p.m. UTC | #11
On Wed, Nov 9, 2022 at 5:14 AM Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> On 2022/11/09 11:20, Paul Moore wrote:
> > On Tue, Nov 8, 2022 at 5:20 AM Tetsuo Handa
> > <penguin-kernel@i-love.sakura.ne.jp> wrote:
> >> What I'm asking you are that:
> >>
> >>   Please don't lock out out-of-tree LSM modules (by requiring an LSM id integer value
> >>   which are assigned to only in-tree LSM modules) because we can't accept whatever LSM
> >>   modules as in-tree.
> >>
> >>   Please don't lock out loadable LSM modules (by using fixed sized array) because
> >>   locking out loadable LSM modules reduces the value of your LSM stacking work.
> >>
> >> Quite simple.
> >
> > Tetsuo, at this point I think we all understand your concern and I
> > appreciate and respect the passion you have for your argument.
> > However, I think the rest of the developers, including myself, have
> > also made our points very clear.  While there may still be revisions
> > to the syscall patches, I believe identifying LSMs via a token value
> > as opposed to a string value is the better option for the upstream
> > Linux Kernel.
>
> I'm not opposing to identifying LSMs via a token value. I'm opposing to who can
> obtain a token value, for I haven't heard a clear promise that we shall allow
> whatever LSM modules to obtain a token value.

In that case, let me be very clear on this issue: at this point in
time I will not merge patches which assign LSM ID tokens in the
upstream Linux Kernel to out-of-tree LSMs.  If there is a significant
change, e.g. the overall kernel policy towards out-of-tree code, we
can reconsider this policy but as of right now only upstream LSMs will
have LSM ID tokens assigned to them; in-development LSMs are free to
temporarily assign themselves an ID token (which may change when the
LSM is merged upstream), and out-of-tree LSMs are free to do whatever
they like with respect to their code, just as they do now.

> > Thank you for your comments, but I'm considering this settled.
> >
>
> Never settled, unless you all promise that we shall assign a token value to whatever
> LSM modules (regardless of whether that LSM module is already in-tree or not).

As the person who ultimately is responsible for supporting,
maintaining, and merging LSM related patches into the upstream Linux
Kernel I am considering this issue settled until there is some other
significant change that warrants reconsideration of the policy
mentioned above.  Of course you are welcome to disagree, and you can
continue to voice your objections if you like, but the issue is
settled in my mind.
Tetsuo Handa Nov. 9, 2022, 11:57 p.m. UTC | #12
On 2022/11/09 23:48, Paul Moore wrote:
>                                             If there is a significant
> change, e.g. the overall kernel policy towards out-of-tree code, we
> can reconsider this policy but as of right now only upstream LSMs will
> have LSM ID tokens assigned to them; in-development LSMs are free to
> temporarily assign themselves an ID token (which may change when the
> LSM is merged upstream), and out-of-tree LSMs are free to do whatever
> they like with respect to their code, just as they do now.

If in-development LSMs and out-of-tree LSMs cannot get a stable ID token,
developers cannot write and publish userspace tools which make use of ID
token. If ID collision happens by use of temporarily ID token, this token
is no longer an identifier. That is a pointless and needless constraint
for getting LSM modules created / tested / used.
Kees Cook Nov. 10, 2022, 2:22 a.m. UTC | #13
On November 9, 2022 3:57:06 PM PST, Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> wrote:
>On 2022/11/09 23:48, Paul Moore wrote:
>>                                             If there is a significant
>> change, e.g. the overall kernel policy towards out-of-tree code, we
>> can reconsider this policy but as of right now only upstream LSMs will
>> have LSM ID tokens assigned to them; in-development LSMs are free to
>> temporarily assign themselves an ID token (which may change when the
>> LSM is merged upstream), and out-of-tree LSMs are free to do whatever
>> they like with respect to their code, just as they do now.
>
>If in-development LSMs and out-of-tree LSMs cannot get a stable ID token,
>developers cannot write and publish userspace tools which make use of ID
>token. If ID collision happens by use of temporarily ID token, this token
>is no longer an identifier. That is a pointless and needless constraint
>for getting LSM modules created / tested / used.

You have to let this go. You aren't hearing us: this ID reservation process is not a problem for anyone but you. It is the same for all the syscalls that get added, and all the prctls, etc etc. This isn't a problem for userspace tools using those, and there won't be a problem here either.

We will not support out of tree code, so needing ID stability for out-of-tree LSMs isn't a valid argument.

Additionally, not having an LSM built into a distro kernel is a distro kernel problem. Open a bug with them and get it fixed. E.g. Ubuntu has no problem with multiple LSMs:

$ grep 'CONFIG_SECURITY_[^_]*[ =]' /boot/config-$(
uname -r)
...
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
CONFIG_SECURITY_TOMOYO=y
CONFIG_SECURITY_APPARMOR=y
# CONFIG_SECURITY_LOADPIN is not set
CONFIG_SECURITY_YAMA=y
CONFIG_SECURITY_SAFESETID=y
CONFIG_SECURITY_LANDLOCK=y

And they just leave the "exclusive"s disabled at runtime:
CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor"

-Kees
Tetsuo Handa Nov. 10, 2022, 4:10 a.m. UTC | #14
On 2022/11/10 11:22, Kees Cook wrote:
> On November 9, 2022 3:57:06 PM PST, Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> wrote:
>> On 2022/11/09 23:48, Paul Moore wrote:
>>>                                             If there is a significant
>>> change, e.g. the overall kernel policy towards out-of-tree code, we
>>> can reconsider this policy but as of right now only upstream LSMs will
>>> have LSM ID tokens assigned to them; in-development LSMs are free to
>>> temporarily assign themselves an ID token (which may change when the
>>> LSM is merged upstream), and out-of-tree LSMs are free to do whatever
>>> they like with respect to their code, just as they do now.
>>
>> If in-development LSMs and out-of-tree LSMs cannot get a stable ID token,
>> developers cannot write and publish userspace tools which make use of ID
>> token. If ID collision happens by use of temporarily ID token, this token
>> is no longer an identifier. That is a pointless and needless constraint
>> for getting LSM modules created / tested / used.
> 
> You have to let this go. You aren't hearing us: this ID reservation process
> is not a problem for anyone but you. It is the same for all the syscalls
> that get added, and all the prctls, etc etc. This isn't a problem for userspace
> tools using those, and there won't be a problem here either.
> 
> We will not support out of tree code, so needing ID stability for out-of-tree
> LSMs isn't a valid argument.
> 

This ID reservation process is very much a problem for you all.

In https://lkml.kernel.org/r/CAHC9VhQGnEcoYeGpwbbXbMrG1dOvJ=2ohd4zPYoqBJK9p1mSjQ@mail.gmail.com ,
Paul said that it is becoming increasingly difficult for people to find time to
review potential new LSMs.

  >> Many modules
  >>
  >>     SimpleFlow ( 2016/04/21 https://lwn.net/Articles/684825/ )
  >>     HardChroot ( 2016/07/29 https://lwn.net/Articles/695984/ )
  >>     Checmate ( 2016/08/04 https://lwn.net/Articles/696344/ )
  >>     LandLock ( 2016/08/25 https://lwn.net/Articles/698226/ )
  >>     PTAGS ( 2016/09/29 https://lwn.net/Articles/702639/ )
  >>     CaitSith ( 2016/10/21 https://lwn.net/Articles/704262/ )
  >>     SafeName ( 2016/05/03 https://lwn.net/Articles/686021/ )
  >>     WhiteEgret ( 2017/05/30 https://lwn.net/Articles/724192/ )
  >>     shebang ( 2017/06/09 https://lwn.net/Articles/725285/ )
  >>     S.A.R.A. ( 2017/06/13 https://lwn.net/Articles/725230/ )
  >>
  >> are proposed 5 or 6 years ago, but mostly became silent...
  > 
  > At least one of those, Landlock, has been merged upstream and is now
  > available in modern released Linux Kernels.  As far as the other LSMs
  > are concerned, I don't recall there ever being significant interest
  > among other developers or users to warrant their inclusion upstream.
  > If the authors believe that has changed, or is simply not true, they
  > are always welcome to post their patches again for discussion, review,
  > and potential upstreaming.  However, I will caution that it is
  > becoming increasingly difficult for people to find time to review
  > potential new LSMs so it may a while to attract sufficient comments
  > and feedback.

Actually, previous CaitSith proposal in 2016 at
https://lkml.kernel.org/r/1477054150-4772-1-git-send-email-penguin-kernel@I-love.SAKURA.ne.jp
died because nobody except John Johansen showed interest, and John could not
find time to review.

We are getting more and more difficult to get new LSM module in-tree.
An in-development code being remaining out-of-tree shall happen. And you are
declaring that we ignore LSM modules which cannot get enough interests.
That's horrible and unacceptable.

What I'm repeating since
https://lkml.kernel.org/r/2225aec6-f0f3-d38e-ee3c-6139a7c25a37@I-love.SAKURA.ne.jp is that

  You are making LSM interface more and more unattractive. The consequence would be
  "The LSM interface is dead. We will give up implementing as LSMs."

Quite simple.
Paul Moore Nov. 10, 2022, 4:45 a.m. UTC | #15
On Wed, Nov 9, 2022 at 11:12 PM Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> On 2022/11/10 11:22, Kees Cook wrote:
> > On November 9, 2022 3:57:06 PM PST, Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> wrote:
> >> On 2022/11/09 23:48, Paul Moore wrote:
> >>>                                             If there is a significant
> >>> change, e.g. the overall kernel policy towards out-of-tree code, we
> >>> can reconsider this policy but as of right now only upstream LSMs will
> >>> have LSM ID tokens assigned to them; in-development LSMs are free to
> >>> temporarily assign themselves an ID token (which may change when the
> >>> LSM is merged upstream), and out-of-tree LSMs are free to do whatever
> >>> they like with respect to their code, just as they do now.
> >>
> >> If in-development LSMs and out-of-tree LSMs cannot get a stable ID token,
> >> developers cannot write and publish userspace tools which make use of ID
> >> token. If ID collision happens by use of temporarily ID token, this token
> >> is no longer an identifier. That is a pointless and needless constraint
> >> for getting LSM modules created / tested / used.
> >
> > You have to let this go. You aren't hearing us: this ID reservation process
> > is not a problem for anyone but you. It is the same for all the syscalls
> > that get added, and all the prctls, etc etc. This isn't a problem for userspace
> > tools using those, and there won't be a problem here either.
> >
> > We will not support out of tree code, so needing ID stability for out-of-tree
> > LSMs isn't a valid argument.
> >
>
> This ID reservation process is very much a problem for you all.
>
> In https://lkml.kernel.org/r/CAHC9VhQGnEcoYeGpwbbXbMrG1dOvJ=2ohd4zPYoqBJK9p1mSjQ@mail.gmail.com ,
> Paul said that it is becoming increasingly difficult for people to find time to
> review potential new LSMs.

It is important that you understand that difficult does not mean
impossible.  As Kees pointed out the rate of LSM acceptance is roughly
at the same level as the rest of the kernel.  The rate of upstream LSM
review also has very little, if anything, to do with the LSM ID
token/string argument.

Beyond that, I'm trying to be polite, but I completely agree with
Kees' statement that you need to let this go.  We are going to be
moving forward with the LSM ID token over the string values.  I'm
sorry we couldn't come to an agreement that satisfies you, but I'm
done discussing this at this point in time.  We can revisit this
decision if something changes, but in the meantime please let this go;
a decision has been made and I'm no longer considering arguments on
this topic.
diff mbox series

Patch

diff --git a/security/caitsith/caitsith.h b/security/caitsith/caitsith.h
new file mode 100644
index 000000000000..b85050d2d5e3
--- /dev/null
+++ b/security/caitsith/caitsith.h
@@ -0,0 +1,919 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * caitsith.h
+ *
+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
+ *
+ * Version: 0.2.10   2021/06/06
+ */
+
+#ifndef _SECURITY_CAITSITH_INTERNAL_H
+#define _SECURITY_CAITSITH_INTERNAL_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/utime.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/poll.h>
+#include <linux/binfmts.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/net.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/un.h>
+#include <linux/namei.h>
+#include <linux/fs_struct.h>
+#include <linux/hash.h>
+#include <linux/kthread.h>
+#include <linux/magic.h>
+#include <linux/uaccess.h>
+#include <linux/sched/signal.h>
+#include <net/sock.h>
+#include <net/af_unix.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/udp.h>
+#include <linux/ctype.h>
+#include <linux/magic.h>
+#include <uapi/linux/mount.h>
+#include <linux/uidgid.h>
+
+/* Index numbers for Capability Controls. */
+enum cs_capability_acl_index {
+	/* socket(PF_ROUTE, *, *)                                      */
+	CS_USE_ROUTE_SOCKET,
+	/* socket(PF_PACKET, *, *)                                     */
+	CS_USE_PACKET_SOCKET,
+	CS_MAX_CAPABILITY_INDEX
+};
+
+/* Enumeration definition for internal use. */
+
+/* Index numbers for "struct cs_condition". */
+enum cs_conditions_index {
+	CS_INVALID_CONDITION,
+	CS_SELF_UID,             /* current_uid()   */
+	CS_SELF_EUID,            /* current_euid()  */
+	CS_SELF_SUID,            /* current_suid()  */
+	CS_SELF_FSUID,           /* current_fsuid() */
+	CS_SELF_GID,             /* current_gid()   */
+	CS_SELF_EGID,            /* current_egid()  */
+	CS_SELF_SGID,            /* current_sgid()  */
+	CS_SELF_FSGID,           /* current_fsgid() */
+	CS_SELF_PID,             /* sys_getpid()   */
+	CS_SELF_PPID,            /* sys_getppid()  */
+	CS_SELF_DOMAIN,
+	CS_SELF_EXE,
+	CS_EXEC_ARGC,            /* "struct linux_binprm *"->argc */
+	CS_EXEC_ENVC,            /* "struct linux_binprm *"->envc */
+	CS_OBJ_IS_SOCKET,        /* S_IFSOCK */
+	CS_OBJ_IS_SYMLINK,       /* S_IFLNK */
+	CS_OBJ_IS_FILE,          /* S_IFREG */
+	CS_OBJ_IS_BLOCK_DEV,     /* S_IFBLK */
+	CS_OBJ_IS_DIRECTORY,     /* S_IFDIR */
+	CS_OBJ_IS_CHAR_DEV,      /* S_IFCHR */
+	CS_OBJ_IS_FIFO,          /* S_IFIFO */
+	CS_MODE_SETUID,          /* S_ISUID */
+	CS_MODE_SETGID,          /* S_ISGID */
+	CS_MODE_STICKY,          /* S_ISVTX */
+	CS_MODE_OWNER_READ,      /* S_IRUSR */
+	CS_MODE_OWNER_WRITE,     /* S_IWUSR */
+	CS_MODE_OWNER_EXECUTE,   /* S_IXUSR */
+	CS_MODE_GROUP_READ,      /* S_IRGRP */
+	CS_MODE_GROUP_WRITE,     /* S_IWGRP */
+	CS_MODE_GROUP_EXECUTE,   /* S_IXGRP */
+	CS_MODE_OTHERS_READ,     /* S_IROTH */
+	CS_MODE_OTHERS_WRITE,    /* S_IWOTH */
+	CS_MODE_OTHERS_EXECUTE,  /* S_IXOTH */
+	CS_TRANSIT_DOMAIN,
+	CS_COND_SARG0,
+	CS_COND_SARG1,
+	CS_COND_SARG2,
+	CS_COND_SARG3,
+	CS_COND_NARG0,
+	CS_COND_NARG1,
+	CS_COND_NARG2,
+	CS_COND_IPARG,
+	CS_COND_DOMAIN,
+	CS_IMM_GROUP,
+	CS_IMM_NAME_ENTRY,
+	CS_IMM_NUMBER_ENTRY1,
+	CS_IMM_NUMBER_ENTRY2,
+#ifdef CONFIG_SECURITY_CAITSITH_NETWORK
+	CS_IMM_IPV4ADDR_ENTRY1,
+	CS_IMM_IPV4ADDR_ENTRY2,
+	CS_IMM_IPV6ADDR_ENTRY1,
+	CS_IMM_IPV6ADDR_ENTRY2,
+#endif
+	CS_ARGV_ENTRY,
+	CS_ENVP_ENTRY,
+	CS_PATH_ATTRIBUTE_START = 192,
+	CS_PATH_ATTRIBUTE_END = 255
+} __packed;
+
+enum cs_path_attribute_index {
+	CS_PATH_ATTRIBUTE_UID,
+	CS_PATH_ATTRIBUTE_GID,
+	CS_PATH_ATTRIBUTE_INO,
+	CS_PATH_ATTRIBUTE_TYPE,
+	CS_PATH_ATTRIBUTE_MAJOR,
+	CS_PATH_ATTRIBUTE_MINOR,
+	CS_PATH_ATTRIBUTE_PERM,
+	CS_PATH_ATTRIBUTE_DEV_MAJOR,
+	CS_PATH_ATTRIBUTE_DEV_MINOR,
+	CS_PATH_ATTRIBUTE_FSMAGIC,
+	CS_MAX_PATH_ATTRIBUTE
+} __packed;
+
+/* Index numbers for group entries. */
+enum cs_group_id {
+	CS_STRING_GROUP,
+	CS_NUMBER_GROUP,
+#ifdef CONFIG_SECURITY_CAITSITH_NETWORK
+	CS_IP_GROUP,
+#endif
+	CS_MAX_GROUP
+} __packed;
+
+/* Index numbers for functionality. */
+enum cs_mac_index {
+	CS_MAC_EXECUTE,
+	CS_MAC_READ,
+	CS_MAC_WRITE,
+	CS_MAC_APPEND,
+	CS_MAC_CREATE,
+	CS_MAC_UNLINK,
+#ifdef CONFIG_SECURITY_CAITSITH_GETATTR
+	CS_MAC_GETATTR,
+#endif
+	CS_MAC_MKDIR,
+	CS_MAC_RMDIR,
+	CS_MAC_MKFIFO,
+	CS_MAC_MKSOCK,
+	CS_MAC_TRUNCATE,
+	CS_MAC_SYMLINK,
+	CS_MAC_MKBLOCK,
+	CS_MAC_MKCHAR,
+	CS_MAC_LINK,
+	CS_MAC_RENAME,
+	CS_MAC_CHMOD,
+	CS_MAC_CHOWN,
+	CS_MAC_CHGRP,
+	CS_MAC_IOCTL,
+	CS_MAC_CHROOT,
+	CS_MAC_MOUNT,
+	CS_MAC_UMOUNT,
+	CS_MAC_PIVOT_ROOT,
+#ifdef CONFIG_SECURITY_CAITSITH_NETWORK
+	CS_MAC_INET_STREAM_BIND,
+	CS_MAC_INET_STREAM_LISTEN,
+	CS_MAC_INET_STREAM_CONNECT,
+	CS_MAC_INET_STREAM_ACCEPT,
+	CS_MAC_INET_DGRAM_BIND,
+	CS_MAC_INET_DGRAM_SEND,
+	CS_MAC_INET_RAW_BIND,
+	CS_MAC_INET_RAW_SEND,
+	CS_MAC_UNIX_STREAM_BIND,
+	CS_MAC_UNIX_STREAM_LISTEN,
+	CS_MAC_UNIX_STREAM_CONNECT,
+	CS_MAC_UNIX_STREAM_ACCEPT,
+	CS_MAC_UNIX_DGRAM_BIND,
+	CS_MAC_UNIX_DGRAM_SEND,
+	CS_MAC_UNIX_SEQPACKET_BIND,
+	CS_MAC_UNIX_SEQPACKET_LISTEN,
+	CS_MAC_UNIX_SEQPACKET_CONNECT,
+	CS_MAC_UNIX_SEQPACKET_ACCEPT,
+#endif
+#ifdef CONFIG_SECURITY_CAITSITH_ENVIRON
+	CS_MAC_ENVIRON,
+#endif
+	CS_MAC_MODIFY_POLICY,
+#ifdef CONFIG_SECURITY_CAITSITH_CAPABILITY
+	CS_MAC_USE_NETLINK_SOCKET,
+	CS_MAC_USE_PACKET_SOCKET,
+#endif
+#ifdef CONFIG_SECURITY_CAITSITH_AUTO_DOMAIN_TRANSITION
+	CS_MAC_AUTO_DOMAIN_TRANSITION,
+#endif
+#ifdef CONFIG_SECURITY_CAITSITH_MANUAL_DOMAIN_TRANSITION
+	CS_MAC_MANUAL_DOMAIN_TRANSITION,
+#endif
+	CS_MAX_MAC_INDEX,
+	/* Map undefined functions to CS_MAX_MAC_INDEX */
+#ifndef CONFIG_SECURITY_CAITSITH_GETATTR
+	CS_MAC_GETATTR = CS_MAX_MAC_INDEX,
+#endif
+#ifndef CONFIG_SECURITY_CAITSITH_NETWORK
+	CS_MAC_INET_STREAM_BIND = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_STREAM_LISTEN = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_STREAM_CONNECT = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_STREAM_ACCEPT = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_DGRAM_BIND = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_DGRAM_SEND = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_RAW_BIND = CS_MAX_MAC_INDEX,
+	CS_MAC_INET_RAW_SEND = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_STREAM_BIND = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_STREAM_LISTEN = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_STREAM_CONNECT = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_STREAM_ACCEPT = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_DGRAM_BIND = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_DGRAM_SEND = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_SEQPACKET_BIND = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_SEQPACKET_LISTEN = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_SEQPACKET_CONNECT = CS_MAX_MAC_INDEX,
+	CS_MAC_UNIX_SEQPACKET_ACCEPT = CS_MAX_MAC_INDEX,
+#endif
+#ifndef CONFIG_SECURITY_CAITSITH_ENVIRON
+	CS_MAC_ENVIRON = CS_MAX_MAC_INDEX,
+#endif
+#ifndef CONFIG_SECURITY_CAITSITH_CAPABILITY
+	CS_MAC_USE_NETLINK_SOCKET = CS_MAX_MAC_INDEX,
+	CS_MAC_USE_PACKET_SOCKET = CS_MAX_MAC_INDEX,
+#endif
+#ifndef CONFIG_SECURITY_CAITSITH_AUTO_DOMAIN_TRANSITION
+	CS_MAC_AUTO_DOMAIN_TRANSITION = CS_MAX_MAC_INDEX,
+#endif
+#ifndef CONFIG_SECURITY_CAITSITH_MANUAL_DOMAIN_TRANSITION
+	CS_MAC_MANUAL_DOMAIN_TRANSITION = CS_MAX_MAC_INDEX,
+#endif
+} __packed;
+
+/* Index numbers for statistic information. */
+enum cs_memory_stat_type {
+	CS_MEMORY_POLICY,
+	CS_MEMORY_AUDIT,
+	CS_MEMORY_QUERY,
+	CS_MAX_MEMORY_STAT
+} __packed;
+
+enum cs_matching_result {
+	CS_MATCHING_UNMATCHED,
+	CS_MATCHING_ALLOWED,
+	CS_MATCHING_DENIED,
+	CS_MAX_MATCHING
+} __packed;
+
+/* Index numbers for stat(). */
+enum cs_path_stat_index {
+	/* Do not change this order. */
+	CS_PATH1,
+	CS_PATH1_PARENT,
+	CS_PATH2,
+	CS_PATH2_PARENT,
+	CS_MAX_PATH_STAT
+} __packed;
+
+/* Index numbers for entry type. */
+enum cs_policy_id {
+	CS_ID_GROUP,
+#ifdef CONFIG_SECURITY_CAITSITH_NETWORK
+	CS_ID_IP_GROUP,
+#endif
+	CS_ID_STRING_GROUP,
+	CS_ID_NUMBER_GROUP,
+	CS_ID_CONDITION,
+	CS_ID_NAME,
+	CS_ID_ACL,
+	CS_ID_DOMAIN,
+	CS_MAX_POLICY
+} __packed;
+
+/* Index numbers for statistic information. */
+enum cs_policy_stat_type {
+	CS_STAT_POLICY_UPDATES,
+	CS_STAT_REQUEST_DENIED,
+	CS_MAX_POLICY_STAT
+} __packed;
+
+/* Index numbers for /sys/kernel/security/caitsith/ interfaces. */
+enum cs_securityfs_interface_index {
+	CS_POLICY,
+	CS_PROCESS_STATUS,
+	CS_AUDIT,
+	CS_VERSION,
+	CS_QUERY,
+} __packed;
+
+/* Index numbers for special mount operations. */
+enum cs_special_mount {
+	CS_MOUNT_BIND,            /* mount --bind /source /dest   */
+	CS_MOUNT_MOVE,            /* mount --move /old /new       */
+	CS_MOUNT_REMOUNT,         /* mount -o remount /dir        */
+	CS_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */
+	CS_MOUNT_MAKE_PRIVATE,    /* mount --make-private /dir    */
+	CS_MOUNT_MAKE_SLAVE,      /* mount --make-slave /dir      */
+	CS_MOUNT_MAKE_SHARED,     /* mount --make-shared /dir     */
+	CS_MAX_SPECIAL_MOUNT
+} __packed;
+
+/* Index numbers for type of numeric values. */
+enum cs_value_type {
+	CS_VALUE_TYPE_INVALID,
+	CS_VALUE_TYPE_DECIMAL,
+	CS_VALUE_TYPE_OCTAL,
+	CS_VALUE_TYPE_HEXADECIMAL,
+} __packed;
+
+/* Constants definition for internal use. */
+
+/*
+ * CaitSith uses this hash only when appending a string into the string table.
+ * Frequency of appending strings is very low. So we don't need large (e.g.
+ * 64k) hash size. 256 will be sufficient.
+ */
+#define CS_HASH_BITS 8
+#define CS_MAX_HASH (1u << CS_HASH_BITS)
+
+/*
+ * CaitSith checks only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET.
+ * Therefore, we don't need SOCK_MAX.
+ */
+#define CS_SOCK_MAX 6
+
+/* Size of temporary buffer for execve() operation. */
+#define CS_EXEC_TMPSIZE     4096
+
+/* Patterns for auditing logs quota. */
+#define CS_MAX_LOG_QUOTA 256
+
+/* Garbage collector is trying to kfree() this element. */
+#define CS_GC_IN_PROGRESS -1
+
+/* Current thread is doing open(3) ? */
+#define CS_OPEN_FOR_IOCTL_ONLY           2
+/* Current thread is doing do_execve() ? */
+#define CS_TASK_IS_IN_EXECVE             4
+/*
+ * Current thread is allowed to modify policy via
+ * /sys/kernel/security/caitsith/ interface?
+ */
+#define CS_TASK_IS_MANAGER               8
+
+/*
+ * Retry this request. Returned by cs_supervisor() if policy violation has
+ * occurred in enforcing mode and the userspace daemon decided to retry.
+ *
+ * We must choose a positive value in order to distinguish "granted" (which is
+ * 0) and "rejected" (which is a negative value) and "retry".
+ */
+#define CS_RETRY_REQUEST 1
+
+/* Size of read buffer for /sys/kernel/security/caitsith/ interface. */
+#define CS_MAX_IO_READ_QUEUE 64
+
+/* Structure definition for internal use. */
+
+/* Common header for holding ACL entries. */
+struct cs_acl_head {
+	struct list_head list;
+	s8 is_deleted; /* true or false or CS_GC_IN_PROGRESS */
+} __packed;
+
+/* Common header for shared entries. */
+struct cs_shared_acl_head {
+	struct list_head list;
+	atomic_t users;
+} __packed;
+
+/* Common header for individual entries. */
+struct cs_acl_info {
+	struct list_head list;
+	struct list_head acl_info_list;
+	struct cs_condition *cond; /* Maybe NULL. */
+	bool is_deleted;
+	bool is_deny;
+	u16 priority;
+	u8 audit;
+};
+
+/* Structure for "string_group"/"number_group"/"ip_group" directive. */
+struct cs_group {
+	struct cs_shared_acl_head head;
+	/* Name of group (without leading "@"). */
+	const struct cs_path_info *group_name;
+	/*
+	 * List of "struct cs_string_group" or "struct cs_number_group" or
+	 * "struct cs_ip_group".
+	 */
+	struct list_head member_list;
+};
+
+/* Structure for "string_group" directive. */
+struct cs_string_group {
+	struct cs_acl_head head;
+	const struct cs_path_info *member_name;
+};
+
+/* Structure for "number_group" directive. */
+struct cs_number_group {
+	struct cs_acl_head head;
+	u8 radix;
+	unsigned long value[2];
+};
+
+/* Structure for "ip_group" directive. */
+struct cs_ip_group {
+	struct cs_acl_head head;
+	bool is_ipv6;
+	/* Structure for holding an IP address. */
+	struct in6_addr ip[2]; /* Big endian. */
+};
+
+/* Subset of "struct stat". Used by conditional ACL and audit logs. */
+struct cs_mini_stat {
+	kuid_t uid;
+	kgid_t gid;
+	ino_t ino;
+	umode_t mode;
+	dev_t dev;
+	dev_t rdev;
+	unsigned long fsmagic;
+};
+
+/* Structure for dumping argv[] and envp[] of "struct linux_binprm". */
+struct cs_page_dump {
+	struct page *page;    /* Previously dumped page. */
+	char *data;           /* Contents of "page". Size is PAGE_SIZE. */
+};
+
+/* Structure for entries which follows "struct cs_condition". */
+union cs_condition_element {
+	struct {
+		enum cs_conditions_index left;
+		enum cs_conditions_index right;
+		bool is_not;
+		u8 radix;
+	};
+	struct cs_group *group;
+	const struct cs_path_info *path;
+	u32 ip; /* Repeat 4 times if IPv6 address. */
+	unsigned long value;
+};
+
+/* Structure for optional arguments. */
+struct cs_condition {
+	struct cs_shared_acl_head head;
+	u32 size; /* Memory size allocated for this entry. */
+	/* union cs_condition_element condition[]; */
+};
+
+/* Structure for holding a token. */
+struct cs_path_info {
+	const char *name;
+	u32 hash;          /* = full_name_hash(name, strlen(name)) */
+	u32 total_len;     /* = strlen(name)                       */
+	u32 const_len;     /* = cs_const_part_length(name)        */
+};
+
+/* Structure for request info. */
+struct cs_request_info {
+	/* For holding parameters. */
+	struct cs_request_param {
+		const struct cs_path_info *s[4];
+		unsigned long i[3];
+#ifdef CONFIG_SECURITY_CAITSITH_NETWORK
+		const u8 *ip; /* Big endian. */
+		bool is_ipv6;
+#endif
+	} param;
+	/* For holding pathnames and attributes. */
+	struct {
+		/*
+		 * True if cs_get_attributes() was already called, false
+		 * otherwise.
+		 */
+		bool validate_done;
+		/* True if @stat[] is valid. */
+		bool stat_valid[CS_MAX_PATH_STAT];
+		/* Pointer to file objects. */
+		struct path path[2];
+		/*
+		 * Information on @path[0], @path[0]'s parent directory,
+		 * @path[1] and @path[1]'s parent directory.
+		 */
+		struct cs_mini_stat stat[CS_MAX_PATH_STAT];
+		/*
+		 * Name of @path[0] and @path[1].
+		 * Cleared by cs_clear_request_info().
+		 */
+		struct cs_path_info pathname[2];
+	} obj;
+	struct {
+		struct linux_binprm *bprm;
+		struct cs_domain_info *previous_domain;
+		/* For dumping argv[] and envp[]. */
+		struct cs_page_dump dump;
+		/* For temporary use. Size is CS_EXEC_TMPSIZE bytes. */
+		char *tmp;
+	};
+	/*
+	 * Name of current thread's executable.
+	 * Cleared by cs_clear_request_info().
+	 */
+	struct cs_path_info exename;
+	/*
+	 * Matching "struct cs_acl_info" is copied. Used for caitsith-queryd.
+	 * Valid until cs_read_unlock().
+	 */
+	struct cs_acl_info *matched_acl;
+	/*
+	 * Matching domain transition is copied.
+	 * Valid until cs_read_unlock().
+	 */
+	const struct cs_path_info *transition;
+	const struct cs_path_info *transition_candidate;
+	/*
+	 * For holding operation index used for this request.
+	 * One of values in "enum cs_mac_index".
+	 */
+	enum cs_mac_index type;
+	/* For holding matching result. */
+	enum cs_matching_result result;
+	/*
+	 * For counting number of retries made for this request.
+	 * This counter is incremented whenever cs_supervisor() returned
+	 * CS_RETRY_REQUEST.
+	 */
+	u8 retry;
+	/* For holding max audit log count for this matching entry. */
+	u8 audit;
+	/*
+	 * Set to true if condition could not be checked due to out of memory.
+	 * This flag is used for returning out of memory flag back to
+	 * cs_check_acl_list(). Thus, this flag will not be set if out of
+	 * memory occurred before cs_check_acl_list() is called.
+	 */
+	bool failed_by_oom;
+};
+
+/* Structure for domain information. */
+struct cs_domain_info {
+	struct list_head list;
+	/* Name of this domain. Never NULL. */
+	const struct cs_path_info *domainname;
+};
+
+/* Structure for holding string data. */
+struct cs_name {
+	struct cs_shared_acl_head head;
+	int size; /* Memory size allocated for this entry. */
+	struct cs_path_info entry;
+};
+
+/*
+ * Structure for reading/writing policy via /sys/kernel/security/caitsith/
+ * interfaces.
+ */
+struct cs_io_buffer {
+	/* Exclusive lock for this structure.   */
+	struct mutex io_sem;
+	char __user *read_user_buf;
+	size_t read_user_buf_avail;
+	struct {
+		struct list_head *group;
+		struct list_head *acl;
+		struct list_head *subacl;
+		const union cs_condition_element *cond;
+		size_t avail;
+		unsigned int step;
+		unsigned int query_index;
+		u16 index;
+		u8 cond_step;
+		u8 w_pos;
+		enum cs_mac_index acl_index;
+		bool eof;
+		bool print_this_acl_only;
+		bool version_done;
+		bool stat_done;
+		bool quota_done;
+		bool group_done;
+		const char *w[CS_MAX_IO_READ_QUEUE];
+	} r;
+	struct {
+		char *data;
+		struct cs_acl_info *acl;
+		size_t avail;
+		enum cs_mac_index acl_index;
+		bool is_delete;
+		bool is_deny;
+		u16 priority;
+	} w;
+	/* Buffer for reading.                  */
+	char *read_buf;
+	/* Size of read buffer.                 */
+	size_t readbuf_size;
+	/* Buffer for writing.                  */
+	char *write_buf;
+	/* Size of write buffer.                */
+	size_t writebuf_size;
+	/* Type of interface. */
+	enum cs_securityfs_interface_index type;
+	/* Users counter protected by cs_io_buffer_list_lock. */
+	u8 users;
+	/* List for telling GC not to kfree() elements. */
+	struct list_head list;
+};
+
+/* Structure for representing YYYY/MM/DD hh/mm/ss. */
+struct cs_time {
+	u16 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 min;
+	u8 sec;
+};
+
+/* Prototype definition for internal use. */
+
+int __init cs_init_module(void);
+void cs_check_profile(void);
+bool cs_dump_page(struct linux_binprm *bprm, unsigned long pos,
+		  struct cs_page_dump *dump);
+bool cs_get_exename(struct cs_path_info *buf);
+bool cs_manager(void);
+bool cs_transit_domain(const char *domainname);
+char *cs_encode(const char *str);
+char *cs_encode2(const char *str, int str_len);
+char *cs_realpath(const struct path *path);
+char *cs_get_exe(void);
+int cs_audit_log(struct cs_request_info *r);
+int cs_check_acl(struct cs_request_info *r, const bool clear);
+void cs_del_condition(struct list_head *element);
+void cs_fill_path_info(struct cs_path_info *ptr);
+void cs_get_attributes(struct cs_request_info *r);
+void cs_notify_gc(struct cs_io_buffer *head, const bool is_register);
+void cs_populate_patharg(struct cs_request_info *r, const bool first);
+void cs_transition_failed(const char *domainname);
+void cs_warn_oom(const char *function);
+int cs_chroot_permission(const struct path *path);
+int cs_chmod_permission(const struct path *path, mode_t mode);
+int cs_chown_permission(const struct path *path, kuid_t user, kgid_t group);
+int cs_fcntl_permission(struct file *file, unsigned int cmd,
+			unsigned long arg);
+int cs_ioctl_permission(struct file *filp, unsigned int cmd,
+			unsigned long arg);
+int cs_link_permission(const struct path *old, const struct path *new);
+int cs_mkdir_permission(const struct path *path, unsigned int mode);
+int cs_mknod_permission(const struct path *path, const unsigned int mode,
+			unsigned int dev);
+int cs_mount_permission(const char *dev_name, const struct path *path,
+			const char *type, unsigned long flags,
+			void *data_page);
+int cs_move_mount_permission(const struct path *from_path,
+			     const struct path *to_path);
+int cs_pivot_root_permission(const struct path *old_path,
+			     const struct path *new_path);
+int cs_rename_permission(const struct path *old, const struct path *new);
+int cs_symlink_permission(const struct path *path, const char *from);
+int cs_truncate_permission(const struct path *path);
+int cs_umount_permission(const struct path *path, int flags);
+int cs_unlink_permission(const struct path *path);
+int cs_socket_create_permission(int family, int type, int protocol);
+int cs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
+			      int addr_len);
+int cs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
+				 int addr_len);
+int cs_socket_listen_permission(struct socket *sock);
+int cs_socket_post_accept_permission(struct socket *sock,
+				     struct socket *newsock);
+int cs_socket_sendmsg_permission(struct socket *sock,
+				 struct msghdr *msg, int size);
+int cs_rmdir_permission(const struct path *path);
+int cs_getattr_permission(const struct path *path);
+bool cs_capable(const u8 operation);
+int cs_open_permission(const struct path *path, const int flag);
+
+/* Variable definition for internal use. */
+
+extern bool cs_policy_loaded;
+extern struct cs_domain_info cs_kernel_domain;
+extern struct cs_path_info cs_null_name;
+extern struct list_head cs_acl_list[CS_MAX_MAC_INDEX];
+extern struct list_head cs_condition_list;
+extern struct list_head cs_domain_list;
+extern struct list_head cs_group_list[CS_MAX_GROUP];
+extern struct list_head cs_name_list[CS_MAX_HASH];
+extern struct mutex cs_policy_lock;
+extern struct srcu_struct cs_ss;
+extern unsigned int cs_memory_used[CS_MAX_MEMORY_STAT];
+
+/* Inlined functions for internal use. */
+
+/**
+ * cs_pathcmp - strcmp() for "struct cs_path_info" structure.
+ *
+ * @a: Pointer to "struct cs_path_info".
+ * @b: Pointer to "struct cs_path_info".
+ *
+ * Returns true if @a != @b, false otherwise.
+ */
+static inline bool cs_pathcmp(const struct cs_path_info *a,
+			      const struct cs_path_info *b)
+{
+	return a->hash != b->hash || strcmp(a->name, b->name);
+}
+
+/**
+ * cs_read_lock - Take lock for protecting policy.
+ *
+ * Returns index number for cs_read_unlock().
+ */
+static inline int cs_read_lock(void)
+{
+	return srcu_read_lock(&cs_ss);
+}
+
+/**
+ * cs_read_unlock - Release lock for protecting policy.
+ *
+ * @idx: Index number returned by cs_read_lock().
+ *
+ * Returns nothing.
+ */
+static inline void cs_read_unlock(const int idx)
+{
+	srcu_read_unlock(&cs_ss, idx);
+}
+
+/**
+ * cs_sys_getppid - Copy of getppid().
+ *
+ * Returns parent process's PID.
+ *
+ * Alpha does not have getppid() defined. To be able to build this module on
+ * Alpha, I have to copy getppid() from kernel/timer.c.
+ */
+static inline pid_t cs_sys_getppid(void)
+{
+	pid_t pid;
+
+	rcu_read_lock();
+	pid = task_tgid_vnr(rcu_dereference(current->real_parent));
+	rcu_read_unlock();
+	return pid;
+}
+
+/**
+ * cs_sys_getpid - Copy of getpid().
+ *
+ * Returns current thread's PID.
+ *
+ * Alpha does not have getpid() defined. To be able to build this module on
+ * Alpha, I have to copy getpid() from kernel/timer.c.
+ */
+static inline pid_t cs_sys_getpid(void)
+{
+	return task_tgid_vnr(current);
+}
+
+/**
+ * cs_put_condition - Drop reference on "struct cs_condition".
+ *
+ * @cond: Pointer to "struct cs_condition". Maybe NULL.
+ *
+ * Returns nothing.
+ */
+static inline void cs_put_condition(struct cs_condition *cond)
+{
+	if (cond)
+		atomic_dec(&cond->head.users);
+}
+
+/**
+ * cs_put_group - Drop reference on "struct cs_group".
+ *
+ * @group: Pointer to "struct cs_group". Maybe NULL.
+ *
+ * Returns nothing.
+ */
+static inline void cs_put_group(struct cs_group *group)
+{
+	if (group)
+		atomic_dec(&group->head.users);
+}
+
+/**
+ * cs_put_name - Drop reference on "struct cs_name".
+ *
+ * @name: Pointer to "struct cs_path_info". Maybe NULL.
+ *
+ * Returns nothing.
+ */
+static inline void cs_put_name(const struct cs_path_info *name)
+{
+	if (name)
+		atomic_dec(&container_of(name, struct cs_name, entry)->
+			   head.users);
+}
+
+/*
+ * Structure for holding "struct cs_domain_info *" and "u32 cs_flags" for
+ * each "struct task_struct".
+ *
+ * "struct cs_domain_info *" and "u32 cs_flags" for each "struct task_struct"
+ * are maintained outside that "struct task_struct". Therefore, cs_security
+ * != task_struct . This keeps KABI for distributor's prebuilt kernels but
+ * entails slow access.
+ *
+ * Memory for this structure is allocated when current thread tries to access
+ * it. Therefore, if memory allocation failed, current thread will be killed by
+ * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
+ */
+struct cs_security {
+	struct list_head list;
+	const struct task_struct *task;
+	struct cs_domain_info *cs_domain_info;
+	u32 cs_flags;
+	struct cs_request_info *r; /* Maybe NULL. */
+	struct rcu_head rcu;
+};
+
+void __init cs_main_init(void);
+bool cs_used_by_cred(const struct cs_domain_info *domain);
+int cs_start_execve(struct linux_binprm *bprm, struct cs_request_info **rp);
+void cs_finish_execve(int retval, struct cs_request_info *r);
+int cs_sysctl_permission(enum cs_mac_index type,
+			 const struct cs_path_info *filename);
+
+#define CS_TASK_SECURITY_HASH_BITS 12
+#define CS_MAX_TASK_SECURITY_HASH (1u << CS_TASK_SECURITY_HASH_BITS)
+extern struct list_head cs_task_security_list[CS_MAX_TASK_SECURITY_HASH];
+
+struct cs_security *cs_find_task_security(const struct task_struct *task);
+
+/**
+ * cs_current_security - Get "struct cs_security" for current thread.
+ *
+ * Returns pointer to "struct cs_security" for current thread.
+ */
+static inline struct cs_security *cs_current_security(void)
+{
+	return cs_find_task_security(current);
+}
+
+/**
+ * cs_task_domain - Get "struct cs_domain_info" for specified thread.
+ *
+ * @task: Pointer to "struct task_struct".
+ *
+ * Returns pointer to "struct cs_security" for specified thread.
+ */
+static inline struct cs_domain_info *cs_task_domain(struct task_struct *task)
+{
+	struct cs_domain_info *domain;
+
+	rcu_read_lock();
+	domain = cs_find_task_security(task)->cs_domain_info;
+	rcu_read_unlock();
+	return domain;
+}
+
+/**
+ * cs_current_domain - Get "struct cs_domain_info" for current thread.
+ *
+ * Returns pointer to "struct cs_domain_info" for current thread.
+ */
+static inline struct cs_domain_info *cs_current_domain(void)
+{
+	return cs_find_task_security(current)->cs_domain_info;
+}
+
+/**
+ * cs_task_flags - Get flags for specified thread.
+ *
+ * @task: Pointer to "struct task_struct".
+ *
+ * Returns flags for specified thread.
+ */
+static inline u32 cs_task_flags(struct task_struct *task)
+{
+	u32 cs_flags;
+
+	rcu_read_lock();
+	cs_flags = cs_find_task_security(task)->cs_flags;
+	rcu_read_unlock();
+	return cs_flags;
+}
+
+/**
+ * cs_current_flags - Get flags for current thread.
+ *
+ * Returns flags for current thread.
+ */
+static inline u32 cs_current_flags(void)
+{
+	return cs_find_task_security(current)->cs_flags;
+}
+
+#endif