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-next>] [day] [month] [year] [list]
Date:   Tue, 10 May 2022 15:14:42 +0800
From:   butt3rflyh4ck <butterflyhuangxx@...il.com>
To:     jack@...e.com
Cc:     LKML <linux-kernel@...r.kernel.org>
Subject: A slab-out-of-bounds Write when invoke udf_write_fi via ioctl

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

##reproduce
CONFIG_KASAN is opened.
[   27.437559][ T4631] loop0: detected capacity change from 0 to 5376
[   27.440865][ T4631] UDF-fs: warning (device loop0): udf_load_vrs:
No anchor found
[   27.441638][ T4631] UDF-fs: Scanning with blocksize 512 failed
[   27.444203][ T4631] UDF-fs: INFO Mounting volume 'LinuxUDF',
timestamp 2020/09/19 18:44 (1000)
[   27.462341][ T4631]
==================================================================
[   27.463081][ T4631] BUG: KASAN: slab-out-of-bounds in
udf_write_fi+0x353/0x1170
[   27.463778][ T4631] Write of size 165 at addr ffff888014fe5c98 by
task udf_write_fi1/4631
[   27.464524][ T4631]
[   27.464736][ T4631] CPU: 0 PID: 4631 Comm: udf_write_fi1 Not
tainted 5.18.0-rc5-00028-ga7391ad35724 #47
[   27.465598][ T4631] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.14.0-2 04/01/2014
[   27.466427][ T4631] Call Trace:
[   27.466721][ T4631]  <TASK>
[   27.466990][ T4631]  dump_stack_lvl+0x11c/0x1b4
[   27.467416][ T4631]  print_address_description.constprop.0.cold+0xeb/0x48f
[   27.468051][ T4631]  ? udf_write_fi+0x353/0x1170
[   27.468481][ T4631]  kasan_report.cold+0xf4/0x1c6
[   27.468914][ T4631]  ? udf_get_fileident+0x271/0x2d0
[   27.469371][ T4631]  ? udf_write_fi+0x353/0x1170
[   27.469801][ T4631]  kasan_check_range+0x13d/0x180
[   27.470246][ T4631]  memcpy+0x39/0x60
[   27.470588][ T4631]  udf_write_fi+0x353/0x1170
[   27.470998][ T4631]  ? udf_new_tag+0x1fd/0x3c0
[   27.471412][ T4631]  udf_add_entry+0x10c7/0x24d0
[   27.471822][ T4631]  ? udf_write_fi+0x1170/0x1170
[   27.472218][ T4631]  ? __mark_inode_dirty+0x76a/0xb00
[   27.472643][ T4631]  ? lock_downgrade+0x810/0x810
[   27.473045][ T4631]  udf_add_nondir+0xf8/0x410
[   27.473424][ T4631]  ? udf_rename+0x1050/0x1050
[   27.473806][ T4631]  ? userns_owner+0x30/0x30
[   27.474177][ T4631]  ? rcu_read_lock_sched_held+0x3a/0xa0
[   27.474628][ T4631]  ? __mark_inode_dirty+0x5f8/0xb00
[   27.475051][ T4631]  ? udf_get_parent+0x1c0/0x1c0
[   27.475455][ T4631]  lookup_open.isra.0+0xec3/0x1760
[   27.475876][ T4631]  ? lock_release+0x890/0x890
[   27.476273][ T4631]  ? path_lookupat+0x6b0/0x6b0
[   27.476670][ T4631]  ? __mnt_want_write+0x184/0x260
[   27.477107][ T4631]  path_openat+0x7d5/0x2360
[   27.477480][ T4631]  ? lookup_open.isra.0+0x1760/0x1760
[   27.477915][ T4631]  ? lockdep_hardirqs_on_prepare+0x430/0x430
[   27.478412][ T4631]  ? lockdep_hardirqs_on_prepare+0x430/0x430
[   27.478901][ T4631]  do_filp_open+0x199/0x3d0
[   27.479271][ T4631]  ? find_held_lock+0x2d/0x110
[   27.479663][ T4631]  ? may_open_dev+0xd0/0xd0
[   27.480036][ T4631]  ? rwlock_bug.part.0+0x90/0x90
[   27.480429][ T4631]  ? _raw_spin_unlock+0x24/0x40
[   27.480825][ T4631]  ? alloc_fd+0x1ef/0x560
[   27.481173][ T4631]  ? getname_flags.part.0+0x89/0x440
[   27.481602][ T4631]  do_sys_openat2+0x11e/0x3f0
[   27.481978][ T4631]  ? build_open_flags+0x490/0x490
[   27.482384][ T4631]  ? lock_downgrade+0x810/0x810
[   27.482777][ T4631]  __x64_sys_openat+0x11b/0x1d0
[   27.483188][ T4631]  ? __ia32_sys_open+0x190/0x190
[   27.483594][ T4631]  ? lockdep_hardirqs_on_prepare+0x22b/0x430
[   27.484177][ T4631]  ? syscall_enter_from_user_mode+0x21/0x80
[   27.484890][ T4631]  ? lockdep_hardirqs_on+0x8b/0x110
[   27.485538][ T4631]  do_syscall_64+0x35/0xb0
[   27.486095][ T4631]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[   27.486692][ T4631] RIP: 0033:0x44914d
[   27.487019][ T4631] Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3
0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b
4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff 8
[   27.488797][ T4631] RSP: 002b:00007ffc787d2f68 EFLAGS: 00000246
ORIG_RAX: 0000000000000101
[   27.489518][ T4631] RAX: ffffffffffffffda RBX: 0000000000400540
RCX: 000000000044914d
[   27.490179][ T4631] RDX: 0000000000000040 RSI: 0000000020000140
RDI: 0000000000000005
[   27.490825][ T4631] RBP: 00007ffc787d2f80 R08: 0000000020000170
R09: 0000000000000000
[   27.491469][ T4631] R10: 0000000000000000 R11: 0000000000000246
R12: 0000000000404dd0
[   27.492125][ T4631] R13: 0000000000000000 R14: 00000000004c0018
R15: 0000000000400540

If needed a reproduce, I can provided to you.




Regards,
   butt3rflyh4ck.




-- 
Active Defense Lab of Venustech

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ