mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-26 04:07:45 +03:00
OpenZFS 6314 - buffer overflow in dsl_dataset_name
Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Prakash Surya <prakash.surya@delphix.com> Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Approved by: Dan McDonald <danmcd@omniti.com> Ported-by: Brian Behlendorf <behlendorf1@llnl.gov> OpenZFS-issue: https://www.illumos.org/issues/6314 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/d6160ee
This commit is contained in:
committed by
Brian Behlendorf
parent
43e52eddb1
commit
eca7b76001
+35
-16
@@ -670,22 +670,38 @@ dsl_dataset_name(dsl_dataset_t *ds, char *name)
|
||||
dsl_dir_name(ds->ds_dir, name);
|
||||
VERIFY0(dsl_dataset_get_snapname(ds));
|
||||
if (ds->ds_snapname[0]) {
|
||||
(void) strcat(name, "@");
|
||||
VERIFY3U(strlcat(name, "@", ZFS_MAX_DATASET_NAME_LEN),
|
||||
<, ZFS_MAX_DATASET_NAME_LEN);
|
||||
/*
|
||||
* We use a "recursive" mutex so that we
|
||||
* can call dprintf_ds() with ds_lock held.
|
||||
*/
|
||||
if (!MUTEX_HELD(&ds->ds_lock)) {
|
||||
mutex_enter(&ds->ds_lock);
|
||||
(void) strcat(name, ds->ds_snapname);
|
||||
VERIFY3U(strlcat(name, ds->ds_snapname,
|
||||
ZFS_MAX_DATASET_NAME_LEN), <,
|
||||
ZFS_MAX_DATASET_NAME_LEN);
|
||||
mutex_exit(&ds->ds_lock);
|
||||
} else {
|
||||
(void) strcat(name, ds->ds_snapname);
|
||||
VERIFY3U(strlcat(name, ds->ds_snapname,
|
||||
ZFS_MAX_DATASET_NAME_LEN), <,
|
||||
ZFS_MAX_DATASET_NAME_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dsl_dataset_namelen(dsl_dataset_t *ds)
|
||||
{
|
||||
int len;
|
||||
VERIFY0(dsl_dataset_get_snapname(ds));
|
||||
mutex_enter(&ds->ds_lock);
|
||||
len = dsl_dir_namelen(ds->ds_dir) + 1 + strlen(ds->ds_snapname);
|
||||
mutex_exit(&ds->ds_lock);
|
||||
return (len);
|
||||
}
|
||||
|
||||
void
|
||||
dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
|
||||
{
|
||||
@@ -1255,10 +1271,10 @@ dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
|
||||
int error = 0;
|
||||
dsl_dataset_t *ds;
|
||||
char *name, *atp;
|
||||
char dsname[MAXNAMELEN];
|
||||
char dsname[ZFS_MAX_DATASET_NAME_LEN];
|
||||
|
||||
name = nvpair_name(pair);
|
||||
if (strlen(name) >= MAXNAMELEN)
|
||||
if (strlen(name) >= ZFS_MAX_DATASET_NAME_LEN)
|
||||
error = SET_ERROR(ENAMETOOLONG);
|
||||
if (error == 0) {
|
||||
atp = strchr(name, '@');
|
||||
@@ -1431,7 +1447,7 @@ dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
|
||||
pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
|
||||
dsl_dataset_t *ds;
|
||||
char *name, *atp;
|
||||
char dsname[MAXNAMELEN];
|
||||
char dsname[ZFS_MAX_DATASET_NAME_LEN];
|
||||
|
||||
name = nvpair_name(pair);
|
||||
atp = strchr(name, '@');
|
||||
@@ -1478,7 +1494,7 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
|
||||
suspended = fnvlist_alloc();
|
||||
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
|
||||
pair = nvlist_next_nvpair(snaps, pair)) {
|
||||
char fsname[MAXNAMELEN];
|
||||
char fsname[ZFS_MAX_DATASET_NAME_LEN];
|
||||
char *snapname = nvpair_name(pair);
|
||||
char *atp;
|
||||
void *cookie;
|
||||
@@ -1687,7 +1703,7 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
|
||||
zap_cursor_retrieve(&zc, &za) == 0;
|
||||
zap_cursor_advance(&zc)) {
|
||||
dsl_dataset_t *clone;
|
||||
char buf[ZFS_MAXNAMELEN];
|
||||
char buf[ZFS_MAX_DATASET_NAME_LEN];
|
||||
VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
|
||||
za.za_first_integer, FTAG, &clone));
|
||||
dsl_dir_name(clone->ds_dir, buf);
|
||||
@@ -1797,7 +1813,7 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
||||
get_clones_stat(ds, nv);
|
||||
} else {
|
||||
if (ds->ds_prev != NULL && ds->ds_prev != dp->dp_origin_snap) {
|
||||
char buf[MAXNAMELEN];
|
||||
char buf[ZFS_MAX_DATASET_NAME_LEN];
|
||||
dsl_dataset_name(ds->ds_prev, buf);
|
||||
dsl_prop_nvlist_add_string(nv, ZFS_PROP_PREV_SNAP, buf);
|
||||
}
|
||||
@@ -1848,8 +1864,9 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
||||
}
|
||||
|
||||
if (!dsl_dataset_is_snapshot(ds)) {
|
||||
/* 6 extra bytes for /%recv */
|
||||
char recvname[ZFS_MAX_DATASET_NAME_LEN + 6];
|
||||
dsl_dataset_t *recv_ds;
|
||||
char recvname[ZFS_MAXNAMELEN];
|
||||
|
||||
/*
|
||||
* A failed "newfs" (e.g. full) resumable receive leaves
|
||||
@@ -1863,9 +1880,11 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
||||
* for the prop.
|
||||
*/
|
||||
dsl_dataset_name(ds, recvname);
|
||||
(void) strcat(recvname, "/");
|
||||
(void) strcat(recvname, recv_clone_name);
|
||||
if (dsl_dataset_hold(dp, recvname, FTAG, &recv_ds) == 0) {
|
||||
if (strlcat(recvname, "/", sizeof (recvname)) <
|
||||
sizeof (recvname) &&
|
||||
strlcat(recvname, recv_clone_name, sizeof (recvname)) <
|
||||
sizeof (recvname) &&
|
||||
dsl_dataset_hold(dp, recvname, FTAG, &recv_ds) == 0) {
|
||||
get_receive_resume_stats(recv_ds, nv);
|
||||
dsl_dataset_rele(recv_ds, FTAG);
|
||||
}
|
||||
@@ -1990,7 +2009,7 @@ dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
|
||||
|
||||
/* dataset name + 1 for the "@" + the new snapshot name must fit */
|
||||
if (dsl_dir_namelen(hds->ds_dir) + 1 +
|
||||
strlen(ddrsa->ddrsa_newsnapname) >= MAXNAMELEN)
|
||||
strlen(ddrsa->ddrsa_newsnapname) >= ZFS_MAX_DATASET_NAME_LEN)
|
||||
error = SET_ERROR(ENAMETOOLONG);
|
||||
|
||||
return (error);
|
||||
@@ -2223,7 +2242,7 @@ dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
dsl_dataset_t *ds, *clone;
|
||||
uint64_t cloneobj;
|
||||
char namebuf[ZFS_MAXNAMELEN];
|
||||
char namebuf[ZFS_MAX_DATASET_NAME_LEN];
|
||||
|
||||
VERIFY0(dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds));
|
||||
|
||||
@@ -2776,7 +2795,7 @@ promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag)
|
||||
* Promote a clone.
|
||||
*
|
||||
* If it fails due to a conflicting snapshot name, "conflsnap" will be filled
|
||||
* in with the name. (It must be at least MAXNAMELEN bytes long.)
|
||||
* in with the name. (It must be at least ZFS_MAX_DATASET_NAME_LEN bytes long.)
|
||||
*/
|
||||
int
|
||||
dsl_dataset_promote(const char *name, char *conflsnap)
|
||||
|
||||
Reference in New Issue
Block a user