static int ipsec_sa_wipe(struct ipsec_sa *ips) { if(ips == NULL) { return -ENODATA; } /* paranoid clean up */ if(ips->ips_addr_s != NULL) { memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); kfree(ips->ips_addr_s); } ips->ips_addr_s = NULL; if(ips->ips_addr_d != NULL) { memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); kfree(ips->ips_addr_d); } ips->ips_addr_d = NULL; if(ips->ips_addr_p != NULL) { memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); kfree(ips->ips_addr_p); } ips->ips_addr_p = NULL; #ifdef CONFIG_IPSEC_NAT_TRAVERSAL if(ips->ips_natt_oa) { memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); kfree(ips->ips_natt_oa); } ips->ips_natt_oa = NULL; #endif if(ips->ips_key_a != NULL) { memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); kfree(ips->ips_key_a); } ips->ips_key_a = NULL; if(ips->ips_key_e != NULL) { if (ips->ips_alg_enc && ips->ips_alg_enc->ixt_e_destroy_key) { ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, ips->ips_key_e); } else { memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); kfree(ips->ips_key_e); } } ips->ips_key_e = NULL; if(ips->ips_iv != NULL) { memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); kfree(ips->ips_iv); } ips->ips_iv = NULL; if(ips->ips_ident_s.data != NULL) { memset((caddr_t)(ips->ips_ident_s.data), 0, ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_s.data); } ips->ips_ident_s.data = NULL; if(ips->ips_ident_d.data != NULL) { memset((caddr_t)(ips->ips_ident_d.data), 0, ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_d.data); } ips->ips_ident_d.data = NULL; if (ips->ips_alg_enc||ips->ips_alg_auth) { ipsec_alg_sa_wipe(ips); } BUG_ON(atomic_read(&ips->ips_refcount) != 0); memset((caddr_t)ips, 0, sizeof(*ips)); kfree(ips); ips = NULL; return 0; }
int ipsec_sa_wipe(struct ipsec_sa *ips) { int hashval; struct ipsec_sa **tpp; if (ips == NULL) return -ENODATA; #if IPSEC_SA_REF_CODE /* remove me from the SArefTable */ if (debug_xform) { char sa[SATOT_BUF]; size_t sa_len; struct IPsecSArefSubTable *subtable = NULL; if (IPsecSAref2table(IPsecSA2SAref(ips)) < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES && ipsec_sadb.refTable != NULL) subtable = ipsec_sadb.refTable[ IPsecSAref2table(IPsecSA2SAref(ips))]; sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_wipe: " "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n", sa_len ? sa : " (error)", ips, ips->ips_ref, IPsecSAref2table(IPsecSA2SAref(ips)), subtable, subtable ? IPsecSAref2entry(IPsecSA2SAref(ips)) : 0); } if (ips->ips_ref != IPSEC_SAREF_NULL) { struct IPsecSArefSubTable *subtable = NULL; int ref_table = IPsecSAref2table(IPsecSA2SAref(ips)); int ref_entry = IPsecSAref2entry(IPsecSA2SAref(ips)); if (ref_table < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { subtable = ipsec_sadb.refTable[ref_table]; if (subtable != NULL && subtable->entry[ref_entry] == ips) { subtable->entry[ref_entry] = NULL; } } ips->ips_ref = IPSEC_SAREF_NULL; } #endif /* IPSEC_SA_REF_CODE */ /* paranoid clean up */ if (ips->ips_addr_s != NULL) { memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); kfree(ips->ips_addr_s); } ips->ips_addr_s = NULL; if (ips->ips_addr_d != NULL) { memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); kfree(ips->ips_addr_d); } ips->ips_addr_d = NULL; if (ips->ips_addr_p != NULL) { memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); kfree(ips->ips_addr_p); } ips->ips_addr_p = NULL; if (ips->ips_natt_oa) { memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); kfree(ips->ips_natt_oa); } ips->ips_natt_oa = NULL; if (ips->ips_key_a != NULL) { #ifdef CONFIG_KLIPS_ALG if (ips->ips_alg_auth && ips->ips_alg_auth->ixt_a_destroy_key) { ips->ips_alg_auth->ixt_a_destroy_key(ips->ips_alg_auth, ips->ips_key_a); } else #endif { memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); kfree(ips->ips_key_a); } } ips->ips_key_a = NULL; if (ips->ips_key_e != NULL) { #ifdef CONFIG_KLIPS_ALG if (ips->ips_alg_enc && ips->ips_alg_enc->ixt_e_destroy_key) { ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, ips->ips_key_e); } else #endif { memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); kfree(ips->ips_key_e); } } ips->ips_key_e = NULL; if (ips->ips_iv != NULL) { memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); kfree(ips->ips_iv); } ips->ips_iv = NULL; #ifdef CONFIG_KLIPS_OCF if (ips->ocf_in_use) ipsec_ocf_sa_free(ips); #endif if (ips->ips_ident_s.data != NULL) { memset((caddr_t)(ips->ips_ident_s.data), 0, ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_s.data); } ips->ips_ident_s.data = NULL; if (ips->ips_ident_d.data != NULL) { memset((caddr_t)(ips->ips_ident_d.data), 0, ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_d.data); } ips->ips_ident_d.data = NULL; #ifdef CONFIG_KLIPS_ALG if (ips->ips_alg_enc || ips->ips_alg_auth) ipsec_alg_sa_wipe(ips); ips->ips_alg_enc = NULL; ips->ips_alg_auth = NULL; #endif if (ips->ips_prev) ips->ips_prev->ips_next = ips->ips_next; if (ips->ips_next) { ips->ips_next->ips_prev = ips->ips_prev; ipsec_sa_put(ips->ips_next, IPSEC_REFALLOC); } ips->ips_next = NULL; ips->ips_prev = NULL; hashval = IPS_HASH(&ips->ips_said); tpp = &ipsec_sadb_hash[hashval]; while (*tpp) { if (*tpp == ips) *tpp = ips->ips_hnext; else tpp = &((*tpp)->ips_hnext); } if (ips->ips_hnext) ipsec_sa_put(ips->ips_hnext, IPSEC_REFALLOC); ips->ips_hnext = NULL; BUG_ON(atomic_read(&ips->ips_refcount) != 0); #ifdef IPSEC_SA_RECOUNT_DEBUG if (ips == ipsec_sa_raw) { ipsec_sa_raw = ips->ips_raw; } else { struct ipsec_sa *raw = ipsec_sa_raw; while (raw) { if (raw->ips_raw == ips) { raw->ips_raw = ips->ips_raw; break; } raw = raw->ips_raw; } } #endif if (ips->ips_out != NULL) { ipsec_dev_put(ips->ips_out); ips->ips_out = NULL; } memset((caddr_t)ips, 0, sizeof(*ips)); kfree(ips); ips = NULL; return 0; }
int ipsec_sa_wipe(struct ipsec_sa *ips) { if(!ips) { return -ENODATA; } if(ips->ips_addr_s) { memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); kfree(ips->ips_addr_s); } ips->ips_addr_s = NULL; if(ips->ips_addr_d) { memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); kfree(ips->ips_addr_d); } ips->ips_addr_d = NULL; if(ips->ips_addr_p) { memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); kfree(ips->ips_addr_p); } ips->ips_addr_p = NULL; #ifdef CONFIG_IPSEC_NAT_TRAVERSAL if(ips->ips_natt_oa) { memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); kfree(ips->ips_natt_oa); } ips->ips_natt_oa = NULL; #endif if(ips->ips_key_a) { memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); kfree(ips->ips_key_a); } ips->ips_key_a = NULL; if(ips->ips_key_e) { memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); kfree(ips->ips_key_e); } ips->ips_key_e = NULL; if(ips->ips_iv) { memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); kfree(ips->ips_iv); } ips->ips_iv = NULL; if(ips->ips_ident_s.data) { memset((caddr_t)(ips->ips_ident_s.data), 0, ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_s.data); } ips->ips_ident_s.data = NULL; if(ips->ips_ident_d.data) { memset((caddr_t)(ips->ips_ident_d.data), 0, ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_d.data); } ips->ips_ident_d.data = NULL; if (IPSEC_ALG_SA_ESP_ENC(ips)||IPSEC_ALG_SA_ESP_AUTH(ips)) { ipsec_alg_sa_wipe(ips); } memset((caddr_t)ips, 0, sizeof(*ips)); kfree(ips); ips = NULL; return 0; }