From nobody Wed Jul 16 19:33:48 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 4bj5p44BDxz61tN8; Wed, 16 Jul 2025 19:33:48 +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 4bj5p42nY1z3cH7; Wed, 16 Jul 2025 19:33:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1752694428; 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=ORDB9rjhKEl6ZMRhKPeTwdjhndGcdJwmYEOZj3pud5U=; b=R+yJiEHBdzMPsiBuhYJsqKCZVxK9AoFkBWAjkiSuZPVXDitf6wUnLJN4JuEGWvK6SDGpq2 0DETT7HjGK7c7qLbRU2gaMow3dZzj5YOB8MpqPT0lJH1JBG2FLpWLRH/67pgmFgsLRgdCd pTtsZf/aWsSLwPuhZGxke2AopSmtmqPF+16ix8HEN8w9+U9DVMDr8xi6hFNigxUNjALn7+ k6LFGxDzk4ZBBiWvyZltcg1g4hADp2xWQQG8Jom3KURN4R6N0/pE0xc6+0KMOxW5oEfXFR 8rnjohhXkZJ39iWYsV8GlOaSZR/dazkDX5K8TYW4FgYKtgIb8SZEicw3LzA8iw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1752694428; 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=ORDB9rjhKEl6ZMRhKPeTwdjhndGcdJwmYEOZj3pud5U=; b=R6Iuc1Imx3EaaZhRtSAGCXpvWPY5bYuuS/zZWrYU4IY6jCPQK18zD7R28m8UUp1cs8PI58 1reydl6U4z+2nPQYyEPbWJ1UGwf8o31NTAV85z9QdhvqlgWddlXdXKUh2Clu4SJ90jY8dr L+e9ek58vn/482j9igtTupwd3kCNInZcJjNnya3VAvu84/7EqJCviCAivf8nGzEd21rbp4 PJFEymbXCE3jb7a2zBKapkHWGW42UAOo1o9KzhYTmvWHnf4DVKf6urgzWLgzrlEmbdLJ+R qyKiw4SQqab8Qg5X1wqGXnD1eIsOEkTosJ7LaJbX67WcH3kT/0YaEpJ7a5ncqg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1752694428; a=rsa-sha256; cv=none; b=wnS6+4Qd1G7QU3VgBU0WlTpUVY46ifiQugkI2N19idsCmjll44nmk4gTs/sgpscJKKcNHr SlmGoTyomJhLfD6MIcWKkh/HBiXl44aABEW4YPlxaMZfR1ZrVmSgKsSUEivMqvsMMGhQE6 5Qnbpvf4/Pz9ZCzcOTD63dpIEgv9RYmid4Q95UZcLE7DKvTJo5Q9lATNzckLOXNJjo+BuL PNy8ux214AYDElFPNu74W1f9vu+gSdGe/wd9HPnwNH39adcji6TRYlgMNDACwFOrkZ78RX 96f7CG6XO7F8Lb6iOcsKJfGfMUKNjiyGaeq46dSGYVxR0WBdNXxKGdXA/Mib8Q== 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 4bj5p41ysNz7Wj; Wed, 16 Jul 2025 19:33:48 +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 56GJXmgH016365; Wed, 16 Jul 2025 19:33:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 56GJXmuH016362; Wed, 16 Jul 2025 19:33:48 GMT (envelope-from git) Date: Wed, 16 Jul 2025 19:33:48 GMT Message-Id: <202507161933.56GJXmuH016362@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 55f80afa17e8 - main - 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/main X-Git-Reftype: branch X-Git-Commit: 55f80afa17e8926f69660f19631194bcf7fa66f4 Auto-Submitted: auto-generated The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=55f80afa17e8926f69660f19631194bcf7fa66f4 commit 55f80afa17e8926f69660f19631194bcf7fa66f4 Author: Dag-Erling Smørgrav AuthorDate: 2025-07-16 19:33:24 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-07-16 19:33:41 +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 --- 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 c7438147c0a0..c5ef1f686093 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 @@ -729,7 +730,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; @@ -741,6 +742,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 88bf4917a851..37889241e8c3 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; } @@ -314,12 +318,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); } @@ -446,6 +451,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; @@ -471,7 +477,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); @@ -783,6 +794,7 @@ udf_readdir(struct vop_readdir_args *a) struct udf_uiodir uiodir; struct udf_dirstream *ds; uint64_t *cookies = NULL; + uint64_t len; int ncookies; int error = 0; @@ -811,8 +823,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? */ @@ -904,7 +920,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 @@ -914,6 +931,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; @@ -1116,13 +1135,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); @@ -1133,6 +1153,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