From nobody Thu Jul 24 13:02:40 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bnrl46R3Wz62Tds; Thu, 24 Jul 2025 13:02:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bnrl44Kkjz3T9K; Thu, 24 Jul 2025 13:02:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1753362160; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nwTodgoQ9QdfycpG4alokaVxgV7nDfrUfd3UV4+wgtw=; b=diMJJHvVP/915H1sEda7868Oz/WkxdbbCBc0Ko4YRhbE8aheOoR5i+5Xoqbi3kPnPQ1WHC 9Hn3UzLD8IuvyiirsXw0cmBZGU3XSItMpO74YPY7gvE9h5pXtisCPjgIMa4GAnlqKacFKm aQZJBYZ1osdPykFm+NyaW+jLmM9G0Qscyh/RPokvTB68XRqkCD1GjcjTyZO5Eymn76lmLG Vx2cft18I2c3xzdTExz25rbdZgY67Anh/lBll9ADVlRXOHqa1vGJeGixjdS5OyG8sVkUSP xoL3xNaA1IdakISdBhK3S0ZdpIev4uNylZOpoSAPM+mC/Km1Y37GERwkL5QC3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1753362160; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nwTodgoQ9QdfycpG4alokaVxgV7nDfrUfd3UV4+wgtw=; b=a/GDdrn1zluQsHogAUlymvlSRZKyuPmkHIYpxdeQ/D85OA7bn1fhaCTt3aehCA1VFZmFXF Yrbuur2ukDuLDlU2q6KsBjrk6sJi7UAGmlLyjy7SIJKBJqvt0yfEs11g/qYXPBz3ceYPRg W8wda0bxIXAK/ge03iNSRWa0UFqJbQy6fzIwyDk6OFf3zA4tlfM9/0uezAerYFvnEw2+Lq ExiNmAQz95CnMFXyRjc6IeQp+T7t32AjmLK5yksurmsyCWzvjYuEql6ebRUv+kuGfQt2S6 JG0DxYgtiJCTDzFQpr3FungdNMQeCI12J+xRWfaB0UiBNbyk6m7WaC8Nxl2B0A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1753362160; a=rsa-sha256; cv=none; b=RfVqQzh1/w3SJZ1sZDs/f+3jZWaXSjnohFSA3mu6F+/jsuJ995fO30YTj+Zyd4k+Isu3pb pRozFesFGTypyR1RGuyNvMtinSeETezJIu9Blrx4sKEIa1HWgkNXhvtgKZWv2rQ2qHKoA+ 2jo9+0cxLIbxYLlsTh/Cyu7aKOobbcSqGSE7x+CTGl7BckiETs+jZJDBihc30YAs9m9eXP UJi4D/B+MuKegnpJQfpzcpFJhyDHBno/X7eeHfOnHWQmOiDtHslgagzu2hxpP/zQ9UyKFU sd3ZK7RM+BDu12p7t6Ex6bL7+YgAUVijY9MgwobDVS/zkVGq49/lrhuifO728w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bnrl43lFPz10Cd; Thu, 24 Jul 2025 13:02:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 56OD2eYZ001665; Thu, 24 Jul 2025 13:02:40 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 56OD2esR001662; Thu, 24 Jul 2025 13:02:40 GMT (envelope-from git) Date: Thu, 24 Jul 2025 13:02:40 GMT Message-Id: <202507241302.56OD2esR001662@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 4cafd1021a5b - stable/13 - udf: Improve input validation. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 4cafd1021a5b6002812f4446794541eab8c08534 Auto-Submitted: auto-generated The branch stable/13 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=4cafd1021a5b6002812f4446794541eab8c08534 commit 4cafd1021a5b6002812f4446794541eab8c08534 Author: Dag-Erling Smørgrav AuthorDate: 2025-07-16 19:33:24 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-07-24 13:02:12 +0000 udf: Improve input validation. The existing code frequently assigns unsigned 64-bit values to variables that are signed and / or shorter without checking for overflow. Try to deal with these cases. While here, fix two structs that used single-element arrays in place of flexible array members. PR: 287896 MFC after: 1 week Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D51339 (cherry picked from commit 55f80afa17e8926f69660f19631194bcf7fa66f4) --- sys/fs/udf/ecma167-udf.h | 4 ++-- sys/fs/udf/udf_vfsops.c | 7 ++++++- sys/fs/udf/udf_vnops.c | 48 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/sys/fs/udf/ecma167-udf.h b/sys/fs/udf/ecma167-udf.h index 839bbec08254..19e114763cac 100644 --- a/sys/fs/udf/ecma167-udf.h +++ b/sys/fs/udf/ecma167-udf.h @@ -243,7 +243,7 @@ struct part_map_spare { uint8_t n_st; /* Number of Sparing Tables */ uint8_t reserved1; uint32_t st_size; - uint32_t st_loc[1]; + uint32_t st_loc[]; } __packed; union udf_pmap { @@ -266,7 +266,7 @@ struct udf_sparing_table { uint16_t rt_l; /* Relocation Table len */ uint8_t reserved[2]; uint32_t seq_num; - struct spare_map_entry entries[1]; + struct spare_map_entry entries[]; } __packed; /* Partition Descriptor [3/10.5] */ diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index 4c9208642dea..cebc136b418a 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -739,7 +740,7 @@ udf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) struct ifid *ifhp; struct vnode *nvp; struct udf_node *np; - off_t fsize; + uint64_t fsize; int error; ifhp = (struct ifid *)fhp; @@ -751,6 +752,10 @@ udf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) np = VTON(nvp); fsize = le64toh(np->fentry->inf_len); + if (fsize > OFF_MAX) { + *vpp = NULLVP; + return (EIO); + } *vpp = nvp; vnode_create_vobject(*vpp, fsize, curthread); diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c index d85bb9970913..8051b1e24d22 100644 --- a/sys/fs/udf/udf_vnops.c +++ b/sys/fs/udf/udf_vnops.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -182,11 +183,14 @@ udf_access(struct vop_access_args *a) } static int -udf_open(struct vop_open_args *ap) { +udf_open(struct vop_open_args *ap) +{ struct udf_node *np = VTON(ap->a_vp); - off_t fsize; + uint64_t fsize; fsize = le64toh(np->fentry->inf_len); + if (fsize > OFF_MAX) + return (EIO); vnode_create_vobject(ap->a_vp, fsize, ap->a_td); return 0; } @@ -317,12 +321,13 @@ udf_getattr(struct vop_getattr_args *a) * that directories consume at least one logical block, * make it appear so. */ - if (fentry->logblks_rec != 0) { - vap->va_size = - le64toh(fentry->logblks_rec) * node->udfmp->bsize; - } else { + vap->va_size = le64toh(fentry->logblks_rec); + if (vap->va_size == 0) vap->va_size = node->udfmp->bsize; - } + else if (vap->va_size > UINT64_MAX / node->udfmp->bsize) + vap->va_size = UINT64_MAX; + else + vap->va_size *= node->udfmp->bsize; } else { vap->va_size = le64toh(fentry->inf_len); } @@ -449,6 +454,7 @@ udf_read(struct vop_read_args *ap) struct buf *bp; uint8_t *data; daddr_t lbn, rablock; + uint64_t len; off_t diff, fsize; ssize_t n; int error = 0; @@ -474,7 +480,12 @@ udf_read(struct vop_read_args *ap) return (error); } - fsize = le64toh(node->fentry->inf_len); + len = le64toh(node->fentry->inf_len); + if (len > OFF_MAX) { + /* too big, just cap to the requested length */ + len = uio->uio_resid; + } + fsize = len; udfmp = node->udfmp; do { lbn = lblkno(udfmp, uio->uio_offset); @@ -786,6 +797,7 @@ udf_readdir(struct vop_readdir_args *a) struct udf_uiodir uiodir; struct udf_dirstream *ds; u_long *cookies = NULL; + uint64_t len; int ncookies; int error = 0; @@ -815,8 +827,12 @@ udf_readdir(struct vop_readdir_args *a) * Iterate through the file id descriptors. Give the parent dir * entry special attention. */ - ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), - node->udfmp); + len = le64toh(node->fentry->inf_len); + if (len > INT_MAX) { + /* too big, just cap to INT_MAX */ + len = INT_MAX; + } + ds = udf_opendir(node, uio->uio_offset, len, node->udfmp); while ((fid = udf_getfid(ds)) != NULL) { /* XXX Should we return an error on a bad fid? */ @@ -908,7 +924,8 @@ udf_readlink(struct vop_readlink_args *ap) struct udf_node *node; void *buf; char *cp; - int error, len, root; + uint64_t len; + int error, root; /* * A symbolic link in UDF is a list of variable-length path @@ -918,6 +935,8 @@ udf_readlink(struct vop_readlink_args *ap) vp = ap->a_vp; node = VTON(vp); len = le64toh(node->fentry->inf_len); + if (len > MAXPATHLEN) + return (EIO); buf = malloc(len, M_DEVBUF, M_WAITOK); iov[0].iov_len = len; iov[0].iov_base = buf; @@ -1120,13 +1139,14 @@ udf_lookup(struct vop_cachedlookup_args *a) struct udf_mnt *udfmp; struct fileid_desc *fid = NULL; struct udf_dirstream *ds; + uint64_t fsize; u_long nameiop; u_long flags; char *nameptr; long namelen; ino_t id = 0; int offset, error = 0; - int fsize, lkflags, ltype, numdirpasses; + int lkflags, ltype, numdirpasses; dvp = a->a_dvp; node = VTON(dvp); @@ -1137,6 +1157,10 @@ udf_lookup(struct vop_cachedlookup_args *a) nameptr = a->a_cnp->cn_nameptr; namelen = a->a_cnp->cn_namelen; fsize = le64toh(node->fentry->inf_len); + if (fsize > INT_MAX) { + /* too big, just cap to INT_MAX */ + fsize = INT_MAX; + } /* * If this is a LOOKUP and we've already partially searched through