Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Dec 1999 14:44:21 -0500 (EST)
From:      Robert Watson <robert@cyrus.watson.org>
To:        freebsd-fs@freebsd.org
Subject:   Request for objections: extended attribute and ACL interfaces
Message-ID:  <Pine.BSF.3.96.991215143741.22637F-500000@fledge.watson.org>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]

As previously discussed in some detail on freebsd-arch, freebsd-security,
and posix1e, I have been working on adding support for file system access
control lists (among other things), and the supporting extended attribute
interface required to store additional meta-data in UFS and other file
systems.  After a fair amount of hashing out, the interfaces seem to
please most interested parties (i.e., we've verified that the attribute
interface is sufficiently flexible for the needs of the HPFS folk, the
attribute interface provides the functionality for capabilities, acls,
mandatory access control labels, privileged code signatures, etc, and the
acl interface can handle posix.1e acls, as well as providing a mechanism
for managing other acl schemes, such as those in AFS and Coda), and we're
planning to commit these interfaces on Friday, unless objections are
raised.  Please note that these are only the interfaces, not the actually
code itself, but standardizing the interfaces (especially vfs calls) makes
it easy to add the code later via kernel modules, and used in other file
systems currently provided by third parties (ARLA and Coda in particular). 

Attached please find four files, text introductions to both extended
attributes and acls, and the sys/ header files providing more detailed
information on the specifics of the interfaces.  The extended descriptions
include rationale, information on implementations in other operating
systems, and the interface that descriptions and semantics.

Commited would be:
	Changes to vnode_if.src to describe the new calls
	Changes to mount.h and vfs_default.c to add the vfsop calls
	Changes to vfsops arrays for various file systems so that
		they return EOPNOTSUPP for the vfs calls
	Syscalls in vfs_syscalls.c to perform name lookup and invoke
		the vfsops/vnops
	Addition of kern/kern_acl.c to provide common routines for
		third party file systems.

No changes would be made to underlying file systems other than to allow
them to return EOPNOTSUPP for the vfs call; with vnops this is not
necessary as the vnode interface will return EOPNOTSUPP for any fs not
supporting a call.

The UFS EA supporting code would not be committed, as it is experimental
and not well tested.  Neither will the UFS ACLs over EAs support.  Both of
these will be made available soon, however, and will rely on having
vnops/vfsops/syscalls assigned and available.  :-)

  Robert N M Watson 

robert@fledge.watson.org              http://www.watson.org/~robert/
PGP key fingerprint: AF B5 5F FF A6 4A 79 37  ED 5F 55 E9 58 04 6A B1
TIS Labs at Network Associates, Safeport Network Services

[-- Attachment #2 --]
Extended Attributes
-------------------

Introduction

Extended Attributes provide the ability for the kernel or userland processes
to associate additional meta-data with files and directories.


Rationale

There are a number of potential applications for extended attributes, but
the driving force behind the current implemetation is extended security
services: many more complex security mechanisms require additional state
associated with each file or directory.  For example, ACLs require per-
file storage, as do capabilities, and MAC labels.  Implementations of
all of these features exist for FreeBSD, but await storage in the file
system.  Extended attributes provide a generalized way in which to manage
this additional meta-data, for file stores that are do not allow for
storing this data directly.

Additionally, there are a number of existing file systems that support
extended attributes, and it is desirable to expose this functionality in
FreeBSD when processes are accessing data stored in the file system.

Providing a single and comprehensive vnode and syscall interface will
allow this storage and access to occur in a consistent way across file
systems.


Services

Each vnode may now have a series of named attributes associated with it,
in addition to the existing flat file data accessible via current calls,
and existing attributes.  The simplist way to describe the semantics is
to compare named attributes to a set of environmental variable assignments.
A variable may be defined or undefined, and if defined, it may have 0 or
more bytes of data associated with it.  While it might be possible to
modify an attribute, many implementations limit this behavior to replacing
an existing value rather than editing it in the style of VOP_WRITE
acting on a section of a flat file.  Attributes may be retrieved, set,
and removed (to take a name from defined to undefined).  

The vnode interface limits names to null-terminated strings, but allows
attribute values to be any binary blob describable using a struct uio.
Underlying file systems may place additional limits on the size and
structure of names, as well as the size of data.  File systems may also
place specific interpretations on specific names, limiting the structure
of values assigned to those names.  While underlying file systems may
choose to modify attribute values, it is recommended that they replace
existing values with new values when the attribute is set, allowing an
effectively atomic value replacement service.


Exiting Implementations

A number of existing file systems provide support for extended attributes,
including IBM's HPFS, Apple's HFS+, and SGI's XFS.  In general, this support
allows for some number of names, and additionally values, to be associated
with each file, and places constraints on the size of these attributes.  For
example, in HPFS, there is a maximum of 64k of additional meta-data for each
file or directory.

A similar but distinct service is that of named file forks--each file is
in fact a set of named flat file spaces, each distinct and individually
addressable using the general-purpose file access semantics.  For example, 
in Windows NT, it is possible to open seperate file descriptors for each
file fork, and store large volumes of information in each fork.  An attribute
service is not intended to provide such broad services, although attributes
could be support by such a service: similarly, it would be possible to
expose file forks through the attribute interface, but probably not desirable
given that the attribute interface is intended for different functionality.


Vnode Interface Extensions

Three new vnode calls provide the majority of required and common access
methods to extended attributes.  These calls are similar to the existing
calls for modifying vnode attributes (VOP_GETATTR and VOP_SETATTR), except
that they additionally allow the specification of an attribute name, as
well as accepting a general purpose binary blob, not a specific structure.

#
#% getextattr   vp      = = =
#
vop_getextattr {
        IN struct vnode *vp;
        IN char *name;
        INOUT struct uio *uio;
        IN struct ucred *cred;
        IN struct proc *p;
};

vop_getextattr retrieves a named attribute (name) from a specific vnode
(vp), and returns it to a set of buffers (uio), either in userspace or
sysspace.  To authorize the call, a credential structure is provided (cred),
as well as a process for handling scheduling and locks (p).  This call
makes the same use of uio as VOP_READ (and in fact may be implemented over
VOP_READ in some cases), paying attention to the uio resid and offset
variables, but bounding retrieval at the size of the attribute data currently
stored in the attribute.  A null credential pointer may be passed to
indicate that the kernel, and not a specific process, is making this request.

As with readv, the uio resid field will be updated to reflect the amount
of data read.  Zero is returned on success, otherwise an errno value to
reflect the failure.

No locks must be held to make this VOP_ call.

This call may fail in a number of ways, including
returning ENOENT if the attribute name is not defined, EIO if an I/O
error occurs, ENXIO if the underlying file system does not support the type
of access requested (i.e., reading attributes from an unsupported type of
file)
, ENOMEM if memory is not available to support this
operation, EDEADLK if locks are not available, EACCES if the credentials
passed cannot authorize the request, EFAULT if the uio structure refers to
an invalid userspace address (see copyin()), and EINVAL if the arguments (such
as name formatting) are invalid.  Additionally, EOPNOTSUPP may be returned
if the file system does not support the retrieval of extended attributes.

#
#% setextattr   vp      L L L
#
vop_setextattr {
        IN struct vnode *vp;
        IN char *name;
        INOUT struct uio *uio;
        IN struct ucred *cred;
        IN struct proc *p;
};

vop_setextattr sets a named attribute (name) for a specific vnode (vp),
finding the value to set in a set of buffers (uio), either in userspace
or sysspace.  To authorize this call, a credential structure is provided
(cred), as well as a process for handling scheduling and locks (p).  This
call makes the same use of uio as VOP_WRITE (and in fact may be implemented
over VOP_WRITE in some cases), paying attention to the uio resid variable,
although optionally rejecting non-zero offset fields as they may violate
the replacement not modification rule described in Semantics.  A null
credential pointer may be passed to indicate that the kernel, and not a
specific process, is making this request.

As with writev, the uio resid field will be updated to reflect the
amount of data read.  Zero is returned on success, otherwise an errno
value to reflect the failure.

An exclusive lock must be held on (vp) to make this VOP_ call.

This call may fail in a number of ways, including all failure modes of
vop_getextattr.  Additionally, it is possible to receive: EFBIG if the
attribute value is larger than some administrative or allocation limit,
ENOSPC if the device is out of space but otherwise would have allowed
the call to succeed, and EROFS if the file system is mounted readonly.
EOPNOTSUPP may be returned if the file system does not support the
setting of extended attributes.

#
#% rmextattr    vp      L L L
#
vop_rmextattr {
        IN struct vnode *vp;
        IN char *name;
        IN struct ucred *cred;
        IN struct proc *p;
};

vop_rmextattr removes a named attribute (name) for a specific vnode (vp).
To authorize this call, a credential structure is provided (cred), as well
as a process for handling scheduling and locks (p).  A null credential
pointer may be passed to indicate that the kernel, and not a specific
process, is making this request.

Zero is returned on success, otherwise an errno value to reflect the
failure.

An exclusive lock must be held on (vp) to make this VOP_ call.

This call may fail in a number of ways, all of which are documented above
for vop_setextattr.  EOPNOTSUPP may be returned if the file system does
not support the removal of an extended attribute.


VFS Interfaces

To support an extended attribute implementation on UFS, one additional
VFS call is defined:

        int     (*vfs_extattrctl) __P((struct mount *mp, int cmd, 
                                      char *attrname, caddr_t arg,
                                      struct proc *p)); 

This is similar to the UFS vfs_quotactl call, allowing for the runtime
configuration of extended attribute mechanisms, including backing
files for attribute storage.  The details are UFS-specific, but there is
precedent for UFS-specific VFS calls to configure USF-specific behavior.
While in the long term, it would probably be desirable to specify a
general mechanism for pushing configuration state into VFS's, this
mechanism works well given the tast.  The UFS extended attribute
implementation backs extended attributes into vnodes (usually stored
in the same file system, although not necessarily), indexed by the
inode number of the vnode to which the attribute is applied.  cmd may
currently take on the values:

#define UFS_EXTATTR_CMD_START   0x00000001
#define UFS_EXTATTR_CMD_STOP    0x00000002
#define UFS_EXTATTR_CMD_ENABLE  0x00000003
#define UFS_EXTATTR_CMD_DISABLE 0x00000004

Which refer to starting and stopping extended attribute support on a
particular UFS file system (mp), as well as enabling and disabling the
backing of specific attributes onto specific attribute files (arg is
cast of char *).  This behavior may change some, and as such is not
documented here further.


Syscalls

Each vnode call is currently exposed via one syscall:

int     extattr_set_file(char *path, char *attrname, struct iovec *iovp,
        u_int iovcnt);
int     extattr_get_file(char *path, char *attrname, struct iovec *iovp,
        u_int iovcnt);
int     extattr_rm_file(char *path, char *attrname);

For each call, path is converted via namei() to a vnode, with locking
for the second and third calls.  While the vnode interface does not place
a limit on the length of attribute names, the syscall must copy the userland
string into kernel space for the vnode call, so places a limit of 
EXTATTR_MAXNAMELEN characters on the nul-terminated string, including the
nul terminator.  In the current implementation, EXTATTR_MAXNAMELEN is
defined as NAME_MAX, which is 255 characters.  This does not preclude
increasing this limit, or underlying file systems supporting higher or
lower limits.  The iovp and iovcnt arguments are similar to those found
in readv and writev, and are converted by the syscall wrappers into
appropriately formated uio structures for the vnode call.

The VFS call is exposed via one syscall:

int     extattrctl(char *path, int cmd, char *attrname, caddr_t arg);

The mountpoint is retrieved from path, the attribute name read into a kernel
buffer, and the other arguments passed straight through.


[-- Attachment #3 --]
/*-
 * Copyright (c) 1999 Robert N. M. Watson
 * All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
 *
 *	$Id $
 */

#ifndef _SYS_EXTATTR_H_
#define _SYS_EXTATTR_H_

#define EXTATTR_MAXNAMELEN	NAME_MAX

#ifdef KERNEL

#else /* KERNEL */

int	extattrctl(char *path, int cmd, char *attrname, caddr_t arg);
int	extattr_set_file(char *path, char *attrname, struct iovec *iovp,
	u_int iovcnt);
int	extattr_get_file(char *path, char *attrname, struct iovec *iovp,
	u_int iovcnt);
int	extattr_rm_file(char *path, char *attrname);


#endif /* KERNEL */


#endif /* _SYS_EXTATTR_H_ */

[-- Attachment #4 --]
Access Control Lists
--------------------

Introduction

Access Control lists extend the UNIX file and directory permission set to
allow file owners to define additional rights for specific users and groups
for that file.


Rationale

The current UNIX permission model is quite limited: it allows a file owner
to specify a limited set of rights (read, write, execute/lookup) over
a limited set of principals (file owner, file group, and other).  This relies
on the system administrator to maintain groups for all possible permutations
of users that wish to share files while not making the file accessible to
all users on the system, an inappropriate assumption in most multi-user
environments.  POSIX.1e defines an Access Control List extension that
allows users to specify additional users and groups for a file, and
rights for them over the file.

This allows a number of security improvements, both from the perspective
of regular users sharing files, and also from a systems perspective as it
allows the increased use of the privilege of least principal: that processes
be given only the rights that they require.  For example, ACLs simplify
managing data sharing for system services such as mail.

Although ACLs may vary in semantics from file system to file system, just
as the precise details of file semantics vary, it is useful to define
a single and comprehensive vnode and syscall interface to allow
consistent access across file systems.


Services

As with file semantics, ACL semantics may vary from file system to file
system.  For example, permissions in a distributed system such as AFS or
Coda may have quite different implications from permissions used locally
in UFS/FFS.  However, ACLs generally have roughly the same syntactic form:
a list of principals, and for each principal, a set of rights.  Similarly,
there are similar operations regardless of the file system: setting and
retrieving ACLs, as well as checking the validity of an ACL for a target
file in an environment where the validity of ACLs varies by target.  As
such, we define a standard vnode interface, syscall interface, and
set of syntax requirements for ACLs.  This permits individual implementations,
such as POSIX.1e on UFS/FFS, to define their own semantics, yet use the
same interface as other implementations, such as AFS or Coda permissions.


Existing Implementations

A number of operating systems support ACLs, or have addon packages that
provide ACL functionality.  Many of these implementations are based on the
POSIX.1e draft, some with minor interface changes.  Solaris and IRIX
both support ACLs in the base file system without addons; in the case of
IRIX, the implementation is almost entirely POSIX.1e-compliant.  In the
case of Solaris, there are significant differences between the interface
and POSIX.1e.  Linux also has an ACL implementation, originally closer
to Solaris, but now moving in the direction of POSIX.1e.  A number of
other operating systems also support ACLs, but were not available to us
for inspection.  A cross-platform POSIX.1e implementation mailing list
is available for discussion of the POSIX.1e interface and its practical
implementation aspects.  Send email to majordomo@cyrus.watson.org, 
containing "subscribe posix1e".


ACL Syntax

POSIX.1e defines ACLs and ACL Entries, the components of ACLs.  In the
FreeBSD POSIX.1e ACL implementation, these object types are backed by
structures:

struct acl_entry {
        acl_tag_t       ae_tag;
        uid_t   ae_id;
        acl_perm_t      ae_perm;
};
typedef struct acl_entry        *acl_entry_t;

struct acl {
        int     acl_cnt;
        struct acl_entry        acl_entry[MAX_ACL_ENTRIES];
};
typedef struct acl      *acl_t;

Each entry refers to a principal namespace (acl_tag_t), has
a qualifier indicating which principal in the namespace is intended
(uid_t), and assigns a specific set of rights (acl_perm_t).  A set of
these entries is then combined to form a complete ACL.

POSIX.1e defines a large library of functions for manipulating these
ACLs and ACL entries in the abstract (without awareness of the underlying
C structures, wherever possible), as well as the more relevant interfaces
for retrieving and submitting ACLs associated with objects.  In the FreeBSD
implementation, these interfaces are backed by slightly more general
syscalls, which in turn forward requests to slightly more general vnode
operations; at each step along the way, the same syntax for ACLs is
preserved, and the checking of semantics is generally left to the
implementing file systems.

POSIX.1e also defines an ACL type, to distinguish different ACLs in the
case that an object may have more than one ACL assigned to it.  POSIX.1e
uses two values--one for access ACLs, and one for default ACLs only
appropriate where the object is a directory.  This type specifier is
exposed in the API, and not stored in an ACL, as a particular ACL may
be valid (and applicable) in both cases, and it is necessary to compare
ACLs as the same type, even if they are different "acl types" in the
POSIX.1e sense.

In the current VFS interface, access to files is verified by submitting
a vnode reference, as well as credentials, to VOP_ACCESS (and others)
and checking of rights is handled within the VFS.  With ACLs, this does
not change, so the verification of ACLs is generally hidden from most
kernel code.  Similarly, as with attributes, the storage of ACLs is left
up to the file system: in the case of the FreeBSD UFS/FFS implementation,
an extended attribute mechanism is relied upon to provide storage for
ACLs.


Vnode Interface Extensions

Three new vnode calls provide the majority of required and common access
methods for ACLs, although the practical implementation of a number of
these operations is affected by ACLs in file systems that support ACLs.
These calls are similar to existing calls for modifying vnode attributes
(VOP_GETATTR and VOP_SETATTR), except that instead of passing vattrs,
these routines pass struct acl's, as well as an "acl type".  While the
interface does not put limits on the contents of either the ACL nor its
type, the underlying implementation will evaluate the submitted ACLs
based on its own semantics, and may reject any it finds unfit.

#
#% getacl       vp      = = =
#
vop_getacl {
        IN struct vnode *vp;
        IN acl_type_t type;
        OUT struct acl *aclp;
        IN struct ucred *cred;
        IN struct proc *p;
};

vop_getacl returns an ACL of type (type) from a specific vnode (vp), and
returns it to an ACL buffer (aclp) in sysspace.  To authorize the call, a
credential structure is provided (cred), as well as a process for handling
scheduling and locks (p).  A null credential pointer may be passed in to
indicate that the kernel, and not a specific process, is making this
request.

As with vop_getattr, the ACL structure pointed to by aclp will be updated
to reflect the current state of the vnode ACL in question.  Zero is
returned on success, otherwise an errno value to reflect the failure.

No locks must be held to make this VOP_ call.

This call may fail in a number of ways, including:

ENOMEM	Insufficient memory to fulfill request
EACCES	Permission was denied in reading this ACL
EINVAL	The acl type passed is invalid for the vnode
EOPNOTSUPP	This file system does not support vop_getacl

#
#% setacl       vp      L L L
# 
vop_setacl {
        IN struct vnode *vp;
        IN acl_type_t type;
        IN struct acl *aclp;
        IN struct ucred *cred;
        IN struct proc *p;
};

vop_setacl sets an ACL of type (type) for a specific vnode (vp), finding
the ACL to set in the structure pointed to by aclp in sysspace.  To
delete an ACL of that type, a null aclp pointer may be passed.  To
authorize this call, a credential structure is provided (cred), as well
as a process for handling scheduling and locks (p).  A null credential
pointer may be passed in to indicate that the kernel, and not a specific
process, is making this request.

Zero is returned on success, otherwise an errno value to reflect the
failure.

An exclusive lock must be held on (vp) to make this VOP call.

This call may fail in a number of ways, including all failure modes of
vop_getacl.  Additionally, it is possible to receive:

ENOSPC	The fiel system is out of space
EROFS	The file system is readonly

# 
#% aclcheck     vp      = = = 
#
vop_aclcheck {
        IN struct vnode *vp;
        IN acl_type_t type;
        IN struct acl *aclp;
        IN struct ucred *cred;
        IN struct proc *p;
};

vop_aclcheck allows the caller to verify the validity of an ACL (aclp)
of type (type) for a specific vnode (vp).  This should usually be an
indicator of whether or not the VFS layer would return EINVAL for a
similar call to vop_setacl, and allows userland processes to check ACL
validity for a particular target.  To authorize this call, a credential
structure is provided (cred), as well as a process for handling scheduling
and locks (p).  A null credential pointer may be passed in to indicate
that the kernel, and not a specific process, is making this request.

Zero is returned on success, otherwise an errno value to reflect the
failure.

No locks must be held to make this VOP_ call.

This call may fail in a number of ways, including all failure modes of
vop_getacl.


VFS Interfaces

There are no VFS interfaces relating to ACLs currently defined.


Syscalls

Each vnode call is exposed via a number of syscalls:

int     acl_syscall_get_file(char *path, acl_type_t type, struct acl *aclp);
int     acl_syscall_set_file(char *path, acl_type_t type, struct acl *aclp);
int     acl_syscall_get_fd(int filedes, acl_type_t type, struct acl *aclp);
int     acl_syscall_set_fd(int filedes, acl_type_t type, struct acl *aclp);
int     acl_syscall_delete_def_file(const char *path_p);
int     acl_syscall_delete_def_fd(int filedes);
int     acl_syscall_aclcheck_file(char *path, acl_type_t type,
                                  struct acl *aclp);
int     acl_syscall_aclcheck_fd(int filedes, acl_type_t type,
                                struct acl *aclp);

These are the syscalls necessary to provide the POSIX.1e ACL manipulation
functions.  In some cases, a broder range of functionality is available than
required for POSIX.1e.


[-- Attachment #5 --]
/*-
 * Copyright (c) 1999 Robert N. M. Watson
 * All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
 *
 *	$Id $
 */
/* 
 * Userland/kernel interface for Access Control Lists
 */

#ifndef _SYS_ACL_H
#define _SYS_ACL_H

/*
 * POSIX.1e ACL types
 */

#define MAX_ACL_ENTRIES 32    /* maximum entries in an ACL */
#define _POSIX_ACL_PATH_MAX     MAX_ACL_ENTRIES

typedef int	acl_type_t;
typedef int	acl_tag_t;
typedef mode_t	acl_perm_t;

struct acl_entry {
	acl_tag_t	ae_tag;
	uid_t	ae_id;
	acl_perm_t	ae_perm;
};
typedef struct acl_entry	*acl_entry_t;

struct acl {
	int	acl_cnt;
	struct acl_entry	acl_entry[MAX_ACL_ENTRIES];
};
typedef struct acl	*acl_t;

/*
 * Possible valid values for a_type of acl_entry_t
 */
#define ACL_USER_OBJ	0x00000001
#define ACL_USER	0x00000002
#define ACL_GROUP_OBJ	0x00000004
#define ACL_GROUP	0x00000008
#define ACL_MASK	0x00000010
#define ACL_OTHER	0x00000020
#define ACL_OTHER_OBJ	ACL_OTHER
#define ACL_AFS_ID	0x00000040

#define ACL_TYPE_ACCESS		0x00000000
#define ACL_TYPE_DEFAULT	0x00000001

/*
 * Possible flags in a_perm field
 */
#define ACL_PERM_EXEC		0x0001
#define ACL_PERM_WRITE		0x0002
#define ACL_PERM_READ		0x0004
#define ACL_PERM_NONE		0x0000
#define ACL_PERM_BITS		(ACL_PERM_EXEC | ACL_PERM_WRITE | ACL_PERM_READ)
#define ACL_POSIX1E_BITS	(ACL_PERM_EXEC | ACL_PERM_WRITE | ACL_PERM_READ)

#ifdef KERNEL

/*
 * Storage for ACLs and support structures
 */
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_ACL);
#endif


/*
 * Dummy declarations so that we can expose acl_access all over the place
 * without worrying about including ucred and friends.  vnode.h does the
 * same thing.
 */
struct ucred;
struct proc;


/*
 * Functions exposed to the rest of the kernel/vfs
 */
int	posix1e_acl_access(struct acl *a_acl, int a_mode, struct ucred *a_cred,
			   struct proc *a_p);

/* 
 * Currently disabled due to cyclic include acl.h requires vnode, and vice
 * versa?
 * #ifdef _SYS_VNODE.H
 * XXX this prevents warnings hither and thither, but probably isn't a good
 * idea.  It's surprising how many FS source files don't include vnode.h,
 * yet do include other code for FS support.
 */
struct vattr;
struct vop_getacl_args;
struct vop_aclcheck_args;
void	generic_attr_to_posix1e_acl(struct acl *a_acl, struct vattr *vattr);
int	generic_vop_getacl(struct vop_getacl_args *ap);
int	generic_vop_aclcheck(struct vop_aclcheck_args *ap);
int	posix1e_vop_aclcheck(struct vop_aclcheck_args *ap);


#else /* KERNEL */

/*
 * Syscall interface -- use the library calls instead as the syscalls
 * have strict acl entry ordering requirements
 */
int	acl_syscall_get_file(char *path, acl_type_t type, struct acl *aclp);
int	acl_syscall_set_file(char *path, acl_type_t type, struct acl *aclp);
int	acl_syscall_get_fd(int filedes, acl_type_t type, struct acl *aclp);
int	acl_syscall_set_fd(int filedes, acl_type_t type, struct acl *aclp);
int	acl_syscall_delete_def_file(const char *path_p);
int	acl_syscall_delete_def_fd(int filedes);
int	acl_syscall_aclcheck_file(char *path, acl_type_t type,
				  struct acl *aclp);
int	acl_syscall_aclcheck_fd(int filedes, acl_type_t type,
				struct acl *aclp);


/*
 * Supported POSIX.1e ACL manipulation and assignment/retrieval API
 */
int	acl_calc_mask(acl_t *acl_p);
int	acl_delete_def_file(const char *path_p);
int	acl_delete_def_fd(int filedes);
acl_t	acl_from_text(const char *buf_p);
acl_t	acl_get_fd(int fd, acl_type_t type);
acl_t	acl_get_file(const char *path_p, acl_type_t type);
acl_t	acl_init(int count);
int	acl_set_fd(int fd, acl_t acl, acl_type_t type);
int	acl_set_file(const char *path_p, acl_type_t type, acl_t acl);
char	*acl_to_text(acl_t acl, ssize_t *len_p);
int	acl_valid(acl_t acl);
int	acl_valid_file(const char *path_p, acl_type_t type, acl_t acl);
int	acl_valid_fd(int fd, acl_type_t type, acl_t acl);
int	acl_free(void *obj_p);


#endif /* KERNEL */
#endif /* _SYS_ACL_H */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.991215143741.22637F-500000>