From: Kevin Chou Date: Sat, 18 May 2019 05:48:49 +0000 (+0800) Subject: fix segmentation fault X-Git-Tag: release-1.9.3rc1~34^2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F28%2Fhead;p=thirdparty%2Funbound.git fix segmentation fault --- diff --git a/ipset/ipset.c b/ipset/ipset.c index 55ef05c3d..fb16c06a3 100755 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -33,6 +33,23 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) { return 0; } +static struct mnl_socket * open_mnl_socket() { + struct mnl_socket *mnl; + + mnl = mnl_socket_open(NETLINK_NETFILTER); + if (!mnl) { + log_err("ipset: could not open netfilter."); + return NULL; + } + + if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) { + mnl_socket_close(mnl); + log_err("ipset: could not bind netfilter."); + return NULL; + } + return mnl; +} + static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) { struct nlmsghdr *nlh; struct nfgenmsg *nfg; @@ -98,8 +115,14 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru uint8_t *rr_data; mnl = (struct mnl_socket *)ie->mnl; - if (mnl == NULL) { - return -1; + if (!mnl) { + // retry to create mnl socket + mnl = open_mnl_socket(); + if (!mnl) { + return -1; + } + + ie->mnl = mnl; } for (i = 0; i < return_msg->rep->rrset_count; ++i) { @@ -119,7 +142,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru } } - if (setname != NULL) { + if (setname) { dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN); if (dlen == 0) { log_err("bad domain name"); @@ -146,6 +169,9 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru ret = add_to_ipset(mnl, setname, rr_data + 2, af); if (ret < 0) { log_err("ipset: could not add %s into %s", dname, setname); + + mnl_socket_close(mnl); + ie->mnl = NULL; break; } } @@ -154,58 +180,48 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru } } } - } + } } return 0; } int ipset_init(struct module_env* env, int id) { - struct mnl_socket *mnl; + struct ipset_env *ipset_env; - struct ipset_env *ipset_env = (struct ipset_env *)calloc(1, - sizeof(struct ipset_env)); - if(!ipset_env) { + ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env)); + if (!ipset_env) { log_err("malloc failure"); return 0; } - env->modinfo[id] = (void*)ipset_env; + + env->modinfo[id] = (void *)ipset_env; + + ipset_env->mnl == NULL; ipset_env->name_v4 = env->cfg->ipset_name_v4; ipset_env->name_v6 = env->cfg->ipset_name_v6; - ipset_env->v4_enabled = (ipset_env->name_v4 == NULL) || (strlen(ipset_env->name_v4) == 0) ? 0 : 1; - ipset_env->v6_enabled = (ipset_env->name_v6 == NULL) || (strlen(ipset_env->name_v6) == 0) ? 0 : 1; + ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1; + ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1; if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) { log_err("ipset: set name no configuration?"); return 0; } - mnl = mnl_socket_open(NETLINK_NETFILTER); - if (mnl <= 0) { - log_err("ipset: could not open netfilter."); - return 0; - } - - if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) { - mnl_socket_close(mnl); - log_err("ipset: could not bind netfilter."); - return 0; - } - - ipset_env->mnl = mnl; - return 1; } void ipset_deinit(struct module_env *env, int id) { struct mnl_socket *mnl; + struct ipset_env *ipset_env; - struct ipset_env* ipset_env; - if(!env || !env->modinfo[id]) + if (!env || !env->modinfo[id]) { return; - ipset_env = (struct ipset_env*)env->modinfo[id]; + } + + ipset_env = (struct ipset_env *)env->modinfo[id]; mnl = (struct mnl_socket *)ipset_env->mnl; if (mnl) { @@ -218,11 +234,13 @@ void ipset_deinit(struct module_env *env, int id) { } static int ipset_new(struct module_qstate* qstate, int id) { - struct ipset_qstate* iq = (struct ipset_qstate*)regional_alloc( + struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc( qstate->region, sizeof(struct ipset_qstate)); qstate->minfo[id] = iq; - if(!iq) + if (!iq) { return 0; + } + memset(iq, 0, sizeof(*iq)); /* initialise it */ /* TODO */ @@ -236,42 +254,47 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id, struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id]; verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s", id, strextstate(qstate->ext_state[id]), strmodulevent(event)); - if(iq) log_query_info(VERB_QUERY, "ipset operate: query", - &qstate->qinfo); + if (iq) { + log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo); + } /* perform ipset state machine */ - if((event == module_event_new || event == module_event_pass) && - iq == NULL) { - if(!ipset_new(qstate, id)) { + if ((event == module_event_new || event == module_event_pass) && !iq) { + if (!ipset_new(qstate, id)) { (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); return; } iq = (struct ipset_qstate*)qstate->minfo[id]; } - if(iq && (event == module_event_pass || event == module_event_new)) { + if (iq && (event == module_event_pass || event == module_event_new)) { qstate->ext_state[id] = module_wait_module; return; } - if(iq && (event == module_event_moddone)) { - ipset_update(qstate->env, qstate->return_msg, ie); + if (iq && (event == module_event_moddone)) { + if (qstate->return_msg && qstate->return_msg->rep) { + ipset_update(qstate->env, qstate->return_msg, ie); + } qstate->ext_state[id] = module_finished; return; } - if(iq && outbound) { + + if (iq && outbound) { /* ipset does not need to process responses at this time * ignore it. ipset_process_response(qstate, iq, ie, id, outbound, event); */ return; } - if(event == module_event_error) { + + if (event == module_event_error) { verbose(VERB_ALGO, "got called with event error, giving up"); (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); return; } - if(!iq && (event == module_event_moddone)) { + + if (!iq && (event == module_event_moddone)) { /* during priming, module done but we never started */ qstate->ext_state[id] = module_finished; return; @@ -281,25 +304,26 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id, (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); } -void ipset_inform_super(struct module_qstate* ATTR_UNUSED(qstate), - int ATTR_UNUSED(id), struct module_qstate* ATTR_UNUSED(super)) { +void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate), + int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) { /* ipset does not use subordinate requests at this time */ verbose(VERB_ALGO, "ipset inform_super was called"); } -void ipset_clear(struct module_qstate* qstate, int id) { - struct cachedb_qstate* iq; - if(!qstate) +void ipset_clear(struct module_qstate *qstate, int id) { + struct cachedb_qstate *iq; + if (!qstate) { return; - iq = (struct cachedb_qstate*)qstate->minfo[id]; - if(iq) { + } + iq = (struct cachedb_qstate *)qstate->minfo[id]; + if (iq) { /* free contents of iq */ /* TODO */ } qstate->minfo[id] = NULL; } -size_t ipset_get_mem(struct module_env* env, int id) { +size_t ipset_get_mem(struct module_env *env, int id) { struct ipset_env *ie = (struct ipset_env *)env->modinfo[id]; if (!ie) { return 0; @@ -320,4 +344,3 @@ struct module_func_block * ipset_get_funcblock(void) { return &ipset_block; } -