From nobody Fri May 10 16:57:10 2024 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+93423+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+93423+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1662559356; cv=none; d=zohomail.com; s=zohoarc; b=DhQXpGiIK1fB86D/j3oPJ9gqje0NAvh6tqf5Q28Vc48MDdYmSnNaO8tEkXV2W8fPONNxnz0pU4qZuuRQUTJJCLqfPOCTBZA/rxohMqzmwsYWYtu36xu5/PO3y7N4AxlnFnCtV0BKO9wzSn1ZM2b3pw//uO2qOhSDzQW7IPuRCag= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1662559356; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=41XIqVg45vvCcuqR0hlyadOk+TvMDqcv7a9Snk6DMak=; b=bwW2b9vt3lzfSVVoNw/T5Ma9qCOF7mICjRRRcHQttjM5F0osC6frIVL4Wq7tnPc6v44jEoUX8thHuJHwMrKMnWd6hrYPqVDqYqqax7/mQtx1byitdKKJMzOML3jQsu/LDRIVa1SmCZWDNxhkuudBYrNnAD8vkX3Sa6huCoXYQJ4= 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+93423+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1662559356481988.2173815240236; Wed, 7 Sep 2022 07:02:36 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 5BsFYY1788612xdCfFrVH7Uy; Wed, 07 Sep 2022 07:02:36 -0700 X-Received: from mail-lj1-f170.google.com (mail-lj1-f170.google.com [209.85.208.170]) by mx.groups.io with SMTP id smtpd.web10.8016.1662559355071112403 for ; Wed, 07 Sep 2022 07:02:35 -0700 X-Received: by mail-lj1-f170.google.com with SMTP id y18so1342213ljh.12 for ; Wed, 07 Sep 2022 07:02:34 -0700 (PDT) X-Gm-Message-State: CR36nFFBpW9PtHixaqzEPUddx1787277AA= X-Google-Smtp-Source: AA6agR73Nicd3YoQR0No4gnmzOa3knGdQKMlPPzKctsvgwbel0xQYeLAJExFaIXFXMWnW79F2k28Zw== X-Received: by 2002:a2e:3003:0:b0:268:7c2d:765c with SMTP id w3-20020a2e3003000000b002687c2d765cmr1030912ljw.120.1662559350246; Wed, 07 Sep 2022 07:02:30 -0700 (PDT) X-Received: from localhost.localdomain ([176.59.149.223]) by smtp.gmail.com with ESMTPSA id o12-20020ac24e8c000000b0049482979fe0sm2506399lfr.179.2022.09.07.07.02.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Sep 2022 07:02:29 -0700 (PDT) From: "Savva Mitrofanov" To: devel@edk2.groups.io Cc: =?UTF-8?q?Marvin=20H=C3=A4user?= , Pedro Falcato , Vitaly Cheptsov Subject: [edk2-devel] [edk2-platforms][PATCH v5 1/2] Ext4Pkg: Add symbolic links support Date: Wed, 7 Sep 2022 20:02:12 +0600 Message-Id: <20220907140213.13286-2-savvamtr@gmail.com> In-Reply-To: <20220907140213.13286-1-savvamtr@gmail.com> References: <20220907140213.13286-1-savvamtr@gmail.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: 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,savvamtr@gmail.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1662559356; bh=NUIFdaOjqzTkgKpLZRb7ctwI2IUceDcKaU0L0SVbaps=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=J76hfbER1jIogw5TrMKRWk6uUX+AfKwswpOz+YeFgyG77g4Olo53xVU+I7NCvet8JJ1 7Chh+JXNk7g+WSLSjtDPsNzR3o4+68YuEuo8X4kB3jxO6VOTo0MeMZAE8HJDyIP3U3wyJ umgKeoG3RtpC74qqafEBXMTZQGyqJl0nJ9A= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1662559358537100010 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3677 Provided support for symlink file type. Added routine which allows reading and following them through recursive open() call. As a security meausure implemented simple symlink loop check with nest level limit equal 8. Also this patch moves Ext4Open functionality to internal routine. Cc: Marvin H=C3=A4user Cc: Pedro Falcato Cc: Vitaly Cheptsov Signed-off-by: Savva Mitrofanov --- Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.inf | 1 + Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h | 13 +- Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h | 72 +++++- Features/Ext4Pkg/Ext4Dxe/File.c | 169 +++++++++++-- Features/Ext4Pkg/Ext4Dxe/Inode.c | 15 ++ Features/Ext4Pkg/Ext4Dxe/Symlink.c | 261 ++++++++++++++++++++ 6 files changed, 492 insertions(+), 39 deletions(-) diff --git a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.inf b/Features/Ext4Pkg/Ext4Dx= e/Ext4Dxe.inf index deaf89fb3743..a153fc41ccd6 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.inf +++ b/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.inf @@ -108,6 +108,7 @@ Directory.c Extents.c File.c + Symlink.c Collation.c Ext4Disk.h Ext4Dxe.h diff --git a/Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h b/Features/Ext4Pkg/Ext4Dxe= /Ext4Disk.h index 7a19d2f79d53..4fd91a423324 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h +++ b/Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h @@ -171,7 +171,7 @@ #define EXT4_DIRTY_FL 0x00000100 #define EXT4_COMPRBLK_FL 0x00000200 #define EXT4_NOCOMPR_FL 0x00000400 -#define EXT4_ECOMPR_FL 0x00000800 +#define EXT4_ENCRYPT_FL 0x00000800 #define EXT4_BTREE_FL 0x00001000 #define EXT4_INDEX_FL 0x00002000 #define EXT4_JOURNAL_DATA_FL 0x00004000 @@ -332,11 +332,12 @@ STATIC_ASSERT ( "ext4 block group descriptor struct has incorrect size" ); =20 -#define EXT4_DBLOCKS 12 -#define EXT4_IND_BLOCK 12 -#define EXT4_DIND_BLOCK 13 -#define EXT4_TIND_BLOCK 14 -#define EXT4_NR_BLOCKS 15 +#define EXT4_DBLOCKS 12 +#define EXT4_IND_BLOCK 12 +#define EXT4_DIND_BLOCK 13 +#define EXT4_TIND_BLOCK 14 +#define EXT4_NR_BLOCKS 15 +#define EXT4_FAST_SYMLINK_MAX_SIZE EXT4_NR_BLOCKS * sizeof(UINT32) =20 #define EXT4_GOOD_OLD_INODE_SIZE 128U =20 diff --git a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h b/Features/Ext4Pkg/Ext4Dxe/= Ext4Dxe.h index 81e59a4babc9..6d352d3995f1 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h +++ b/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h @@ -31,8 +31,14 @@ =20 #include "Ext4Disk.h" =20 +#define SYMLOOP_MAX 8 #define EXT4_NAME_MAX 255 - +// +// We need to specify path length limit for security purposes, to prevent = possible +// overflows and dead-loop conditions. Originally this limit is absent in = FS design, +// but present in UNIX distros and shell environments, which may varies fr= om 1024 to 4096. +// +#define EXT4_EFI_PATH_MAX 4096 #define EXT4_DRIVER_VERSION 0x0000 =20 /** @@ -324,11 +330,11 @@ number of read bytes. **/ EFI_STATUS Ext4Read ( - IN EXT4_PARTITION *Partition, - IN EXT4_FILE *File, - OUT VOID *Buffer, - IN UINT64 Offset, - IN OUT UINTN *Length + IN EXT4_PARTITION *Partition, + IN EXT4_FILE *File, + OUT VOID *Buffer, + IN UINT64 Offset, + IN OUT UINTN *Length ); =20 /** @@ -368,6 +374,7 @@ struct _Ext4File { =20 UINT64 OpenMode; UINT64 Position; + UINT32 SymLoops; =20 EXT4_PARTITION *Partition; =20 @@ -497,6 +504,45 @@ Ext4SetupFile ( IN EXT4_PARTITION *Partition ); =20 +/** + Opens a new file relative to the source file's location. + + @param[out] FoundFile A pointer to the location to return the opened ha= ndle for the new + file. + @param[in] Source A pointer to the EXT4_FILE instance that is the f= ile + handle to the source location. This would typical= ly be an open + handle to a directory. + @param[in] FileName The Null-terminated string of the name of the fil= e to be opened. + The file name may contain the following path modi= fiers: "\", ".", + and "..". + @param[in] OpenMode The mode to open the file. The only valid combina= tions that the + file may be opened with are: Read, Read/Write, or= Create/Read/Write. + @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which cas= e these are the + attribute bits for the newly created file. + + @retval EFI_SUCCESS The file was opened. + @retval EFI_NOT_FOUND The specified file could not be found on th= e device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or = the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or op= en a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open= the file. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +EFI_STATUS +Ext4OpenInternal ( + OUT EXT4_FILE **FoundFile, + IN EXT4_FILE *Source, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + /** Closes a file. =20 @@ -774,6 +820,18 @@ Ext4FileIsDir ( IN CONST EXT4_FILE *File ); =20 +/** + Checks if a file is a symlink. + + @param[in] File Pointer to the opened file. + + @return BOOLEAN Whether file is a symlink +**/ +BOOLEAN +Ext4FileIsSymlink ( + IN CONST EXT4_FILE *File + ); + /** Checks if a file is a regular file. @param[in] File Pointer to the opened file. @@ -797,7 +855,7 @@ Ext4FileIsReg ( it's a regular file or a directory, since most other file types don't make sense under UEFI. **/ -#define Ext4FileIsOpenable(File) (Ext4FileIsReg(File) || Ext4FileIsDir(Fi= le)) +#define Ext4FileIsOpenable(File) (Ext4FileIsReg (File) || Ext4FileIsDir (= File) || Ext4FileIsSymlink (File)) =20 #define EXT4_INODE_HAS_FIELD(Inode, Field) = \ (Inode->i_extra_isize + EXT4_GOOD_OLD_INODE_SIZE >=3D = \ diff --git a/Features/Ext4Pkg/Ext4Dxe/File.c b/Features/Ext4Pkg/Ext4Dxe/Fil= e.c index ff1746d5640a..86ccfff8603a 100644 --- a/Features/Ext4Pkg/Ext4Dxe/File.c +++ b/Features/Ext4Pkg/Ext4Dxe/File.c @@ -9,6 +9,26 @@ =20 #include =20 +/** + Reads a symlink file. + + @param[in] Partition Pointer to the ext4 partition. + @param[in] File Pointer to the open symlink file. + @param[out] Symlink Pointer to the output unicode symlink string. + + @retval EFI_SUCCESS Symlink was read. + @retval EFI_ACCESS_DENIED Symlink is encrypted. + @retval EFI_OUT_OF_RESOURCES Memory allocation error. + @retval EFI_INVALID_PARAMETER Symlink path has incorrect length + @retval EFI_VOLUME_CORRUPTED Symlink read block size differ from inode = value +**/ +EFI_STATUS +Ext4ReadSymlink ( + IN EXT4_PARTITION *Partition, + IN EXT4_FILE *File, + OUT CHAR16 **Symlink + ); + /** Duplicates a file structure. =20 @@ -137,11 +157,11 @@ Ext4DirCanLookup ( /** Opens a new file relative to the source file's location. =20 - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that = is the file + @param[out] FoundFile A pointer to the location to return the opened ha= ndle for the new + file. + @param[in] Source A pointer to the EXT4_FILE instance that is the f= ile handle to the source location. This would typical= ly be an open handle to a directory. - @param[out] NewHandle A pointer to the location to return the opened ha= ndle for the new - file. @param[in] FileName The Null-terminated string of the name of the fil= e to be opened. The file name may contain the following path modi= fiers: "\", ".", and "..". @@ -165,13 +185,12 @@ Ext4DirCanLookup ( =20 **/ EFI_STATUS -EFIAPI -Ext4Open ( - IN EFI_FILE_PROTOCOL *This, - OUT EFI_FILE_PROTOCOL **NewHandle, - IN CHAR16 *FileName, - IN UINT64 OpenMode, - IN UINT64 Attributes +Ext4OpenInternal ( + OUT EXT4_FILE **FoundFile, + IN EXT4_FILE *Source, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes ) { EXT4_FILE *Current; @@ -180,13 +199,14 @@ Ext4Open ( CHAR16 PathSegment[EXT4_NAME_MAX + 1]; UINTN Length; EXT4_FILE *File; + CHAR16 *Symlink; EFI_STATUS Status; =20 - Current =3D (EXT4_FILE *)This; + Current =3D Source; Partition =3D Current->Partition; Level =3D 0; =20 - DEBUG ((DEBUG_FS, "[ext4] Ext4Open %s\n", FileName)); + DEBUG ((DEBUG_FS, "[ext4] Ext4OpenInternal %s\n", FileName)); // If the path starts with a backslash, we treat the root directory as t= he base directory if (FileName[0] =3D=3D L'\\') { FileName++; @@ -194,6 +214,11 @@ Ext4Open ( } =20 while (FileName[0] !=3D L'\0') { + if (Partition->Root->SymLoops > SYMLOOP_MAX) { + DEBUG ((DEBUG_FS, "[ext4] Symloop limit is hit !\n")); + return EFI_ACCESS_DENIED; + } + // Discard leading path separators while (FileName[0] =3D=3D L'\\') { FileName++; @@ -238,18 +263,45 @@ Ext4Open ( } =20 // Check if this is a valid file to open in EFI - - // What to do with symlinks? They're nonsense when absolute but may - // be useful when they're relative. Right now, they're ignored, since = they - // bring a lot of trouble for something that's not as useful in our ca= se. - // If you want to link, use hard links. - if (!Ext4FileIsOpenable (File)) { Ext4CloseInternal (File); // This looks like an /okay/ status to return. return EFI_ACCESS_DENIED; } =20 + // + // Reading symlink and then trying to follow it + // + if (Ext4FileIsSymlink (File)) { + Partition->Root->SymLoops++; + DEBUG ((DEBUG_FS, "[ext4] File %s is symlink, trying to read it\n", = PathSegment)); + Status =3D Ext4ReadSymlink (Partition, File, &Symlink); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_FS, "[ext4] Error reading %s symlink!\n", PathSegmen= t)); + return Status; + } + + DEBUG ((DEBUG_FS, "[ext4] File %s is linked to %s\n", PathSegment, S= ymlink)); + // + // Close symlink file + // + Ext4CloseInternal (File); + // + // Open linked file by recursive call of Ext4OpenFile + // + Status =3D Ext4OpenInternal (FoundFile, Current, Symlink, OpenMode, = Attributes); + FreePool (Symlink); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_FS, "[ext4] Error opening linked file %s\n", Symlink= )); + return Status; + } + + // + // Set File to newly opened + // + File =3D *FoundFile; + } + if (Level !=3D 0) { // Careful not to close the base directory Ext4CloseInternal (Current); @@ -273,12 +325,75 @@ Ext4Open ( return EFI_ACCESS_DENIED; } =20 - *NewHandle =3D &Current->Protocol; + *FoundFile =3D Current; =20 DEBUG ((DEBUG_FS, "[ext4] Opened filename %s\n", Current->Dentry->Name)); return EFI_SUCCESS; } =20 +/** + Opens a new file relative to the source file's location. + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that = is the file + handle to the source location. This would typical= ly be an open + handle to a directory. + @param[out] NewHandle A pointer to the location to return the opened ha= ndle for the new + file. + @param[in] FileName The Null-terminated string of the name of the fil= e to be opened. + The file name may contain the following path modi= fiers: "\", ".", + and "..". + @param[in] OpenMode The mode to open the file. The only valid combina= tions that the + file may be opened with are: Read, Read/Write, or= Create/Read/Write. + @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which cas= e these are the + attribute bits for the newly created file. + @retval EFI_SUCCESS The file was opened. + @retval EFI_NOT_FOUND The specified file could not be found on th= e device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or = the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or op= en a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open= the file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +Ext4Open ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EXT4_FILE *FoundFile; + EXT4_FILE *Source; + + Source =3D (EXT4_FILE *)This; + + // + // Reset SymLoops counter + // + Source->Partition->Root->SymLoops =3D 0; + + Status =3D Ext4OpenInternal ( + &FoundFile, + Source, + FileName, + OpenMode, + Attributes + ); + + if (!EFI_ERROR (Status)) { + *NewHandle =3D &FoundFile->Protocol; + } + + return Status; +} + /** Closes a specified file handle. =20 @@ -588,7 +703,7 @@ Ext4GetVolumeName ( =20 // s_volume_name is only valid on dynamic revision; old filesystems don'= t support this if (Partition->SuperBlock.s_rev_level =3D=3D EXT4_DYNAMIC_REV) { - CopyMem (TempVolName, (CONST CHAR8 *)Partition->SuperBlock.s_volume_na= me, 16); + CopyMem (TempVolName, Partition->SuperBlock.s_volume_name, 16); TempVolName[16] =3D '\0'; =20 Status =3D UTF8StrToUCS2 (TempVolName, &VolumeName); @@ -754,12 +869,14 @@ Ext4GetInfo ( OUT VOID *Buffer ) { + EXT4_FILE *File; EXT4_PARTITION *Partition; =20 - Partition =3D ((EXT4_FILE *)This)->Partition; + File =3D (EXT4_FILE *)This; + Partition =3D File->Partition; =20 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { - return Ext4GetFileInfo ((EXT4_FILE *)This, Buffer, BufferSize); + return Ext4GetFileInfo (File, Buffer, BufferSize); } =20 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { @@ -870,12 +987,12 @@ Ext4SetInfo ( ) { EXT4_FILE *File; - EXT4_PARTITION *Part; + EXT4_PARTITION *Partition; =20 - File =3D (EXT4_FILE *)This; - Part =3D File->Partition; + File =3D (EXT4_FILE *)This; + Partition =3D File->Partition; =20 - if (Part->ReadOnly) { + if (Partition->ReadOnly) { return EFI_WRITE_PROTECTED; } =20 diff --git a/Features/Ext4Pkg/Ext4Dxe/Inode.c b/Features/Ext4Pkg/Ext4Dxe/In= ode.c index 7f8be2f02643..5ccb4d2bfc42 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Inode.c +++ b/Features/Ext4Pkg/Ext4Dxe/Inode.c @@ -255,6 +255,21 @@ Ext4FileIsDir ( return (File->Inode->i_mode & EXT4_INO_TYPE_DIR) =3D=3D EXT4_INO_TYPE_DI= R; } =20 +/** + Checks if a file is a symlink. + + @param[in] File Pointer to the opened file. + + @return BOOLEAN Whether file is a symlink +**/ +BOOLEAN +Ext4FileIsSymlink ( + IN CONST EXT4_FILE *File + ) +{ + return (File->Inode->i_mode & EXT4_INO_TYPE_SYMLINK) =3D=3D EXT4_INO_TYP= E_SYMLINK; +} + /** Checks if a file is a regular file. @param[in] File Pointer to the opened file. diff --git a/Features/Ext4Pkg/Ext4Dxe/Symlink.c b/Features/Ext4Pkg/Ext4Dxe/= Symlink.c new file mode 100644 index 000000000000..0905417ffb88 --- /dev/null +++ b/Features/Ext4Pkg/Ext4Dxe/Symlink.c @@ -0,0 +1,261 @@ +/** @file + Symbolic links routines + + Copyright (c) 2022 Savva Mitrofanov All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "Ext4Dxe.h" + +/** + Detects if a symlink is a fast symlink. + + @param[in] File Pointer to the opened file. + + @return BOOLEAN Whether symlink is a fast symlink +**/ +STATIC +BOOLEAN +Ext4SymlinkIsFastSymlink ( + IN CONST EXT4_FILE *File + ) +{ + // + // Detection logic of the fast-symlink splits into two behaviors - old a= nd new. + // The old behavior is based on comparing the extended attribute blocks + // with the inode's i_blocks, and if it's zero we know the inode isn't s= toring + // the link in filesystem blocks, so we look to the inode->i_data. + // The new behavior is apparently needed only with the large EA inode fe= ature. + // In this case we check that inode size less than maximum fast symlink = size. + // So, we revert to the old behavior if the large EA inode feature is no= t set. + // + UINT32 FileAcl; + UINT32 ExtAttrBlocks; + + if ((File->Inode->i_flags & EXT4_EA_INODE_FL) =3D=3D 0) { + FileAcl =3D File->Inode->i_file_acl; + if (EXT4_IS_64_BIT (File->Partition)) { + // + // We don't care about final value, we are just checking for any bit= is set + // so, thats why we neglect LShiftU64(.., 32) + // + FileAcl |=3D File->Inode->i_osd2.data_linux.l_i_file_acl_high; + } + + ExtAttrBlocks =3D FileAcl !=3D 0 ? (File->Partition->BlockSize >> 9) := 0; + + return File->Inode->i_blocks =3D=3D ExtAttrBlocks; + } + + return EXT4_INODE_SIZE (File->Inode) <=3D EXT4_FAST_SYMLINK_MAX_SIZE; +} + +/** + Reads a fast symlink file. + + @param[in] Partition Pointer to the ext4 partition. + @param[in] File Pointer to the open symlink file. + @param[out] AsciiSymlink Pointer to the output ascii symlink str= ing. + @param[out] AsciiSymlinkSize Pointer to the output ascii symlink str= ing length. + + @retval EFI_SUCCESS Fast symlink was read. + @retval EFI_OUT_OF_RESOURCES Memory allocation error. +**/ +STATIC +EFI_STATUS +Ext4ReadFastSymlink ( + IN EXT4_PARTITION *Partition, + IN EXT4_FILE *File, + OUT CHAR8 **AsciiSymlink, + OUT UINT32 *AsciiSymlinkSize + ) +{ + UINT32 SymlinkSize; + CHAR8 *AsciiSymlinkTmp; + + // + // Fast-symlink's EXT4_INODE_SIZE is not necessarily validated when we c= hecked it in + // Ext4SymlinkIsFastSymlink(), so truncate if necessary. + // + SymlinkSize =3D (UINT32)MIN (EXT4_INODE_SIZE (File->Inode), EXT4_FAST_SY= MLINK_MAX_SIZE); + + AsciiSymlinkTmp =3D AllocatePool (SymlinkSize + 1); + if (AsciiSymlinkTmp =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "[ext4] Failed to allocate symlink ascii string b= uffer\n")); + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (AsciiSymlinkTmp, File->Inode->i_data, SymlinkSize); + + // + // Add null-terminator + // + AsciiSymlinkTmp[SymlinkSize] =3D '\0'; + + *AsciiSymlink =3D AsciiSymlinkTmp; + *AsciiSymlinkSize =3D SymlinkSize + 1; + + return EFI_SUCCESS; +} + +/** + Reads a slow symlink file. + + @param[in] Partition Pointer to the ext4 partition. + @param[in] File Pointer to the open symlink file. + @param[out] AsciiSymlink Pointer to the output ascii symlink str= ing. + @param[out] AsciiSymlinkSize Pointer to the output ascii symlink str= ing length. + + @retval EFI_SUCCESS Slow symlink was read. + @retval EFI_OUT_OF_RESOURCES Memory allocation error. + @retval EFI_INVALID_PARAMETER Slow symlink path has incorrect length + @retval EFI_VOLUME_CORRUPTED Symlink read block size differ from inode = value +**/ +STATIC +EFI_STATUS +Ext4ReadSlowSymlink ( + IN EXT4_PARTITION *Partition, + IN EXT4_FILE *File, + OUT CHAR8 **AsciiSymlink, + OUT UINT32 *AsciiSymlinkSize + ) +{ + EFI_STATUS Status; + CHAR8 *SymlinkTmp; + UINT64 SymlinkSizeTmp; + UINT32 SymlinkAllocateSize; + UINTN ReadSize; + + SymlinkSizeTmp =3D EXT4_INODE_SIZE (File->Inode); + + // + // Allocate EXT4_INODE_SIZE + 1 + // + if (SymlinkSizeTmp >=3D EXT4_EFI_PATH_MAX) { + DEBUG (( + DEBUG_WARN, + "[ext4] Warn: symlink path maximum length was hit!\n" + )); + return EFI_INVALID_PARAMETER; + } + + SymlinkAllocateSize =3D (UINT32)SymlinkSizeTmp + 1; + + SymlinkTmp =3D AllocatePool (SymlinkAllocateSize); + if (SymlinkTmp =3D=3D NULL) { + DEBUG ((DEBUG_FS, "[ext4] Failed to allocate symlink ascii string buff= er\n")); + return EFI_OUT_OF_RESOURCES; + } + + ReadSize =3D (UINTN)SymlinkSizeTmp; + Status =3D Ext4Read (Partition, File, SymlinkTmp, File->Position, &Rea= dSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_FS, "[ext4] Failed to read symlink from blocks with stat= us %r\n", Status)); + FreePool (SymlinkTmp); + return Status; + } + + // + // Add null-terminator + // + SymlinkTmp[SymlinkSizeTmp] =3D '\0'; + + if (SymlinkSizeTmp !=3D ReadSize) { + DEBUG (( + DEBUG_FS, + "[ext4] Error! The size of the read block doesn't match the value fr= om the inode!\n" + )); + return EFI_VOLUME_CORRUPTED; + } + + *AsciiSymlinkSize =3D SymlinkAllocateSize; + *AsciiSymlink =3D SymlinkTmp; + + return EFI_SUCCESS; +} + +/** + Reads a symlink file. + + @param[in] Partition Pointer to the ext4 partition. + @param[in] File Pointer to the open symlink file. + @param[out] Symlink Pointer to the output unicode symlink string. + + @retval EFI_SUCCESS Symlink was read. + @retval EFI_ACCESS_DENIED Symlink is encrypted. + @retval EFI_OUT_OF_RESOURCES Memory allocation error. + @retval EFI_INVALID_PARAMETER Symlink path has incorrect length + @retval EFI_VOLUME_CORRUPTED Symlink read block size differ from inode = value +**/ +EFI_STATUS +Ext4ReadSymlink ( + IN EXT4_PARTITION *Partition, + IN EXT4_FILE *File, + OUT CHAR16 **Symlink + ) +{ + EFI_STATUS Status; + CHAR8 *SymlinkTmp; + UINT32 SymlinkSize; + CHAR16 *Symlink16Tmp; + CHAR16 *Needle; + + // + // Assume that we alread read Inode via Ext4ReadInode + // Skip reading, just check encryption flag + // + if ((File->Inode->i_flags & EXT4_ENCRYPT_FL) !=3D 0) { + DEBUG ((DEBUG_WARN, "[ext4] Warn: symlink is encrypted\n")); + return EFI_ACCESS_DENIED; + } + + if (Ext4SymlinkIsFastSymlink (File)) { + Status =3D Ext4ReadFastSymlink (Partition, File, &SymlinkTmp, &Symlink= Size); + } else { + Status =3D Ext4ReadSlowSymlink (Partition, File, &SymlinkTmp, &Symlink= Size); + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_FS, "[ext4] Symlink read error with Status %r\n", Status= )); + return Status; + } + + Symlink16Tmp =3D AllocatePool (SymlinkSize * sizeof (CHAR16)); + if (Symlink16Tmp =3D=3D NULL) { + DEBUG ((DEBUG_FS, "[ext4] Failed to allocate symlink unicode string bu= ffer\n")); + FreePool (SymlinkTmp); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D AsciiStrToUnicodeStrS ( + SymlinkTmp, + Symlink16Tmp, + SymlinkSize + ); + + FreePool (SymlinkTmp); + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_FS, + "[ext4] Failed to convert ascii symlink to unicode with Status %r\n", + Status + )); + FreePool (Symlink16Tmp); + FreePool (SymlinkTmp); + return Status; + } + + // + // Convert to UEFI slashes + // + for (Needle =3D Symlink16Tmp; *Needle !=3D L'\0'; Needle++) { + if (*Needle =3D=3D L'/') { + *Needle =3D L'\\'; + } + } + + *Symlink =3D Symlink16Tmp; + + return Status; +} --=20 2.37.3 -=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 (#93423): https://edk2.groups.io/g/devel/message/93423 Mute This Topic: https://groups.io/mt/93525496/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- From nobody Fri May 10 16:57:10 2024 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+93422+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+93422+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1662559354; cv=none; d=zohomail.com; s=zohoarc; b=Q2qGLf7SO1JmooBabUGJnIDAVW9QkHu+Yn97Pcum2UVIDSLd1hafylEAcbaF61fmpiG0yAK5G2Jd1KjKzdJHODhzq2kwBCqGcxtEemwepgPcD/Tl083UouzXNeYakJUgcpa9wp8LFppJ8nL3dBVWj18ewDsHQsdgWkvq3kYFTCc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1662559354; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=O3g/llICGMRdiJpGZx9DrYgHXaPuXdfWeKkNrwV6hxs=; b=HCOkBW3+0LklGiPUTeL5oo0iXGtangFpPqqqf9gWNi4e4mzhHYmlgraiO/6PDJUOazwv6LohXjrKOu0FCi7/2WYej2fP7VC/BoxySXZroNN+nLcYoO/JGgao2jFGbSr1GlqRRm8PpW1cIPFq3avuGA3L2pgMxXCcirHwC9tf794= 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+93422+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 166255935485154.84012761765189; Wed, 7 Sep 2022 07:02:34 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id j5V7YY1788612x3Md6LNyGgi; Wed, 07 Sep 2022 07:02:34 -0700 X-Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) by mx.groups.io with SMTP id smtpd.web12.8124.1662559353599798596 for ; Wed, 07 Sep 2022 07:02:33 -0700 X-Received: by mail-lj1-f179.google.com with SMTP id by6so16063906ljb.11 for ; Wed, 07 Sep 2022 07:02:33 -0700 (PDT) X-Gm-Message-State: OmNNPwxgrKgnuHOUvxl6Ob6Qx1787277AA= X-Google-Smtp-Source: AA6agR7qZSHKTnAe3HN8rgd+2KF+KZ5qAS1UOKVUrEfi5or2VqZwihGsHbDDtjMESPdx/VAioOzZ4w== X-Received: by 2002:a2e:a448:0:b0:262:f7c4:31ad with SMTP id v8-20020a2ea448000000b00262f7c431admr1035408ljn.283.1662559351658; Wed, 07 Sep 2022 07:02:31 -0700 (PDT) X-Received: from localhost.localdomain ([176.59.149.223]) by smtp.gmail.com with ESMTPSA id o12-20020ac24e8c000000b0049482979fe0sm2506399lfr.179.2022.09.07.07.02.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Sep 2022 07:02:31 -0700 (PDT) From: "Savva Mitrofanov" To: devel@edk2.groups.io Cc: =?UTF-8?q?Marvin=20H=C3=A4user?= , Pedro Falcato , Vitaly Cheptsov Subject: [edk2-devel] [edk2-platforms][PATCH v5 2/2] Ext4Pkg: Add base containing record macro for EXT4_FILE Date: Wed, 7 Sep 2022 20:02:13 +0600 Message-Id: <20220907140213.13286-3-savvamtr@gmail.com> In-Reply-To: <20220907140213.13286-1-savvamtr@gmail.com> References: <20220907140213.13286-1-savvamtr@gmail.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: 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,savvamtr@gmail.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1662559354; bh=TmsOWqeCDw9T0kDf4RT5ctmR+AEG9P4rxiqoLQV6PhU=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=aidyDY4xtMWTIXSR2iKG3v4okYEVwbLIL2A4GvchGYVNJPiTp+btkYzlJXl0DYQIX1a ciDmriiaUDjFU02Sjn74NU6tmAImxtnXiHLpwkYCFwkdVty5/cWzvk5ZvHv6tlRpz0FHD QQiJaBFEZhc2hAci87HAwdVgj6WH3uMKfl8= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1662559356388100005 Content-Type: text/plain; charset="utf-8" We shouldn't use direct casts, because in the future it could break the code, so using BASE_CR would be safe against possible structure changes and rearrangements Cc: Marvin H=C3=A4user Cc: Pedro Falcato Cc: Vitaly Cheptsov Signed-off-by: Savva Mitrofanov Reviewed-by: Marvin H=C3=A4user --- Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h | 2 ++ Features/Ext4Pkg/Ext4Dxe/File.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h b/Features/Ext4Pkg/Ext4Dxe/= Ext4Dxe.h index 6d352d3995f1..adf3c13f6ea9 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h +++ b/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h @@ -386,6 +386,8 @@ struct _Ext4File { EXT4_DENTRY *Dentry; }; =20 +#define EXT4_FILE_FROM_THIS(This) BASE_CR ((This), EXT4_FILE, Protocol) + #define EXT4_FILE_FROM_OPEN_FILES_NODE(Node) = \ BASE_CR(Node, EXT4_FILE, OpenFilesListNode) =20 diff --git a/Features/Ext4Pkg/Ext4Dxe/File.c b/Features/Ext4Pkg/Ext4Dxe/Fil= e.c index 86ccfff8603a..04198a53bfc0 100644 --- a/Features/Ext4Pkg/Ext4Dxe/File.c +++ b/Features/Ext4Pkg/Ext4Dxe/File.c @@ -372,7 +372,7 @@ Ext4Open ( EXT4_FILE *FoundFile; EXT4_FILE *Source; =20 - Source =3D (EXT4_FILE *)This; + Source =3D EXT4_FILE_FROM_THIS (This); =20 // // Reset SymLoops counter @@ -409,7 +409,7 @@ Ext4Close ( IN EFI_FILE_PROTOCOL *This ) { - return Ext4CloseInternal ((EXT4_FILE *)This); + return Ext4CloseInternal (EXT4_FILE_FROM_THIS (This)); } =20 /** @@ -490,7 +490,7 @@ Ext4ReadFile ( EXT4_PARTITION *Partition; EFI_STATUS Status; =20 - File =3D (EXT4_FILE *)This; + File =3D EXT4_FILE_FROM_THIS (This); Partition =3D File->Partition; =20 ASSERT (Ext4FileIsOpenable (File)); @@ -541,7 +541,7 @@ Ext4WriteFile ( { EXT4_FILE *File; =20 - File =3D (EXT4_FILE *)This; + File =3D EXT4_FILE_FROM_THIS (This); =20 if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) { return EFI_ACCESS_DENIED; @@ -571,7 +571,7 @@ Ext4GetPosition ( { EXT4_FILE *File; =20 - File =3D (EXT4_FILE *)This; + File =3D EXT4_FILE_FROM_THIS (This); =20 if (Ext4FileIsDir (File)) { return EFI_UNSUPPORTED; @@ -604,7 +604,7 @@ Ext4SetPosition ( { EXT4_FILE *File; =20 - File =3D (EXT4_FILE *)This; + File =3D EXT4_FILE_FROM_THIS (This); =20 // Only seeks to 0 (so it resets the ReadDir operation) are allowed if (Ext4FileIsDir (File) && (Position !=3D 0)) { @@ -872,7 +872,7 @@ Ext4GetInfo ( EXT4_FILE *File; EXT4_PARTITION *Partition; =20 - File =3D (EXT4_FILE *)This; + File =3D EXT4_FILE_FROM_THIS (This); Partition =3D File->Partition; =20 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { @@ -989,7 +989,7 @@ Ext4SetInfo ( EXT4_FILE *File; EXT4_PARTITION *Partition; =20 - File =3D (EXT4_FILE *)This; + File =3D EXT4_FILE_FROM_THIS (This); Partition =3D File->Partition; =20 if (Partition->ReadOnly) { --=20 2.37.3 -=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 (#93422): https://edk2.groups.io/g/devel/message/93422 Mute This Topic: https://groups.io/mt/93525494/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-