From: NeilBrown Basic v4 acl definitions, to be used by server ACL implementation Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- 25-akpm/fs/nfsd/Makefile | 3 25-akpm/fs/nfsd/nfs4acl.c | 203 +++++++++++++++++++++++++++++++++++++++ 25-akpm/include/linux/nfs4.h | 57 ++++++++++ 25-akpm/include/linux/nfs4_acl.h | 50 +++++++++ 4 files changed, 312 insertions(+), 1 deletion(-) diff -puN fs/nfsd/Makefile~nfsd-basic-v4-acl-definitions fs/nfsd/Makefile --- 25/fs/nfsd/Makefile~nfsd-basic-v4-acl-definitions 2004-08-01 21:10:04.099262264 -0700 +++ 25-akpm/fs/nfsd/Makefile 2004-08-01 21:10:04.108260896 -0700 @@ -7,5 +7,6 @@ obj-$(CONFIG_NFSD) += nfsd.o nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o -nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o +nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ + nfs4acl.o nfsd-objs := $(nfsd-y) diff -puN fs/nfsd/nfs4acl.c~nfsd-basic-v4-acl-definitions fs/nfsd/nfs4acl.c --- 25/fs/nfsd/nfs4acl.c~nfsd-basic-v4-acl-definitions 2004-08-01 21:10:04.100262112 -0700 +++ 25-akpm/fs/nfsd/nfs4acl.c 2004-08-01 21:10:04.109260744 -0700 @@ -0,0 +1,203 @@ +/* + * fs/nfs4acl/acl.c + * + * Common NFSv4 ACL handling code. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * Jeff Sedlak + * J. Bruce Fields + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct nfs4_acl * +nfs4_acl_new(void) +{ + struct nfs4_acl *acl; + + if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL) + return NULL; + + acl->naces = 0; + INIT_LIST_HEAD(&acl->ace_head); + + return acl; +} + +void +nfs4_acl_free(struct nfs4_acl *acl) +{ + struct list_head *h; + struct nfs4_ace *ace; + + if (!acl) + return; + + while (!list_empty(&acl->ace_head)) { + h = acl->ace_head.next; + list_del(h); + ace = list_entry(h, struct nfs4_ace, l_ace); + kfree(ace); + } + + kfree(acl); + + return; +} + +int +nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, + int whotype, uid_t who) +{ + struct nfs4_ace *ace; + + if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL) + return -1; + + ace->type = type; + ace->flag = flag; + ace->access_mask = access_mask; + ace->whotype = whotype; + ace->who = who; + + list_add_tail(&ace->l_ace, &acl->ace_head); + acl->naces++; + + return 0; +} + +static struct { + char *string; + int stringlen; + int type; +} s2t_map[] = { + { + .string = "OWNER@", + .stringlen = sizeof("OWNER@") - 1, + .type = NFS4_ACL_WHO_OWNER, + }, + { + .string = "GROUP@", + .stringlen = sizeof("GROUP@") - 1, + .type = NFS4_ACL_WHO_GROUP, + }, + { + .string = "EVERYONE@", + .stringlen = sizeof("EVERYONE@") - 1, + .type = NFS4_ACL_WHO_EVERYONE, + }, +}; + +int +nfs4_acl_get_whotype(char *p, u32 len) +{ + int i; + + for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) { + if (s2t_map[i].stringlen == len && + 0 == memcmp(s2t_map[i].string, p, len)) + return s2t_map[i].type; + } + return NFS4_ACL_WHO_NAMED; +} + +int +nfs4_acl_write_who(int who, char *p) +{ + int i; + + for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) { + if (s2t_map[i].type == who) { + memcpy(p, s2t_map[i].string, s2t_map[i].stringlen); + return s2t_map[i].stringlen; + } + } + BUG(); + return -1; +} + +static inline int +match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who) +{ + switch (ace->whotype) { + case NFS4_ACL_WHO_NAMED: + return who == ace->who; + case NFS4_ACL_WHO_OWNER: + return who == owner; + case NFS4_ACL_WHO_GROUP: + return who == group; + case NFS4_ACL_WHO_EVERYONE: + return 1; + default: + return 0; + } +} + +/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */ +int +nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group, + uid_t who, u32 mask) +{ + struct nfs4_ace *ace; + u32 allowed = 0; + + list_for_each_entry(ace, &acl->ace_head, l_ace) { + if (!match_who(ace, group, owner, who)) + continue; + switch (ace->type) { + case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE: + allowed |= ace->access_mask; + if ((allowed & mask) == mask) + return 0; + break; + case NFS4_ACE_ACCESS_DENIED_ACE_TYPE: + if (ace->access_mask & mask) + return -EACCES; + break; + } + } + return -EACCES; +} + +EXPORT_SYMBOL(nfs4_acl_new); +EXPORT_SYMBOL(nfs4_acl_free); +EXPORT_SYMBOL(nfs4_acl_add_ace); +EXPORT_SYMBOL(nfs4_acl_get_whotype); +EXPORT_SYMBOL(nfs4_acl_write_who); +EXPORT_SYMBOL(nfs4_acl_permission); diff -puN include/linux/nfs4_acl.h~nfsd-basic-v4-acl-definitions include/linux/nfs4_acl.h --- 25/include/linux/nfs4_acl.h~nfsd-basic-v4-acl-definitions 2004-08-01 21:10:04.102261808 -0700 +++ 25-akpm/include/linux/nfs4_acl.h 2004-08-01 21:10:04.110260592 -0700 @@ -0,0 +1,50 @@ +/* + * include/linux/nfs4_acl.c + * + * Common NFSv4 ACL handling definitions. + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LINUX_NFS4_ACL_H +#define LINUX_NFS4_ACL_H + +#include + +struct nfs4_acl *nfs4_acl_new(void); +void nfs4_acl_free(struct nfs4_acl *); +int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); +int nfs4_acl_get_whotype(char *, u32); +int nfs4_acl_write_who(int who, char *p); +int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group, + uid_t who, u32 mask); + +#endif /* LINUX_NFS4_ACL_H */ diff -puN include/linux/nfs4.h~nfsd-basic-v4-acl-definitions include/linux/nfs4.h --- 25/include/linux/nfs4.h~nfsd-basic-v4-acl-definitions 2004-08-01 21:10:04.104261504 -0700 +++ 25-akpm/include/linux/nfs4.h 2004-08-01 21:10:04.109260744 -0700 @@ -13,6 +13,9 @@ #ifndef _LINUX_NFS4_H #define _LINUX_NFS4_H +#include +#include + #define NFS4_VERIFIER_SIZE 8 #define NFS4_FHSIZE 128 #define NFS4_MAXNAMLEN NAME_MAX @@ -52,6 +55,60 @@ #define ACL4_SUPPORT_AUDIT_ACL 0x04 #define ACL4_SUPPORT_ALARM_ACL 0x08 +#define NFS4_ACE_FILE_INHERIT_ACE 0x00000001 +#define NFS4_ACE_DIRECTORY_INHERIT_ACE 0x00000002 +#define NFS4_ACE_NO_PROPAGATE_INHERIT_ACE 0x00000004 +#define NFS4_ACE_INHERIT_ONLY_ACE 0x00000008 +#define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010 +#define NFS4_ACE_FAILED_ACCESS_ACE_FLAG 0x00000020 +#define NFS4_ACE_IDENTIFIER_GROUP 0x00000040 +#define NFS4_ACE_OWNER 0x00000080 +#define NFS4_ACE_GROUP 0x00000100 +#define NFS4_ACE_EVERYONE 0x00000200 + +#define NFS4_ACE_READ_DATA 0x00000001 +#define NFS4_ACE_LIST_DIRECTORY 0x00000001 +#define NFS4_ACE_WRITE_DATA 0x00000002 +#define NFS4_ACE_ADD_FILE 0x00000002 +#define NFS4_ACE_APPEND_DATA 0x00000004 +#define NFS4_ACE_ADD_SUBDIRECTORY 0x00000004 +#define NFS4_ACE_READ_NAMED_ATTRS 0x00000008 +#define NFS4_ACE_WRITE_NAMED_ATTRS 0x00000010 +#define NFS4_ACE_EXECUTE 0x00000020 +#define NFS4_ACE_DELETE_CHILD 0x00000040 +#define NFS4_ACE_READ_ATTRIBUTES 0x00000080 +#define NFS4_ACE_WRITE_ATTRIBUTES 0x00000100 +#define NFS4_ACE_DELETE 0x00010000 +#define NFS4_ACE_READ_ACL 0x00020000 +#define NFS4_ACE_WRITE_ACL 0x00040000 +#define NFS4_ACE_WRITE_OWNER 0x00080000 +#define NFS4_ACE_SYNCHRONIZE 0x00100000 +#define NFS4_ACE_GENERIC_READ 0x00120081 +#define NFS4_ACE_GENERIC_WRITE 0x00160106 +#define NFS4_ACE_GENERIC_EXECUTE 0x001200A0 +#define NFS4_ACE_MASK_ALL 0x001F01FF + +enum nfs4_acl_whotype { + NFS4_ACL_WHO_NAMED = 0, + NFS4_ACL_WHO_OWNER, + NFS4_ACL_WHO_GROUP, + NFS4_ACL_WHO_EVERYONE, +}; + +struct nfs4_ace { + uint32_t type; + uint32_t flag; + uint32_t access_mask; + int whotype; + uid_t who; + struct list_head l_ace; +}; + +struct nfs4_acl { + uint32_t naces; + struct list_head ace_head; +}; + typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier; typedef struct { char data[16]; } nfs4_stateid; _