summaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_byteswap.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2009-01-15 13:59:39 -0800
committerBrian Behlendorf <[email protected]>2009-01-15 13:59:39 -0800
commitfb5f0bc83330c8a0236c4d34a23723ac1974971a (patch)
tree51880dcfa8ec9e8e80b8c44e9ffc55a4b7160216 /module/zfs/zfs_byteswap.c
parent42bcb36c8987b0b11411ce6cf8339694b624a17c (diff)
Rebase master to b105
Diffstat (limited to 'module/zfs/zfs_byteswap.c')
-rw-r--r--module/zfs/zfs_byteswap.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/module/zfs/zfs_byteswap.c b/module/zfs/zfs_byteswap.c
index ab97f83eb..cd36696f9 100644
--- a/module/zfs/zfs_byteswap.c
+++ b/module/zfs/zfs_byteswap.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/zfs_context.h>
#include <sys/vfs.h>
#include <sys/fs/zfs.h>
@@ -63,6 +61,20 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
while (ptr < end) {
if (zfs_layout) {
+ /*
+ * Avoid overrun. Embedded aces can have one
+ * of several sizes. We don't know exactly
+ * how many our present, only the size of the
+ * buffer containing them. That size may be
+ * larger than needed to hold the aces
+ * present. As long as we do not do any
+ * swapping beyond the end of our block we are
+ * okay. It it safe to swap any non-ace data
+ * within the block since it is just zeros.
+ */
+ if (ptr + sizeof (zfs_ace_hdr_t) > end) {
+ break;
+ }
zacep = (zfs_ace_t *)ptr;
zacep->z_hdr.z_access_mask =
BSWAP_32(zacep->z_hdr.z_access_mask);
@@ -71,6 +83,10 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
BSWAP_16(zacep->z_hdr.z_type);
entry_type = zacep->z_hdr.z_flags & ACE_TYPE_FLAGS;
} else {
+ /* Overrun avoidance */
+ if (ptr + sizeof (ace_t) > end) {
+ break;
+ }
acep = (ace_t *)ptr;
acep->a_access_mask = BSWAP_32(acep->a_access_mask);
acep->a_flags = BSWAP_16(acep->a_flags);
@@ -87,8 +103,14 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
break;
case ACE_IDENTIFIER_GROUP:
default:
+ /* Overrun avoidance */
if (zfs_layout) {
- zacep->z_fuid = BSWAP_64(zacep->z_fuid);
+ if (ptr + sizeof (zfs_ace_t) <= end) {
+ zacep->z_fuid = BSWAP_64(zacep->z_fuid);
+ } else {
+ entry_size = sizeof (zfs_ace_t);
+ break;
+ }
}
switch (ace_type) {
case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
@@ -169,7 +191,8 @@ zfs_znode_byteswap(void *buf, size_t size)
if (zp->zp_acl.z_acl_version == ZFS_ACL_VERSION) {
zfs_acl_byteswap((void *)&zp->zp_acl.z_ace_data[0],
ZFS_ACE_SPACE);
- } else
+ } else {
zfs_oldace_byteswap((ace_t *)&zp->zp_acl.z_ace_data[0],
ACE_SLOT_CNT);
+ }
}