简体   繁体   中英

Segmentation fault incrementing a map

I am trying to trace/fix a segmentation fault in my program. My program works fine when perform() has only one iteration of "protos", but not with two. On the second, I get a segmentation fault after the first iteration. I am pretty sure that the way I am dealing with iterating and deleting elements in my map in write_blacklist() is correct, but it still reports that it is the error. I thought that it may be because the map is empty, but I did checks to avoid that and it still throws a segmentation fault.

For write_blacklist(), all it should just safely do its iterations and delete the map elements that meet the conditions.

(gdb) run
Starting program: /root/BruteBlock/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
openssh
vsftpd
115.239.198.235 already in blacklist, skipping...
121.14.7.244 already in blacklist, skipping...
42.7.26.88 already in blacklist, skipping...
143.137.151.22 already in blacklist, skipping...
58.87.67.58 already in blacklist, skipping...
60.173.82.156 already in blacklist, skipping...
[New Thread 0x7ffff2d34700 (LWP 2087)]
[Thread 0x7ffff2d34700 (LWP 2087) exited]
[New Thread 0x7ffff2d34700 (LWP 2088)]
[Thread 0x7ffff2d34700 (LWP 2088) exited]
[New Thread 0x7ffff2d34700 (LWP 2089)]
[Thread 0x7ffff2d34700 (LWP 2089) exited]
Detaching after fork from child process 2090.
115.239.198.235 already in iptables, skipping...
121.14.7.244 already in iptables, skipping...
42.7.26.88 already in iptables, skipping...
143.137.151.22 already in iptables, skipping...
58.87.67.58 already in iptables, skipping...
60.173.82.156 already in iptables, skipping...
[New Thread 0x7ffff2d34700 (LWP 2091)]
[Thread 0x7ffff2d34700 (LWP 2091) exited]

Program received signal SIGSEGV, Segmentation fault.
0x000000000040c1e6 in std::__detail::_Hash_node<std::pair<std::string const, int>, true>::_M_next (this=0x0)
    at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:285
285       { return static_cast<_Hash_node*>(this->_M_nxt); }
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.26-21.el7.x86_64 glibc-2.17-196.el7_4.2.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-8.el7.x86_64 libcom_err-1.42.9-10.el7.x86_64 libcurl-7.29.0-42.el7_4.1.x86_64 libgcc-4.8.5-16.el7_4.1.x86_64 libidn-1.28-4.el7.x86_64 libselinux-2.5-11.el7.x86_64 libssh2-1.4.3-10.el7_2.1.x86_64 libstdc++-4.8.5-16.el7_4.1.x86_64 nspr-4.13.1-1.0.el7_3.x86_64 nss-3.28.4-15.el7_4.x86_64 nss-pem-1.0.3-4.el7.x86_64 nss-softokn-3.28.3-8.el7_4.x86_64 nss-softokn-freebl-3.28.3-8.el7_4.x86_64 nss-sysinit-3.28.4-15.el7_4.x86_64 nss-util-3.28.4-3.el7.x86_64 openldap-2.4.44-5.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 pcre-8.32-17.el7.x86_64 sqlite-3.7.17-8.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) bt
#0  0x000000000040c1e6 in std::__detail::_Hash_node<std::pair<std::string const, int>, true>::_M_next (this=0x0)
    at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:285
#1  0x000000000040a829 in std::__detail::_Node_iterator_base<std::pair<std::string const, int>, true>::_M_incr (
    this=0x7fffffffde20) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:314
#2  0x0000000000409612 in std::__detail::_Node_iterator<std::pair<std::string const, int>, false, true>::operator++ (
    this=0x7fffffffde20) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:369
Python Exception <class 'gdb.error'> There is no member or method named _M_bbegin.: 
#3  0x000000000040597e in BruteBlock::write_blacklist (this=0x7fffffffe130, ips=std::unordered_map with 0 elements, 
    output_file="/etc/blacklist.lst") at BruteBlock.cpp:68
#4  0x0000000000406552 in BruteBlock::perform (this=0x7fffffffe130) at BruteBlock.cpp:188
#5  0x0000000000404e8c in main () at main.cpp:18

main.cpp:

while (true) {
18: b.perform();
    sleep(b.get_interval());
}

BruteBlock.cpp::perform():

void BruteBlock::perform() {
    // Hopefully this will become more elegant!
    for (auto i : protos) {
        std::unordered_map<std::string, int> r(retr_fails(i.logfile, i.expr));
        if (r.empty()) {
        } else {
            write_blacklist(r, blacklist_);
188:        block(blacklist_);
        }
    }
}

BruteBlock.cpp::write_blacklist():

void BruteBlock::write_blacklist(std::unordered_map<std::string, int> &ips, const std::string &output_file) {
    std::ifstream is(output_file.c_str());

    if (!is) throw std::runtime_error("Error opening blacklist");
    if (ips.empty()) return;

    // ignore duplicates
    std::string buf;
    while (std::getline(is, buf)) {
        if (ips.find(buf) != ips.end()) {
            ips.erase(buf);
            std::cout << buf << " already in blacklist, skipping..." << '\n';
        }
    }

    // delete the IPs that don't meet the criteria
    auto a = ips.begin();
    while (a != ips.end()) {
        if (a->second < max_attempts_) {
            a = ips.erase(a);
        } else {
            if (a->second > max_attempts_) {
                if (check_reports(a->first) < max_reports_) {
                    a = ips.erase(a);
                }
            }
68:         ++a;
        }
    }

    // write the remaining IPs to the blacklist
    std::ofstream os(output_file.c_str(), std::ios_base::app);

    if (!os) throw std::invalid_argument("Error opening blacklist file");

    for (auto f : ips) {
        if ((f.second > max_attempts_) && (check_reports(f.first) > max_reports_)) {
            os << f.first << '\n';
            std::cout << f.first << " had " << f.second << " failed attempts and " << check_reports(f.first)
                      << " abuse reports, adding to blacklist...\n";
        }
    }

}

In your last loop, j3 lines above the line you've labeled with 68: , you have a = ips.erase(a); . If you're erasing the last node in the map, a will point to ips.end() after that erase. When you attempt to increment a on line 68 you get the segmentation fault since you can't increment an iterator the end iterator.

The solution would be to not increment a if you're erasing it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM