Make 'struct acl' larger, as required to support NFSv4 ACLs. Provide
compatibility interfaces in both kernel and libc. Reviewed by: rwatson
This commit is contained in:
parent
682eec57c4
commit
ae1add4e55
@ -3,6 +3,6 @@
|
||||
|
||||
PROG= cp
|
||||
SRCS= cp.c utils.c
|
||||
CFLAGS+= -DVM_AND_BUFFER_CACHE_SYNCHRONIZED
|
||||
CFLAGS+= -DVM_AND_BUFFER_CACHE_SYNCHRONIZED -D_ACL_PRIVATE
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -2,8 +2,11 @@
|
||||
|
||||
.PATH: ${.CURDIR}/posix1e
|
||||
|
||||
CFLAGS+=-D_ACL_PRIVATE
|
||||
|
||||
SRCS+= acl_calc_mask.c \
|
||||
acl_copy.c \
|
||||
acl_compat.c \
|
||||
acl_delete.c \
|
||||
acl_delete_entry.c \
|
||||
acl_entry.c \
|
||||
|
@ -21,15 +21,12 @@ FBSD_1.0 {
|
||||
acl_get_link_np;
|
||||
acl_get_fd;
|
||||
acl_get_fd_np;
|
||||
acl_get_perm_np;
|
||||
acl_get_permset;
|
||||
acl_get_qualifier;
|
||||
acl_get_tag_type;
|
||||
acl_init;
|
||||
acl_dup;
|
||||
acl_add_perm;
|
||||
acl_clear_perms;
|
||||
acl_delete_perm;
|
||||
acl_set_file;
|
||||
acl_set_link_np;
|
||||
acl_set_fd;
|
||||
@ -67,3 +64,9 @@ FBSD_1.0 {
|
||||
mac_set_link;
|
||||
mac_set_proc;
|
||||
};
|
||||
|
||||
FBSD_1.1 {
|
||||
acl_add_perm;
|
||||
acl_delete_perm;
|
||||
acl_get_perm_np;
|
||||
};
|
||||
|
59
lib/libc/posix1e/acl_compat.c
Normal file
59
lib/libc/posix1e/acl_compat.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
|
||||
* 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.
|
||||
*
|
||||
* ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/acl.h>
|
||||
|
||||
/*
|
||||
* Compatibility wrappers for applications compiled against libc from before
|
||||
* NFSv4 ACLs were added.
|
||||
*/
|
||||
int
|
||||
__oldacl_get_perm_np(acl_permset_t permset_d, oldacl_perm_t perm)
|
||||
{
|
||||
|
||||
return (acl_get_perm_np(permset_d, perm));
|
||||
}
|
||||
|
||||
int
|
||||
__oldacl_add_perm(acl_permset_t permset_d, oldacl_perm_t perm)
|
||||
{
|
||||
|
||||
return (acl_add_perm(permset_d, perm));
|
||||
}
|
||||
|
||||
int
|
||||
__oldacl_delete_perm(acl_permset_t permset_d, oldacl_perm_t perm)
|
||||
{
|
||||
|
||||
return (acl_delete_perm(permset_d, perm));
|
||||
}
|
||||
|
||||
__sym_compat(acl_get_perm_np, __oldacl_get_perm_np, FBSD_1.0);
|
||||
__sym_compat(acl_add_perm, __oldacl_add_perm, FBSD_1.0);
|
||||
__sym_compat(acl_delete_perm, __oldacl_delete_perm, FBSD_1.0);
|
@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include "un-namespace.h"
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "acl_support.h"
|
||||
|
||||
int
|
||||
acl_delete_def_file(const char *path_p)
|
||||
{
|
||||
@ -56,6 +58,7 @@ int
|
||||
acl_delete_file_np(const char *path_p, acl_type_t type)
|
||||
{
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
return (__acl_delete_file(path_p, type));
|
||||
}
|
||||
|
||||
@ -63,13 +66,14 @@ int
|
||||
acl_delete_link_np(const char *path_p, acl_type_t type)
|
||||
{
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
return (__acl_delete_link(path_p, type));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
acl_delete_fd_np(int filedes, acl_type_t type)
|
||||
{
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
return (___acl_delete_fd(filedes, type));
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p)
|
||||
(**entry_p).ae_tag = ACL_UNDEFINED_TAG;
|
||||
(**entry_p).ae_id = ACL_UNDEFINED_ID;
|
||||
(**entry_p).ae_perm = ACL_PERM_NONE;
|
||||
(**entry_p).ae_entry_type = 0;
|
||||
(**entry_p).ae_flags = 0;
|
||||
|
||||
(*acl_p)->ats_cur_entry = 0;
|
||||
|
||||
|
@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "acl_support.h"
|
||||
|
||||
acl_t
|
||||
acl_get_file(const char *path_p, acl_type_t type)
|
||||
{
|
||||
@ -60,6 +62,7 @@ acl_get_file(const char *path_p, acl_type_t type)
|
||||
if (aclp == NULL)
|
||||
return (NULL);
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
error = __acl_get_file(path_p, type, &aclp->ats_acl);
|
||||
if (error) {
|
||||
acl_free(aclp);
|
||||
@ -79,6 +82,7 @@ acl_get_link_np(const char *path_p, acl_type_t type)
|
||||
if (aclp == NULL)
|
||||
return (NULL);
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
error = __acl_get_link(path_p, type, &aclp->ats_acl);
|
||||
if (error) {
|
||||
acl_free(aclp);
|
||||
@ -117,6 +121,7 @@ acl_get_fd_np(int fd, acl_type_t type)
|
||||
if (aclp == NULL)
|
||||
return (NULL);
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
error = ___acl_get_fd(fd, type, &aclp->ats_acl);
|
||||
if (error) {
|
||||
acl_free(aclp);
|
||||
|
@ -54,8 +54,10 @@ acl_init(int count)
|
||||
}
|
||||
|
||||
acl = malloc(sizeof(struct acl_t_struct));
|
||||
if (acl != NULL)
|
||||
if (acl != NULL) {
|
||||
bzero(acl, sizeof(struct acl_t_struct));
|
||||
acl->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
|
||||
}
|
||||
|
||||
return (acl);
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
type = _acl_type_unold(type);
|
||||
if (_posix1e_acl(acl, type)) {
|
||||
error = _posix1e_acl_sort(acl);
|
||||
if (error) {
|
||||
@ -80,6 +81,7 @@ acl_set_link_np(const char *path_p, acl_type_t type, acl_t acl)
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
type = _acl_type_unold(type);
|
||||
if (_posix1e_acl(acl, type)) {
|
||||
error = _posix1e_acl_sort(acl);
|
||||
if (error) {
|
||||
@ -114,6 +116,7 @@ acl_set_fd_np(int fd, acl_t acl, acl_type_t type)
|
||||
{
|
||||
int error;
|
||||
|
||||
type = _acl_type_unold(type);
|
||||
if (_posix1e_acl(acl, type)) {
|
||||
error = _posix1e_acl_sort(acl);
|
||||
if (error) {
|
||||
|
@ -376,3 +376,24 @@ _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
|
||||
* counterpart. It's neccessary for the old (pre-NFS4 ACLs) binaries
|
||||
* to work with new libc and kernel. Fixing 'type' for old binaries with
|
||||
* old libc and new kernel is being done by kern/vfs_acl.c:type_unold().
|
||||
*/
|
||||
int
|
||||
_acl_type_unold(acl_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS_OLD:
|
||||
return (ACL_TYPE_ACCESS);
|
||||
|
||||
case ACL_TYPE_DEFAULT_OLD:
|
||||
return (ACL_TYPE_DEFAULT);
|
||||
|
||||
default:
|
||||
return (type);
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#define _POSIX1E_ACL_STRING_PERM_MAXSIZE 3 /* read, write, exec */
|
||||
|
||||
int _acl_type_unold(acl_type_t type);
|
||||
int _posix1e_acl_check(acl_t acl);
|
||||
int _posix1e_acl_sort(acl_t acl);
|
||||
int _posix1e_acl(acl_t acl, acl_type_t type);
|
||||
|
@ -81,6 +81,7 @@ acl_valid_file_np(const char *pathp, acl_type_t type, acl_t acl)
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
type = _acl_type_unold(type);
|
||||
if (_posix1e_acl(acl, type)) {
|
||||
error = _posix1e_acl_sort(acl);
|
||||
if (error) {
|
||||
@ -101,6 +102,7 @@ acl_valid_link_np(const char *pathp, acl_type_t type, acl_t acl)
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
type = _acl_type_unold(type);
|
||||
if (_posix1e_acl(acl, type)) {
|
||||
error = _posix1e_acl_sort(acl);
|
||||
if (error) {
|
||||
@ -121,6 +123,7 @@ acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
type = _acl_type_unold(type);
|
||||
if (_posix1e_acl(acl, type)) {
|
||||
error = _posix1e_acl_sort(acl);
|
||||
if (error) {
|
||||
@ -131,6 +134,5 @@ acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
|
||||
|
||||
acl->ats_cur_entry = 0;
|
||||
|
||||
|
||||
return (___acl_aclcheck_fd(fd, type, &acl->ats_acl));
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
PROG= restore
|
||||
LINKS= ${BINDIR}/restore ${BINDIR}/rrestore
|
||||
CFLAGS+=-DRRESTORE
|
||||
CFLAGS+=-DRRESTORE -D_ACL_PRIVATE
|
||||
WARNS?= 0
|
||||
SRCS= main.c interactive.c restore.c dirs.c symtab.c tape.c utilities.c \
|
||||
dumprmt.c
|
||||
|
@ -409,6 +409,8 @@ acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid, gid_t gid, mode_t mode)
|
||||
|
||||
acl_entry.ae_tag = tag;
|
||||
acl_entry.ae_perm = acl_posix1e_mode_to_perm(tag, mode);
|
||||
acl_entry.ae_entry_type = 0;
|
||||
acl_entry.ae_flags = 0;
|
||||
switch(tag) {
|
||||
case ACL_USER_OBJ:
|
||||
acl_entry.ae_id = uid;
|
||||
|
@ -56,7 +56,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
static MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists");
|
||||
CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES);
|
||||
|
||||
MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists");
|
||||
|
||||
static int vacl_set_acl(struct thread *td, struct vnode *vp,
|
||||
acl_type_t type, struct acl *aclp);
|
||||
@ -65,6 +67,133 @@ static int vacl_get_acl(struct thread *td, struct vnode *vp,
|
||||
static int vacl_aclcheck(struct thread *td, struct vnode *vp,
|
||||
acl_type_t type, struct acl *aclp);
|
||||
|
||||
int
|
||||
acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES)
|
||||
return (EINVAL);
|
||||
|
||||
bzero(dest, sizeof(*dest));
|
||||
|
||||
dest->acl_cnt = source->acl_cnt;
|
||||
dest->acl_maxcnt = ACL_MAX_ENTRIES;
|
||||
|
||||
for (i = 0; i < dest->acl_cnt; i++) {
|
||||
dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
|
||||
dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
|
||||
dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES)
|
||||
return (EINVAL);
|
||||
|
||||
bzero(dest, sizeof(*dest));
|
||||
|
||||
dest->acl_cnt = source->acl_cnt;
|
||||
|
||||
for (i = 0; i < dest->acl_cnt; i++) {
|
||||
dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
|
||||
dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
|
||||
dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* At one time, "struct ACL" was extended in order to add support for NFSv4
|
||||
* ACLs. Instead of creating compatibility versions of all the ACL-related
|
||||
* syscalls, they were left intact. It's possible to find out what the code
|
||||
* calling these syscalls (libc) expects basing on "type" argument - if it's
|
||||
* either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were
|
||||
* known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct
|
||||
* oldacl". If it's something else, then it's the new "struct acl". In the
|
||||
* latter case, the routines below just copyin/copyout the contents. In the
|
||||
* former case, they copyin the "struct oldacl" and convert it to the new
|
||||
* format.
|
||||
*/
|
||||
static int
|
||||
acl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type)
|
||||
{
|
||||
int error;
|
||||
struct oldacl old;
|
||||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS_OLD:
|
||||
case ACL_TYPE_DEFAULT_OLD:
|
||||
error = copyin(user_acl, &old, sizeof(old));
|
||||
if (error != 0)
|
||||
break;
|
||||
acl_copy_oldacl_into_acl(&old, kernel_acl);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl));
|
||||
if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
acl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type)
|
||||
{
|
||||
int error;
|
||||
struct oldacl old;
|
||||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS_OLD:
|
||||
case ACL_TYPE_DEFAULT_OLD:
|
||||
error = acl_copy_acl_into_oldacl(kernel_acl, &old);
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
error = copyout(&old, user_acl, sizeof(old));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (fuword((char *)user_acl +
|
||||
offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES)
|
||||
return (EINVAL);
|
||||
|
||||
error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl));
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
|
||||
* counterpart. It's required for old (pre-NFS4 ACLs) libc to work
|
||||
* with new kernel. Fixing 'type' for old binaries with new libc
|
||||
* is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold().
|
||||
*/
|
||||
static int
|
||||
acl_type_unold(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS_OLD:
|
||||
return (ACL_TYPE_ACCESS);
|
||||
|
||||
case ACL_TYPE_DEFAULT_OLD:
|
||||
return (ACL_TYPE_DEFAULT);
|
||||
|
||||
default:
|
||||
return (type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* These calls wrap the real vnode operations, and are called by the syscall
|
||||
* code once the syscall has converted the path or file descriptor to a vnode
|
||||
@ -85,7 +214,7 @@ vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
|
||||
int error;
|
||||
|
||||
inkernelacl = acl_alloc(M_WAITOK);
|
||||
error = copyin(aclp, inkernelacl, sizeof(struct acl));
|
||||
error = acl_copyin(aclp, inkernelacl, type);
|
||||
if (error)
|
||||
goto out;
|
||||
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
|
||||
@ -97,7 +226,8 @@ vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
|
||||
if (error != 0)
|
||||
goto out_unlock;
|
||||
#endif
|
||||
error = VOP_SETACL(vp, type, inkernelacl, td->td_ucred, td);
|
||||
error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl,
|
||||
td->td_ucred, td);
|
||||
#ifdef MAC
|
||||
out_unlock:
|
||||
#endif
|
||||
@ -125,13 +255,15 @@ vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type,
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#endif
|
||||
error = VOP_GETACL(vp, type, inkernelacl, td->td_ucred, td);
|
||||
error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl,
|
||||
td->td_ucred, td);
|
||||
|
||||
#ifdef MAC
|
||||
out:
|
||||
#endif
|
||||
VOP_UNLOCK(vp, 0);
|
||||
if (error == 0)
|
||||
error = copyout(inkernelacl, aclp, sizeof(struct acl));
|
||||
error = acl_copyout(inkernelacl, aclp, type);
|
||||
acl_free(inkernelacl);
|
||||
return (error);
|
||||
}
|
||||
@ -154,7 +286,7 @@ vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type)
|
||||
if (error)
|
||||
goto out;
|
||||
#endif
|
||||
error = VOP_SETACL(vp, type, 0, td->td_ucred, td);
|
||||
error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td);
|
||||
#ifdef MAC
|
||||
out:
|
||||
#endif
|
||||
@ -174,7 +306,7 @@ vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
|
||||
int error;
|
||||
|
||||
inkernelacl = acl_alloc(M_WAITOK);
|
||||
error = copyin(aclp, inkernelacl, sizeof(struct acl));
|
||||
error = acl_copyin(aclp, inkernelacl, type);
|
||||
if (error)
|
||||
goto out;
|
||||
error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td);
|
||||
@ -430,6 +562,7 @@ acl_alloc(int flags)
|
||||
struct acl *aclp;
|
||||
|
||||
aclp = malloc(sizeof(*aclp), M_ACL, flags);
|
||||
aclp->acl_maxcnt = ACL_MAX_ENTRIES;
|
||||
|
||||
return (aclp);
|
||||
}
|
||||
|
119
sys/sys/acl.h
119
sys/sys/acl.h
@ -43,39 +43,104 @@
|
||||
* POSIX.1e ACL types and related constants.
|
||||
*/
|
||||
|
||||
typedef uint32_t acl_tag_t;
|
||||
typedef uint32_t acl_perm_t;
|
||||
typedef uint16_t acl_entry_type_t;
|
||||
typedef uint16_t acl_flag_t;
|
||||
typedef int acl_type_t;
|
||||
typedef int *acl_permset_t;
|
||||
typedef uint16_t *acl_flagset_t;
|
||||
|
||||
/*
|
||||
* With 254 entries, "struct acl_t_struct" is exactly one 4kB page big.
|
||||
* Note that with NFS4 ACLs, the maximum number of ACL entries one
|
||||
* may set on file or directory is about half of ACL_MAX_ENTRIES.
|
||||
*
|
||||
* If you increase this, you might also need to increase
|
||||
* _ACL_T_ALIGNMENT_BITS in lib/libc/posix1e/acl_support.h.
|
||||
*
|
||||
* The maximum number of POSIX.1e ACLs is controlled
|
||||
* by OLDACL_MAX_ENTRIES. Changing that one will break binary
|
||||
* compatibility with pre-8.0 userland and change on-disk ACL layout.
|
||||
*/
|
||||
#define ACL_MAX_ENTRIES 254
|
||||
|
||||
#if defined(_KERNEL) || defined(_ACL_PRIVATE)
|
||||
|
||||
#define POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM
|
||||
#define POSIX1E_ACL_ACCESS_EXTATTR_NAME "posix1e.acl_access"
|
||||
#define POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM
|
||||
#define POSIX1E_ACL_DEFAULT_EXTATTR_NAME "posix1e.acl_default"
|
||||
#define ACL_MAX_ENTRIES 32 /* maximum entries in an ACL */
|
||||
#define NFS4_ACL_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM
|
||||
#define NFS4_ACL_EXTATTR_NAME "nfs4.acl"
|
||||
#define OLDACL_MAX_ENTRIES 32
|
||||
|
||||
typedef int acl_type_t;
|
||||
typedef int acl_tag_t;
|
||||
typedef mode_t acl_perm_t;
|
||||
typedef mode_t *acl_permset_t;
|
||||
/*
|
||||
* "struct oldacl" is used in compatibility ACL syscalls and for on-disk
|
||||
* storage of POSIX.1e ACLs.
|
||||
*/
|
||||
typedef int oldacl_tag_t;
|
||||
typedef mode_t oldacl_perm_t;
|
||||
|
||||
struct oldacl_entry {
|
||||
oldacl_tag_t ae_tag;
|
||||
uid_t ae_id;
|
||||
oldacl_perm_t ae_perm;
|
||||
};
|
||||
typedef struct oldacl_entry *oldacl_entry_t;
|
||||
|
||||
struct oldacl {
|
||||
int acl_cnt;
|
||||
struct oldacl_entry acl_entry[OLDACL_MAX_ENTRIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* Current "struct acl".
|
||||
*/
|
||||
struct acl_entry {
|
||||
acl_tag_t ae_tag;
|
||||
uid_t ae_id;
|
||||
acl_perm_t ae_perm;
|
||||
/* "allow" or "deny". Unused in POSIX ACLs. */
|
||||
acl_entry_type_t ae_entry_type;
|
||||
/* Flags control inheritance. Unused in POSIX ACLs. */
|
||||
acl_flag_t ae_flags;
|
||||
};
|
||||
typedef struct acl_entry *acl_entry_t;
|
||||
|
||||
/* internal ACL structure */
|
||||
/*
|
||||
* Internal ACL structure, used in libc, kernel APIs and for on-disk
|
||||
* storage of NFS4 ACLs. POSIX.1e ACLs use "struct oldacl" for on-disk
|
||||
* storage.
|
||||
*/
|
||||
struct acl {
|
||||
int acl_cnt;
|
||||
unsigned int acl_maxcnt;
|
||||
unsigned int acl_cnt;
|
||||
/* Will be required e.g. to implement NFSv4.1 ACL inheritance. */
|
||||
int acl_spare[4];
|
||||
struct acl_entry acl_entry[ACL_MAX_ENTRIES];
|
||||
};
|
||||
|
||||
/* external ACL structure */
|
||||
/*
|
||||
* ACL structure internal to libc.
|
||||
*/
|
||||
struct acl_t_struct {
|
||||
struct acl ats_acl;
|
||||
int ats_cur_entry;
|
||||
/* Will be used for ACL branding. */
|
||||
int ats_spare;
|
||||
};
|
||||
typedef struct acl_t_struct *acl_t;
|
||||
|
||||
#else /* _KERNEL || _ACL_PRIVATE */
|
||||
|
||||
typedef void *acl_entry_t;
|
||||
typedef void *acl_t;
|
||||
|
||||
#endif /* !_KERNEL && !_ACL_PRIVATE */
|
||||
|
||||
/*
|
||||
* Possible valid values for ae_tag field.
|
||||
* Possible valid values for ae_tag field. For explanation, see acl(9).
|
||||
*/
|
||||
#define ACL_UNDEFINED_TAG 0x00000000
|
||||
#define ACL_USER_OBJ 0x00000001
|
||||
@ -87,13 +152,17 @@ typedef struct acl_t_struct *acl_t;
|
||||
#define ACL_OTHER_OBJ ACL_OTHER
|
||||
|
||||
/*
|
||||
* Possible valid values for acl_type_t arguments.
|
||||
* Possible valid values for acl_type_t arguments. First two
|
||||
* are provided only for backwards binary compatibility.
|
||||
*/
|
||||
#define ACL_TYPE_ACCESS 0x00000000
|
||||
#define ACL_TYPE_DEFAULT 0x00000001
|
||||
#define ACL_TYPE_ACCESS_OLD 0x00000000
|
||||
#define ACL_TYPE_DEFAULT_OLD 0x00000001
|
||||
#define ACL_TYPE_ACCESS 0x00000002
|
||||
#define ACL_TYPE_DEFAULT 0x00000003
|
||||
|
||||
/*
|
||||
* Possible flags in ae_perm field.
|
||||
* Possible flags in ae_perm field for POSIX.1e ACLs. Note
|
||||
* that ACL_EXECUTE may be used in both NFSv4 and POSIX.1e ACLs.
|
||||
*/
|
||||
#define ACL_EXECUTE 0x0001
|
||||
#define ACL_WRITE 0x0002
|
||||
@ -103,13 +172,14 @@ typedef struct acl_t_struct *acl_t;
|
||||
#define ACL_POSIX1E_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ)
|
||||
|
||||
/*
|
||||
* Possible entry_id values for acl_get_entry()
|
||||
* Possible entry_id values for acl_get_entry(3).
|
||||
*/
|
||||
#define ACL_FIRST_ENTRY 0
|
||||
#define ACL_NEXT_ENTRY 1
|
||||
|
||||
/*
|
||||
* Undefined value in ae_id field
|
||||
* Undefined value in ae_id field. ae_id should be set to this value
|
||||
* iff ae_tag is ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER or ACL_EVERYONE.
|
||||
*/
|
||||
#define ACL_UNDEFINED_ID ((uid_t)-1)
|
||||
|
||||
@ -126,7 +196,7 @@ typedef struct acl_t_struct *acl_t;
|
||||
#define ACL_PRESERVE_MASK (~ACL_OVERRIDE_MASK)
|
||||
|
||||
/*
|
||||
* File system independent code to move back and forth between POSIX mode and
|
||||
* Filesystem-independent code to move back and forth between POSIX mode and
|
||||
* POSIX.1e ACL representations.
|
||||
*/
|
||||
acl_perm_t acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode);
|
||||
@ -141,17 +211,28 @@ mode_t acl_posix1e_newfilemode(mode_t cmode,
|
||||
struct acl *dacl);
|
||||
struct acl *acl_alloc(int flags);
|
||||
void acl_free(struct acl *aclp);
|
||||
int acl_copy_oldacl_into_acl(const struct oldacl *source,
|
||||
struct acl *dest);
|
||||
int acl_copy_acl_into_oldacl(const struct acl *source,
|
||||
struct oldacl *dest);
|
||||
|
||||
/*
|
||||
* File system independent syntax check for a POSIX.1e ACL.
|
||||
* To allocate 'struct acl', use acl_alloc()/acl_free() instead of this.
|
||||
*/
|
||||
MALLOC_DECLARE(M_ACL);
|
||||
|
||||
/*
|
||||
* Filesystem-independent syntax check for a POSIX.1e ACL.
|
||||
*/
|
||||
int acl_posix1e_check(struct acl *acl);
|
||||
|
||||
#else /* !_KERNEL */
|
||||
|
||||
#if defined(_ACL_PRIVATE)
|
||||
|
||||
/*
|
||||
* Syscall interface -- use the library calls instead as the syscalls have
|
||||
* strict acl entry ordering requirements.
|
||||
* strict ACL entry ordering requirements.
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
int __acl_aclcheck_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
|
||||
@ -170,6 +251,8 @@ int __acl_set_file(const char *_path, acl_type_t _type, struct acl *_aclp);
|
||||
int __acl_set_link(const char *_path, acl_type_t _type, struct acl *_aclp);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _ACL_PRIVATE */
|
||||
|
||||
/*
|
||||
* Supported POSIX.1e ACL manipulation and assignment/retrieval API _np calls
|
||||
* are local extensions that reflect an environment capable of opening file
|
||||
|
@ -140,6 +140,56 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip)
|
||||
DIP_SET(ip, i_mode, ip->i_mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read POSIX.1e ACL from an EA. Return error if its not found
|
||||
* or if any other error has occured.
|
||||
*/
|
||||
static int
|
||||
ufs_get_oldacl(acl_type_t type, struct oldacl *old, struct vnode *vp,
|
||||
struct thread *td)
|
||||
{
|
||||
int error, len;
|
||||
struct inode *ip = VTOI(vp);
|
||||
|
||||
len = sizeof(*old);
|
||||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
error = vn_extattr_get(vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAME, &len, (char *) old,
|
||||
td);
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
if (vp->v_type != VDIR)
|
||||
return (EINVAL);
|
||||
error = vn_extattr_get(vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAME, &len, (char *) old,
|
||||
td);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (len != sizeof(*old)) {
|
||||
/*
|
||||
* A short (or long) read, meaning that for some reason
|
||||
* the ACL is corrupted. Return EPERM since the object
|
||||
* DAC protections are unsafe.
|
||||
*/
|
||||
printf("ufs_get_oldacl(): Loaded invalid ACL "
|
||||
"(len = %d), inumber %d on %s\n", len,
|
||||
ip->i_number, ip->i_fs->fs_fsmnt);
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the ACL on a file.
|
||||
*
|
||||
@ -147,18 +197,12 @@ ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip)
|
||||
* assemble both into a final ACL product. Right now this is not done
|
||||
* very efficiently.
|
||||
*/
|
||||
int
|
||||
ufs_getacl(ap)
|
||||
struct vop_getacl_args /* {
|
||||
struct vnode *vp;
|
||||
struct acl_type_t type;
|
||||
struct acl *aclp;
|
||||
struct ucred *cred;
|
||||
struct thread *td;
|
||||
} */ *ap;
|
||||
static int
|
||||
ufs_getacl_posix1e(struct vop_getacl_args *ap)
|
||||
{
|
||||
struct inode *ip = VTOI(ap->a_vp);
|
||||
int error, len;
|
||||
int error;
|
||||
struct oldacl *old;
|
||||
|
||||
/*
|
||||
* XXX: If ufs_getacl() should work on file systems not supporting
|
||||
@ -167,121 +211,83 @@ ufs_getacl(ap)
|
||||
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
* Attempt to retrieve the ACL based on the ACL type.
|
||||
* Attempt to retrieve the ACL from the extended attributes.
|
||||
*/
|
||||
bzero(ap->a_aclp, sizeof(*ap->a_aclp));
|
||||
len = sizeof(*ap->a_aclp);
|
||||
switch(ap->a_type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
/*
|
||||
* ACL_TYPE_ACCESS ACLs may or may not be stored in the
|
||||
* EA, as they are in fact a combination of the inode
|
||||
* ownership/permissions and the EA contents. If the
|
||||
* EA is present, merge the two in a temporary ACL
|
||||
* storage, otherwise just return the inode contents.
|
||||
*/
|
||||
error = vn_extattr_get(ap->a_vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAME, &len, (char *) ap->a_aclp,
|
||||
ap->a_td);
|
||||
switch (error) {
|
||||
/* XXX: If ufs_getacl() should work on filesystems without
|
||||
* the EA configured, add case EOPNOTSUPP here. */
|
||||
case ENOATTR:
|
||||
error = ufs_get_oldacl(ap->a_type, old, ap->a_vp, ap->a_td);
|
||||
switch (error) {
|
||||
/*
|
||||
* XXX: If ufs_getacl() should work on filesystems
|
||||
* without the EA configured, add case EOPNOTSUPP here.
|
||||
*/
|
||||
case ENOATTR:
|
||||
switch (ap->a_type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
/*
|
||||
* Legitimately no ACL set on object, purely
|
||||
* emulate it through the inode. These fields will
|
||||
* be updated when the ACL is synchronized with
|
||||
* the inode later.
|
||||
*/
|
||||
ap->a_aclp->acl_cnt = 3;
|
||||
ap->a_aclp->acl_entry[0].ae_tag = ACL_USER_OBJ;
|
||||
ap->a_aclp->acl_entry[0].ae_id = ACL_UNDEFINED_ID;
|
||||
ap->a_aclp->acl_entry[0].ae_perm = ACL_PERM_NONE;
|
||||
ap->a_aclp->acl_entry[1].ae_tag = ACL_GROUP_OBJ;
|
||||
ap->a_aclp->acl_entry[1].ae_id = ACL_UNDEFINED_ID;
|
||||
ap->a_aclp->acl_entry[1].ae_perm = ACL_PERM_NONE;
|
||||
ap->a_aclp->acl_entry[2].ae_tag = ACL_OTHER;
|
||||
ap->a_aclp->acl_entry[2].ae_id = ACL_UNDEFINED_ID;
|
||||
ap->a_aclp->acl_entry[2].ae_perm = ACL_PERM_NONE;
|
||||
old->acl_cnt = 3;
|
||||
old->acl_entry[0].ae_tag = ACL_USER_OBJ;
|
||||
old->acl_entry[0].ae_id = ACL_UNDEFINED_ID;
|
||||
old->acl_entry[0].ae_perm = ACL_PERM_NONE;
|
||||
old->acl_entry[1].ae_tag = ACL_GROUP_OBJ;
|
||||
old->acl_entry[1].ae_id = ACL_UNDEFINED_ID;
|
||||
old->acl_entry[1].ae_perm = ACL_PERM_NONE;
|
||||
old->acl_entry[2].ae_tag = ACL_OTHER;
|
||||
old->acl_entry[2].ae_id = ACL_UNDEFINED_ID;
|
||||
old->acl_entry[2].ae_perm = ACL_PERM_NONE;
|
||||
break;
|
||||
|
||||
case ACL_TYPE_DEFAULT:
|
||||
/*
|
||||
* Unlike ACL_TYPE_ACCESS, there is no relationship
|
||||
* between the inode contents and the ACL, and it is
|
||||
* therefore possible for the request for the ACL
|
||||
* to fail since the ACL is undefined. In this
|
||||
* situation, return success and an empty ACL,
|
||||
* as required by POSIX.1e.
|
||||
*/
|
||||
old->acl_cnt = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 0:
|
||||
error = acl_copy_oldacl_into_acl(old, ap->a_aclp);
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
if (ap->a_type == ACL_TYPE_ACCESS)
|
||||
ufs_sync_acl_from_inode(ip, ap->a_aclp);
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (len != sizeof(*ap->a_aclp)) {
|
||||
/*
|
||||
* A short (or long) read, meaning that for
|
||||
* some reason the ACL is corrupted. Return
|
||||
* EPERM since the object DAC protections
|
||||
* are unsafe.
|
||||
*/
|
||||
printf("ufs_getacl(): Loaded invalid ACL ("
|
||||
"%d bytes), inumber %d on %s\n", len,
|
||||
ip->i_number, ip->i_fs->fs_fsmnt);
|
||||
return (EPERM);
|
||||
}
|
||||
ufs_sync_acl_from_inode(ip, ap->a_aclp);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACL_TYPE_DEFAULT:
|
||||
if (ap->a_vp->v_type != VDIR) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
error = vn_extattr_get(ap->a_vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAME, &len,
|
||||
(char *) ap->a_aclp, ap->a_td);
|
||||
/*
|
||||
* Unlike ACL_TYPE_ACCESS, there is no relationship between
|
||||
* the inode contents and the ACL, and it is therefore
|
||||
* possible for the request for the ACL to fail since the
|
||||
* ACL is undefined. In this situation, return success
|
||||
* and an empty ACL, as required by POSIX.1e.
|
||||
*/
|
||||
switch (error) {
|
||||
/* XXX: If ufs_getacl() should work on filesystems without
|
||||
* the EA configured, add case EOPNOTSUPP here. */
|
||||
case ENOATTR:
|
||||
bzero(ap->a_aclp, sizeof(*ap->a_aclp));
|
||||
ap->a_aclp->acl_cnt = 0;
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (len != sizeof(*ap->a_aclp)) {
|
||||
/*
|
||||
* A short (or long) read, meaning that for
|
||||
* some reason the ACL is corrupted. Return
|
||||
* EPERM since the object default DAC
|
||||
* protections are unsafe.
|
||||
*/
|
||||
printf("ufs_getacl(): Loaded invalid ACL ("
|
||||
"%d bytes), inumber %d on %s\n", len,
|
||||
ip->i_number, ip->i_fs->fs_fsmnt);
|
||||
return (EPERM);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
free(old, M_ACL);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ufs_getacl(ap)
|
||||
struct vop_getacl_args /* {
|
||||
struct vnode *vp;
|
||||
acl_type_t type;
|
||||
struct acl *aclp;
|
||||
struct ucred *cred;
|
||||
struct thread *td;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (ufs_getacl_posix1e(ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the ACL on a file.
|
||||
*
|
||||
@ -291,18 +297,12 @@ ufs_getacl(ap)
|
||||
* a fair number of different access checks may be required to go ahead
|
||||
* with the operation at all.
|
||||
*/
|
||||
int
|
||||
ufs_setacl(ap)
|
||||
struct vop_setacl_args /* {
|
||||
struct vnode *vp;
|
||||
acl_type_t type;
|
||||
struct acl *aclp;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
} */ *ap;
|
||||
static int
|
||||
ufs_setacl_posix1e(struct vop_setacl_args *ap)
|
||||
{
|
||||
struct inode *ip = VTOI(ap->a_vp);
|
||||
int error;
|
||||
struct oldacl *old;
|
||||
|
||||
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
|
||||
return (EOPNOTSUPP);
|
||||
@ -349,10 +349,15 @@ ufs_setacl(ap)
|
||||
|
||||
switch(ap->a_type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAME, sizeof(*ap->a_aclp),
|
||||
(char *) ap->a_aclp, ap->a_td);
|
||||
old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO);
|
||||
error = acl_copy_acl_into_oldacl(ap->a_aclp, old);
|
||||
if (error == 0) {
|
||||
error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_ACCESS_EXTATTR_NAME, sizeof(*old),
|
||||
(char *) old, ap->a_td);
|
||||
}
|
||||
free(old, M_ACL);
|
||||
break;
|
||||
|
||||
case ACL_TYPE_DEFAULT:
|
||||
@ -372,11 +377,17 @@ ufs_setacl(ap)
|
||||
*/
|
||||
if (error == ENOATTR)
|
||||
error = 0;
|
||||
} else
|
||||
error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAME,
|
||||
sizeof(*ap->a_aclp), (char *) ap->a_aclp, ap->a_td);
|
||||
} else {
|
||||
old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO);
|
||||
error = acl_copy_acl_into_oldacl(ap->a_aclp, old);
|
||||
if (error == 0) {
|
||||
error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
|
||||
POSIX1E_ACL_DEFAULT_EXTATTR_NAME,
|
||||
sizeof(*old), (char *) old, ap->a_td);
|
||||
}
|
||||
free(old, M_ACL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -404,12 +415,9 @@ ufs_setacl(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the validity of an ACL for a file.
|
||||
*/
|
||||
int
|
||||
ufs_aclcheck(ap)
|
||||
struct vop_aclcheck_args /* {
|
||||
ufs_setacl(ap)
|
||||
struct vop_setacl_args /* {
|
||||
struct vnode *vp;
|
||||
acl_type_t type;
|
||||
struct acl *aclp;
|
||||
@ -418,6 +426,13 @@ ufs_aclcheck(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (ufs_setacl_posix1e(ap));
|
||||
}
|
||||
|
||||
static int
|
||||
ufs_aclcheck_posix1e(struct vop_aclcheck_args *ap)
|
||||
{
|
||||
|
||||
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
@ -438,7 +453,28 @@ ufs_aclcheck(ap)
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (ap->a_aclp->acl_cnt > OLDACL_MAX_ENTRIES)
|
||||
return (EINVAL);
|
||||
|
||||
return (acl_posix1e_check(ap->a_aclp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the validity of an ACL for a file.
|
||||
*/
|
||||
int
|
||||
ufs_aclcheck(ap)
|
||||
struct vop_aclcheck_args /* {
|
||||
struct vnode *vp;
|
||||
acl_type_t type;
|
||||
struct acl *aclp;
|
||||
struct ucred *cred;
|
||||
struct thread *td;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (ufs_aclcheck_posix1e(ap));
|
||||
}
|
||||
|
||||
#endif /* !UFS_ACL */
|
||||
|
Loading…
x
Reference in New Issue
Block a user