Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sparc64] nmap.git : Program received signal SIGBUS, Bus error. #2173

Open
mator opened this issue Nov 6, 2020 · 14 comments · May be fixed by #2508
Open

[sparc64] nmap.git : Program received signal SIGBUS, Bus error. #2173

mator opened this issue Nov 6, 2020 · 14 comments · May be fixed by #2508
Labels

Comments

@mator
Copy link

mator commented Nov 6, 2020

Compiling the latest version of nmap from git , trying to scan a host, programs aborts with SIGBUS error.
I wasn't able to git bisect, since earlier versions does not compile for me (and there's no git tags as well)...

Previous debian version of nmap (7.80) works without problems.

To Reproduce

# ./nmap -sF 127.0.0.1 -p22
Starting Nmap 7.91SVN ( https://nmap.org ) at 2020-11-06 17:35 MSK
Bus error (core dumped)

Expected behavior
to be able to scan ports

Version info (please complete the following information):

  • OS:
# uname -a
Linux ttip 5.7.0-3-sparc64-smp #1 SMP Debian 5.7.17-1 (2020-08-23) sparc64 GNU/Linux
  • Output of nmap --version:
# ./nmap --version
Nmap version 7.91SVN ( https://nmap.org )
Platform: sparc64-unknown-linux-gnu
Compiled with: libz-1.2.11 libpcre-8.39 libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without: liblua openssl libssh2
Available nsock engines: epoll poll select

$ git log --oneline -1
041838d98 (HEAD -> master, origin/master, origin/HEAD) Clean up packet.lua, add a few unit tests.
  • Output of nmap --iflist
# ./nmap --iflist
Starting Nmap 7.91SVN ( https://nmap.org ) at 2020-11-06 17:36 MSK
************************INTERFACES************************
DEV  (SHORT) IP/MASK                     TYPE        UP MTU   MAC
lo   (lo)    127.0.0.1/8                 loopback    up 65536
lo   (lo)    ::1/128                     loopback    up 65536
eth0 (eth0)  192.168.158.92/24           ethernet    up 1500  00:14:4F:F8:12:A3

Additional context
configured with :

$ ./configure --without-ncat --without-liblua --without-libssh2 --without-nping --without-zenmap --without-ndiff --without-openssl --enable-debug

gdb run (backtrace) :

# gdb -q nmap
(gdb) set args -sF 127.0.0.1 -p22
(gdb) run
Starting program: /1/mator/nmap.git/nmap -sF 127.0.0.1 -p22
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/sparc64-linux-gnu/libthread_db.so.1".
Starting Nmap 7.91SVN ( https://nmap.org ) at 2020-11-06 17:32 MSK

Program received signal SIGBUS, Bus error.
accept_ip (p=0x1000093e570 "", h=0x1000093e450, datalink=<optimized out>, offset=14) at tcpip.cc:1494
1494    static bool accept_ip (const unsigned char *p, const struct pcap_pkthdr *h, int datalink, size_t offset) {
(gdb) bt
#0  accept_ip (p=0x1000093e570 "", h=0x1000093e450, datalink=<optimized out>, offset=14) at tcpip.cc:1494
#1  0x00000100000c5d8c in read_reply_pcap (pd=0x1000093e240, to_usec=999873,
    accept_callback=0x100000a2354 <accept_ip(unsigned char const*, pcap_pkthdr const*, int, size_t)>, p=0x7feffffd898, head=0x7feffffd890, rcvdtime=0x7feffffda00,
    datalink=0x7feffffd880, offset=0x7feffffd888) at netutil.cc:4246
#2  0x00000100000a42d4 in readip_pcap (pd=0x1000093e240, len=0x7feffffd9e8, to_usec=999873, rcvdtime=0x7feffffda00, linknfo=0x7feffffda10, validate=<optimized out>)
    at tcpip.cc:1526
#3  0x000001000008e418 in get_pcap_result (USI=0x7feffffe0d0, stime=<optimized out>) at scan_engine_raw.cc:1755
#4  0x0000010000086974 in waitForResponses (USI=0x7feffffe0d0) at scan_engine.cc:2550
#5  ultra_scan (Targets=..., ports=<optimized out>, scantype=<optimized out>, to=<optimized out>) at scan_engine.cc:2762
#6  0x0000010000058bc0 in nmap_main (argc=<optimized out>, argv=<optimized out>) at nmap.cc:2156
#7  0x0000010000030c5c in main (argc=<optimized out>, argv=0x7fefffff638) at main.cc:169
(gdb)
@mator mator added the Nmap label Nov 6, 2020
@mator mator changed the title [sparc64] Program received signal SIGBUS, Bus error. [sparc64] nmap.git : Program received signal SIGBUS, Bus error. Nov 6, 2020
@glaubitz
Copy link

glaubitz commented Nov 6, 2020

@mator Did you try bisecting this? It looks to me that the function pointer is misaligned.

@glaubitz
Copy link

glaubitz commented Nov 7, 2020

Bisecting lead me to this commit 4ffeb09:

4ffeb09ad3c51e44438b455bc327580934f6528d is the first bad commit
commit 4ffeb09ad3c51e44438b455bc327580934f6528d
Author: dmiller <dmiller@e0a8ed71-7df4-0310-8962-fdc924857419>
Date:   Mon Jan 13 21:48:04 2020 +0000

    Use libnetutil's read_reply_pcap to deduplicate pcap reading logic.

 libnetutil/netutil.cc |  86 ++++++++++++++--
 libnetutil/netutil.h  |  10 ++
 tcpip.cc              | 268 ++++++++++----------------------------------------
 tcpip.h               |  14 +--
 4 files changed, 142 insertions(+), 236 deletions(-)

@mator
Copy link
Author

mator commented Nov 7, 2020

git blame shown me the same commit id:

nmap.git$ git blame -L :accept_ip tcpip.cc 
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1494) static bool accept_ip (const unsigned char *p, const struct pcap_pkthdr *h, int datalink, size_t offset) {
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1495)   struct ip *ip = NULL;
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1496) 
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1497)   if (h->caplen < offset + sizeof(struct ip)) {
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1498)     return false;
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1499)   }
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1500)   ip = (struct ip *) (p + offset);
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1501)   switch (ip->ip_v) {
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1502)     case 4:
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1503)     case 6:
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1504)       break;
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1505)     default:
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1506)       return false;
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1507)       break;
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1508)   }
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1509) 
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1510)   return true;
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1511) }
4ffeb09ad3 (dmiller 2020-01-13 21:48:04 +0000 1512) 

@glaubitz
Copy link

glaubitz commented Nov 7, 2020

That cast ip = (struct ip *) (p + offset); looks suspicious. I'll try to replace it with a ```memcpy()``.

@glaubitz
Copy link

glaubitz commented Nov 7, 2020

Hmm, it's definitely the function pointer which is misaligned:

(gdb) r
Starting program: /home/glaubitz/nmap/nmap -sF 127.0.0.1 -p22
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/sparc64-linux-gnu/libthread_db.so.1".
Starting Nmap 7.91SVN ( https://nmap.org ) at 2020-11-07 17:42 CET

Program received signal SIGBUS, Bus error.
accept_ip (p=0x10000971340 "", h=0x10000971220, datalink=<optimized out>, offset=14) at tcpip.cc:1494
1494    static bool accept_ip (const unsigned char *p, const struct pcap_pkthdr *h, int datalink, size_t offset) {
(gdb) p &accept_ip
$1 = (bool (*)(const unsigned char *, const pcap_pkthdr *, int, size_t)) 0x100000af2ac <accept_ip(unsigned char const*, pcap_pkthdr const*, int, size_t)>
(gdb)

But I have no idea why that happens. I don't see any obvious sources for misalignment.

But I have no clue to be honest.

@dmiller-nmap
Copy link

Thanks for reporting this. Can you give some more information about your compiler and what options you used to build Nmap? A copy of config.log would be ideal, but the first 50 lines of Makefile would work, too.

@glaubitz
Copy link

I can do that later today as I just got up (CET time). But just as a heads-up, there is a fast SPARC Linux machine in the GCC compile farm that can be accessed by anyone: https://gcc.gnu.org/wiki/CompileFarm

@mator
Copy link
Author

mator commented Nov 11, 2020

@dmiller-nmap

configure line:

$ ./configure --without-ncat --without-liblua --without-libssh2 --without-nping --without-zenmap --without-ndiff --without-openssl --enable-debug

compiler info:

mator@ttip:/1/mator$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/sparc64-linux-gnu/10/lto-wrapper
Target: sparc64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.0-16' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=sparc64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --disable-libphobos --enable-objc-gc=auto --enable-multiarch --disable-werror --with-cpu-32=ultrasparc --enable-targets=all --with-long-double-128 --enable-multilib --enable-checking=release --build=sparc64-linux-gnu --host=sparc64-linux-gnu --target=sparc64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.0 (Debian 10.2.0-16)

makefile head:

mator@ttip:/1/mator/nmap.git$ head -50 Makefile
# Extract the version string from nmap.h.
export NMAP_VERSION := $(shell grep '^\#[ \t]*define[ \t]\+NMAP_VERSION' nmap.h | sed -e 's/.*"\(.*\)".*/\1/' -e 'q')
NMAP_PLATFORM=sparc64-unknown-linux-gnu
datarootdir = ${prefix}/share
prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
sbindir = ${exec_prefix}/sbin
mandir = ${datarootdir}/man
top_srcdir = .
srcdir = .
nmapdatadir = ${datarootdir}/nmap
deskdir = $(prefix)/share/applications
NMAPDEVDIR=~/nmap-private-dev

export NBASEDIR=nbase
export NSOCKDIR=nsock
export LIBLUADIR = liblua
export LIBLINEARDIR = liblinear
export NDIR=$(shell pwd)
export LIBLINEAR_LIBS = $(top_srcdir)/liblinear/liblinear.a
export NCATDIR=ncat
CC = gcc
CXX = g++
CCOPT =
DBGFLAGS =
STRIP = /usr/bin/strip
LIBPCAPDIR = libpcap
LIBSSH2DIR = libssh2
ZLIBDIR = libz
LIBPCREDIR = libpcre
export LIBDNETDIR = libdnet-stripped
ZENMAPDIR = zenmap
NDIFFDIR = ndiff
NPINGDIR = nping
PYTHON = /usr/bin/python2
DEFS = -DHAVE_CONFIG_H -DNMAP_PLATFORM=\"$(NMAP_PLATFORM)\" -DNMAPDATADIR=\"$(nmapdatadir)\"
# With GCC, add extra security checks to source code.
# http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
# Level 1 only makes changes that don't affect "conforming" programs,
# while level 2 enforces additional restrictions.
DEFS += -D_FORTIFY_SOURCE=2
# For mtrace debugging -- see MTRACE define in main.cc for instructions
# Should only be enabled during debugging and not in any real release.
# DEFS += -DMTRACE=1
CXXFLAGS = -g -O2 -Wall -fno-strict-aliasing $(DBGFLAGS) $(CCOPT)
CPPFLAGS = -I$(top_srcdir)/liblinear -DNOLUA -I$(top_srcdir)/libdnet-stripped/include  -I$(top_srcdir)/nbase -I$(top_srcdir)/nsock/include $(DEFS)
CFLAGS = -g -O2 -Wall $(DBGFLAGS) $(CCOPT)
STATIC =
LDFLAGS = -Wl,-E  -Lnbase -Lnsock/src/ $(DBGFLAGS) $(STATIC)

nmap config.log https://gist.github.com/mator/dacbaa6a955dfc88352d19814158973b

@mator
Copy link
Author

mator commented Dec 16, 2020

still valid for master branch

$ git br -v
* master 57b7e56a6 Fix a couple isIgnoredState calls to the new prototype.

@glaubitz
Copy link

According to @karcherm the problem is most likely related to the odd sizes of Ethernet packages (if I remember correctly).

You have to make sure the data is properly aligned before continuing with processing them.

@karcherm
Copy link

Well, the term "odd" is slightly misleading here. The standard ethernet ("Ethernet II") header consists of the 6-byte recipient address, the 6-byte sender address and the 2-byte protocol type field. The total size of that header is 14 bytes, which is (while even) not divisible by 4. If an IP packet is transfered over Ethernet using standard framing, the IP header is immediately following the the ethernet header. The design of the IP header makes sure that all fields are correctly aligned (i.e. 32-bit fields like sender and receiver IP address are on offsets divisible by 4, relative to the start of the IP header). The same is true for UDP and TCP: As long as the first byte of the IP header is aligned on an address divisble by 4, all 32-bit fields are correctly aligned.
It seems like nmap aligns the ethernet frame on an address divisible by 4, which misaligns all 32-bit fields of the IP/TCP/UDP header structures. IIRC "ip->ip_v" is a bit-field access to access a four-bit field containing the IP version. gcc probably compiles the bit field access as 32-bit word load and masking. So that's where the unaligned access comes from if the pointer "ip" is not aligned to a 32-bit boundary.

@kulikjak
Copy link

kulikjak commented Aug 1, 2022

I've just hit this on Solaris (SPARC) as well - any update on this (or workaround)?

I tried replacing the ip = (struct ip *) (p + offset); in accept_ip with memcpy, but then it broke in a slightly different place and after replacing it on several of them and still didn't make it work, I stopped.

4ffeb09 change removed alignedbuf that was previously used most likely because of this - I brought it back in the same place, but there are still other similar failures on other places - it will need more carefully directed fix (but I am not yet sure where).

@kulikjak kulikjak linked a pull request Aug 23, 2022 that will close this issue
@kulikjak
Copy link

I found the issue and managed to fix it with PR #2508.

@glaubitz
Copy link

I found the issue and managed to fix it with PR #2508.

Awesome work, thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
@mator @glaubitz @karcherm @dmiller-nmap @kulikjak and others