Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-26 Thread Andreas Grünbacher
2015-06-25 23:40 GMT+02:00 Stefan (metze) Metzmacher :
>>> I'm wondering if the size of an ace should be dynamic,
>>> which might make it possible to support other ace types
>>> in future. E.g. supporting other identities like 128-bit values
>>> to make it easier to map Windows SIDS.
>>
>> I'm working on additionally supporting unmapped user@domain and
>> group@domain identifier strings; we have to deal with that case in the
>> nfs client; that may be useful for Samba as well.
>
> Can this be any string? So would
> "S-1-5-21-4052121579-2079768045-1474639452-1001" also work?

I don't see why not, we'd just need to prevent namespace clashes.

> How would the current thread/process get a "token" that would match such
> an ace?

Solaris seems to solve this by what they call ephemeral ids; that concept may
become useful.

> [...]
> In general shouldn't kuid_t uid = current_fsuid(); be at the top of the
> function just once?

It really is just a pointer dereference.

Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-26 Thread Andreas Grünbacher
2015-06-25 23:40 GMT+02:00 Stefan (metze) Metzmacher me...@samba.org:
 I'm wondering if the size of an ace should be dynamic,
 which might make it possible to support other ace types
 in future. E.g. supporting other identities like 128-bit values
 to make it easier to map Windows SIDS.

 I'm working on additionally supporting unmapped user@domain and
 group@domain identifier strings; we have to deal with that case in the
 nfs client; that may be useful for Samba as well.

 Can this be any string? So would
 S-1-5-21-4052121579-2079768045-1474639452-1001 also work?

I don't see why not, we'd just need to prevent namespace clashes.

 How would the current thread/process get a token that would match such
 an ace?

Solaris seems to solve this by what they call ephemeral ids; that concept may
become useful.

 [...]
 In general shouldn't kuid_t uid = current_fsuid(); be at the top of the
 function just once?

It really is just a pointer dereference.

Thanks,
Andreas
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-25 Thread Stefan (metze) Metzmacher
Hi Andreas,

>> I'm wondering if the size of an ace should be dynamic,
>> which might make it possible to support other ace types
>> in future. E.g. supporting other identities like 128-bit values
>> to make it easier to map Windows SIDS.
> 
> I'm working on additionally supporting unmapped user@domain and
> group@domain identifier strings; we have to deal with that case in the
> nfs client; that may be useful for Samba as well.

Can this be any string? So would
"S-1-5-21-4052121579-2079768045-1474639452-1001" also work?

How would the current thread/process get a "token" that would match such
an ace?

>> Even without 128-bit ids, it would be very useful to mark an
>> ace so that it applies to a uid or gid at the same time.
>> This would reduce the size of the ace list when Samba uses
>> IDMAP_TYPE_BOTH, which means a SID is mapped to a unix id, which
>> is user (uid) and group (gid) at the same time. This feature is required
>> in order to support SID-Histories on accounts.
>> Currently Samba needs to add two aces (one uid and one gid)
>> in order to represent one Windows ace.
> 
> It's not clear to me if supporting this would be a good idea right now.
> The kernel would have to treat each such entry like two separate entries
> internally. How would we map a combined user-space "uid + gid"
> number to a kernel uid and gid since it could map to two distinct
> numbers there?

No, the numeric value is the same.

I think richacl_permission() is the only place that requires any action.

richacl_for_each_entry(ace, acl) {
unsigned int ace_mask = ace->e_mask;

if (richace_is_inherit_only(ace))
continue;
if (richace_is_owner(ace)) {
if (!uid_eq(current_fsuid(), inode->i_uid))
continue;
} else if (richace_is_group(ace)) {
if (!in_owning_group)
continue;
+   } else if (richace_is_unix_both(ace)) {
+   kuid_t uid = current_fsuid();
+
+   if (!uid_eq(uid, ace->e_id.xid) && 
!in_group_p(ace->e_id.xid))
+   continue;
} else if (richace_is_unix_user(ace)) {
kuid_t uid = current_fsuid();

if (!uid_eq(uid, ace->e_id.uid))
continue;
} else if (richace_is_unix_group(ace)) {
if (!in_group_p(ace->e_id.gid))
continue;
} else
goto entry_matches_everyone;

In general shouldn't kuid_t uid = current_fsuid(); be at the top of the
function just once?

>> I haven't looked at the claims based acls on Windows, but it would be
>> good if the new infrastructure is dynamic enough to support something
>> like that in a future version.
> 
> I don't know, I have yet to see a use case that isn't totally crazy.

Ok, I found the a_version in struct richacl_xattr.

metze



signature.asc
Description: OpenPGP digital signature


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-25 Thread Andreas Grünbacher
Hi,

2015-06-25 21:58 GMT+02:00 Stefan (metze) Metzmacher :
> Is that also the on disk representation?

that's not the xattr representation, no.

> I'm wondering if the size of an ace should be dynamic,
> which might make it possible to support other ace types
> in future. E.g. supporting other identities like 128-bit values
> to make it easier to map Windows SIDS.

I'm working on additionally supporting unmapped user@domain and
group@domain identifier strings; we have to deal with that case in the
nfs client; that may be useful for Samba as well.

> Even without 128-bit ids, it would be very useful to mark an
> ace so that it applies to a uid or gid at the same time.
> This would reduce the size of the ace list when Samba uses
> IDMAP_TYPE_BOTH, which means a SID is mapped to a unix id, which
> is user (uid) and group (gid) at the same time. This feature is required
> in order to support SID-Histories on accounts.
> Currently Samba needs to add two aces (one uid and one gid)
> in order to represent one Windows ace.

It's not clear to me if supporting this would be a good idea right now.
The kernel would have to treat each such entry like two separate entries
internally. How would we map a combined user-space "uid + gid"
number to a kernel uid and gid since it could map to two distinct
numbers there?

> I haven't looked at the claims based acls on Windows, but it would be
> good if the new infrastructure is dynamic enough to support something
> like that in a future version.

I don't know, I have yet to see a use case that isn't totally crazy.

Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-25 Thread Stefan (metze) Metzmacher
Hi Andreas,

> +#define RICHACE_OWNER_SPECIAL_ID 0
> +#define RICHACE_GROUP_SPECIAL_ID 1
> +#define RICHACE_EVERYONE_SPECIAL_ID  2
> +
> +struct richace {
> + unsigned short  e_type;
> + unsigned short  e_flags;
> + unsigned inte_mask;
> + union {
> + kuid_t  uid;
> + kgid_t  gid;
> + unsigned intspecial;
> + } e_id;
> +};
> +
> +struct richacl {
> + atomic_ta_refcount;
> + unsigned inta_owner_mask;
> + unsigned inta_group_mask;
> + unsigned inta_other_mask;
> + unsigned short  a_count;
> + unsigned short  a_flags;
> + struct richace  a_entries[0];
> +};

Is that also the on disk representation?

I'm wondering if the size of an ace should be dynamic,
which might make it possible to support other ace types
in future. E.g. supporting other identities like 128-bit values
to make it easier to map Windows SIDS.

Even without 128-bit ids, it would be very useful to mark an
ace so that it applies to a uid or gid at the same time.
This would reduce the size of the ace list when Samba uses
IDMAP_TYPE_BOTH, which means a SID is mapped to a unix id, which
is user (uid) and group (gid) at the same time. This feature is required
in order to support SID-Histories on accounts.
Currently Samba needs to add two aces (one uid and one gid)
in order to represent one Windows ace.

I haven't looked at the claims based acls on Windows, but it would be
good if the new infrastructure is dynamic enough to support something
like that in a future version.

Thanks very much on your persistent to bring richacls forward!

metze



signature.asc
Description: OpenPGP digital signature


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-25 Thread Stefan (metze) Metzmacher
Hi Andreas,

 +#define RICHACE_OWNER_SPECIAL_ID 0
 +#define RICHACE_GROUP_SPECIAL_ID 1
 +#define RICHACE_EVERYONE_SPECIAL_ID  2
 +
 +struct richace {
 + unsigned short  e_type;
 + unsigned short  e_flags;
 + unsigned inte_mask;
 + union {
 + kuid_t  uid;
 + kgid_t  gid;
 + unsigned intspecial;
 + } e_id;
 +};
 +
 +struct richacl {
 + atomic_ta_refcount;
 + unsigned inta_owner_mask;
 + unsigned inta_group_mask;
 + unsigned inta_other_mask;
 + unsigned short  a_count;
 + unsigned short  a_flags;
 + struct richace  a_entries[0];
 +};

Is that also the on disk representation?

I'm wondering if the size of an ace should be dynamic,
which might make it possible to support other ace types
in future. E.g. supporting other identities like 128-bit values
to make it easier to map Windows SIDS.

Even without 128-bit ids, it would be very useful to mark an
ace so that it applies to a uid or gid at the same time.
This would reduce the size of the ace list when Samba uses
IDMAP_TYPE_BOTH, which means a SID is mapped to a unix id, which
is user (uid) and group (gid) at the same time. This feature is required
in order to support SID-Histories on accounts.
Currently Samba needs to add two aces (one uid and one gid)
in order to represent one Windows ace.

I haven't looked at the claims based acls on Windows, but it would be
good if the new infrastructure is dynamic enough to support something
like that in a future version.

Thanks very much on your persistent to bring richacls forward!

metze



signature.asc
Description: OpenPGP digital signature


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-25 Thread Andreas Grünbacher
Hi,

2015-06-25 21:58 GMT+02:00 Stefan (metze) Metzmacher me...@samba.org:
 Is that also the on disk representation?

that's not the xattr representation, no.

 I'm wondering if the size of an ace should be dynamic,
 which might make it possible to support other ace types
 in future. E.g. supporting other identities like 128-bit values
 to make it easier to map Windows SIDS.

I'm working on additionally supporting unmapped user@domain and
group@domain identifier strings; we have to deal with that case in the
nfs client; that may be useful for Samba as well.

 Even without 128-bit ids, it would be very useful to mark an
 ace so that it applies to a uid or gid at the same time.
 This would reduce the size of the ace list when Samba uses
 IDMAP_TYPE_BOTH, which means a SID is mapped to a unix id, which
 is user (uid) and group (gid) at the same time. This feature is required
 in order to support SID-Histories on accounts.
 Currently Samba needs to add two aces (one uid and one gid)
 in order to represent one Windows ace.

It's not clear to me if supporting this would be a good idea right now.
The kernel would have to treat each such entry like two separate entries
internally. How would we map a combined user-space uid + gid
number to a kernel uid and gid since it could map to two distinct
numbers there?

 I haven't looked at the claims based acls on Windows, but it would be
 good if the new infrastructure is dynamic enough to support something
 like that in a future version.

I don't know, I have yet to see a use case that isn't totally crazy.

Thanks,
Andreas
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-25 Thread Stefan (metze) Metzmacher
Hi Andreas,

 I'm wondering if the size of an ace should be dynamic,
 which might make it possible to support other ace types
 in future. E.g. supporting other identities like 128-bit values
 to make it easier to map Windows SIDS.
 
 I'm working on additionally supporting unmapped user@domain and
 group@domain identifier strings; we have to deal with that case in the
 nfs client; that may be useful for Samba as well.

Can this be any string? So would
S-1-5-21-4052121579-2079768045-1474639452-1001 also work?

How would the current thread/process get a token that would match such
an ace?

 Even without 128-bit ids, it would be very useful to mark an
 ace so that it applies to a uid or gid at the same time.
 This would reduce the size of the ace list when Samba uses
 IDMAP_TYPE_BOTH, which means a SID is mapped to a unix id, which
 is user (uid) and group (gid) at the same time. This feature is required
 in order to support SID-Histories on accounts.
 Currently Samba needs to add two aces (one uid and one gid)
 in order to represent one Windows ace.
 
 It's not clear to me if supporting this would be a good idea right now.
 The kernel would have to treat each such entry like two separate entries
 internally. How would we map a combined user-space uid + gid
 number to a kernel uid and gid since it could map to two distinct
 numbers there?

No, the numeric value is the same.

I think richacl_permission() is the only place that requires any action.

richacl_for_each_entry(ace, acl) {
unsigned int ace_mask = ace-e_mask;

if (richace_is_inherit_only(ace))
continue;
if (richace_is_owner(ace)) {
if (!uid_eq(current_fsuid(), inode-i_uid))
continue;
} else if (richace_is_group(ace)) {
if (!in_owning_group)
continue;
+   } else if (richace_is_unix_both(ace)) {
+   kuid_t uid = current_fsuid();
+
+   if (!uid_eq(uid, ace-e_id.xid)  
!in_group_p(ace-e_id.xid))
+   continue;
} else if (richace_is_unix_user(ace)) {
kuid_t uid = current_fsuid();

if (!uid_eq(uid, ace-e_id.uid))
continue;
} else if (richace_is_unix_group(ace)) {
if (!in_group_p(ace-e_id.gid))
continue;
} else
goto entry_matches_everyone;

In general shouldn't kuid_t uid = current_fsuid(); be at the top of the
function just once?

 I haven't looked at the claims based acls on Windows, but it would be
 good if the new infrastructure is dynamic enough to support something
 like that in a future version.
 
 I don't know, I have yet to see a use case that isn't totally crazy.

Ok, I found the a_version in struct richacl_xattr.

metze



signature.asc
Description: OpenPGP digital signature


[RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-24 Thread Andreas Gruenbacher
A richacl consists of an NFSv4 acl and an owner, group, and other mask.
These three masks correspond to the owner, group, and other file
permission bits, but they contain NFSv4 permissions instead of POSIX
permissions.

Each entry in the NFSv4 acl applies to the file owner (OWNER@), the owning
group (GROUP@), everyone (EVERYONE@), or to a specific uid or gid.

As in the standard POSIX file permission model, each process is the
owner, group, or other file class.  A richacl grants a requested access
only if the NFSv4 acl in the richacl grants the access (according to the
NFSv4 permission check algorithm), and the file mask that applies to the
process includes the requested permissions.

Signed-off-by: Andreas Gruenbacher 
---
 fs/Makefile |   2 +
 fs/richacl_base.c   |  58 +++
 include/linux/richacl.h | 258 
 3 files changed, 318 insertions(+)
 create mode 100644 fs/richacl_base.c
 create mode 100644 include/linux/richacl.h

diff --git a/fs/Makefile b/fs/Makefile
index cb92fd4..654e716 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -47,6 +47,8 @@ obj-$(CONFIG_COREDUMP)+= coredump.o
 obj-$(CONFIG_SYSCTL)   += drop_caches.o
 
 obj-$(CONFIG_FHANDLE)  += fhandle.o
+obj-$(CONFIG_FS_RICHACL)   += richacl.o
+richacl-y  := richacl_base.o
 
 obj-y  += quota/
 
diff --git a/fs/richacl_base.c b/fs/richacl_base.c
new file mode 100644
index 000..164b902
--- /dev/null
+++ b/fs/richacl_base.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006, 2010  Novell, Inc.
+ * Copyright (C) 2015  Red Hat, Inc.
+ * Written by Andreas Gruenbacher 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+MODULE_LICENSE("GPL");
+
+/**
+ * richacl_alloc  -  allocate a richacl
+ * @count: number of entries
+ */
+struct richacl *
+richacl_alloc(int count, gfp_t gfp)
+{
+   size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+   struct richacl *acl = kzalloc(size, gfp);
+
+   if (acl) {
+   atomic_set(>a_refcount, 1);
+   acl->a_count = count;
+   }
+   return acl;
+}
+EXPORT_SYMBOL_GPL(richacl_alloc);
+
+/**
+ * richacl_clone  -  create a copy of a richacl
+ */
+struct richacl *
+richacl_clone(const struct richacl *acl, gfp_t gfp)
+{
+   int count = acl->a_count;
+   size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+   struct richacl *dup = kmalloc(size, gfp);
+
+   if (dup) {
+   memcpy(dup, acl, size);
+   atomic_set(>a_refcount, 1);
+   }
+   return dup;
+}
diff --git a/include/linux/richacl.h b/include/linux/richacl.h
new file mode 100644
index 000..feebc2f
--- /dev/null
+++ b/include/linux/richacl.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2006, 2010  Novell, Inc.
+ * Copyright (C) 2015  Red Hat, Inc.
+ * Written by Andreas Gruenbacher 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __RICHACL_H
+#define __RICHACL_H
+
+#define RICHACE_OWNER_SPECIAL_ID   0
+#define RICHACE_GROUP_SPECIAL_ID   1
+#define RICHACE_EVERYONE_SPECIAL_ID2
+
+struct richace {
+   unsigned short  e_type;
+   unsigned short  e_flags;
+   unsigned inte_mask;
+   union {
+   kuid_t  uid;
+   kgid_t  gid;
+   unsigned intspecial;
+   } e_id;
+};
+
+struct richacl {
+   atomic_ta_refcount;
+   unsigned inta_owner_mask;
+   unsigned inta_group_mask;
+   unsigned inta_other_mask;
+   unsigned short  a_count;
+   unsigned short  a_flags;
+   struct richace  a_entries[0];
+};
+
+#define richacl_for_each_entry(_ace, _acl) \
+   for (_ace = (_acl)->a_entries; \
+_ace != (_acl)->a_entries + (_acl)->a_count; \
+_ace++)
+
+#define richacl_for_each_entry_reverse(_ace, _acl) \
+   for (_ace = (_acl)->a_entries + (_acl)->a_count - 1; \
+_ace != 

[RFC v4 06/31] richacl: In-memory representation and helper functions

2015-06-24 Thread Andreas Gruenbacher
A richacl consists of an NFSv4 acl and an owner, group, and other mask.
These three masks correspond to the owner, group, and other file
permission bits, but they contain NFSv4 permissions instead of POSIX
permissions.

Each entry in the NFSv4 acl applies to the file owner (OWNER@), the owning
group (GROUP@), everyone (EVERYONE@), or to a specific uid or gid.

As in the standard POSIX file permission model, each process is the
owner, group, or other file class.  A richacl grants a requested access
only if the NFSv4 acl in the richacl grants the access (according to the
NFSv4 permission check algorithm), and the file mask that applies to the
process includes the requested permissions.

Signed-off-by: Andreas Gruenbacher agrue...@redhat.com
---
 fs/Makefile |   2 +
 fs/richacl_base.c   |  58 +++
 include/linux/richacl.h | 258 
 3 files changed, 318 insertions(+)
 create mode 100644 fs/richacl_base.c
 create mode 100644 include/linux/richacl.h

diff --git a/fs/Makefile b/fs/Makefile
index cb92fd4..654e716 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -47,6 +47,8 @@ obj-$(CONFIG_COREDUMP)+= coredump.o
 obj-$(CONFIG_SYSCTL)   += drop_caches.o
 
 obj-$(CONFIG_FHANDLE)  += fhandle.o
+obj-$(CONFIG_FS_RICHACL)   += richacl.o
+richacl-y  := richacl_base.o
 
 obj-y  += quota/
 
diff --git a/fs/richacl_base.c b/fs/richacl_base.c
new file mode 100644
index 000..164b902
--- /dev/null
+++ b/fs/richacl_base.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006, 2010  Novell, Inc.
+ * Copyright (C) 2015  Red Hat, Inc.
+ * Written by Andreas Gruenbacher agr...@kernel.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include linux/sched.h
+#include linux/module.h
+#include linux/fs.h
+#include linux/slab.h
+#include linux/richacl.h
+
+MODULE_LICENSE(GPL);
+
+/**
+ * richacl_alloc  -  allocate a richacl
+ * @count: number of entries
+ */
+struct richacl *
+richacl_alloc(int count, gfp_t gfp)
+{
+   size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+   struct richacl *acl = kzalloc(size, gfp);
+
+   if (acl) {
+   atomic_set(acl-a_refcount, 1);
+   acl-a_count = count;
+   }
+   return acl;
+}
+EXPORT_SYMBOL_GPL(richacl_alloc);
+
+/**
+ * richacl_clone  -  create a copy of a richacl
+ */
+struct richacl *
+richacl_clone(const struct richacl *acl, gfp_t gfp)
+{
+   int count = acl-a_count;
+   size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+   struct richacl *dup = kmalloc(size, gfp);
+
+   if (dup) {
+   memcpy(dup, acl, size);
+   atomic_set(dup-a_refcount, 1);
+   }
+   return dup;
+}
diff --git a/include/linux/richacl.h b/include/linux/richacl.h
new file mode 100644
index 000..feebc2f
--- /dev/null
+++ b/include/linux/richacl.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2006, 2010  Novell, Inc.
+ * Copyright (C) 2015  Red Hat, Inc.
+ * Written by Andreas Gruenbacher agr...@kernel.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __RICHACL_H
+#define __RICHACL_H
+
+#define RICHACE_OWNER_SPECIAL_ID   0
+#define RICHACE_GROUP_SPECIAL_ID   1
+#define RICHACE_EVERYONE_SPECIAL_ID2
+
+struct richace {
+   unsigned short  e_type;
+   unsigned short  e_flags;
+   unsigned inte_mask;
+   union {
+   kuid_t  uid;
+   kgid_t  gid;
+   unsigned intspecial;
+   } e_id;
+};
+
+struct richacl {
+   atomic_ta_refcount;
+   unsigned inta_owner_mask;
+   unsigned inta_group_mask;
+   unsigned inta_other_mask;
+   unsigned short  a_count;
+   unsigned short  a_flags;
+   struct richace  a_entries[0];
+};
+
+#define richacl_for_each_entry(_ace, _acl) \
+   for (_ace = (_acl)-a_entries; \
+_ace != (_acl)-a_entries + (_acl)-a_count; \
+_ace++)
+
+#define