Merge branch 'pknock'

Kernel warnings and oopses resulting from the inversion (HEAD^2)
reported by user mancha (mancha!debian-tor@gateway/tor-sasl/mancha) on
irc.freenode.net/#netfilter.
This commit is contained in:
Jan Engelhardt
2011-02-28 20:48:23 +01:00
2 changed files with 39 additions and 42 deletions

View File

@@ -1,6 +1,9 @@
HEAD HEAD
==== ====
Fixes:
- xt_pknock: avoid crash when hash TFM could not be allocated
- xt_pknock: avoid inversion of rule lookup that led to warnings
v1.33 (2011-02-02) v1.33 (2011-02-02)

View File

@@ -398,19 +398,15 @@ peer_gc(unsigned long r)
/** /**
* Compares length and name equality for the rules. * Compares length and name equality for the rules.
*
* @info
* @rule
* @return: 0 equals, 1 otherwise
*/ */
static inline bool static inline bool
rulecmp(const struct xt_pknock_mtinfo *info, const struct xt_pknock_rule *rule) rulecmp(const struct xt_pknock_mtinfo *info, const struct xt_pknock_rule *rule)
{ {
if (info->rule_name_len != rule->rule_name_len) if (info->rule_name_len != rule->rule_name_len)
return true;
if (strncmp(info->rule_name, rule->rule_name, info->rule_name_len) != 0)
return true;
return false; return false;
if (strncmp(info->rule_name, rule->rule_name, info->rule_name_len) != 0)
return false;
return true;
} }
/** /**
@@ -451,7 +447,8 @@ add_rule(struct xt_pknock_mtinfo *info)
list_for_each_safe(pos, n, &rule_hashtable[hash]) { list_for_each_safe(pos, n, &rule_hashtable[hash]) {
rule = list_entry(pos, struct xt_pknock_rule, head); rule = list_entry(pos, struct xt_pknock_rule, head);
if (rulecmp(info, rule)) { if (!rulecmp(info, rule))
continue;
++rule->ref_count; ++rule->ref_count;
if (info->option & XT_PKNOCK_OPENSECRET) { if (info->option & XT_PKNOCK_OPENSECRET) {
@@ -459,16 +456,12 @@ add_rule(struct xt_pknock_mtinfo *info)
rule->autoclose_time = info->autoclose_time; rule->autoclose_time = info->autoclose_time;
} }
if (info->option & XT_PKNOCK_CHECKIP) { if (info->option & XT_PKNOCK_CHECKIP)
pr_debug("add_rule() (AC)" pr_debug("add_rule() (AC) rule found: %s - "
" rule found: %s - "
"ref_count: %d\n", "ref_count: %d\n",
rule->rule_name, rule->rule_name, rule->ref_count);
rule->ref_count);
}
return true; return true;
} }
}
rule = kmalloc(sizeof(*rule), GFP_KERNEL); rule = kmalloc(sizeof(*rule), GFP_KERNEL);
if (rule == NULL) if (rule == NULL)
@@ -523,7 +516,8 @@ remove_rule(struct xt_pknock_mtinfo *info)
unsigned int hash = pknock_hash(info->rule_name, info->rule_name_len, unsigned int hash = pknock_hash(info->rule_name, info->rule_name_len,
ipt_pknock_hash_rnd, rule_hashsize); ipt_pknock_hash_rnd, rule_hashsize);
if (list_empty(&rule_hashtable[hash])) return; if (list_empty(&rule_hashtable[hash]))
return;
list_for_each_safe(pos, n, &rule_hashtable[hash]) { list_for_each_safe(pos, n, &rule_hashtable[hash]) {
rule = list_entry(pos, struct xt_pknock_rule, head); rule = list_entry(pos, struct xt_pknock_rule, head);
@@ -576,7 +570,8 @@ static struct peer *get_peer(struct xt_pknock_rule *rule, __be32 ip)
list_for_each_safe(pos, n, &rule->peer_head[hash]) { list_for_each_safe(pos, n, &rule->peer_head[hash]) {
peer = list_entry(pos, struct peer, head); peer = list_entry(pos, struct peer, head);
if (peer->ip == ip) return peer; if (peer->ip == ip)
return peer;
} }
return NULL; return NULL;
} }
@@ -1043,7 +1038,8 @@ static bool pknock_mt(const struct sk_buff *skb,
add_peer(peer, rule); add_peer(peer, rule);
} }
if (peer == NULL) goto out; if (peer == NULL)
goto out;
update_peer(peer, info, rule, &hdr); update_peer(peer, info, rule, &hdr);
} }
@@ -1087,15 +1083,15 @@ static int pknock_mt_check(const struct xt_mtchk_param *par)
RETURN_ERR("No crypto support available; " RETURN_ERR("No crypto support available; "
"cannot use opensecret/closescret\n"); "cannot use opensecret/closescret\n");
#endif #endif
if ((info->option & XT_PKNOCK_OPENSECRET) && (info->ports_count != 1)) if (info->option & XT_PKNOCK_OPENSECRET && info->ports_count != 1)
RETURN_ERR("--opensecret must have just one knock port\n"); RETURN_ERR("--opensecret must have just one knock port\n");
if (info->option & XT_PKNOCK_KNOCKPORT) { if (info->option & XT_PKNOCK_KNOCKPORT) {
if (info->option & XT_PKNOCK_CHECKIP) if (info->option & XT_PKNOCK_CHECKIP)
RETURN_ERR("Can't specify --knockports with --checkip.\n"); RETURN_ERR("Can't specify --knockports with --checkip.\n");
if ((info->option & XT_PKNOCK_OPENSECRET) && if (info->option & XT_PKNOCK_OPENSECRET &&
!(info->option & XT_PKNOCK_CLOSESECRET)) !(info->option & XT_PKNOCK_CLOSESECRET))
RETURN_ERR("--opensecret must go with --closesecret.\n"); RETURN_ERR("--opensecret must go with --closesecret.\n");
if ((info->option & XT_PKNOCK_CLOSESECRET) && if (info->option & XT_PKNOCK_CLOSESECRET &&
!(info->option & XT_PKNOCK_OPENSECRET)) !(info->option & XT_PKNOCK_OPENSECRET))
RETURN_ERR("--closesecret must go with --opensecret.\n"); RETURN_ERR("--closesecret must go with --opensecret.\n");
} }
@@ -1115,13 +1111,11 @@ static int pknock_mt_check(const struct xt_mtchk_param *par)
RETURN_ERR("you must specify --time.\n"); RETURN_ERR("you must specify --time.\n");
} }
if (info->option & XT_PKNOCK_OPENSECRET) { if (info->option & XT_PKNOCK_OPENSECRET &&
if (info->open_secret_len == info->close_secret_len) { info->open_secret_len == info->close_secret_len &&
if (memcmp(info->open_secret, info->close_secret, memcmp(info->open_secret, info->close_secret,
info->open_secret_len) == 0) info->open_secret_len) == 0)
RETURN_ERR("opensecret & closesecret cannot be equal.\n"); RETURN_ERR("opensecret & closesecret cannot be equal.\n");
}
}
if (!add_rule(info)) if (!add_rule(info))
/* should ENOMEM here */ /* should ENOMEM here */
@@ -1166,11 +1160,10 @@ static int __init xt_pknock_mt_init(void)
} }
crypto.tfm = crypto_alloc_hash(crypto.algo, 0, CRYPTO_ALG_ASYNC); crypto.tfm = crypto_alloc_hash(crypto.algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(crypto.tfm)) {
if (crypto.tfm == NULL) {
printk(KERN_ERR PKNOCK "failed to load transform for %s\n", printk(KERN_ERR PKNOCK "failed to load transform for %s\n",
crypto.algo); crypto.algo);
return -ENXIO; return PTR_ERR(crypto.tfm);
} }
crypto.size = crypto_hash_digestsize(crypto.tfm); crypto.size = crypto_hash_digestsize(crypto.tfm);
@@ -1195,7 +1188,8 @@ static void __exit xt_pknock_mt_exit(void)
kfree(rule_hashtable); kfree(rule_hashtable);
#ifdef PK_CRYPTO #ifdef PK_CRYPTO
if (crypto.tfm != NULL) crypto_free_hash(crypto.tfm); if (crypto.tfm != NULL)
crypto_free_hash(crypto.tfm);
#endif #endif
} }