[PATCH] IP hooks

From: James Morris (jmorrisat_private)
Date: Sat Jul 21 2001 - 10:27:33 PDT

  • Next message: James Morris: "[PATCH] net device hooks"

    On Fri, 20 Jul 2001, Chris Vance wrote:
    
    >
    > To that end, we are going to see what we can do with the netfilter code
    > rather than directly modifying the ip input/ouput
    > routines or modifying the sk_buff structure (which apparently would be
    > difficult to gain approval for).
    >
    
    Hi Chris, folks,
    
    Attached below is an initial patch which use Netfilter to implement
    access & audit hooks for IP-layer networking.
    
    It consists of a "glue" module which grabs every Netfilter hook twice,
    before and after packets are passed through the standard iptables-based
    packet filtering and mangling mechanisms.  (This is probably overkill, but
    it's difficult to know exactly which hooks and priorities implementations
    will want to use.  If needed, the code can be modified to accept
    parameters specifying which hooks and priorities to grab).  Once the
    packets have been hooked by Netfilter, they are passed to LSM as ip_ops
    calls.
    
    These calls correspond to IPv4 packets which pass through the following
    paths in the stack:
    
    	pre-routing
    	local input (to user process)
    	forwarding
    	local output (from user process)
    	post-routing
    
    Note that I've included Keith Owen's softirq bugfix for the 2.4.6-pre4/3
    kernels, which is needed for Netfilter applications and some other
    networking components.
    
    As far as I can see, the this patch will allow at least the selinux code
    to do what it needs to do at the IP layer.  Some further hooks may be
    required (not using Netfilter) to implement more capabilities calls, but
    the real purpose of this code is to have something for discussion.
    
    At this stage, it will probably only work as a module, and you need
    Netfilter enabled in the kernel configuration before it appears as an
    option in the Security menu.
    
    - James
    -- 
    James Morris
    <jmorrisat_private>
    
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/include/asm-i386/softirq.h lsm-w3/include/asm-i386/softirq.h
    --- lsm/include/asm-i386/softirq.h	Fri Jun 29 23:18:16 2001
    +++ lsm-w3/include/asm-i386/softirq.h	Sun Jul 22 02:54:12 2001
    @@ -36,13 +36,13 @@
     									\
     			".section .text.lock,\"ax\";"			\
     			"2: pushl %%eax; pushl %%ecx; pushl %%edx;"	\
    -			"call do_softirq;"				\
    +			"call %c1;"					\
     			"popl %%edx; popl %%ecx; popl %%eax;"		\
     			"jmp 1b;"					\
     			".previous;"					\
     									\
     		: /* no output */					\
    -		: "r" (ptr)						\
    +		: "r" (ptr), "i" (do_softirq)				\
     		/* no registers clobbered */ );				\
     } while (0)
    
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/include/linux/security.h lsm-w3/include/linux/security.h
    --- lsm/include/linux/security.h	Sat Jul 21 15:07:21 2001
    +++ lsm-w3/include/linux/security.h	Sun Jul 22 02:54:12 2001
    @@ -124,6 +124,24 @@
     struct socket_security_ops {
     };
    
    +struct sk_buff;
    +struct net_device;
    +typedef unsigned int (*ip_opfn)(unsigned int hooknum, struct sk_buff **skb,
    +                                const struct net_device *in, const struct net_device *out,
    +                                int (*okfn)(struct sk_buff *));
    +struct ip_security_ops {
    +	ip_opfn preroute_first;
    +	ip_opfn preroute_last;
    +	ip_opfn input_first;
    +	ip_opfn input_last;
    +	ip_opfn forward_first;
    +	ip_opfn forward_last;
    +	ip_opfn output_first;
    +	ip_opfn output_last;
    +	ip_opfn postroute_first;
    +	ip_opfn postroute_last;
    +};
    +
     struct module_security_ops {
      	int  (* create_module)		(const char *name_user, size_t size);
      	int  (* init_module)		(const char *name_user, struct module *mod_user);
    @@ -197,6 +215,7 @@
     	struct file_security_ops	* file_ops;
     	struct task_security_ops	* task_ops;
     	struct socket_security_ops	* socket_ops;
    +	struct ip_security_ops		* ip_ops;
     	struct module_security_ops 	* module_ops;
     	struct ipc_security_ops		* ipc_ops;
     	struct msg_msg_security_ops	* msg_msg_ops;
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/kernel/Makefile lsm-w3/kernel/Makefile
    --- lsm/kernel/Makefile	Thu Jun 28 04:01:57 2001
    +++ lsm-w3/kernel/Makefile	Sun Jul 22 00:47:12 2001
    @@ -22,6 +22,8 @@
     obj-$(CONFIG_PM) += pm.o
     obj-$(CONFIG_CAPABILITIES) += capability_plug.o
    
    +obj-$(CONFIG_LSM_IP) += ip_lsm_glue.o
    +
     ifneq ($(CONFIG_IA64),y)
     # According to Alan Modra <alanat_private>, the -fno-omit-frame-pointer is
     # needed for x86 only.  Why this used to be enabled for all architectures is beyond
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/kernel/capability_plug.c lsm-w3/kernel/capability_plug.c
    --- lsm/kernel/capability_plug.c	Sat Jul 21 15:07:21 2001
    +++ lsm-w3/kernel/capability_plug.c	Sun Jul 22 02:43:08 2001
    @@ -19,6 +19,7 @@
     #include <linux/slab.h>
     #include <linux/smp_lock.h>
     #include <asm/uaccess.h>
    +#include <linux/netfilter.h>
    
     /* flag to keep track of how we were registered */
     static int secondary;
    @@ -295,6 +296,37 @@
     	return;
     }
    
    +static unsigned int cap_ip_preroute_first	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_preroute_last	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_input_first		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_input_last		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_forward_first	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_forward_last		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_output_first		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_output_last		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_postroute_first	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int cap_ip_postroute_last	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +
     static int cap_module_create_module	(const char *name_user, size_t size)			{return 0;}
     static int cap_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
     static int cap_module_delete_module	(const char *name_user)					{return 0;}
    @@ -404,6 +436,19 @@
    
     static struct socket_security_ops cap_socket_ops = {};
    
    +static struct ip_security_ops cap_ip_ops = {
    +	preroute_first:		cap_ip_preroute_first,
    +	preroute_last:		cap_ip_preroute_last,
    +	input_first:		cap_ip_input_first,
    +	input_last:		cap_ip_input_last,
    +	forward_first:		cap_ip_forward_first,
    +	forward_last:		cap_ip_forward_last,
    +	output_first:		cap_ip_output_first,
    +	output_last:		cap_ip_output_last,
    +	postroute_first:	cap_ip_postroute_first,
    +	postroute_last:		cap_ip_postroute_last,
    +};
    +
     static struct module_security_ops cap_module_ops = {
     	create_module:	cap_module_create_module,
     	init_module:	cap_module_init_module,
    @@ -475,6 +520,7 @@
     	file_ops:		&cap_file_ops,
     	task_ops:		&cap_task_ops,
     	socket_ops:		&cap_socket_ops,
    +	ip_ops:			&cap_ip_ops,
     	module_ops:		&cap_module_ops,
     	ipc_ops:		&cap_ipc_ops,
     	msg_msg_ops:		&cap_msg_ops,
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/kernel/ip_lsm_glue.c lsm-w3/kernel/ip_lsm_glue.c
    --- lsm/kernel/ip_lsm_glue.c	Thu Jan  1 10:00:00 1970
    +++ lsm-w3/kernel/ip_lsm_glue.c	Sun Jul 22 02:50:12 2001
    @@ -0,0 +1,152 @@
    +/*
    + * Nefilter IPv4 Operations Glue Module for LSM
    + *
    + * Copyright (c) 2001 James Morris <jmorrisat_private>
    + * This code is GPL.
    + *
    + */
    +#include <linux/config.h>
    +#include <linux/module.h>
    +#include <linux/security.h>
    +#include <linux/netfilter.h>
    +#include <linux/netfilter_ipv4.h>
    +
    +#define NF_IP_PRI_LSM_FIRST (NF_IP_PRI_FIRST + 20)
    +#define NF_IP_PRI_LSM_LAST  (NF_IP_PRI_LAST - 20)
    +
    +static unsigned int
    +preroute_first(unsigned int hooknum, struct sk_buff **pskb,
    +               const struct net_device *in, const struct net_device *out,
    +               int (*okfn)(struct sk_buff *))
    +{
    +	return security_ops->ip_ops->preroute_first(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +preroute_last(unsigned int hooknum, struct sk_buff **pskb,
    +              const struct net_device *in, const struct net_device *out,
    +              int (*okfn)(struct sk_buff *))
    +{
    +	return security_ops->ip_ops->preroute_last(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +input_first(unsigned int hooknum, struct sk_buff **pskb,
    +            const struct net_device *in, const struct net_device *out,
    +            int (*okfn)(struct sk_buff *))
    +{
    +	 return security_ops->ip_ops->input_first(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +input_last(unsigned int hooknum, struct sk_buff **pskb,
    +           const struct net_device *in, const struct net_device *out,
    +           int (*okfn)(struct sk_buff *))
    +{
    +	return security_ops->ip_ops->input_last(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +forward_first(unsigned int hooknum, struct sk_buff **pskb,
    +              const struct net_device *in, const struct net_device *out,
    +              int (*okfn)(struct sk_buff *))
    +{
    +        return security_ops->ip_ops->forward_first(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +forward_last(unsigned int hooknum, struct sk_buff **pskb,
    +             const struct net_device *in, const struct net_device *out,
    +             int (*okfn)(struct sk_buff *))
    +{
    +        return security_ops->ip_ops->forward_last(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +output_first(unsigned int hooknum, struct sk_buff **pskb,
    +             const struct net_device *in, const struct net_device *out,
    +             int (*okfn)(struct sk_buff *))
    +{
    +        return security_ops->ip_ops->output_first(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +output_last(unsigned int hooknum, struct sk_buff **pskb,
    +            const struct net_device *in, const struct net_device *out,
    +            int (*okfn)(struct sk_buff *))
    +{
    +        return security_ops->ip_ops->output_last(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +postroute_first(unsigned int hooknum, struct sk_buff **pskb,
    +                const struct net_device *in, const struct net_device *out,
    +                int (*okfn)(struct sk_buff *))
    +{
    +        return security_ops->ip_ops->postroute_first(hooknum, pskb, in, out, okfn);
    +}
    +
    +static unsigned int
    +postroute_last(unsigned int hooknum, struct sk_buff **pskb,
    +               const struct net_device *in, const struct net_device *out,
    +               int (*okfn)(struct sk_buff *))
    +{
    +        return security_ops->ip_ops->postroute_last(hooknum, pskb, in, out, okfn);
    +}
    +
    +static struct nf_hook_ops lsm_ip_ops[] = {
    +	{ { NULL, NULL }, preroute_first,
    +	PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_LSM_FIRST },
    +
    +	{ { NULL, NULL }, preroute_last,
    +	PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_LSM_LAST },
    +
    +	{ { NULL, NULL }, input_first,
    +	PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LSM_FIRST },
    +
    +	{ { NULL, NULL }, input_last,
    +	PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LSM_LAST },
    +
    +	{ { NULL, NULL }, forward_first,
    +	PF_INET, NF_IP_FORWARD, NF_IP_PRI_LSM_FIRST },
    +
    +	{ { NULL, NULL }, forward_last,
    +	PF_INET, NF_IP_FORWARD, NF_IP_PRI_LSM_LAST },
    +
    +	{ { NULL, NULL }, output_first,
    +	PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_LSM_FIRST },
    +
    +	{ { NULL, NULL }, output_last,
    +	PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_LSM_LAST },
    +
    +	{ { NULL, NULL }, postroute_first,
    +	PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_LSM_FIRST },
    +
    +	{ { NULL, NULL }, postroute_last,
    +	PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_LSM_LAST }
    +};
    +
    +static int __init init(void)
    +{
    +	int i;
    +
    +	/* Hook registration never returns error (for now) */
    +	for (i = 0; i < sizeof(lsm_ip_ops)/sizeof(struct nf_hook_ops); i++)
    +		nf_register_hook(&lsm_ip_ops[i]);
    +
    +	return 0;
    +}
    +
    +static void __exit fini(void)
    +{
    +	unsigned int i;
    +
    +	for (i = 0; i < sizeof(lsm_ip_ops)/sizeof(struct nf_hook_ops); i++)
    +		nf_unregister_hook(&lsm_ip_ops[i]);
    +}
    +
    +module_init(init);
    +module_exit(fini);
    +
    +MODULE_DESCRIPTION("Nefilter IPv4 Operations Glue for Linux Security Module");
    +
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/kernel/security.c lsm-w3/kernel/security.c
    --- lsm/kernel/security.c	Sat Jul 21 15:07:21 2001
    +++ lsm-w3/kernel/security.c	Sun Jul 22 02:37:05 2001
    @@ -30,7 +30,7 @@
    
     #include <linux/module.h>
     #include <linux/sysctl.h>
    -
    +#include <linux/netfilter.h>
    
    
    
    @@ -132,6 +132,39 @@
    
     static void dummy_task_kmod_set_label	(void)	                {return;}
    
    +
    +static unsigned int dummy_ip_preroute_first 	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_preroute_last	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_input_first	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_input_last		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_forward_first	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_forward_last	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_output_first		(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_output_last	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_postroute_first	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +static unsigned int dummy_ip_postroute_last	(unsigned int hooknum, struct sk_buff **pskb,
    +                                                 const struct net_device *in, const struct net_device *out,
    +                                                 int (*okfn)(struct sk_buff *)) {return NF_ACCEPT;}
    +
    +
     static int dummy_module_create_module	(const char *name_user, size_t size)			{return 0;}
     static int dummy_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
     static int dummy_module_delete_module	(const char *name_user)					{return 0;}
    @@ -239,6 +272,19 @@
    
     static struct socket_security_ops dummy_socket_ops = {};
    
    +static struct ip_security_ops dummy_ip_ops = {
    +	preroute_first:		dummy_ip_preroute_first,
    +	preroute_last:		dummy_ip_preroute_last,
    +	input_first:		dummy_ip_input_first,
    +	input_last:		dummy_ip_input_last,
    +	forward_first:		dummy_ip_forward_first,
    +	forward_last:		dummy_ip_forward_last,
    +	output_first:		dummy_ip_output_first,
    +	output_last:		dummy_ip_output_last,
    +	postroute_first:	dummy_ip_postroute_first,
    +	postroute_last:		dummy_ip_postroute_last,
    +};
    +
     static struct module_security_ops dummy_module_ops = {
     	create_module:	dummy_module_create_module,
     	init_module:	dummy_module_init_module,
    @@ -310,6 +356,7 @@
     	file_ops:		&dummy_file_ops,
     	task_ops:		&dummy_task_ops,
     	socket_ops:		&dummy_socket_ops,
    +	ip_ops:			&dummy_ip_ops,
     	ipc_ops:		&dummy_ipc_ops,
     	module_ops:		&dummy_module_ops,
     	msg_msg_ops:		&dummy_msg_msg_ops,
    @@ -380,6 +427,7 @@
     	    !ops->file_ops ||
     	    !ops->task_ops ||
     	    !ops->socket_ops ||
    +	    !ops->ip_ops ||
     	    !ops->module_ops ||
     	    !ops->ipc_ops ||
     	    !ops->msg_msg_ops ||
    diff -urN --exclude SCCS --exclude BitKeeper --exclude ChangeSet lsm/security/Config.in lsm-w3/security/Config.in
    --- lsm/security/Config.in	Thu Jul  5 15:28:18 2001
    +++ lsm-w3/security/Config.in	Sun Jul 22 00:17:51 2001
    @@ -4,5 +4,5 @@
     mainmenu_option next_comment
     comment 'Security options'
     tristate 'Capabilities Support' CONFIG_CAPABILITIES
    -
    +dep_tristate 'IP Networking Support' CONFIG_LSM_IP $CONFIG_NETFILTER
     endmenu
    
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Sat Jul 21 2001 - 10:29:59 PDT