Bug 2062340

Summary: aide detects SIGBUS then exits in error when a file gets truncated
Product: Red Hat Enterprise Linux 8 Reporter: Renaud Métrich <rmetrich>
Component: aideAssignee: Radovan Sroka <rsroka>
Status: CLOSED MIGRATED QA Contact: Martin Zelený <mzeleny>
Severity: medium Docs Contact:
Priority: medium    
Version: 8.5CC: dapospis
Target Milestone: rcKeywords: MigratedToJIRA, Triaged
Target Release: ---Flags: pm-rhel: mirror+
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-08-16 15:19:47 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Renaud Métrich 2022-03-09 15:18:30 UTC
Description of problem:

When aide is processing a file to compute its hash and the file gets truncated, SIGBUS signal pops up and aide prints a message:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
Caught SIGBUS/SEGV while mmapping. File was truncated while aide was running?
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

It then exits in error upon receiving a new SIGBUS again.

The root cause for this is aide internally maps the file in memory using mmap(), then the hash computation is done through calling libgcrypt routines which die upon accessing bad address (SIGBUS), due to the file being truncated.

Version-Release number of selected component (if applicable):

aide-0.15 (RHEL7) and 0.16 (RHEL8)

How reproducible:

Always

Steps to Reproduce: (RHEL7 code base, but similar, line numbers change a bit)

1. Create `/foo/file`

    -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
    # mkdir /foo
    # dd if=/dev/zero of=/foo/file bs=1M count=100
    -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

2. Edit `/etc/aide.conf` to remove everything and add handling of `/foo`

    -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
    [...]
    #/boot/   CONTENT_EX
    [... commented out until end ...]

    /foo/ CONTENT_EX
    -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

3. Execute *aide* under GDB

    -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
    # gdb --args aide --init
    (gdb) break do_md.c:362
    (gdb) run
    -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

4. Once GDB stopped, truncate the file

    ~~~
    # truncate -s 0 /foo/file
    ~~~

5. Continue execution

    ~~~
    (gdb) cont
    ~~~

Actual results:

SIGBUS caught once with proper message, but then again while `catch_mmap==0`, causing *aide* to exit:

~~~
Program received signal SIGBUS, Bus error.
transform (hd=hd@entry=0x7ffff7ff5290, data=0x7ffff4491001 <Address 0x7ffff4491001 out of bounds>, 
    data@entry=0x7ffff4491000 <Address 0x7ffff4491000 out of bounds>) at sha256.c:186
186	        p2[3] = *data++;
(gdb) bt
#0  transform (hd=hd@entry=0x7ffff7ff5290, data=0x7ffff4491001 <Address 0x7ffff4491001 out of bounds>, 
    data@entry=0x7ffff4491000 <Address 0x7ffff4491000 out of bounds>) at sha256.c:186
#1  0x00007ffff789b04f in sha256_write (context=0x7ffff7ff5290, inbuf_arg=<optimized out>, inlen=16777216)
    at sha256.c:291
#2  0x00007ffff7875f7f in md_write (a=0x7ffff7ff5008, inbuf=inbuf@entry=0x7ffff4491000, inlen=inlen@entry=16777216)
    at md.c:800
#3  0x00007ffff7877145 in _gcry_md_write (hd=<optimized out>, inbuf=inbuf@entry=0x7ffff4491000, 
    inlen=inlen@entry=16777216) at md.c:808
#4  0x00007ffff7860772 in gcry_md_write (hd=<optimized out>, buffer=buffer@entry=0x7ffff4491000, 
    length=length@entry=16777216) at visibility.c:827
#5  0x000055555556ad43 in update_md (md=0x7fffffffdf50, data=0x7ffff4491000, size=16777216) at md.c:250
#6  0x0000555555567433 in calc_md (old_fs=old_fs@entry=0x7fffffffe190, line=line@entry=0x555555789850) at do_md.c:363
#7  0x000055555556a85b in get_file_attrs (filename=filename@entry=0x555555786d60 "/foo/file", attr=48320481308)
    at gen_list.c:1365
#8  0x0000555555563d00 in db_readline_disk (db=db@entry=256) at db_disk.c:245
#9  0x0000555555563670 in db_readline (db=db@entry=256) at db.c:209
#10 0x000055555556a255 in populate_tree (tree=0x5555557857e0) at gen_list.c:1463
#11 0x00005555555577d0 in main (argc=<optimized out>, argv=<optimized out>) at aide.c:614
(gdb) break sig_handler 
Breakpoint 6 at 0x55555556bef0: file util.c, line 326.
(gdb) cont
Continuing.

Breakpoint 6, sig_handler (signum=7) at util.c:326
326	{
(gdb) next
327	  switch(signum){
(gdb) 
330	    error(200,"Caught SIGBUS/SIGSEGV\n");
(gdb) 
331	    if(conf->catch_mmap==1){
(gdb) 
332	      error(4,"Caught SIGBUS/SEGV while mmapping. File was truncated while aide was running?\n");
(gdb) 
Caught SIGBUS/SEGV while mmapping. File was truncated while aide was running?
333	      conf->catch_mmap=0;
(gdb) 
359	  error(220,"Caught signal %d\n",signum);
(gdb) 
363	}
(gdb) 
360	  init_sighandler();
(gdb) 
init_sighandler () at util.c:316
316	  signal(SIGBUS,sig_handler);
(gdb) 
315	{
(gdb) 
316	  signal(SIGBUS,sig_handler);
(gdb) cont
Continuing.

Program received signal SIGBUS, Bus error.
transform (hd=hd@entry=0x7ffff7ff5290, data=0x7ffff4491001 <Address 0x7ffff4491001 out of bounds>, 
    data@entry=0x7ffff4491000 <Address 0x7ffff4491000 out of bounds>) at sha256.c:186
186	        p2[3] = *data++;
(gdb) bt
#0  transform (hd=hd@entry=0x7ffff7ff5290, data=0x7ffff4491001 <Address 0x7ffff4491001 out of bounds>, 
    data@entry=0x7ffff4491000 <Address 0x7ffff4491000 out of bounds>) at sha256.c:186
#1  0x00007ffff789b04f in sha256_write (context=0x7ffff7ff5290, inbuf_arg=<optimized out>, inlen=16777216)
    at sha256.c:291
#2  0x00007ffff7875f7f in md_write (a=0x7ffff7ff5008, inbuf=inbuf@entry=0x7ffff4491000, inlen=inlen@entry=16777216)
    at md.c:800
#3  0x00007ffff7877145 in _gcry_md_write (hd=<optimized out>, inbuf=inbuf@entry=0x7ffff4491000, 
    inlen=inlen@entry=16777216) at md.c:808
#4  0x00007ffff7860772 in gcry_md_write (hd=<optimized out>, buffer=buffer@entry=0x7ffff4491000, 
    length=length@entry=16777216) at visibility.c:827
#5  0x000055555556ad43 in update_md (md=0x7fffffffdf50, data=0x7ffff4491000, size=16777216) at md.c:250
#6  0x0000555555567433 in calc_md (old_fs=old_fs@entry=0x7fffffffe190, line=line@entry=0x555555789850) at do_md.c:363
#7  0x000055555556a85b in get_file_attrs (filename=filename@entry=0x555555786d60 "/foo/file", attr=48320481308)
    at gen_list.c:1365
#8  0x0000555555563d00 in db_readline_disk (db=db@entry=256) at db_disk.c:245
#9  0x0000555555563670 in db_readline (db=db@entry=256) at db.c:209
#10 0x000055555556a255 in populate_tree (tree=0x5555557857e0) at gen_list.c:1463
#11 0x00005555555577d0 in main (argc=<optimized out>, argv=<optimized out>) at aide.c:614
(gdb) cont
Continuing.

Breakpoint 6, sig_handler (signum=7) at util.c:326
326	{
(gdb) next
327	  switch(signum){
(gdb) 
330	    error(200,"Caught SIGBUS/SIGSEGV\n");
(gdb) 
331	    if(conf->catch_mmap==1){
(gdb) 
335	      error(0,"Caught SIGBUS/SEGV. Exiting\n");
(gdb) 
Caught SIGBUS/SEGV. Exiting
336	      exit(EXIT_FAILURE);
(gdb) 
[Inferior 1 (process 3538) exited with code 01]
~~~

Expected results:

File rescanned and aide not exiting in error


Additional info:

To properly handle the signal, we would need to have *aide* code use some kind of `longjump` to restart the operation, it's not possible to continue executing the code being used (`gcry_xxx` functions which are not aware at all of the issue and just use the memory pointers as is). But I don't see how this can be done easily since there would be some memory deallocation to perform first or else *aide* would be leaking memory.

Comment 1 Renaud Métrich 2022-06-29 07:39:20 UTC
This was fixed Upstream recently:

https://github.com/aide/aide/commit/667fb9427000c7203df5f396f6762f3e9a53dec8

Comment 5 Radovan Sroka 2023-08-16 15:15:20 UTC
This bug is going to be migrated.

Contact point for migration questions or issues: rsroka
Guidance for Bugzilla users to test their Jira account or create one if needed:

https://redhat.service-now.com/help?id=kb_article_view&sysparm_article=KB0016394
https://redhat.service-now.com/help?id=kb_article_view&sysparm_article=KB0016694
https://redhat.service-now.com/help?id=kb_article_view&sysparm_article=KB0016774