lynis icon indicating copy to clipboard operation
lynis copied to clipboard

Output error during audit system execution "sh: 1658831612%N: bad number"

Open JavierBaratech opened this issue 1 year ago • 8 comments

Enviroment: Program version: 3.0.8 Operating system: Linux Operating system name: Linux Operating system version: 3.18.120 Kernel version: 3.18.120 Hardware platform: armv7l

[+] Boot and services

sh: 1658832080%N: bad number sh: 1658832081%N: bad number - Service Manager [ SysV Init ] sh: 1658832081%N: bad number sh: 1658832081%N: bad number sh: 1658832081%N: bad number sh: 1658832081%N: bad number - Checking UEFI boot [ DISABLED ] sh: 1658832081%N: bad number sh: 1658832081%N: bad number sh: 1658832082%N: bad number

[+] Kernel

sh: 1658832096%N: bad number - Checking default run level [ 5 ] sh: 1658832096%N: bad number sh: 1658832097%N: bad number - Checking kernel version and release [ DONE ] sh: 1658832097%N: bad number - Checking kernel type [ DONE ]

And so on.

JavierBaratech avatar Jul 26 '22 10:07 JavierBaratech

Hi @JavierBaratech, which distribution are you using?

konstruktoid avatar Jul 26 '22 11:07 konstruktoid

Hi @konstruktoid , I have the same kind of issue than @JavierBaratech. On my side, I don't try Lynis on a distribution, but on a hardware device on which is embedded a Linux OS.

Thanks

Leonard539 avatar Aug 03 '22 16:08 Leonard539

Without knowing which device or toolset it is, it's hard to actually test this.

konstruktoid avatar Aug 03 '22 19:08 konstruktoid

I assume it's the date command that causes 1658832080%N, so which version are you using?

konstruktoid avatar Aug 03 '22 19:08 konstruktoid

For me it turned out the be the busybox implementation of date. (Check by running date --help). The weird formatting of a date can be reproduced by executing: date "+%s%N".

Inside of the GetTimestamp function in a script called functions lynis determines whether to call date with or without nanoseconds based on the distro:

GetTimestamp() {
    ts=0
    case "${OS}" in
        "Linux")
            ts=$(date "+%s%N")
        ;;
        *)
            ts=$(date "+%s")
        ;;
    esac
    echo $ts
}

This doesn't work for the busybox date implementation as it by default doesn't have nanosecond support. Which will return "1658832080%N". This causes the described crash a bit later when the timestamp returned from GetTimestamp will be used inside of register as a number:

Register() {

...
CURRENT_TS=$(GetTimestamp)
if [ ${PREVIOUS_TS} -gt 0 ]; then
    SLOW_TEST=0
    TIME_THRESHOLD=$SLOW_TEST_THRESHOLD  # seconds

    # Calculate timing and determine if we use seconds or nanoseconds (more precise)
    TIME_DIFF=$((CURRENT_TS - PREVIOUS_TS))
    if [ ${CURRENT_TS} -gt 1000000000000000000 ]; then
        TIME_DIFF_FORMAT="nanoseconds"
        TIME_THRESHOLD=$((TIME_THRESHOLD * 1000000000))
        if [ ${TIME_DIFF} -gt ${TIME_THRESHOLD} ]; then
            SLOW_TEST=1
            # Convert back to seconds for readability
            TIME_DIFF_FORMAT="seconds"
            TIME_DIFF=$(echo ${TIME_DIFF} | ${AWKBINARY} '{printf "%f",$1/1000000000}')
        fi
    else
        TIME_DIFF_FORMAT="seconds"
        if [ ${TIME_DIFF} -gt ${TIME_THRESHOLD} ]; then
            SLOW_TEST=1
        fi
    fi
    if [ ${SLOW_TEST} -eq 1 ]; then
        DisplayWarning "Test ${PREVIOUS_TEST} had a long execution: ${TIME_DIFF} ${TIME_DIFF_FORMAT}"
        Report "slow_test[]=${PREVIOUS_TEST},${TIME_DIFF}"
    fi
fi

...

}

Two ways to fix this:

  • When building an embedded version of Linux using yocto you can update the configuration files for busybox /poky/meta/recipes-core/busybox/busybox/defconfig and /poky/meta-poky/recipes-core/busybox/busybox/poky-tiny/defconfig. Where in both files I configured CONFIG_FEATURE_DD_SIGNAL_HANDLING=y.
  • Updating the GetTimestamp function to always return the date without nanoseconds.

But overall it might be worth considering to remove the Nanoseconds feature from the timing as a whole.

HansHoogerwerf avatar Oct 17 '22 10:10 HansHoogerwerf

Thanks @HansHoogerwerf for the analysis.

I think there is an a better option to make it as precise as possible for systems that support it, while adding compatibility for others: Add a quick test in the GetTimeStamp routine to see if we are dealing with busybox and then test if it returns the right output. That is, if the output is an integer, then use nanoseconds, otherwise fallback to using seconds.

Want to help creating that in the form of a pull request?

mboelen avatar Oct 17 '22 11:10 mboelen

@mboelen

Hey I fully agree with just checking the possibility that $(date +%N) returns a number. I have tested that on both the system with nanoseconds and the one without and it works fine.

I am however not an bash expert and also the corporate laptop is resisting by not wanting to clone my forked repository.

If it is not too much work for you to add this just go ahead, otherwise I will see if I can find some free time to create a PR.

HansHoogerwerf avatar Oct 17 '22 13:10 HansHoogerwerf

First time I created an PR on github like this. I do not know how to link it to this issue:

https://github.com/CISOfy/lynis/pull/1340

HansHoogerwerf avatar Oct 17 '22 13:10 HansHoogerwerf