CVE-2020-24717 (published 2020-08-27T19:15Z)

OpenZFS before 2.0.0-rc1, when used on FreeBSD, misinterprets group permissions as user permissions, as demonstrated by mode 0770 being equivalent to mode 0777.

Severity: HIGH
CVSS v2 base score: 7.2 (AV:L/AC:L/Au:N/C:C/I:C/A:C)
CVSS v3 base score: 7.8, HIGH (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-276
cwe_name: Incorrect Default Permissions
description: During installation, installed file permissions are set to allow anyone to modify those files.
extended_description: 
      
      
     
     

Fix information:
repo_url: https://github.com/openzfs/zfs
commit_details: repo_url: https://github.com/openzfs/zfs
author: Matthew Macy
author_date: 2020-08-18 09:57:07-07:00
msg: 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
repository: repo_url: https://github.com/openzfs/zfs
repo_name: openzfs/zfs
description: OpenZFS on Linux and FreeBSD
repo_language: C
owner: openzfs
file_changes: filename: idmap.h
change_type: ModificationType.ADD
diff: @@ -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 */

programming_language: C
filename: kidmap.h
change_type: ModificationType.ADD
diff: @@ -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_ */

programming_language: C
filename: sid.h
change_type: ModificationType.MODIFY
diff: @@ -28,6 +28,8 @@
 
 #ifndef _OPENSOLARIS_SYS_SID_H_
 #define	_OPENSOLARIS_SYS_SID_H_
+#include <sys/idmap.h>
+#include <sys/kidmap.h>
 
 typedef struct ksiddomain {
 	char	*kd_name;	/* Domain part of SID */

programming_language: C
filename: Makefile.bsd
change_type: ModificationType.MODIFY
diff: @@ -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 \

programming_language: Shell
filename: zfs_acl.c
change_type: ModificationType.MODIFY
diff: @@ -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);
 }
 

programming_language: C
filename: zfs_fuid_os.c
change_type: ModificationType.DELETE
diff: @@ -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);
-}

programming_language: unknown
filename: zfs_fuid.c
change_type: ModificationType.MODIFY
diff: @@ -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

programming_language: C