* nf-next: sysrq and condition 20100421 @ 2010-04-21 10:26 Jan Engelhardt 2010-04-21 10:26 ` [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ Jan Engelhardt 2010-04-21 10:26 ` [PATCH 2/2] netfilter: xtables: inclusion of xt_condition Jan Engelhardt 0 siblings, 2 replies; 15+ messages in thread From: Jan Engelhardt @ 2010-04-21 10:26 UTC (permalink / raw) To: kaber; +Cc: netfilter-devel The following changes since commit 6c79bf0f2440fd250c8fce8d9b82fcf03d4e8350: Bart De Schuymer (1): netfilter: bridge-netfilter: fix refragmenting IP traffic encapsulated in PPPoE traffic are available in the git repository at: git://dev.medozas.de/linux sysrq_cond Jan Engelhardt (2): netfilter: xtables: inclusion of xt_SYSRQ netfilter: xtables: inclusion of xt_condition include/linux/netfilter/Kbuild | 1 + include/linux/netfilter/xt_condition.h | 14 ++ net/netfilter/Kconfig | 20 ++ net/netfilter/Makefile | 2 + net/netfilter/xt_SYSRQ.c | 354 ++++++++++++++++++++++++++++++++ net/netfilter/xt_condition.c | 243 ++++++++++++++++++++++ 6 files changed, 634 insertions(+), 0 deletions(-) create mode 100644 include/linux/netfilter/xt_condition.h create mode 100644 net/netfilter/xt_SYSRQ.c create mode 100644 net/netfilter/xt_condition.c ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 10:26 nf-next: sysrq and condition 20100421 Jan Engelhardt @ 2010-04-21 10:26 ` Jan Engelhardt 2010-04-21 12:59 ` Patrick McHardy 2010-04-21 10:26 ` [PATCH 2/2] netfilter: xtables: inclusion of xt_condition Jan Engelhardt 1 sibling, 1 reply; 15+ messages in thread From: Jan Engelhardt @ 2010-04-21 10:26 UTC (permalink / raw) To: kaber; +Cc: netfilter-devel The SYSRQ target will allow to remotely invoke sysrq on the local machine. Authentication is by means of a pre-shared key that can either be transmitted plaintext or digest-secured. Signed-off-by: Jan Engelhardt <jengelh@medozas.de> --- net/netfilter/Kconfig | 12 ++ net/netfilter/Makefile | 1 + net/netfilter/xt_SYSRQ.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 367 insertions(+), 0 deletions(-) create mode 100644 net/netfilter/xt_SYSRQ.c diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 673a6c8..bfd9b6f 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -502,6 +502,18 @@ config NETFILTER_XT_TARGET_RATEEST To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_TARGET_SYSRQ + tristate '"SYSRQ" - remote sysrq invocation' + depends on NETFILTER_ADVANCED + ---help--- + This option enables the "SYSRQ" target which can be used to trigger + sysrq from a remote machine using a magic UDP packet with a pre-shared + password. This is useful when the receiving host has locked up in an + Oops yet still can process incoming packets. + + Besides plaintext packets, digest-secured SYSRQ requests will be + supported when CONFIG_CRYPTO is enabled. + config NETFILTER_XT_TARGET_TEE tristate '"TEE" - packet cloning to alternate destiantion' depends on NETFILTER_ADVANCED diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 14e3a8f..f032195 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_SYSRQ) += xt_SYSRQ.o obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o diff --git a/net/netfilter/xt_SYSRQ.c b/net/netfilter/xt_SYSRQ.c new file mode 100644 index 0000000..929b204 --- /dev/null +++ b/net/netfilter/xt_SYSRQ.c @@ -0,0 +1,354 @@ +/* + * "SYSRQ" target extension for Netfilter + * Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2010 + * + * Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 or later as published by the Free Software Foundation. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/ipv6.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/sysrq.h> +#include <linux/udp.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/netfilter/x_tables.h> +#include <linux/crypto.h> +#include <linux/scatterlist.h> +#include <net/ip.h> + +#if defined(CONFIG_CRYPTO) || defined(CRYPTO_CONFIG_MODULE) +# define WITH_CRYPTO 1 +#endif +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +# define WITH_IPV6 1 +#endif + +static bool sysrq_once; +static char sysrq_password[64]; +static char sysrq_hash[16] = "sha1"; +static long sysrq_seqno; +static int sysrq_debug; +module_param_string(password, sysrq_password, sizeof(sysrq_password), + S_IRUSR | S_IWUSR); +module_param_string(hash, sysrq_hash, sizeof(sysrq_hash), S_IRUSR); +module_param_named(seqno, sysrq_seqno, long, S_IRUSR | S_IWUSR); +module_param_named(debug, sysrq_debug, int, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(password, "password for remote sysrq"); +MODULE_PARM_DESC(hash, "hash algorithm, default sha1"); +MODULE_PARM_DESC(seqno, "sequence number for remote sysrq"); +MODULE_PARM_DESC(debug, "debugging: 0=off, 1=on"); + +#ifdef WITH_CRYPTO +static struct crypto_hash *sysrq_tfm; +static int sysrq_digest_size; +static unsigned char *sysrq_digest_password; +static unsigned char *sysrq_digest; +static char *sysrq_hexdigest; + +/* + * The data is of the form "<requests>,<seqno>,<salt>,<hash>" where <requests> + * is a series of sysrq requests; <seqno> is a sequence number that must be + * greater than the last sequence number; <salt> is some random bytes; and + * <hash> is the hash of everything up to and including the preceding "," + * together with the password. + * + * For example + * + * salt=$RANDOM + * req="s,$(date +%s),$salt" + * echo "$req,$(echo -n $req,secret | sha1sum | cut -c1-40)" + * + * You will want a better salt and password than that though :-) + */ +static unsigned int sysrq_tg(const void *pdata, uint16_t len) +{ + const char *data = pdata; + int i, n; + struct scatterlist sg[2]; + struct hash_desc desc; + int ret; + long new_seqno = 0; + + if (*sysrq_password == '\0') { + if (!sysrq_once) + pr_info("No password set\n"); + sysrq_once = true; + return NF_DROP; + } + if (len == 0) + return NF_DROP; + + for (i = 0; sysrq_password[i] != '\0' && + sysrq_password[i] != '\n'; ++i) + /* loop */; + sysrq_password[i] = '\0'; + + i = 0; + for (n = 0; n < len - 1; ++n) { + if (i == 1 && '0' <= data[n] && data[n] <= '9') + new_seqno = 10L * new_seqno + data[n] - '0'; + if (data[n] == ',' && ++i == 3) + break; + } + ++n; + if (i != 3) { + if (sysrq_debug) + pr_info("badly formatted request\n"); + return NF_DROP; + } + if (sysrq_seqno >= new_seqno) { + if (sysrq_debug) + pr_info("old sequence number ignored\n"); + return NF_DROP; + } + + desc.tfm = sysrq_tfm; + desc.flags = 0; + ret = crypto_hash_init(&desc); + if (ret != 0) + goto hash_fail; + sg_init_table(sg, 2); + sg_set_buf(&sg[0], data, n); + strcpy(sysrq_digest_password, sysrq_password); + i = strlen(sysrq_digest_password); + sg_set_buf(&sg[1], sysrq_digest_password, i); + ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest); + if (ret != 0) + goto hash_fail; + + for (i = 0; i < sysrq_digest_size; ++i) { + sysrq_hexdigest[2*i] = + "0123456789abcdef"[(sysrq_digest[i] >> 4) & 0xf]; + sysrq_hexdigest[2*i+1] = + "0123456789abcdef"[sysrq_digest[i] & 0xf]; + } + sysrq_hexdigest[2*sysrq_digest_size] = '\0'; + if (len - n < sysrq_digest_size) { + if (sysrq_debug) + pr_info("Short digest, expected %s\n", + sysrq_hexdigest); + return NF_DROP; + } + if (strncmp(data + n, sysrq_hexdigest, sysrq_digest_size) != 0) { + if (sysrq_debug) + pr_info("Bad digest, expected %s\n", sysrq_hexdigest); + return NF_DROP; + } + + /* Now we trust the requester */ + sysrq_seqno = new_seqno; + for (i = 0; i < len && data[i] != ','; ++i) { + pr_info("SysRq %c\n", data[i]); + handle_sysrq(data[i], NULL); + } + return NF_ACCEPT; + + hash_fail: + pr_warning("digest failure\n"); + return NF_DROP; +} +#else +static unsigned int sysrq_tg(const void *pdata, uint16_t len) +{ + const char *data = pdata; + char c; + + if (*sysrq_password == '\0') { + if (!sysrq_once) + pr_info("No password set\n"); + sysrq_once = true; + return NF_DROP; + } + + if (len == 0) + return NF_DROP; + + c = *data; + if (strncmp(&data[1], sysrq_password, len - 1) != 0) { + pr_warning("Failed attempt - password mismatch\n"); + return NF_DROP; + } + + handle_sysrq(c, NULL); + return NF_ACCEPT; +} +#endif + +static unsigned int +sysrq_tg4(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct iphdr *iph; + const struct udphdr *udph; + uint16_t len; + + if (skb_linearize(skb) < 0) + return NF_DROP; + + iph = ip_hdr(skb); + if (iph->protocol != IPPROTO_UDP && iph->protocol != IPPROTO_UDPLITE) + return NF_DROP; + + udph = (const void *)iph + ip_hdrlen(skb); + len = ntohs(udph->len) - sizeof(struct udphdr); + + if (sysrq_debug) + pr_info(": %pI4:%u -> :%u len=%u\n", &iph->saddr, + htons(udph->source), htons(udph->dest), len); + return sysrq_tg((void *)udph + sizeof(struct udphdr), len); +} + +#ifdef WITH_IPV6 +static unsigned int +sysrq_tg6(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct ipv6hdr *iph; + const struct udphdr *udph; + unsigned short frag_off; + unsigned int th_off; + uint16_t len; + + if (skb_linearize(skb) < 0) + return NF_DROP; + + iph = ipv6_hdr(skb); + if (ipv6_find_hdr(skb, &th_off, IPPROTO_UDP, &frag_off) < 0 || + frag_off > 0) + return NF_ACCEPT; /* sink it */ + + udph = (const void *)iph + th_off; + len = ntohs(udph->len) - sizeof(struct udphdr); + + if (sysrq_debug) + pr_info("%pI6:%hu -> :%hu len=%u\n", &iph->saddr, + ntohs(udph->source), ntohs(udph->dest), len); + return sysrq_tg(udph + sizeof(struct udphdr), len); +} +#endif + +static int sysrq_tg_check(const struct xt_tgchk_param *par) +{ + if (par->target->family == NFPROTO_IPV4) { + const struct ipt_entry *entry = par->entryinfo; + + if ((entry->ip.proto != IPPROTO_UDP && + entry->ip.proto != IPPROTO_UDPLITE) || + entry->ip.invflags & XT_INV_PROTO) + goto out; + } else if (par->target->family == NFPROTO_IPV6) { + const struct ip6t_entry *entry = par->entryinfo; + + if ((entry->ipv6.proto != IPPROTO_UDP && + entry->ipv6.proto != IPPROTO_UDPLITE) || + entry->ipv6.invflags & XT_INV_PROTO) + goto out; + } + + return true; + + out: + pr_info("only available for UDP and UDP-Lite"); + return false; +} + +static struct xt_target sysrq_tg_reg[] __read_mostly = { + { + .name = "SYSRQ", + .revision = 1, + .family = NFPROTO_IPV4, + .target = sysrq_tg4, + .checkentry = sysrq_tg_check, + .me = THIS_MODULE, + }, +#ifdef WITH_IPV6 + { + .name = "SYSRQ", + .revision = 1, + .family = NFPROTO_IPV6, + .target = sysrq_tg6, + .checkentry = sysrq_tg_check, + .me = THIS_MODULE, + }, +#endif +}; + +static void sysrq_crypto_exit(void) +{ +#ifdef WITH_CRYPTO + if (sysrq_tfm) + crypto_free_hash(sysrq_tfm); + if (sysrq_digest) + kfree(sysrq_digest); + if (sysrq_hexdigest) + kfree(sysrq_hexdigest); + if (sysrq_digest_password) + kfree(sysrq_digest_password); +#endif +} + +static int __init sysrq_crypto_init(void) +{ +#if defined(WITH_CRYPTO) + struct timeval now; + int ret; + + sysrq_tfm = crypto_alloc_hash(sysrq_hash, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(sysrq_tfm)) { + pr_err("Could not find or load %s hash\n", sysrq_hash); + sysrq_tfm = NULL; + ret = PTR_ERR(sysrq_tfm); + goto fail; + } + sysrq_digest_size = crypto_hash_digestsize(sysrq_tfm); + sysrq_digest = kmalloc(sysrq_digest_size, GFP_KERNEL); + ret = -ENOMEM; + if (sysrq_digest == NULL) + goto fail; + sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL); + if (sysrq_hexdigest == NULL) + goto fail; + sysrq_digest_password = kmalloc(sizeof(sysrq_password), GFP_KERNEL); + if (sysrq_digest_password == NULL) + goto fail; + do_gettimeofday(&now); + sysrq_seqno = now.tv_sec; + ret = xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); + if (ret < 0) + goto fail; + return ret; + + fail: + sysrq_crypto_exit(); + return ret; +#else + pr_info("compiled without crypto\n"); +#endif + return -EINVAL; +} + +static int __init sysrq_tg_init(void) +{ + if (sysrq_crypto_init() < 0) + pr_info("starting without crypto\n"); + return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); +} + +static void __exit sysrq_tg_exit(void) +{ + sysrq_crypto_exit(); + xt_unregister_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); +} + +module_init(sysrq_tg_init); +module_exit(sysrq_tg_exit); +MODULE_DESCRIPTION("Xtables: triggering SYSRQ remotely"); +MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_SYSRQ"); +MODULE_ALIAS("ip6t_SYSRQ"); -- 1.7.0.5 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 10:26 ` [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ Jan Engelhardt @ 2010-04-21 12:59 ` Patrick McHardy 2010-04-21 13:07 ` Jan Engelhardt 2012-01-05 13:19 ` Shan Wei 0 siblings, 2 replies; 15+ messages in thread From: Patrick McHardy @ 2010-04-21 12:59 UTC (permalink / raw) To: Jan Engelhardt; +Cc: netfilter-devel, Linux Netdev List Jan Engelhardt wrote: > The SYSRQ target will allow to remotely invoke sysrq on the local > machine. Authentication is by means of a pre-shared key that can > either be transmitted plaintext or digest-secured. I really think this is pushing what netfilter is meant for a bit far. Its basically abusing the firewall ruleset to offer a network service. I can see that its useful to have this in the kernel instead of userspace, but why isn't this implemented as a stand-alone module? That seems like a better design to me and also makes it more useful by not depending on netfilter. > Signed-off-by: Jan Engelhardt <jengelh@medozas.de> > --- > net/netfilter/Kconfig | 12 ++ > net/netfilter/Makefile | 1 + > net/netfilter/xt_SYSRQ.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 367 insertions(+), 0 deletions(-) > create mode 100644 net/netfilter/xt_SYSRQ.c > > diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig > index 673a6c8..bfd9b6f 100644 > --- a/net/netfilter/Kconfig > +++ b/net/netfilter/Kconfig > @@ -502,6 +502,18 @@ config NETFILTER_XT_TARGET_RATEEST > > To compile it as a module, choose M here. If unsure, say N. > > +config NETFILTER_XT_TARGET_SYSRQ > + tristate '"SYSRQ" - remote sysrq invocation' > + depends on NETFILTER_ADVANCED > + ---help--- > + This option enables the "SYSRQ" target which can be used to trigger > + sysrq from a remote machine using a magic UDP packet with a pre-shared > + password. This is useful when the receiving host has locked up in an > + Oops yet still can process incoming packets. > + > + Besides plaintext packets, digest-secured SYSRQ requests will be > + supported when CONFIG_CRYPTO is enabled. > + > config NETFILTER_XT_TARGET_TEE > tristate '"TEE" - packet cloning to alternate destiantion' > depends on NETFILTER_ADVANCED > diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile > index 14e3a8f..f032195 100644 > --- a/net/netfilter/Makefile > +++ b/net/netfilter/Makefile > @@ -56,6 +56,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o > obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o > obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o > obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o > +obj-$(CONFIG_NETFILTER_XT_TARGET_SYSRQ) += xt_SYSRQ.o > obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o > obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o > obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o > diff --git a/net/netfilter/xt_SYSRQ.c b/net/netfilter/xt_SYSRQ.c > new file mode 100644 > index 0000000..929b204 > --- /dev/null > +++ b/net/netfilter/xt_SYSRQ.c > @@ -0,0 +1,354 @@ > +/* > + * "SYSRQ" target extension for Netfilter > + * Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2010 > + * > + * Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * version 2 or later as published by the Free Software Foundation. > + */ > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > +#include <linux/in.h> > +#include <linux/ip.h> > +#include <linux/ipv6.h> > +#include <linux/module.h> > +#include <linux/skbuff.h> > +#include <linux/sysrq.h> > +#include <linux/udp.h> > +#include <linux/netfilter_ipv4/ip_tables.h> > +#include <linux/netfilter_ipv6/ip6_tables.h> > +#include <linux/netfilter/x_tables.h> > +#include <linux/crypto.h> > +#include <linux/scatterlist.h> > +#include <net/ip.h> > + > +#if defined(CONFIG_CRYPTO) || defined(CRYPTO_CONFIG_MODULE) > +# define WITH_CRYPTO 1 > +#endif > +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) > +# define WITH_IPV6 1 > +#endif > + > +static bool sysrq_once; > +static char sysrq_password[64]; > +static char sysrq_hash[16] = "sha1"; > +static long sysrq_seqno; > +static int sysrq_debug; > +module_param_string(password, sysrq_password, sizeof(sysrq_password), > + S_IRUSR | S_IWUSR); > +module_param_string(hash, sysrq_hash, sizeof(sysrq_hash), S_IRUSR); > +module_param_named(seqno, sysrq_seqno, long, S_IRUSR | S_IWUSR); > +module_param_named(debug, sysrq_debug, int, S_IRUSR | S_IWUSR); > +MODULE_PARM_DESC(password, "password for remote sysrq"); > +MODULE_PARM_DESC(hash, "hash algorithm, default sha1"); > +MODULE_PARM_DESC(seqno, "sequence number for remote sysrq"); > +MODULE_PARM_DESC(debug, "debugging: 0=off, 1=on"); > + > +#ifdef WITH_CRYPTO > +static struct crypto_hash *sysrq_tfm; > +static int sysrq_digest_size; > +static unsigned char *sysrq_digest_password; > +static unsigned char *sysrq_digest; > +static char *sysrq_hexdigest; > + > +/* > + * The data is of the form "<requests>,<seqno>,<salt>,<hash>" where <requests> > + * is a series of sysrq requests; <seqno> is a sequence number that must be > + * greater than the last sequence number; <salt> is some random bytes; and > + * <hash> is the hash of everything up to and including the preceding "," > + * together with the password. > + * > + * For example > + * > + * salt=$RANDOM > + * req="s,$(date +%s),$salt" > + * echo "$req,$(echo -n $req,secret | sha1sum | cut -c1-40)" > + * > + * You will want a better salt and password than that though :-) > + */ > +static unsigned int sysrq_tg(const void *pdata, uint16_t len) > +{ > + const char *data = pdata; > + int i, n; > + struct scatterlist sg[2]; > + struct hash_desc desc; > + int ret; > + long new_seqno = 0; > + > + if (*sysrq_password == '\0') { > + if (!sysrq_once) > + pr_info("No password set\n"); > + sysrq_once = true; > + return NF_DROP; > + } > + if (len == 0) > + return NF_DROP; > + > + for (i = 0; sysrq_password[i] != '\0' && > + sysrq_password[i] != '\n'; ++i) > + /* loop */; > + sysrq_password[i] = '\0'; > + > + i = 0; > + for (n = 0; n < len - 1; ++n) { > + if (i == 1 && '0' <= data[n] && data[n] <= '9') > + new_seqno = 10L * new_seqno + data[n] - '0'; > + if (data[n] == ',' && ++i == 3) > + break; > + } > + ++n; > + if (i != 3) { > + if (sysrq_debug) > + pr_info("badly formatted request\n"); > + return NF_DROP; > + } > + if (sysrq_seqno >= new_seqno) { > + if (sysrq_debug) > + pr_info("old sequence number ignored\n"); > + return NF_DROP; > + } > + > + desc.tfm = sysrq_tfm; > + desc.flags = 0; > + ret = crypto_hash_init(&desc); > + if (ret != 0) > + goto hash_fail; > + sg_init_table(sg, 2); > + sg_set_buf(&sg[0], data, n); > + strcpy(sysrq_digest_password, sysrq_password); > + i = strlen(sysrq_digest_password); > + sg_set_buf(&sg[1], sysrq_digest_password, i); > + ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest); > + if (ret != 0) > + goto hash_fail; > + > + for (i = 0; i < sysrq_digest_size; ++i) { > + sysrq_hexdigest[2*i] = > + "0123456789abcdef"[(sysrq_digest[i] >> 4) & 0xf]; > + sysrq_hexdigest[2*i+1] = > + "0123456789abcdef"[sysrq_digest[i] & 0xf]; > + } > + sysrq_hexdigest[2*sysrq_digest_size] = '\0'; > + if (len - n < sysrq_digest_size) { > + if (sysrq_debug) > + pr_info("Short digest, expected %s\n", > + sysrq_hexdigest); > + return NF_DROP; > + } > + if (strncmp(data + n, sysrq_hexdigest, sysrq_digest_size) != 0) { > + if (sysrq_debug) > + pr_info("Bad digest, expected %s\n", sysrq_hexdigest); > + return NF_DROP; > + } > + > + /* Now we trust the requester */ > + sysrq_seqno = new_seqno; > + for (i = 0; i < len && data[i] != ','; ++i) { > + pr_info("SysRq %c\n", data[i]); > + handle_sysrq(data[i], NULL); > + } > + return NF_ACCEPT; > + > + hash_fail: > + pr_warning("digest failure\n"); > + return NF_DROP; > +} > +#else > +static unsigned int sysrq_tg(const void *pdata, uint16_t len) > +{ > + const char *data = pdata; > + char c; > + > + if (*sysrq_password == '\0') { > + if (!sysrq_once) > + pr_info("No password set\n"); > + sysrq_once = true; > + return NF_DROP; > + } > + > + if (len == 0) > + return NF_DROP; > + > + c = *data; > + if (strncmp(&data[1], sysrq_password, len - 1) != 0) { > + pr_warning("Failed attempt - password mismatch\n"); > + return NF_DROP; > + } > + > + handle_sysrq(c, NULL); > + return NF_ACCEPT; > +} > +#endif > + > +static unsigned int > +sysrq_tg4(struct sk_buff *skb, const struct xt_target_param *par) > +{ > + const struct iphdr *iph; > + const struct udphdr *udph; > + uint16_t len; > + > + if (skb_linearize(skb) < 0) > + return NF_DROP; > + > + iph = ip_hdr(skb); > + if (iph->protocol != IPPROTO_UDP && iph->protocol != IPPROTO_UDPLITE) > + return NF_DROP; > + > + udph = (const void *)iph + ip_hdrlen(skb); > + len = ntohs(udph->len) - sizeof(struct udphdr); > + > + if (sysrq_debug) > + pr_info(": %pI4:%u -> :%u len=%u\n", &iph->saddr, > + htons(udph->source), htons(udph->dest), len); > + return sysrq_tg((void *)udph + sizeof(struct udphdr), len); > +} > + > +#ifdef WITH_IPV6 > +static unsigned int > +sysrq_tg6(struct sk_buff *skb, const struct xt_target_param *par) > +{ > + const struct ipv6hdr *iph; > + const struct udphdr *udph; > + unsigned short frag_off; > + unsigned int th_off; > + uint16_t len; > + > + if (skb_linearize(skb) < 0) > + return NF_DROP; > + > + iph = ipv6_hdr(skb); > + if (ipv6_find_hdr(skb, &th_off, IPPROTO_UDP, &frag_off) < 0 || > + frag_off > 0) > + return NF_ACCEPT; /* sink it */ > + > + udph = (const void *)iph + th_off; > + len = ntohs(udph->len) - sizeof(struct udphdr); > + > + if (sysrq_debug) > + pr_info("%pI6:%hu -> :%hu len=%u\n", &iph->saddr, > + ntohs(udph->source), ntohs(udph->dest), len); > + return sysrq_tg(udph + sizeof(struct udphdr), len); > +} > +#endif > + > +static int sysrq_tg_check(const struct xt_tgchk_param *par) > +{ > + if (par->target->family == NFPROTO_IPV4) { > + const struct ipt_entry *entry = par->entryinfo; > + > + if ((entry->ip.proto != IPPROTO_UDP && > + entry->ip.proto != IPPROTO_UDPLITE) || > + entry->ip.invflags & XT_INV_PROTO) > + goto out; > + } else if (par->target->family == NFPROTO_IPV6) { > + const struct ip6t_entry *entry = par->entryinfo; > + > + if ((entry->ipv6.proto != IPPROTO_UDP && > + entry->ipv6.proto != IPPROTO_UDPLITE) || > + entry->ipv6.invflags & XT_INV_PROTO) > + goto out; > + } > + > + return true; > + > + out: > + pr_info("only available for UDP and UDP-Lite"); > + return false; > +} > + > +static struct xt_target sysrq_tg_reg[] __read_mostly = { > + { > + .name = "SYSRQ", > + .revision = 1, > + .family = NFPROTO_IPV4, > + .target = sysrq_tg4, > + .checkentry = sysrq_tg_check, > + .me = THIS_MODULE, > + }, > +#ifdef WITH_IPV6 > + { > + .name = "SYSRQ", > + .revision = 1, > + .family = NFPROTO_IPV6, > + .target = sysrq_tg6, > + .checkentry = sysrq_tg_check, > + .me = THIS_MODULE, > + }, > +#endif > +}; > + > +static void sysrq_crypto_exit(void) > +{ > +#ifdef WITH_CRYPTO > + if (sysrq_tfm) > + crypto_free_hash(sysrq_tfm); > + if (sysrq_digest) > + kfree(sysrq_digest); > + if (sysrq_hexdigest) > + kfree(sysrq_hexdigest); > + if (sysrq_digest_password) > + kfree(sysrq_digest_password); > +#endif > +} > + > +static int __init sysrq_crypto_init(void) > +{ > +#if defined(WITH_CRYPTO) > + struct timeval now; > + int ret; > + > + sysrq_tfm = crypto_alloc_hash(sysrq_hash, 0, CRYPTO_ALG_ASYNC); > + if (IS_ERR(sysrq_tfm)) { > + pr_err("Could not find or load %s hash\n", sysrq_hash); > + sysrq_tfm = NULL; > + ret = PTR_ERR(sysrq_tfm); > + goto fail; > + } > + sysrq_digest_size = crypto_hash_digestsize(sysrq_tfm); > + sysrq_digest = kmalloc(sysrq_digest_size, GFP_KERNEL); > + ret = -ENOMEM; > + if (sysrq_digest == NULL) > + goto fail; > + sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL); > + if (sysrq_hexdigest == NULL) > + goto fail; > + sysrq_digest_password = kmalloc(sizeof(sysrq_password), GFP_KERNEL); > + if (sysrq_digest_password == NULL) > + goto fail; > + do_gettimeofday(&now); > + sysrq_seqno = now.tv_sec; > + ret = xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); > + if (ret < 0) > + goto fail; > + return ret; > + > + fail: > + sysrq_crypto_exit(); > + return ret; > +#else > + pr_info("compiled without crypto\n"); > +#endif > + return -EINVAL; > +} > + > +static int __init sysrq_tg_init(void) > +{ > + if (sysrq_crypto_init() < 0) > + pr_info("starting without crypto\n"); > + return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); > +} > + > +static void __exit sysrq_tg_exit(void) > +{ > + sysrq_crypto_exit(); > + xt_unregister_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); > +} > + > +module_init(sysrq_tg_init); > +module_exit(sysrq_tg_exit); > +MODULE_DESCRIPTION("Xtables: triggering SYSRQ remotely"); > +MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("ipt_SYSRQ"); > +MODULE_ALIAS("ip6t_SYSRQ"); -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 12:59 ` Patrick McHardy @ 2010-04-21 13:07 ` Jan Engelhardt 2010-04-21 13:17 ` Patrick McHardy 2012-01-05 13:19 ` Shan Wei 1 sibling, 1 reply; 15+ messages in thread From: Jan Engelhardt @ 2010-04-21 13:07 UTC (permalink / raw) To: Patrick McHardy Cc: Netfilter Developer Mailing List, Linux Netdev List, John Haxby On Wednesday 2010-04-21 14:59, Patrick McHardy wrote: >Jan Engelhardt wrote: >> The SYSRQ target will allow to remotely invoke sysrq on the local >> machine. Authentication is by means of a pre-shared key that can >> either be transmitted plaintext or digest-secured. > >I really think this is pushing what netfilter is meant for a bit >far. Its basically abusing the firewall ruleset to offer a network >service. > >I can see that its useful to have this in the kernel instead of >userspace, but why isn't this implemented as a stand-alone module? >That seems like a better design to me and also makes it more useful >by not depending on netfilter. That sort of diverts from the earlier what-seemed-to-be-consensus. Oh well, I would not mind holding the single commit up as long as the rest isn't blocked too :-) ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 13:07 ` Jan Engelhardt @ 2010-04-21 13:17 ` Patrick McHardy 2010-04-21 13:35 ` Jan Engelhardt 0 siblings, 1 reply; 15+ messages in thread From: Patrick McHardy @ 2010-04-21 13:17 UTC (permalink / raw) To: Jan Engelhardt Cc: Netfilter Developer Mailing List, Linux Netdev List, John Haxby Jan Engelhardt wrote: > On Wednesday 2010-04-21 14:59, Patrick McHardy wrote: > >> Jan Engelhardt wrote: >>> The SYSRQ target will allow to remotely invoke sysrq on the local >>> machine. Authentication is by means of a pre-shared key that can >>> either be transmitted plaintext or digest-secured. >> I really think this is pushing what netfilter is meant for a bit >> far. Its basically abusing the firewall ruleset to offer a network >> service. >> >> I can see that its useful to have this in the kernel instead of >> userspace, but why isn't this implemented as a stand-alone module? >> That seems like a better design to me and also makes it more useful >> by not depending on netfilter. > > That sort of diverts from the earlier what-seemed-to-be-consensus. > > Oh well, I would not mind holding the single commit up as long as the > rest isn't blocked too :-) Then lets skip this one for now. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 13:17 ` Patrick McHardy @ 2010-04-21 13:35 ` Jan Engelhardt 2010-04-28 14:43 ` John Haxby 0 siblings, 1 reply; 15+ messages in thread From: Jan Engelhardt @ 2010-04-21 13:35 UTC (permalink / raw) To: Patrick McHardy Cc: Netfilter Developer Mailing List, Linux Netdev List, John Haxby On Wednesday 2010-04-21 15:17, Patrick McHardy wrote: >Jan Engelhardt wrote: >> On Wednesday 2010-04-21 14:59, Patrick McHardy wrote: >> >>> Jan Engelhardt wrote: >>>> The SYSRQ target will allow to remotely invoke sysrq on the local >>>> machine. Authentication is by means of a pre-shared key that can >>>> either be transmitted plaintext or digest-secured. >>> I really think this is pushing what netfilter is meant for a bit >>> far. Its basically abusing the firewall ruleset to offer a network >>> service. >>> >>> I can see that its useful to have this in the kernel instead of >>> userspace, but why isn't this implemented as a stand-alone module? >>> That seems like a better design to me and also makes it more useful >>> by not depending on netfilter. >> >> That sort of diverts from the earlier what-seemed-to-be-consensus. >> >> Oh well, I would not mind holding the single commit up as long as the >> rest isn't blocked too :-) > >Then lets skip this one for now. Well you raised the concern before -- namely that kdboe would have the very same feature. And yet, kdboe was not part of the kernel. Neither is the magical stand-alone module. I really prefer to have it in rather than out, because I know that's going to mess up maintenance-here-and-there. I'm already having a big time with xtables-addons that still carries xt_condition and SYSRQ for a while, and it does have some different code lines than the kernel copy. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 13:35 ` Jan Engelhardt @ 2010-04-28 14:43 ` John Haxby 2010-04-28 14:54 ` John Haxby 0 siblings, 1 reply; 15+ messages in thread From: John Haxby @ 2010-04-28 14:43 UTC (permalink / raw) To: Jan Engelhardt Cc: Patrick McHardy, Netfilter Developer Mailing List, Linux Netdev List On 21/04/10 14:35, Jan Engelhardt wrote: > On Wednesday 2010-04-21 15:17, Patrick McHardy wrote: > >> Jan Engelhardt wrote: >> >>> On Wednesday 2010-04-21 14:59, Patrick McHardy wrote: >>> >>> >>>> Jan Engelhardt wrote: >>>> >>>>> The SYSRQ target will allow to remotely invoke sysrq on the local >>>>> machine. Authentication is by means of a pre-shared key that can >>>>> either be transmitted plaintext or digest-secured. >>>>> >>>> I really think this is pushing what netfilter is meant for a bit >>>> far. Its basically abusing the firewall ruleset to offer a network >>>> service. >>>> >>>> I can see that its useful to have this in the kernel instead of >>>> userspace, but why isn't this implemented as a stand-alone module? >>>> That seems like a better design to me and also makes it more useful >>>> by not depending on netfilter. >>>> >>> That sort of diverts from the earlier what-seemed-to-be-consensus. >>> >>> Oh well, I would not mind holding the single commit up as long as the >>> rest isn't blocked too :-) >>> >> Then lets skip this one for now. >> > Well you raised the concern before -- namely that kdboe would have > the very same feature. And yet, kdboe was not part of the kernel. > Neither is the magical stand-alone module. > I really prefer to have it in rather than out, because I know > that's going to mess up maintenance-here-and-there. I'm already > having a big time with xtables-addons that still carries > xt_condition and SYSRQ for a while, and it does have some different > code lines than the kernel copy. > I have to agree with Jan here, but I'd like to raise some additional points. kdboe (or kgdboe) isn't part of the kernel and I don't think it necessarily fits all the use cases for xt_SYSRQ. The one I have in mind is where there is a non-kernel hacker whose machine has got into trouble. The poor harrassed sys admin (in this case) has configured netconsole and knows that sysrq-t and sysrq-m are useful as a first attempt at passing useful information to someone who knows what might be going on and that sysrq-c to get a crash dump will also be useful. (This represents quite a few of the better sys admins that I come across.) xt_SYSRQ is likewise easy to set up and easy to use. It's true that k(g)dboe would provide this kind of information provided that the debuginfo was present on the target machine and the environment was such that any sort of debugging over netconsole was sufficiently secure ... (is it at least as secure as the xt_SYSRQ controls?) I was running over the design of a standalone module in my head on the way in this morning. It seems fairly straightforward, but as I started adding in necessary requirements like limited IP addresses (which I know are not actually secure), limited interfaces (which are more secure in a controlled physical environment), user-space control and so on the more it was sounding as though it would just be a cut-down iptables. And then, of course, that begs the question "why don't you leave all that extra stuff to iptables?" My own interest in getting xt_SYSRQ into the mainline kernel is that it would then be easier to get it accepted in production kernels where it would make the poor beleaguered sys admin's life a little easier. That is, _some_ useful information or even a crash dump could be extracted from the machine before it's big red button time. jch ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-28 14:43 ` John Haxby @ 2010-04-28 14:54 ` John Haxby 2010-04-28 15:03 ` Jan Engelhardt 0 siblings, 1 reply; 15+ messages in thread From: John Haxby @ 2010-04-28 14:54 UTC (permalink / raw) To: Jan Engelhardt Cc: Patrick McHardy, Netfilter Developer Mailing List, Linux Netdev List On 28/04/10 15:43, John Haxby wrote: > > kdboe (or kgdboe) isn't part of the kernel and I don't think it > necessarily fits all the use cases for xt_SYSRQ. The one I have in > mind is where there is a non-kernel hacker whose machine has got into > trouble. The poor harrassed sys admin (in this case) has configured > netconsole and knows that sysrq-t and sysrq-m are useful as a first > attempt at passing useful information to someone who knows what might > be going on and that sysrq-c to get a crash dump will also be > useful. (This represents quite a few of the better sys admins that I > come across.) xt_SYSRQ is likewise easy to set up and easy to use. > It's true that k(g)dboe would provide this kind of information > provided that the debuginfo was present on the target machine and the > environment was such that any sort of debugging over netconsole was > sufficiently secure ... (is it at least as secure as the xt_SYSRQ > controls?) > I really must read what I've written more carefully. I should have gone on to say that I don't see that k(g)dboe will be viable in this use case although for someone actually debugging a kernel on a machine that they have access to xt_SYSRQ leaves an awful lot to be desired :-) But that isn't the common use-case I see -- the one I see is where the sys admins used to have a "crash trolley" which was a console and PS/2 keyboard which they could plug into a machine to get some information, but as many rack machines no longer have anything PS/2 and USB hot plug is unlikely to work on a sick machine we need a sufficiently light mechanism that it will work in most cases (xt_SYSRQ is careful to pre-allocate most of the resources it will need). And then I should have said that moving on to the possibility of a standalone module and that ... > I was running over the design of a standalone module in my head on the > way in this morning. It seems fairly straightforward, but as I > started adding in necessary requirements like limited IP addresses > (which I know are not actually secure), limited interfaces (which are > more secure in a controlled physical environment), user-space control > and so on the more it was sounding as though it would just be a > cut-down iptables. And then, of course, that begs the question "why > don't you leave all that extra stuff to iptables?" So unless I'm missing something obvious and different, I don't see that a standalone module is going to be lightweight enough to be acceptable. Sorry for not making filling this parts in earlier. jch ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-28 14:54 ` John Haxby @ 2010-04-28 15:03 ` Jan Engelhardt 2010-04-28 15:50 ` John Haxby 2010-07-25 16:49 ` Jan Engelhardt 0 siblings, 2 replies; 15+ messages in thread From: Jan Engelhardt @ 2010-04-28 15:03 UTC (permalink / raw) To: John Haxby Cc: Patrick McHardy, Netfilter Developer Mailing List, Linux Netdev List On Wednesday 2010-04-28 16:54, John Haxby wrote: > > use-case I see -- the one I see is where the sys admins used to have a "crash > trolley" which was a console and PS/2 keyboard which they could plug into a > machine to get some information, but as many rack machines no longer have > anything PS/2 and USB hot plug is unlikely to work on a sick machine Oh I can tell you stories... sometimes it's so dead in the water that the console unblanking would not work any more, rendering even any PS/2 useless. Stupid southbridge chipsets blowing up DMA :-) ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-28 15:03 ` Jan Engelhardt @ 2010-04-28 15:50 ` John Haxby 2010-07-25 16:49 ` Jan Engelhardt 1 sibling, 0 replies; 15+ messages in thread From: John Haxby @ 2010-04-28 15:50 UTC (permalink / raw) To: Jan Engelhardt Cc: Patrick McHardy, Netfilter Developer Mailing List, Linux Netdev List On 28/04/10 16:03, Jan Engelhardt wrote: > On Wednesday 2010-04-28 16:54, John Haxby wrote: > >> use-case I see -- the one I see is where the sys admins used to have a "crash >> trolley" which was a console and PS/2 keyboard which they could plug into a >> machine to get some information, but as many rack machines no longer have >> anything PS/2 and USB hot plug is unlikely to work on a sick machine >> > Oh I can tell you stories... sometimes it's so dead in the water that > the console unblanking would not work any more, rendering even any PS/2 > useless. Stupid southbridge chipsets blowing up DMA :-) > There's no hope in that case :-) Just take the machine out and give it a decent burial. On the other hand it's not uncommon to see reports that a machine has "hung totally" that include output from ping to show that it hasn't. Actually it's amazingly common to see this. And in just this situation xt_SYSRQ is still quite likely to work. jch ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-28 15:03 ` Jan Engelhardt 2010-04-28 15:50 ` John Haxby @ 2010-07-25 16:49 ` Jan Engelhardt 2010-07-25 18:13 ` John Haxby 1 sibling, 1 reply; 15+ messages in thread From: Jan Engelhardt @ 2010-07-25 16:49 UTC (permalink / raw) To: John Haxby Cc: Patrick McHardy, Netfilter Developer Mailing List, Linux Netdev List On Wednesday 2010-04-28 17:03, Jan Engelhardt wrote: >On Wednesday 2010-04-28 16:54, John Haxby wrote: >> >> use-case I see -- the one I see is where the sys admins used to have a "crash >> trolley" which was a console and PS/2 keyboard which they could plug into a >> machine to get some information, but as many rack machines no longer have >> anything PS/2 and USB hot plug is unlikely to work on a sick machine > I still think we should merge this. A hold-up like this would have never happened with staging drivers! ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-07-25 16:49 ` Jan Engelhardt @ 2010-07-25 18:13 ` John Haxby 0 siblings, 0 replies; 15+ messages in thread From: John Haxby @ 2010-07-25 18:13 UTC (permalink / raw) To: Jan Engelhardt Cc: Patrick McHardy, Netfilter Developer Mailing List, Linux Netdev List On 25 Jul 2010, at 17:49, Jan Engelhardt wrote: > > On Wednesday 2010-04-28 17:03, Jan Engelhardt wrote: >> On Wednesday 2010-04-28 16:54, John Haxby wrote: >>> >>> use-case I see -- the one I see is where the sys admins used to have a "crash >>> trolley" which was a console and PS/2 keyboard which they could plug into a >>> machine to get some information, but as many rack machines no longer have >>> anything PS/2 and USB hot plug is unlikely to work on a sick machine >> > > I still think we should merge this. A hold-up like this would have never > happened with staging drivers! > Me too. I've been caught up with other things, but Patrick's suggestion of a separate module only half worked out. Using encapsulation sockets, to get the sysrq handled in BH context works well except that there are no encapsulation sockets for IPv6. That, for me at least was a bit of a show stopper. In exploring this, though, I did correct one weakness in the protocol. An opportunistic hacker could take a sysrq packet and replay it to other hosts in the LAN in the hope that they have the same password (this is a realistic weakness rather than a theoretical one). To counter this I simply added the target IP address to the hash. Would you like me to submit that to xt_SYSRQ anyway? (In a couple of weeks I'm afraid, I'm out for a while.) jch ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ 2010-04-21 12:59 ` Patrick McHardy 2010-04-21 13:07 ` Jan Engelhardt @ 2012-01-05 13:19 ` Shan Wei 1 sibling, 0 replies; 15+ messages in thread From: Shan Wei @ 2012-01-05 13:19 UTC (permalink / raw) To: john.haxby Cc: Patrick McHardy, Jan Engelhardt, netfilter-devel, Linux Netdev List, prarit, David Miller Patrick McHardy wrote, at 2010/4/21 20:59: > I really think this is pushing what netfilter is meant for a bit > far. Its basically abusing the firewall ruleset to offer a network > service. > > I can see that its useful to have this in the kernel instead of > userspace, but why isn't this implemented as a stand-alone module? > That seems like a better design to me and also makes it more useful > by not depending on netfilter. It's very useful to remotely sysrq server machines in large data-center. Another solution by Prarit Bhargava is denied by David Miller, see discussion http://patchwork.ozlabs.org/patch/101284/. xt_SYSRQ solution is more convenience for us to use in inner system. I hope this solution can be merged to main tree. :-) But before that, this code need to be fixed (may be need more hashing enhancement). > >> Signed-off-by: Jan Engelhardt <jengelh@medozas.de> >> --- >> +module_param_string(password, sysrq_password, sizeof(sysrq_password), >> + S_IRUSR | S_IWUSR); >> +module_param_string(hash, sysrq_hash, sizeof(sysrq_hash), S_IRUSR); Read only. hash algorithm can be changed. >> +module_param_named(seqno, sysrq_seqno, long, S_IRUSR | S_IWUSR); sysrq_seqno is set using current time in sysrq_crypto_init. Whatever we set, sysrq_seqno is not equal to what we set. >> + if (len == 0) >> + return NF_DROP; malformed packet should be delivered to udp protocol handing. >> + if (i != 3) { >> + if (sysrq_debug) >> + pr_info("badly formatted request\n"); >> + return NF_DROP; Is there 1% possibility for user to send x,x,x,x, type data in udp payload? >> + do_gettimeofday(&now); >> + sysrq_seqno = now.tv_sec; >> + ret = xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); register target. >> +static int __init sysrq_tg_init(void) >> +{ >> + if (sysrq_crypto_init() < 0) >> + pr_info("starting without crypto\n"); >> + return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); register again. This will cause target list dead loop. -- Best Regards Shan Wei ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/2] netfilter: xtables: inclusion of xt_condition 2010-04-21 10:26 nf-next: sysrq and condition 20100421 Jan Engelhardt 2010-04-21 10:26 ` [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ Jan Engelhardt @ 2010-04-21 10:26 ` Jan Engelhardt 2010-04-21 13:07 ` Patrick McHardy 1 sibling, 1 reply; 15+ messages in thread From: Jan Engelhardt @ 2010-04-21 10:26 UTC (permalink / raw) To: kaber; +Cc: netfilter-devel xt_condition can be used by userspace to influence decisions in rules by means of togglable variables without having to reload the entire ruleset. Signed-off-by: Jan Engelhardt <jengelh@medozas.de> --- include/linux/netfilter/Kbuild | 1 + include/linux/netfilter/xt_condition.h | 14 ++ net/netfilter/Kconfig | 8 + net/netfilter/Makefile | 1 + net/netfilter/xt_condition.c | 243 ++++++++++++++++++++++++++++++++ 5 files changed, 267 insertions(+), 0 deletions(-) create mode 100644 include/linux/netfilter/xt_condition.h create mode 100644 net/netfilter/xt_condition.c diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 48767cd..6b67603 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -19,6 +19,7 @@ header-y += xt_TCPOPTSTRIP.h header-y += xt_TEE.h header-y += xt_TPROXY.h header-y += xt_comment.h +header-y += xt_condition.h header-y += xt_connbytes.h header-y += xt_connlimit.h header-y += xt_connmark.h diff --git a/include/linux/netfilter/xt_condition.h b/include/linux/netfilter/xt_condition.h new file mode 100644 index 0000000..4faf3ca --- /dev/null +++ b/include/linux/netfilter/xt_condition.h @@ -0,0 +1,14 @@ +#ifndef _XT_CONDITION_H +#define _XT_CONDITION_H + +#include <linux/types.h> + +struct xt_condition_mtinfo { + char name[31]; + __u8 invert; + + /* Used internally by the kernel */ + void *condvar __attribute__((aligned(8))); +}; + +#endif /* _XT_CONDITION_H */ diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index bfd9b6f..dd74e7d 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -624,6 +624,14 @@ config NETFILTER_XT_MATCH_COMMENT If you want to compile it as a module, say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. +config NETFILTER_XT_MATCH_CONDITION + tristate '"condition" match support' + depends on NETFILTER_ADVANCED + depends on PROC_FS + ---help--- + This option allows you to match firewall rules against condition + variables stored in the /proc/net/nf_condition directory. + config NETFILTER_XT_MATCH_CONNBYTES tristate '"connbytes" per-connection counter match support' depends on NF_CONNTRACK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index f032195..e75d5fa 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o # matches obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONDITION) += xt_condition.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o diff --git a/net/netfilter/xt_condition.c b/net/netfilter/xt_condition.c new file mode 100644 index 0000000..d3dcaa4 --- /dev/null +++ b/net/netfilter/xt_condition.c @@ -0,0 +1,243 @@ +/* + * "condition" match extension for Xtables + * + * Description: This module allows firewall rules to match using + * condition variables available through procfs. + * + * Authors: + * Stephane Ouellette <ouellettes [at] videotron ca>, 2002-10-22 + * Massimiliano Hofer <max [at] nucleus it>, 2006-05-15 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License; either version 2 + * or 3 of the License, as published by the Free Software Foundation. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/spinlock.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_condition.h> +#include <asm/uaccess.h> + +/* Defaults, these can be overridden on the module command-line. */ +static unsigned int condition_list_perms = S_IRUSR | S_IWUSR; +static unsigned int condition_uid_perms; +static unsigned int condition_gid_perms; + +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>"); +MODULE_AUTHOR("Massimiliano Hofer <max@nucleus.it>"); +MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); +MODULE_DESCRIPTION("Allows rules to match against condition variables"); +MODULE_LICENSE("GPL"); +module_param(condition_list_perms, uint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(condition_list_perms, "default permissions on /proc/net/nf_condition/* files"); +module_param(condition_uid_perms, uint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(condition_uid_perms, "default user owner of /proc/net/nf_condition/* files"); +module_param(condition_gid_perms, uint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(condition_gid_perms, "default group owner of /proc/net/nf_condition/* files"); +MODULE_ALIAS("ipt_condition"); +MODULE_ALIAS("ip6t_condition"); + +struct condition_variable { + struct list_head list; + struct proc_dir_entry *status_proc; + unsigned int refcount; + bool enabled; +}; + +/* proc_lock is a user context only semaphore used for write access */ +/* to the conditions' list. */ +static struct mutex proc_lock; + +static LIST_HEAD(conditions_list); +static struct proc_dir_entry *proc_net_condition; + +static int condition_proc_read(char __user *buffer, char **start, off_t offset, + int length, int *eof, void *data) +{ + const struct condition_variable *var = data; + + buffer[0] = var->enabled ? '1' : '0'; + buffer[1] = '\n'; + if (length >= 2) + *eof = true; + return 2; +} + +static int condition_proc_write(struct file *file, const char __user *buffer, + unsigned long length, void *data) +{ + struct condition_variable *var = data; + char newval; + + if (length > 0) { + if (get_user(newval, buffer) != 0) + return -EFAULT; + /* Match only on the first character */ + switch (newval) { + case '0': + var->enabled = false; + break; + case '1': + var->enabled = true; + break; + } + } + return length; +} + +static bool +condition_mt(const struct sk_buff *skb, const struct xt_match_param *par) +{ + const struct xt_condition_mtinfo *info = par->matchinfo; + const struct condition_variable *var = info->condvar; + bool x; + + rcu_read_lock(); + x = rcu_dereference(var->enabled); + rcu_read_unlock(); + + return x ^ info->invert; +} + +static int condition_mt_check(const struct xt_mtchk_param *par) +{ + struct xt_condition_mtinfo *info = par->matchinfo; + struct condition_variable *var; + + /* Forbid certain names */ + if (*info->name == '\0' || *info->name == '.' || + info->name[sizeof(info->name)-1] != '\0' || + memchr(info->name, '/', sizeof(info->name)) != NULL) { + pr_info("name not allowed or too long: \"%.*s\"\n", + (unsigned int)sizeof(info->name), info->name); + return -EINVAL; + } + /* + * Let's acquire the lock, check for the condition and add it + * or increase the reference counter. + */ + if (mutex_lock_interruptible(&proc_lock) != 0) + return -EINTR; + + list_for_each_entry(var, &conditions_list, list) { + if (strcmp(info->name, var->status_proc->name) == 0) { + ++var->refcount; + mutex_unlock(&proc_lock); + info->condvar = var; + return 0; + } + } + + /* At this point, we need to allocate a new condition variable. */ + var = kmalloc(sizeof(struct condition_variable), GFP_KERNEL); + if (var == NULL) { + mutex_unlock(&proc_lock); + return -ENOMEM; + } + + /* Create the condition variable's proc file entry. */ + var->status_proc = create_proc_entry(info->name, condition_list_perms, + proc_net_condition); + if (var->status_proc == NULL) { + kfree(var); + mutex_unlock(&proc_lock); + return -ENOMEM; + } + + var->refcount = 1; + var->enabled = false; + var->status_proc->data = var; + wmb(); + var->status_proc->read_proc = condition_proc_read; + var->status_proc->write_proc = condition_proc_write; + list_add_rcu(&var->list, &conditions_list); + var->status_proc->uid = condition_uid_perms; + var->status_proc->gid = condition_gid_perms; + mutex_unlock(&proc_lock); + info->condvar = var; + return 0; +} + +static void condition_mt_destroy(const struct xt_mtdtor_param *par) +{ + const struct xt_condition_mtinfo *info = par->matchinfo; + struct condition_variable *var = info->condvar; + + mutex_lock(&proc_lock); + if (--var->refcount == 0) { + list_del_rcu(&var->list); + remove_proc_entry(var->status_proc->name, proc_net_condition); + mutex_unlock(&proc_lock); + /* + * synchronize_rcu() would be good enough, but + * synchronize_net() guarantees that no packet + * will go out with the old rule after + * succesful removal. + */ + synchronize_net(); + kfree(var); + return; + } + mutex_unlock(&proc_lock); +} + +static struct xt_match condition_mt_reg __read_mostly = { + .name = "condition", + .revision = 1, + .family = NFPROTO_UNSPEC, + .matchsize = sizeof(struct xt_condition_mtinfo), + .match = condition_mt, + .checkentry = condition_mt_check, + .destroy = condition_mt_destroy, + .me = THIS_MODULE, +}; + +static const char *const dir_name = "nf_condition"; + +static int __net_init condnet_mt_init(struct net *net) +{ + int ret; + + proc_net_condition = proc_mkdir(dir_name, net->proc_net); + if (proc_net_condition == NULL) + return -EACCES; + + ret = xt_register_match(&condition_mt_reg); + if (ret < 0) { + remove_proc_entry(dir_name, net->proc_net); + return ret; + } + + return 0; +} + +static void __net_exit condnet_mt_exit(struct net *net) +{ + xt_unregister_match(&condition_mt_reg); + remove_proc_entry(dir_name, net->proc_net); +} + +static struct pernet_operations condition_mt_netops = { + .init = condnet_mt_init, + .exit = condnet_mt_exit, +}; + +static int __init condition_mt_init(void) +{ + mutex_init(&proc_lock); + return register_pernet_subsys(&condition_mt_netops); +} + +static void __exit condition_mt_exit(void) +{ + unregister_pernet_subsys(&condition_mt_netops); +} + +module_init(condition_mt_init); +module_exit(condition_mt_exit); -- 1.7.0.5 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] netfilter: xtables: inclusion of xt_condition 2010-04-21 10:26 ` [PATCH 2/2] netfilter: xtables: inclusion of xt_condition Jan Engelhardt @ 2010-04-21 13:07 ` Patrick McHardy 0 siblings, 0 replies; 15+ messages in thread From: Patrick McHardy @ 2010-04-21 13:07 UTC (permalink / raw) To: Jan Engelhardt; +Cc: netfilter-devel Jan Engelhardt wrote: > +static bool > +condition_mt(const struct sk_buff *skb, const struct xt_match_param *par) > +{ > + const struct xt_condition_mtinfo *info = par->matchinfo; > + const struct condition_variable *var = info->condvar; > + bool x; > + > + rcu_read_lock(); > + x = rcu_dereference(var->enabled); At the risk of repeating myself, why is this using rcu_dereference() for a boolean? > + rcu_read_unlock(); > + > + return x ^ info->invert; > +} > + > +static int condition_mt_check(const struct xt_mtchk_param *par) > +{ > + struct xt_condition_mtinfo *info = par->matchinfo; > + struct condition_variable *var; > + > + /* Forbid certain names */ > + if (*info->name == '\0' || *info->name == '.' || > + info->name[sizeof(info->name)-1] != '\0' || > + memchr(info->name, '/', sizeof(info->name)) != NULL) { > + pr_info("name not allowed or too long: \"%.*s\"\n", > + (unsigned int)sizeof(info->name), info->name); > + return -EINVAL; > + } > + /* > + * Let's acquire the lock, check for the condition and add it > + * or increase the reference counter. > + */ > + if (mutex_lock_interruptible(&proc_lock) != 0) > + return -EINTR; Also repeating myself - this seems like overkill, the section is short and the mutex should basically never be contended. > + list_for_each_entry(var, &conditions_list, list) { > + if (strcmp(info->name, var->status_proc->name) == 0) { > + ++var->refcount; > + mutex_unlock(&proc_lock); > + info->condvar = var; > + return 0; > + } > + } > + > + /* At this point, we need to allocate a new condition variable. */ > + var = kmalloc(sizeof(struct condition_variable), GFP_KERNEL); > + if (var == NULL) { > + mutex_unlock(&proc_lock); > + return -ENOMEM; > + } > + > + /* Create the condition variable's proc file entry. */ > + var->status_proc = create_proc_entry(info->name, condition_list_perms, > + proc_net_condition); > + if (var->status_proc == NULL) { > + kfree(var); > + mutex_unlock(&proc_lock); > + return -ENOMEM; > + } > + > + var->refcount = 1; > + var->enabled = false; > + var->status_proc->data = var; > + wmb(); Please always comment the use of memory barriers. > + var->status_proc->read_proc = condition_proc_read; > + var->status_proc->write_proc = condition_proc_write; > + list_add_rcu(&var->list, &conditions_list); Still using rcu list variants for no reason. > + var->status_proc->uid = condition_uid_perms; > + var->status_proc->gid = condition_gid_perms; > + mutex_unlock(&proc_lock); > + info->condvar = var; > + return 0; > +} > + > +static void condition_mt_destroy(const struct xt_mtdtor_param *par) > +{ > + const struct xt_condition_mtinfo *info = par->matchinfo; > + struct condition_variable *var = info->condvar; > + > + mutex_lock(&proc_lock); > + if (--var->refcount == 0) { > + list_del_rcu(&var->list); > + remove_proc_entry(var->status_proc->name, proc_net_condition); > + mutex_unlock(&proc_lock); > + /* > + * synchronize_rcu() would be good enough, but > + * synchronize_net() guarantees that no packet > + * will go out with the old rule after > + * succesful removal. > + */ > + synchronize_net(); > + kfree(var); > + return; > + } > + mutex_unlock(&proc_lock); > +} > + > +static struct xt_match condition_mt_reg __read_mostly = { > + .name = "condition", > + .revision = 1, > + .family = NFPROTO_UNSPEC, > + .matchsize = sizeof(struct xt_condition_mtinfo), > + .match = condition_mt, > + .checkentry = condition_mt_check, > + .destroy = condition_mt_destroy, > + .me = THIS_MODULE, > +}; > + > +static const char *const dir_name = "nf_condition"; > + > +static int __net_init condnet_mt_init(struct net *net) > +{ > + int ret; > + > + proc_net_condition = proc_mkdir(dir_name, net->proc_net); > + if (proc_net_condition == NULL) > + return -EACCES; > + > + ret = xt_register_match(&condition_mt_reg); > + if (ret < 0) { > + remove_proc_entry(dir_name, net->proc_net); > + return ret; I'm not sure whether you accidentally posted an old version or why there are none of the changes I asked for during the last review. matches are not registered per namespace. > + } > + > + return 0; > +} > + > +static void __net_exit condnet_mt_exit(struct net *net) > +{ > + xt_unregister_match(&condition_mt_reg); > + remove_proc_entry(dir_name, net->proc_net); > +} > + > +static struct pernet_operations condition_mt_netops = { > + .init = condnet_mt_init, > + .exit = condnet_mt_exit, > +}; > + > +static int __init condition_mt_init(void) > +{ > + mutex_init(&proc_lock); > + return register_pernet_subsys(&condition_mt_netops); > +} > + > +static void __exit condition_mt_exit(void) > +{ > + unregister_pernet_subsys(&condition_mt_netops); > +} > + > +module_init(condition_mt_init); > +module_exit(condition_mt_exit); ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2012-01-05 13:19 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-04-21 10:26 nf-next: sysrq and condition 20100421 Jan Engelhardt 2010-04-21 10:26 ` [PATCH 1/2] netfilter: xtables: inclusion of xt_SYSRQ Jan Engelhardt 2010-04-21 12:59 ` Patrick McHardy 2010-04-21 13:07 ` Jan Engelhardt 2010-04-21 13:17 ` Patrick McHardy 2010-04-21 13:35 ` Jan Engelhardt 2010-04-28 14:43 ` John Haxby 2010-04-28 14:54 ` John Haxby 2010-04-28 15:03 ` Jan Engelhardt 2010-04-28 15:50 ` John Haxby 2010-07-25 16:49 ` Jan Engelhardt 2010-07-25 18:13 ` John Haxby 2012-01-05 13:19 ` Shan Wei 2010-04-21 10:26 ` [PATCH 2/2] netfilter: xtables: inclusion of xt_condition Jan Engelhardt 2010-04-21 13:07 ` Patrick McHardy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).