From nobody Mon Feb 9 21:36:48 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+69057+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+69057+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1608158524; cv=none; d=zohomail.com; s=zohoarc; b=ThfeS48/xXf8oaf83fZb8/7YY+pvA9uGJionVYkV9uAg65ec0ZZvJuMnqLllnlIC+mIQ4u08E7dB+Pumknay3/BRVO4XjqaUlZ7KozvfIK6mXdQO1vsZjHeUDUp4/wF213ILtHGPufnd06Kz61Xa0TKeBCyA+w4hEbRr3xTybB4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1608158524; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=ELV9cx4rWAkc/Y2TNsgL6MPBQUqJMlPiJcs0+JcOp74=; b=C+y1NJhIhnTvi9FUUCu8WDractdXjhZ87jvW/DzrDOlDw3BU9Klvi2P0CXaJ5JaMURdjVDmgAdQvc+LRhzeaxMRkNR7b8c2Oudsym9ZU7XGH5ZqB+tR5ra10QH1C346m9Dd6vE+agLJbaiqwOQWzWRZPyH54bQXbXXA6NgLnkbQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+69057+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1608158524744731.5570134142256; Wed, 16 Dec 2020 14:42:04 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id rCONYY1788612xXIg4GnFDml; Wed, 16 Dec 2020 14:42:04 -0800 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.groups.io with SMTP id smtpd.web09.4892.1608158523714886860 for ; Wed, 16 Dec 2020 14:42:04 -0800 X-Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-464-CO5xvLpBP6mzLnhumGaN6g-1; Wed, 16 Dec 2020 17:42:01 -0500 X-MC-Unique: CO5xvLpBP6mzLnhumGaN6g-1 X-Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D6CBE801A9E; Wed, 16 Dec 2020 22:41:59 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-114-152.ams2.redhat.com [10.36.114.152]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4C7991971D; Wed, 16 Dec 2020 22:41:55 +0000 (UTC) From: "Laszlo Ersek" To: devel@edk2.groups.io, virtio-fs@redhat.com, lersek@redhat.com Cc: Ard Biesheuvel , Jordan Justen , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [edk2-devel] [edk2 PATCH 43/48] OvmfPkg/VirtioFsDxe: handle file rename/move in EFI_FILE_PROTOCOL.SetInfo Date: Wed, 16 Dec 2020 22:11:20 +0100 Message-Id: <20201216211125.19496-44-lersek@redhat.com> In-Reply-To: <20201216211125.19496-1-lersek@redhat.com> References: <20201216211125.19496-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lersek@redhat.com X-Gm-Message-State: OIHC7LBB2ELJgfCXYQNjkHNbx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1608158524; bh=ELV9cx4rWAkc/Y2TNsgL6MPBQUqJMlPiJcs0+JcOp74=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=bHPjmNA9Wht7Fwx48U0q7k5pVfJJqs/ZO9h6DdbVefYCdCqsw/fOBnjH6ra+kZVFUZS Sd9Mnb8meJYZDZj07sLGp/0Wlk0LVBfKXX7TUWsgPyeIRrczL+oBfoNb8DHaDfSevNJti Sg/54VNBVQf2BavV4Qfod8ok7SusUj2mQA8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Using the functions introduced previously, we can now implement the rename operation in VirtioFsSimpleFileSetInfo(). Attribute updates come later. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Philippe Mathieu-Daud=C3=A9 Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3097 Signed-off-by: Laszlo Ersek --- OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c | 234 +++++++++++++++++++- 1 file changed, 233 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c b/OvmfPkg/VirtioFsDxe/Si= mpleFsSetInfo.c index 895b5c029a9e..55169dde78b7 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c @@ -5,16 +5,17 @@ =20 SPDX-License-Identifier: BSD-2-Clause-Patent **/ =20 #include // gEfiFileSystemInfoGuid #include // gEfiFileSystemVolumeLabelIn= fo... #include // StrCmp() #include // CompareGuid() +#include // FreePool() =20 #include "VirtioFsDxe.h" =20 /** Validate a buffer that the EFI_FILE_PROTOCOL.SetInfo() caller passes in = for a particular InformationType GUID. =20 The structure to be validated is supposed to end with a variable-length, @@ -122,16 +123,247 @@ ValidateInfoStructure ( NameField =3D (CHAR16 *)((UINT8 *)Buffer + NameFieldByteOffset); if (NameField[NameFieldChar16s - 1] !=3D L'\0') { return EFI_INVALID_PARAMETER; } =20 return EFI_SUCCESS; } =20 +/** + Rename a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.FileName. + + @param[in,out] VirtioFsFile The VIRTIO_FS_FILE to rename. + + @param[in] NewFileName The new file name requested by + EFI_FILE_PROTOCOL.SetInfo(). + + @retval EFI_SUCCESS The canonical format destination path that is + determined from the input value of + VirtioFsFile->CanonicalPathname and from + NewFileName is identical to the input value of + VirtioFsFile->CanonicalPathname. This means t= hat + EFI_FILE_INFO does not constitute a rename + request. VirtioFsFile has not been changed. + + @retval EFI_SUCCESS VirtioFsFile has been renamed. + VirtioFsFile->CanonicalPathname has assumed t= he + destination pathname in canonical format. + + @retval EFI_ACCESS_DENIED VirtioFsFile refers to the root directory, and + NewFileName expresses an actual rename/move + request. + + @retval EFI_ACCESS_DENIED VirtioFsFile is the (possibly indirect) parent + directory of at least one other VIRTIO_FS_FILE + that is open for the same Virtio Filesystem + (identified by VirtioFsFile->OwnerFs). Renami= ng + VirtioFsFile would invalidate the canonical + pathnames of those VIRTIO_FS_FILE instances; + therefore the request has been rejected. + + @retval EFI_ACCESS_DENIED VirtioFsFile is not open for writing, but + NewFileName expresses an actual rename/move + request. + + @retval EFI_NOT_FOUND At least one dot-dot component in NewFileName + attempted to escape the root directory. + + @return Error codes propagated from underlying functi= ons. +**/ +STATIC +EFI_STATUS +Rename ( + IN OUT VIRTIO_FS_FILE *VirtioFsFile, + IN CHAR16 *NewFileName + ) +{ + + VIRTIO_FS *VirtioFs; + EFI_STATUS Status; + CHAR8 *Destination; + BOOLEAN RootEscape; + UINT64 OldParentDirNodeId; + CHAR8 *OldLastComponent; + UINT64 NewParentDirNodeId; + CHAR8 *NewLastComponent; + + VirtioFs =3D VirtioFsFile->OwnerFs; + + // + // The root directory cannot be renamed. + // + if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, "/") =3D=3D 0) { + if (StrCmp (NewFileName, L"") =3D=3D 0) { + // + // Not a rename request anyway. + // + return EFI_SUCCESS; + } + return EFI_ACCESS_DENIED; + } + + // + // Compose the canonical pathname for the destination. + // + Status =3D VirtioFsComposeRenameDestination (VirtioFsFile->CanonicalPath= name, + NewFileName, &Destination, &RootEscape); + if (EFI_ERROR (Status)) { + return Status; + } + if (RootEscape) { + Status =3D EFI_NOT_FOUND; + goto FreeDestination; + } + // + // If the rename would leave VirtioFsFile->CanonicalPathname unchanged, = then + // EFI_FILE_PROTOCOL.SetInfo() isn't asking for a rename actually. + // + if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, Destination) =3D=3D 0)= { + Status =3D EFI_SUCCESS; + goto FreeDestination; + } + // + // Check if the rename would break the canonical pathnames of other + // VIRTIO_FS_FILE instances of the same VIRTIO_FS. + // + if (VirtioFsFile->IsDirectory) { + UINTN PathLen; + LIST_ENTRY *OpenFilesEntry; + + PathLen =3D AsciiStrLen (VirtioFsFile->CanonicalPathname); + BASE_LIST_FOR_EACH (OpenFilesEntry, &VirtioFs->OpenFiles) { + VIRTIO_FS_FILE *OtherFile; + + OtherFile =3D VIRTIO_FS_FILE_FROM_OPEN_FILES_ENTRY (OpenFilesEntry); + if (OtherFile !=3D VirtioFsFile && + AsciiStrnCmp (VirtioFsFile->CanonicalPathname, + OtherFile->CanonicalPathname, PathLen) =3D=3D 0 && + (OtherFile->CanonicalPathname[PathLen] =3D=3D '\0' || + OtherFile->CanonicalPathname[PathLen] =3D=3D '/')) { + // + // OtherFile refers to the same directory as VirtioFsFile, or is a + // (possibly indirect) child of the directory referred to by + // VirtioFsFile. + // + Status =3D EFI_ACCESS_DENIED; + goto FreeDestination; + } + } + } + // + // From this point on, the file needs to be open for writing. + // + if (!VirtioFsFile->IsOpenForWriting) { + Status =3D EFI_ACCESS_DENIED; + goto FreeDestination; + } + // + // Split both source and destination canonical pathnames into (most spec= ific + // parent directory, last component) pairs. + // + Status =3D VirtioFsLookupMostSpecificParentDir (VirtioFs, + VirtioFsFile->CanonicalPathname, &OldParentDirNodeId, + &OldLastComponent); + if (EFI_ERROR (Status)) { + goto FreeDestination; + } + Status =3D VirtioFsLookupMostSpecificParentDir (VirtioFs, Destination, + &NewParentDirNodeId, &NewLastComponent); + if (EFI_ERROR (Status)) { + goto ForgetOldParentDirNodeId; + } + // + // Perform the rename. If the destination path exists, the rename will f= ail. + // + Status =3D VirtioFsFuseRename (VirtioFs, OldParentDirNodeId, OldLastComp= onent, + NewParentDirNodeId, NewLastComponent); + if (EFI_ERROR (Status)) { + goto ForgetNewParentDirNodeId; + } + + // + // Swap in the new canonical pathname. + // + FreePool (VirtioFsFile->CanonicalPathname); + VirtioFsFile->CanonicalPathname =3D Destination; + Destination =3D NULL; + Status =3D EFI_SUCCESS; + + // + // Fall through. + // +ForgetNewParentDirNodeId: + if (NewParentDirNodeId !=3D VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) { + VirtioFsFuseForget (VirtioFs, NewParentDirNodeId); + } + +ForgetOldParentDirNodeId: + if (OldParentDirNodeId !=3D VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) { + VirtioFsFuseForget (VirtioFs, OldParentDirNodeId); + } + +FreeDestination: + if (Destination !=3D NULL) { + FreePool (Destination); + } + return Status; +} + +/** + Process an EFI_FILE_INFO setting request. +**/ +STATIC +EFI_STATUS +SetFileInfo ( + IN EFI_FILE_PROTOCOL *This, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + VIRTIO_FS_FILE *VirtioFsFile; + EFI_STATUS Status; + EFI_FILE_INFO *FileInfo; + + VirtioFsFile =3D VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This); + + // + // Validate if Buffer passes as EFI_FILE_INFO. + // + Status =3D ValidateInfoStructure ( + BufferSize, // SizeByProtocolCaller + OFFSET_OF (EFI_FILE_INFO, + FileName) + sizeof (CHAR16), // MinimumStructSize + TRUE, // IsSizeByInfoPresent + Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + FileInfo =3D Buffer; + + // + // Perform the rename/move request, if any. + // + Status =3D Rename (VirtioFsFile, FileInfo->FileName); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Update any attributes requested. + // + Status =3D EFI_UNSUPPORTED; + // + // The UEFI spec does not speak about partial failure in + // EFI_FILE_PROTOCOL.SetInfo(); we won't try to roll back the rename (if + // there was one) in case the attribute updates fail. + // + return Status; +} + /** Process an EFI_FILE_SYSTEM_INFO setting request. **/ STATIC EFI_STATUS SetFileSystemInfo ( IN EFI_FILE_PROTOCOL *This, IN UINTN BufferSize, @@ -225,17 +457,17 @@ EFIAPI VirtioFsSimpleFileSetInfo ( IN EFI_FILE_PROTOCOL *This, IN EFI_GUID *InformationType, IN UINTN BufferSize, IN VOID *Buffer ) { if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { - return EFI_UNSUPPORTED; + return SetFileInfo (This, BufferSize, Buffer); } =20 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { return SetFileSystemInfo (This, BufferSize, Buffer); } =20 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid))= { return SetFileSystemVolumeLabelInfo (This, BufferSize, Buffer); --=20 2.19.1.3.g30247aa5d201 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#69057): https://edk2.groups.io/g/devel/message/69057 Mute This Topic: https://groups.io/mt/79024496/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-