lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Tue, 10 May 2022 13:28:38 +0200
From:   Jan Kara <jack@...e.cz>
To:     butt3rflyh4ck <butterflyhuangxx@...il.com>
Cc:     jack@...e.com, LKML <linux-kernel@...r.kernel.org>,
        linux-fsdevel@...r.kernel.org
Subject: Re: A slab-out-of-bounds Write when invoke udf_write_fi via ioctl

On Tue 10-05-22 15:14:42, butt3rflyh4ck wrote:
> Hi, if mounts a malicious udf image,  there is a slab out of bounds
> write  bug when a user invokes udf_write_fi via ioctl.
> I have reproduced it in the latest kernel.
> 
> ##smaple analyse
> the function call chains:
> do_sys_open
>     --->do_sys_openat2
>        --->do_filp_open
>           --->path_openat
>               --->open_last_lookups
>                  --->lookup_open
>                      --->udf_add_nondir
>                         --->udf_add_entry
> 
> There would traverse to get a `fi` in the function udf_add_entry.
> ```
> if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {   [1]
>          block = dinfo->i_location.logicalBlockNum;
>          fi = (struct fileIdentDesc *)
>            (dinfo->i_data + fibh->soffset -
>              udf_ext0_offset(dir) +
>               dinfo->i_lenEAttr);
>              [2]
> } else {
>           block = eloc.logicalBlockNum +
>               ((elen - 1) >>
>             dir->i_sb->s_blocksize_bits);
>             fi = (struct fileIdentDesc *)
>                  (fibh->sbh->b_data + fibh->soffset);
> }
> ```
> [1] if dinfo->i_alloc_type is ICBTAG_FLAG_AD_IN_ICB, [2] it  would
> calculate an offset as `fi`,
> through the debugger, the `fi` is as below:
> ```
>  p/x *(struct fileIdentDesc*)fi
> $24 = {
>   descTag = {
>     tagIdent = 0x2f70,
>     descVersion = 0xea55,
>     tagChecksum = 0xcd,
>     reserved = 0x66,
>     tagSerialNum = 0x511f,
>     descCRC = 0x5a9c,
>     descCRCLength = 0x5142,
>     tagLocation = 0x373ce06a
>   },
>   fileVersionNum = 0x3139,
>   fileCharacteristics = 0xf6,
>   lengthFileIdent = 0x7e,
>   icb = {
>     extLength = 0x6059792,
>     extLocation = {
>       logicalBlockNum = 0x73886466,
>       partitionReferenceNum = 0x7cc6
>     },
>     impUse = {0x3c, 0xcc, 0x4a, 0xed, 0xdc, 0xfb}
>   },
>   lengthOfImpUse = 0x1a6a,
>   impUse = 0xffff888019ca716a
> }
> ```
> These data are wrong and all data are part of  udf image mounted.
> Then next it would invoke function udf_write_fi to write fileident into `fi`.
> ```
> if (fileident) {
>       if (adinicb || (offset + lfi < 0)) {
>           memcpy(udf_get_fi_ident(sfi), fileident, lfi);   [3]
> } else if (offset >= 0) {
>           memcpy(fibh->ebh->b_data + offset, fileident, lfi);
> } else {
>           memcpy(udf_get_fi_ident(sfi), fileident, -offset);
>           memcpy(fibh->ebh->b_data, fileident - offset,
>                   lfi + offset);
>        }
> }
> ```
> The fileident was controlled by user. `sfi` is `fi`, the memcpy
> function is called to copy the data, so an out-of-bounds write occurs

Thanks for report and the analysis. This is indeed a serious bug. I'll send
a fix shortly.

								Honza
-- 
Jan Kara <jack@...e.com>
SUSE Labs, CR

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ