commit 7ed2d25d54b696074c8e787a03a1513d245e8caa Author: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx> Date: Mon Jan 21 13:34:48 2008 +0100 [NETFILTER]: xt_socket: rename from xt_owner xt_owner matches against the ownership of a socket. Currently this only work in the output path when skb->sk is set. I recalled tproxy's xt_socket, which does an explicit socket for the input path and thought that this could be useful for xt_owner. Both modules would then do a lookup, so let's just combine the code into one module. This patch renames xt_owner to xt_socket; the tproxy bits and input path socket lookup will be added when tproxy gets merged. Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx> diff --git a/include/linux/netfilter/xt_owner.h b/include/linux/netfilter/xt_owner.h deleted file mode 100644 index eacd34e..0000000 --- a/include/linux/netfilter/xt_owner.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _XT_OWNER_MATCH_H -#define _XT_OWNER_MATCH_H - -enum { - XT_OWNER_UID = 1 << 0, - XT_OWNER_GID = 1 << 1, - XT_OWNER_SOCKET = 1 << 2, -}; - -struct xt_owner_match_info { - u_int32_t uid; - u_int32_t gid; - u_int8_t match, invert; -}; - -#endif /* _XT_OWNER_MATCH_H */ diff --git a/include/linux/netfilter/xt_socket.h b/include/linux/netfilter/xt_socket.h new file mode 100644 index 0000000..5d7abb0 --- /dev/null +++ b/include/linux/netfilter/xt_socket.h @@ -0,0 +1,16 @@ +#ifndef _LINUX_NETFILTER_XT_SOCKET_H +#define _LINUX_NETFILTER_XT_SOCKET_H 1 + +enum { + XT_SOCKET_UID = 1 << 0, + XT_SOCKET_GID = 1 << 1, + XT_SOCKET_EXISTS = 1 << 2, +}; + +struct xt_socket_mtinfo { + u_int32_t uid; + u_int32_t gid; + u_int8_t match, invert; +}; + +#endif /* _LINUX_NETFILTER_XT_SOCKET_H */ diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index daf5b88..06e98d1 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -620,15 +620,6 @@ config NETFILTER_XT_MATCH_MARK To compile it as a module, choose M here. If unsure, say N. -config NETFILTER_XT_MATCH_OWNER - tristate '"owner" match support' - depends on NETFILTER_XTABLES - depends on NETFILTER_ADVANCED - ---help--- - Socket owner matching allows you to match locally-generated packets - based on who created the socket: the user or group. It is also - possible to check whether a socket actually exists. - config NETFILTER_XT_MATCH_POLICY tristate 'IPsec "policy" match support' depends on NETFILTER_XTABLES && XFRM @@ -723,6 +714,15 @@ config NETFILTER_XT_MATCH_SCTP 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_SOCKET + tristate '"socket" and "owner" match support' + depends on NETFILTER_XTABLES + depends on NETFILTER_ADVANCED + ---help--- + Socket matching allows you to match locally-generated packets + based on who created the socket: the user or group. It is also + possible to check whether a socket actually exists. + config NETFILTER_XT_MATCH_STATE tristate '"state" match support' depends on NETFILTER_XTABLES diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index ea75083..551c1e9 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -68,7 +68,6 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o -obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o @@ -76,6 +75,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c deleted file mode 100644 index d382f9c..0000000 --- a/net/netfilter/xt_owner.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Kernel module to match various things tied to sockets associated with - * locally generated outgoing packets. - * - * (C) 2000 Marc Boucher <marc@xxxxxxx> - * - * Copyright © CC Computer Consultants GmbH, 2007 - * Contact: <jengelh@xxxxxxxxxxxxxxx> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/module.h> -#include <linux/skbuff.h> -#include <linux/file.h> -#include <net/sock.h> -#include <linux/netfilter/x_tables.h> -#include <linux/netfilter/xt_owner.h> -#include <linux/netfilter_ipv4/ipt_owner.h> -#include <linux/netfilter_ipv6/ip6t_owner.h> - -static bool -owner_mt_v0(const struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, const struct xt_match *match, - const void *matchinfo, int offset, unsigned int protoff, - bool *hotdrop) -{ - const struct ipt_owner_info *info = matchinfo; - const struct file *filp; - - if (skb->sk == NULL || skb->sk->sk_socket == NULL) - return false; - - filp = skb->sk->sk_socket->file; - if (filp == NULL) - return false; - - if (info->match & IPT_OWNER_UID) - if ((filp->f_uid != info->uid) ^ - !!(info->invert & IPT_OWNER_UID)) - return false; - - if (info->match & IPT_OWNER_GID) - if ((filp->f_gid != info->gid) ^ - !!(info->invert & IPT_OWNER_GID)) - return false; - - return true; -} - -static bool -owner_mt6_v0(const struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, const struct xt_match *match, - const void *matchinfo, int offset, unsigned int protoff, - bool *hotdrop) -{ - const struct ip6t_owner_info *info = matchinfo; - const struct file *filp; - - if (skb->sk == NULL || skb->sk->sk_socket == NULL) - return false; - - filp = skb->sk->sk_socket->file; - if (filp == NULL) - return false; - - if (info->match & IP6T_OWNER_UID) - if ((filp->f_uid != info->uid) ^ - !!(info->invert & IP6T_OWNER_UID)) - return false; - - if (info->match & IP6T_OWNER_GID) - if ((filp->f_gid != info->gid) ^ - !!(info->invert & IP6T_OWNER_GID)) - return false; - - return true; -} - -static bool -owner_mt(const struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, const struct xt_match *match, - const void *matchinfo, int offset, unsigned int protoff, - bool *hotdrop) -{ - const struct xt_owner_match_info *info = matchinfo; - const struct file *filp; - - if (skb->sk == NULL || skb->sk->sk_socket == NULL) - return (info->match ^ info->invert) == 0; - else if (info->match & info->invert & XT_OWNER_SOCKET) - /* - * Socket exists but user wanted ! --socket-exists. - * (Single ampersands intended.) - */ - return false; - - filp = skb->sk->sk_socket->file; - if (filp == NULL) - return ((info->match ^ info->invert) & - (XT_OWNER_UID | XT_OWNER_GID)) == 0; - - if (info->match & XT_OWNER_UID) - if ((filp->f_uid != info->uid) ^ - !!(info->invert & XT_OWNER_UID)) - return false; - - if (info->match & XT_OWNER_GID) - if ((filp->f_gid != info->gid) ^ - !!(info->invert & XT_OWNER_GID)) - return false; - - return true; -} - -static bool -owner_mt_check_v0(const char *tablename, const void *ip, - const struct xt_match *match, void *matchinfo, - unsigned int hook_mask) -{ - const struct ipt_owner_info *info = matchinfo; - - if (info->match & (IPT_OWNER_PID | IPT_OWNER_SID | IPT_OWNER_COMM)) { - printk(KERN_WARNING KBUILD_MODNAME - ": PID, SID and command matching is not " - "supported anymore\n"); - return false; - } - - return true; -} - -static bool -owner_mt6_check_v0(const char *tablename, const void *ip, - const struct xt_match *match, void *matchinfo, - unsigned int hook_mask) -{ - const struct ip6t_owner_info *info = matchinfo; - - if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { - printk(KERN_WARNING KBUILD_MODNAME - ": PID and SID matching is not supported anymore\n"); - return false; - } - - return true; -} - -static struct xt_match owner_mt_reg[] __read_mostly = { - { - .name = "owner", - .revision = 0, - .family = AF_INET, - .match = owner_mt_v0, - .matchsize = sizeof(struct ipt_owner_info), - .checkentry = owner_mt_check_v0, - .hooks = (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING), - .me = THIS_MODULE, - }, - { - .name = "owner", - .revision = 0, - .family = AF_INET6, - .match = owner_mt6_v0, - .matchsize = sizeof(struct ip6t_owner_info), - .checkentry = owner_mt6_check_v0, - .hooks = (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING), - .me = THIS_MODULE, - }, - { - .name = "owner", - .revision = 1, - .family = AF_INET, - .match = owner_mt, - .matchsize = sizeof(struct xt_owner_match_info), - .hooks = (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING), - .me = THIS_MODULE, - }, - { - .name = "owner", - .revision = 1, - .family = AF_INET6, - .match = owner_mt, - .matchsize = sizeof(struct xt_owner_match_info), - .hooks = (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING), - .me = THIS_MODULE, - }, -}; - -static int __init owner_mt_init(void) -{ - return xt_register_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg)); -} - -static void __exit owner_mt_exit(void) -{ - xt_unregister_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg)); -} - -module_init(owner_mt_init); -module_exit(owner_mt_exit); -MODULE_AUTHOR("Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>"); -MODULE_DESCRIPTION("Xtables: socket owner matching"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_owner"); -MODULE_ALIAS("ip6t_owner"); diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c new file mode 100644 index 0000000..de5116f --- /dev/null +++ b/net/netfilter/xt_socket.c @@ -0,0 +1,213 @@ +/* + * xt_socket - socket property match + * + * (C) 2000 Marc Boucher <marc@xxxxxxx> + * Copyright © CC Computer Consultants GmbH, 2007 - 2008 + * <jengelh@xxxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/file.h> +#include <net/sock.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_socket.h> +#include <linux/netfilter_ipv4/ipt_owner.h> +#include <linux/netfilter_ipv6/ip6t_owner.h> + +static bool +owner_mt_v0(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const struct xt_match *match, + const void *matchinfo, int offset, unsigned int protoff, + bool *hotdrop) +{ + const struct ipt_owner_info *info = matchinfo; + const struct file *filp; + + if (skb->sk == NULL || skb->sk->sk_socket == NULL) + return false; + + filp = skb->sk->sk_socket->file; + if (filp == NULL) + return false; + + if (info->match & IPT_OWNER_UID) + if ((filp->f_uid != info->uid) ^ + !!(info->invert & IPT_OWNER_UID)) + return false; + + if (info->match & IPT_OWNER_GID) + if ((filp->f_gid != info->gid) ^ + !!(info->invert & IPT_OWNER_GID)) + return false; + + return true; +} + +static bool +owner_mt6_v0(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const struct xt_match *match, + const void *matchinfo, int offset, unsigned int protoff, + bool *hotdrop) +{ + const struct ip6t_owner_info *info = matchinfo; + const struct file *filp; + + if (skb->sk == NULL || skb->sk->sk_socket == NULL) + return false; + + filp = skb->sk->sk_socket->file; + if (filp == NULL) + return false; + + if (info->match & IP6T_OWNER_UID) + if ((filp->f_uid != info->uid) ^ + !!(info->invert & IP6T_OWNER_UID)) + return false; + + if (info->match & IP6T_OWNER_GID) + if ((filp->f_gid != info->gid) ^ + !!(info->invert & IP6T_OWNER_GID)) + return false; + + return true; +} + +static bool +socket_mt(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const struct xt_match *match, + const void *matchinfo, int offset, unsigned int protoff, + bool *hotdrop) +{ + const struct xt_socket_mtinfo *info = matchinfo; + const struct file *filp; + const struct sock *sk; + + sk = skb->sk; + if (sk == NULL || sk->sk_socket == NULL) + return (info->match ^ info->invert) == 0; + else if (info->match & info->invert & XT_SOCKET_EXISTS) + /* + * Socket exists but user wanted ! --socket-exists. + * (Single ampersands intended.) + */ + return false; + + filp = sk->sk_socket->file; + if (filp == NULL) + return ((info->match ^ info->invert) & + (XT_SOCKET_UID | XT_SOCKET_GID)) == 0; + + if (info->match & XT_SOCKET_UID) + if ((filp->f_uid != info->uid) ^ + !!(info->invert & XT_SOCKET_UID)) + return false; + + if (info->match & XT_SOCKET_GID) + if ((filp->f_gid != info->gid) ^ + !!(info->invert & XT_SOCKET_GID)) + return false; + + return true; +} + +static bool +owner_mt_check_v0(const char *tablename, const void *ip, + const struct xt_match *match, void *matchinfo, + unsigned int hook_mask) +{ + const struct ipt_owner_info *info = matchinfo; + + if (info->match & (IPT_OWNER_PID | IPT_OWNER_SID | IPT_OWNER_COMM)) { + printk(KERN_WARNING KBUILD_MODNAME + ": PID, SID and command matching is not " + "supported anymore\n"); + return false; + } + + return true; +} + +static bool +owner_mt6_check_v0(const char *tablename, const void *ip, + const struct xt_match *match, void *matchinfo, + unsigned int hook_mask) +{ + const struct ip6t_owner_info *info = matchinfo; + + if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { + printk(KERN_WARNING KBUILD_MODNAME + ": PID and SID matching is not supported anymore\n"); + return false; + } + + return true; +} + +static struct xt_match socket_mt_reg[] __read_mostly = { + { + .name = "owner", + .revision = 0, + .family = AF_INET, + .match = owner_mt_v0, + .matchsize = sizeof(struct ipt_owner_info), + .checkentry = owner_mt_check_v0, + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING), + .me = THIS_MODULE, + }, + { + .name = "owner", + .revision = 0, + .family = AF_INET6, + .match = owner_mt6_v0, + .matchsize = sizeof(struct ip6t_owner_info), + .checkentry = owner_mt6_check_v0, + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING), + .me = THIS_MODULE, + }, + { + .name = "socket", + .revision = 0, + .family = AF_INET, + .match = socket_mt, + .matchsize = sizeof(struct xt_socket_mtinfo), + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING), + .me = THIS_MODULE, + }, + { + .name = "socket", + .revision = 0, + .family = AF_INET6, + .match = socket_mt, + .matchsize = sizeof(struct xt_socket_mtinfo), + .hooks = (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_POST_ROUTING), + .me = THIS_MODULE, + }, +}; + +static int __init socket_mt_init(void) +{ + return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); +} + +static void __exit socket_mt_exit(void) +{ + xt_unregister_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); +} + +module_init(socket_mt_init); +module_exit(socket_mt_exit); +MODULE_AUTHOR("Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>"); +MODULE_DESCRIPTION("Xtables: Socket owner matching"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_owner"); +MODULE_ALIAS("ip6t_owner"); +MODULE_ALIAS("ipt_socket"); +MODULE_ALIAS("ip6t_socket"); - To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html