Skip to content

Commit

Permalink
Add object type checking to zap_lockdir()
Browse files Browse the repository at this point in the history
If a non-ZAP object is passed to zap_lockdir() it will be treated
as a valid ZAP object.  This can result in zap_lockdir() attempting
to read what it believes are leaf blocks from invalid disk locations.
The SCSI layer will eventually generate errors for these bogus IOs
but the caller will hang in zap_get_leaf_byblk().

The good news is that is a situation which can not occur unless the
pool has been damaged.  The bad news is that there are reports from
both FreeBSD and Solaris of damaged pools.  Specifically, there are
normal files in the filesystem which reference another normal file
as their parent.

Since pools like this are known to exist the zap_lockdir() function
has been updated to verify the type of the object.  If a non-ZAP
object has been passed it EINVAL will be returned immediately.

Signed-off-by: Brian Behlendorf <[email protected]>
Issue openzfs#2597
Issue openzfs#2602
  • Loading branch information
behlendorf authored and ryao committed Nov 29, 2014
1 parent 87ddec8 commit 3fc8f0b
Showing 1 changed file with 4 additions and 7 deletions.
11 changes: 4 additions & 7 deletions module/zfs/zap_micro.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ int
zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp)
{
dmu_object_info_t doi;
zap_t *zap;
dmu_buf_t *db;
krw_t lt;
Expand All @@ -457,13 +458,9 @@ zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
if (err)
return (err);

#ifdef ZFS_DEBUG
{
dmu_object_info_t doi;
dmu_object_info_from_db(db, &doi);
ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
}
#endif
dmu_object_info_from_db(db, &doi);
if (DMU_OT_BYTESWAP(doi.doi_type) != DMU_BSWAP_ZAP)
return (SET_ERROR(EINVAL));

zap = dmu_buf_get_user(db);
if (zap == NULL)
Expand Down

0 comments on commit 3fc8f0b

Please sign in to comment.