FreeBSD: Fix UNIX permissions checking

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
Closes #10727
This commit is contained in:
Matthew Macy 2020-08-18 09:57:07 -07:00 committed by GitHub
parent 5e7eaf8fbd
commit 716b53d0a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 174 additions and 99 deletions

View File

@ -0,0 +1,97 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_IDMAP_H
#define _SYS_IDMAP_H
/* Idmap status codes */
#define IDMAP_SUCCESS 0
#define IDMAP_NEXT 1
#define IDMAP_ERR_OTHER -10000
#define IDMAP_ERR_INTERNAL -9999
#define IDMAP_ERR_MEMORY -9998
#define IDMAP_ERR_NORESULT -9997
#define IDMAP_ERR_NOTUSER -9996
#define IDMAP_ERR_NOTGROUP -9995
#define IDMAP_ERR_NOTSUPPORTED -9994
#define IDMAP_ERR_W2U_NAMERULE -9993
#define IDMAP_ERR_U2W_NAMERULE -9992
#define IDMAP_ERR_CACHE -9991
#define IDMAP_ERR_DB -9990
#define IDMAP_ERR_ARG -9989
#define IDMAP_ERR_SID -9988
#define IDMAP_ERR_IDTYPE -9987
#define IDMAP_ERR_RPC_HANDLE -9986
#define IDMAP_ERR_RPC -9985
#define IDMAP_ERR_CLIENT_HANDLE -9984
#define IDMAP_ERR_BUSY -9983
#define IDMAP_ERR_PERMISSION_DENIED -9982
#define IDMAP_ERR_NOMAPPING -9981
#define IDMAP_ERR_NEW_ID_ALLOC_REQD -9980
#define IDMAP_ERR_DOMAIN -9979
#define IDMAP_ERR_SECURITY -9978
#define IDMAP_ERR_NOTFOUND -9977
#define IDMAP_ERR_DOMAIN_NOTFOUND -9976
#define IDMAP_ERR_UPDATE_NOTALLOWED -9975
#define IDMAP_ERR_CFG -9974
#define IDMAP_ERR_CFG_CHANGE -9973
#define IDMAP_ERR_NOTMAPPED_WELLKNOWN -9972
#define IDMAP_ERR_RETRIABLE_NET_ERR -9971
#define IDMAP_ERR_W2U_NAMERULE_CONFLICT -9970
#define IDMAP_ERR_U2W_NAMERULE_CONFLICT -9969
#define IDMAP_ERR_BAD_UTF8 -9968
#define IDMAP_ERR_NONE_GENERATED -9967
#define IDMAP_ERR_PROP_UNKNOWN -9966
#define IDMAP_ERR_NS_LDAP_OP_FAILED -9965
#define IDMAP_ERR_NS_LDAP_PARTIAL -9964
#define IDMAP_ERR_NS_LDAP_CFG -9963
#define IDMAP_ERR_NS_LDAP_BAD_WINNAME -9962
#define IDMAP_ERR_NO_ACTIVEDIRECTORY -9961
/* Reserved GIDs for some well-known SIDs */
#define IDMAP_WK_LOCAL_SYSTEM_GID 2147483648U /* 0x80000000 */
#define IDMAP_WK_CREATOR_GROUP_GID 2147483649U
#define IDMAP_WK__MAX_GID 2147483649U
/* Reserved UIDs for some well-known SIDs */
#define IDMAP_WK_CREATOR_OWNER_UID 2147483648U
#define IDMAP_WK__MAX_UID 2147483648U
/* Reserved SIDs */
#define IDMAP_WK_CREATOR_SID_AUTHORITY "S-1-3"
/*
* Max door RPC size for ID mapping (can't be too large relative to the
* default user-land thread stack size, since clnt_door_call()
* alloca()s). See libidmap:idmap_init().
*/
#define IDMAP_MAX_DOOR_RPC (256 * 1024)
#define IDMAP_SENTINEL_PID UINT32_MAX
#define IDMAP_ID_IS_EPHEMERAL(pid) \
(((pid) > INT32_MAX) && ((pid) != IDMAP_SENTINEL_PID))
#endif /* _SYS_IDMAP_H */

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
*
* $FreeBSD$
*/
#ifndef _OPENSOLARIS_SYS_KIDMAP_H_
#define _OPENSOLARIS_SYS_KIDMAP_H_
#include <sys/idmap.h>
typedef int32_t idmap_stat;
typedef void idmap_get_handle_t;
#define kidmap_get_create() (NULL)
#define kidmap_get_destroy(hdl) do { } while (0)
#define kidmap_get_mappings(hdl) (NULL)
#endif /* _OPENSOLARIS_SYS_KIDMAP_H_ */

View File

@ -28,6 +28,8 @@
#ifndef _OPENSOLARIS_SYS_SID_H_ #ifndef _OPENSOLARIS_SYS_SID_H_
#define _OPENSOLARIS_SYS_SID_H_ #define _OPENSOLARIS_SYS_SID_H_
#include <sys/idmap.h>
#include <sys/kidmap.h>
typedef struct ksiddomain { typedef struct ksiddomain {
char *kd_name; /* Domain part of SID */ char *kd_name; /* Domain part of SID */

View File

@ -27,9 +27,9 @@ CFLAGS+= -I${INCDIR}/os/freebsd/spl
CFLAGS+= -I${INCDIR}/os/freebsd/zfs CFLAGS+= -I${INCDIR}/os/freebsd/zfs
CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h
CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \
CFLAGS+= -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \
CFLAGS+= -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP -DHAVE_KSID
.if ${MACHINE_ARCH} == "amd64" .if ${MACHINE_ARCH} == "amd64"
CFLAGS+= -DHAVE_AVX2 -DHAVE_AVX -D__x86_64 -DHAVE_SSE2 -DHAVE_AVX512F -DHAVE_SSSE3 CFLAGS+= -DHAVE_AVX2 -DHAVE_AVX -D__x86_64 -DHAVE_SSE2 -DHAVE_AVX512F -DHAVE_SSSE3
@ -276,7 +276,6 @@ SRCS+= abd.c \
zfs_file_os.c \ zfs_file_os.c \
zfs_fm.c \ zfs_fm.c \
zfs_fuid.c \ zfs_fuid.c \
zfs_fuid_os.c \
zfs_ioctl.c \ zfs_ioctl.c \
zfs_onexit.c \ zfs_onexit.c \
zfs_quota.c \ zfs_quota.c \

View File

@ -2305,10 +2305,7 @@ zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs,
int int
zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
{ {
boolean_t owner = B_FALSE;
boolean_t groupmbr = B_FALSE;
boolean_t is_attr; boolean_t is_attr;
uid_t uid = crgetuid(cr);
if (zdp->z_pflags & ZFS_AV_QUARANTINED) if (zdp->z_pflags & ZFS_AV_QUARANTINED)
return (1); return (1);
@ -2321,37 +2318,6 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) if (zdp->z_pflags & ZFS_NO_EXECS_DENIED)
return (0); return (0);
mutex_enter(&zdp->z_acl_lock);
if (FUID_INDEX(zdp->z_uid) != 0 || FUID_INDEX(zdp->z_gid) != 0) {
goto out_slow;
}
if (uid == zdp->z_uid) {
owner = B_TRUE;
if (zdp->z_mode & S_IXUSR) {
goto out;
} else {
goto out_slow;
}
}
if (groupmember(zdp->z_gid, cr)) {
groupmbr = B_TRUE;
if (zdp->z_mode & S_IXGRP) {
goto out;
} else {
goto out_slow;
}
}
if (!owner && !groupmbr) {
if (zdp->z_mode & S_IXOTH) {
goto out;
}
}
out:
mutex_exit(&zdp->z_acl_lock);
return (0);
out_slow:
mutex_exit(&zdp->z_acl_lock);
return (1); return (1);
} }

View File

@ -1,51 +0,0 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/zfs_context.h>
#include <sys/dmu.h>
#include <sys/avl.h>
#include <sys/zap.h>
#include <sys/nvpair.h>
#ifdef _KERNEL
#include <sys/sid.h>
#include <sys/zfs_vfsops.h>
#include <sys/zfs_znode.h>
#endif
#include <sys/zfs_fuid.h>
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
cred_t *cr, zfs_fuid_info_t **fuidp)
{
uid_t id;
VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);
id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr);
if (IS_EPHEMERAL(id))
return ((type == ZFS_OWNER) ? UID_NOBODY : GID_NOBODY);
return ((uint64_t)id);
}

View File

@ -387,11 +387,34 @@ zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
cr, ZFS_GROUP); cr, ZFS_GROUP);
} }
#ifdef __FreeBSD__
uid_t
zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
cred_t *cr, zfs_fuid_type_t type)
{
uint32_t index = FUID_INDEX(fuid);
if (index == 0)
return (fuid);
return (UID_NOBODY);
}
#elif defined(__linux__)
uid_t
zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
cred_t *cr, zfs_fuid_type_t type)
{
/*
* The Linux port only supports POSIX IDs, use the passed id.
*/
return (fuid);
}
#else
uid_t uid_t
zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid, zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
cred_t *cr, zfs_fuid_type_t type) cred_t *cr, zfs_fuid_type_t type)
{ {
#ifdef HAVE_KSID
uint32_t index = FUID_INDEX(fuid); uint32_t index = FUID_INDEX(fuid);
const char *domain; const char *domain;
uid_t id; uid_t id;
@ -410,13 +433,8 @@ zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
FUID_RID(fuid), &id); FUID_RID(fuid), &id);
} }
return (id); return (id);
#else
/*
* The Linux port only supports POSIX IDs, use the passed id.
*/
return (fuid);
#endif /* HAVE_KSID */
} }
#endif
/* /*
* Add a FUID node to the list of fuid's being created for this * Add a FUID node to the list of fuid's being created for this
@ -559,9 +577,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
const char *domain; const char *domain;
char *kdomain; char *kdomain;
uint32_t fuid_idx = FUID_INDEX(id); uint32_t fuid_idx = FUID_INDEX(id);
uint32_t rid; uint32_t rid = 0;
idmap_stat status; idmap_stat status;
uint64_t idx = 0; uint64_t idx = UID_NOBODY;
zfs_fuid_t *zfuid = NULL; zfs_fuid_t *zfuid = NULL;
zfs_fuid_info_t *fuidp = NULL; zfs_fuid_info_t *fuidp = NULL;
@ -711,9 +729,11 @@ boolean_t
zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr) zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
{ {
#ifdef HAVE_KSID #ifdef HAVE_KSID
uid_t gid;
#ifdef illumos
ksid_t *ksid = crgetsid(cr, KSID_GROUP); ksid_t *ksid = crgetsid(cr, KSID_GROUP);
ksidlist_t *ksidlist = crgetsidlist(cr); ksidlist_t *ksidlist = crgetsidlist(cr);
uid_t gid;
if (ksid && ksidlist) { if (ksid && ksidlist) {
int i; int i;
@ -746,6 +766,7 @@ zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
} }
} }
} }
#endif /* illumos */
/* /*
* Not found in ksidlist, check posix groups * Not found in ksidlist, check posix groups