From 9b24f0fe87f4de390455f3dc237f20607a508082 Mon Sep 17 00:00:00 2001 From: BjoKaSH Date: Mon, 3 Sep 2012 23:02:52 +0200 Subject: [PATCH] Fixed potential NULL pointer dereference in zap_lookup_norm() In zap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name, uint64_t integer_size, uint64_t num_integers, void *buf, matchtype_t mt, char *realname, int rn_len, boolean_t *ncp) strlcpy() is called with a size of 0, which results in undefined behavior. Calltree (example): ==00:00:00:07.711 27867== Invalid write of size 1 ==00:00:00:07.711 27867== at 0x10016AFFA: strlcpy (mc_replace_strmem.c:373) ==00:00:00:07.711 27867== by 0x1000AF568: zap_lookup_norm (zap_micro.c:683) ==00:00:00:07.711 27867== by 0x1000AF428: zap_lookup (zap_micro.c:645) ==00:00:00:07.711 27867== by 0x10007A78B: dsl_pool_open (dsl_pool.c:92) ==00:00:00:07.711 27867== by 0x100083AB0: spa_load (spa.c:1124) ==00:00:00:07.711 27867== by 0x100084538: spa_open_common (spa.c:1456) ==00:00:00:07.711 27867== by 0x100084783: spa_open (spa.c:1528) ==00:00:00:07.711 27867== by 0x100008404: main (zdb.c:2399) ==00:00:00:07.711 27867== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==00:00:00:07.711 27867== ==00:00:00:07.711 27867== ==00:00:00:07.711 27867== Process terminating with default action of signal 11 (SIGSEGV) ==00:00:00:07.711 27867== Access not within mapped region at address 0x0 Note that zap_lookup() *always* calls zap_lookup_norm() with a zero size argument, which is correct. So zap_lookup_norm() must not depend on implementation-defined behavior regarding strlcpy with zero size. --- usr/src/uts/common/fs/zfs/zap_micro.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usr/src/uts/common/fs/zfs/zap_micro.c b/usr/src/uts/common/fs/zfs/zap_micro.c index 421e0473..487a78ec 100644 --- a/usr/src/uts/common/fs/zfs/zap_micro.c +++ b/usr/src/uts/common/fs/zfs/zap_micro.c @@ -680,8 +680,9 @@ zap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name, err = EINVAL; } else { *(uint64_t *)buf = mze->mze_phys.mze_value; - (void) strlcpy(realname, - mze->mze_phys.mze_name, rn_len); + if (rn_len > 0) /* strlcpy may not be called with size == 0 */ + (void) strlcpy(realname, + mze->mze_phys.mze_name, rn_len); if (ncp) { *ncp = mzap_normalization_conflict(zap, zn, mze);