From 716b53d0a14c72bda16c0872565dd1909757e73f Mon Sep 17 00:00:00 2001 From: Matthew Macy Date: Tue, 18 Aug 2020 09:57:07 -0700 Subject: [PATCH] FreeBSD: Fix UNIX permissions checking Reviewed-by: Ryan Moeller Reviewed-by: Brian Behlendorf Signed-off-by: Matt Macy Closes #10727 --- include/os/freebsd/spl/sys/idmap.h | 97 +++++++++++++++++++++++++++++ include/os/freebsd/spl/sys/kidmap.h | 41 ++++++++++++ include/os/freebsd/spl/sys/sid.h | 2 + module/Makefile.bsd | 7 +-- module/os/freebsd/zfs/zfs_acl.c | 34 ---------- module/os/freebsd/zfs/zfs_fuid_os.c | 51 --------------- module/zfs/zfs_fuid.c | 41 +++++++++--- 7 files changed, 174 insertions(+), 99 deletions(-) create mode 100644 include/os/freebsd/spl/sys/idmap.h create mode 100644 include/os/freebsd/spl/sys/kidmap.h delete mode 100644 module/os/freebsd/zfs/zfs_fuid_os.c diff --git a/include/os/freebsd/spl/sys/idmap.h b/include/os/freebsd/spl/sys/idmap.h new file mode 100644 index 0000000000..39eeb905c7 --- /dev/null +++ b/include/os/freebsd/spl/sys/idmap.h @@ -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 */ diff --git a/include/os/freebsd/spl/sys/kidmap.h b/include/os/freebsd/spl/sys/kidmap.h new file mode 100644 index 0000000000..dc0cf5988a --- /dev/null +++ b/include/os/freebsd/spl/sys/kidmap.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2007 Pawel Jakub Dawidek + * 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 + +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_ */ diff --git a/include/os/freebsd/spl/sys/sid.h b/include/os/freebsd/spl/sys/sid.h index 18b6834250..d3fab8b247 100644 --- a/include/os/freebsd/spl/sys/sid.h +++ b/include/os/freebsd/spl/sys/sid.h @@ -28,6 +28,8 @@ #ifndef _OPENSOLARIS_SYS_SID_H_ #define _OPENSOLARIS_SYS_SID_H_ +#include +#include typedef struct ksiddomain { char *kd_name; /* Domain part of SID */ diff --git a/module/Makefile.bsd b/module/Makefile.bsd index 76889770c5..c6ace9fb56 100644 --- a/module/Makefile.bsd +++ b/module/Makefile.bsd @@ -27,9 +27,9 @@ CFLAGS+= -I${INCDIR}/os/freebsd/spl CFLAGS+= -I${INCDIR}/os/freebsd/zfs CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h -CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 -CFLAGS+= -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ -CFLAGS+= -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP +CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \ + -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \ + -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP -DHAVE_KSID .if ${MACHINE_ARCH} == "amd64" 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_fm.c \ zfs_fuid.c \ - zfs_fuid_os.c \ zfs_ioctl.c \ zfs_onexit.c \ zfs_quota.c \ diff --git a/module/os/freebsd/zfs/zfs_acl.c b/module/os/freebsd/zfs/zfs_acl.c index 7446df1d10..be72d2c240 100644 --- a/module/os/freebsd/zfs/zfs_acl.c +++ b/module/os/freebsd/zfs/zfs_acl.c @@ -2305,10 +2305,7 @@ zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, int zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) { - boolean_t owner = B_FALSE; - boolean_t groupmbr = B_FALSE; boolean_t is_attr; - uid_t uid = crgetuid(cr); if (zdp->z_pflags & ZFS_AV_QUARANTINED) return (1); @@ -2321,37 +2318,6 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) 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); } diff --git a/module/os/freebsd/zfs/zfs_fuid_os.c b/module/os/freebsd/zfs/zfs_fuid_os.c deleted file mode 100644 index 72655d7ff6..0000000000 --- a/module/os/freebsd/zfs/zfs_fuid_os.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#ifdef _KERNEL -#include -#include -#include -#endif -#include - -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); -} diff --git a/module/zfs/zfs_fuid.c b/module/zfs/zfs_fuid.c index 726b923fac..015dde4811 100644 --- a/module/zfs/zfs_fuid.c +++ b/module/zfs/zfs_fuid.c @@ -387,11 +387,34 @@ zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp) 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 zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid, cred_t *cr, zfs_fuid_type_t type) { -#ifdef HAVE_KSID uint32_t index = FUID_INDEX(fuid); const char *domain; uid_t id; @@ -410,13 +433,8 @@ zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid, FUID_RID(fuid), &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 @@ -559,9 +577,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr, const char *domain; char *kdomain; uint32_t fuid_idx = FUID_INDEX(id); - uint32_t rid; + uint32_t rid = 0; idmap_stat status; - uint64_t idx = 0; + uint64_t idx = UID_NOBODY; zfs_fuid_t *zfuid = NULL; zfs_fuid_info_t *fuidp = NULL; @@ -711,9 +729,11 @@ boolean_t zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr) { #ifdef HAVE_KSID + uid_t gid; + +#ifdef illumos ksid_t *ksid = crgetsid(cr, KSID_GROUP); ksidlist_t *ksidlist = crgetsidlist(cr); - uid_t gid; if (ksid && ksidlist) { 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