public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
To: linux-kernel@vger.kernel.org
Subject: [PATCH 2.6 NETFILTER] new netfilter module ipt_program.c
Date: Sat, 11 Sep 2004 13:41:06 +0100	[thread overview]
Message-ID: <20040911124106.GD24787@lkcl.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 969 bytes --]

decided to put this into a separate module.  based on ipt_owner.c.
does full program's pathname.  like ipt_owner, only suitable for
outgoing connections.

userspace-netfilter-patch sent to bugs.debian.org (270852).

as was kindly pointed out already, dealing with per-program
per-packet filtering is at least O(N*M) and some cacheing
would help.

... but it's better than O(N*M*L) in userspace (in fireflier's
present ip_queueing userspace code).

issue of where new function proc_task_dentry_lookup() should
go is still outstanding and i don't have the knowledge or authority
to say or even advise most appropriate location.

l.

-- 
--
Truth, honesty and respect are rare commodities that all spring from
the same well: Love.  If you love yourself and everyone and everything
around you, funnily and coincidentally enough, life gets a lot better.
--
<a href="http://lkcl.net">      lkcl.net      </a> <br />
<a href="mailto:lkcl@lkcl.net"> lkcl@lkcl.net </a> <br />


[-- Attachment #2: f --]
[-- Type: text/plain, Size: 1570 bytes --]

Index: net/ipv4/netfilter/Kconfig
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/net/ipv4/netfilter/Kconfig,v
retrieving revision 1.1.1.7
diff -u -u -r1.1.1.7 Kconfig
--- net/ipv4/netfilter/Kconfig	13 May 2004 18:03:22 -0000	1.1.1.7
+++ net/ipv4/netfilter/Kconfig	11 Sep 2004 12:17:53 -0000
@@ -256,6 +256,15 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_MATCH_PROGRAM
+	tristate "Full program pathname match support"
+	depends on IP_NF_IPTABLES
+	help
+	  Packet program name matching allows you to match locally-generated packets
+	  based on the full path name of the program that generated them.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_MATCH_OWNER
 	tristate "Owner match support"
 	depends on IP_NF_IPTABLES
Index: net/ipv4/netfilter/Makefile
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/net/ipv4/netfilter/Makefile,v
retrieving revision 1.1.1.3
diff -u -u -r1.1.1.3 Makefile
--- net/ipv4/netfilter/Makefile	13 May 2004 18:03:22 -0000	1.1.1.3
+++ net/ipv4/netfilter/Makefile	11 Sep 2004 12:17:53 -0000
@@ -50,6 +50,7 @@
 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+obj-$(CONFIG_IP_NF_MATCH_PROGRAM) += ipt_program.o
 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
 
 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
Index: security/selinux/hooks.c

[-- Attachment #3: ipt_program.h --]
[-- Type: text/x-chdr, Size: 572 bytes --]

#ifndef _IPT_PROGRAM_H
#define _IPT_PROGRAM_H

/* lkcl: whilst most people would care about path names being their
 * full length; whilst some people would want code that allocated
 * the program name in a dynamic size buffer, i don't give a stuff:
 * i just need something that works, and 256 chars is plenty to
 * fit "/usr/lib/mozilla-firefox/bin/firefox-bin" and "/usr/bin/lynx"
 * and "/usr/bin/kdeinit".
 */
#define IPT_PROGNAME_SZ 256

struct ipt_program_info {

	char full_exe_path[IPT_PROGNAME_SZ];

    u_int8_t invert;	/* flags */
};

#endif /*_IPT_PROGRAM_H*/

[-- Attachment #4: ipt_program.c --]
[-- Type: text/x-csrc, Size: 4609 bytes --]

/* Kernel module to match the program name tied to sockets associated with
   locally generated outgoing packets.
   
   */

/*
 * (C) 2004 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 *
 * 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.
 *
 * Module based on ipt_owner.c, by Mark Boucher.
 *
 * (C) 2000 Marc Boucher <marc@mbsi.ca>
 */

#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/file.h>
#include <linux/rwsem.h>
#include <linux/mount.h>
#include <linux/dcache.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <net/sock.h>

#include <linux/netfilter_ipv4/ipt_program.h>
#include <linux/netfilter_ipv4/ip_tables.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luke Kenneth Casson Leighton <lkcl@lkcl.net>");
MODULE_DESCRIPTION("iptables program match");

/* lkcl: this function is in fs/proc/base.c.  it's a generic function
 * derived from proc_exe_link().  it's inappropriate to leave that
 * function in fs/proc/base.c.  but i don't care: i don't have the
 * knowledge to say where it should go.  therefore i'm leaving
 * it in fs/proc/base.c.
 */
extern int proc_task_dentry_lookup(struct task_struct *task,
		                           struct dentry **dentry, 
								   struct vfsmount **mnt);

/*
 * look up the dentry (for the inode) of the task's executable,
 * plus lookup the mountpoint of the filesystem from where that
 * executable came from.   then do exactly the same socket checking
 * that all the other checks seem to be doing.
 */
static int proc_exe_check(struct task_struct *task, 
		                  const char *prog_full_name)
{
    int result;
	struct vfsmount *mnt;
    struct dentry *dentry;
	char exe_path[IPT_PROGNAME_SZ];
	char *p;

	result = proc_task_dentry_lookup(task, &dentry, &mnt);
	if (result != 0)
		return result;

	/* turn the task info (dentry + mountpoint) into a program name... */
	p = d_path(dentry, mnt, exe_path, sizeof(exe_path));
    if (p == ERR_PTR(-ENAMETOOLONG))
		return -1;

    printk("ipt_program: program name %s\n", prog_full_name);
	return strncmp(p, prog_full_name, sizeof(exe_path));
}

static int
match_inode(const struct sk_buff *skb, const char *prog_full_name)
{
	struct task_struct *g, *p;
	struct files_struct *files;
	int i;

	read_lock(&tasklist_lock);
	do_each_thread(g, p) {

		if (proc_exe_check(p, prog_full_name))
			continue;

        //printk("ipt_program: program name %s matched, now looking for socket...\n", prog_full_name);

		task_lock(p);
		files = p->files;
		if(files) {
			spin_lock(&files->file_lock);
			for (i=0; i < files->max_fds; i++) {
				if (fcheck_files(files, i) ==
				    skb->sk->sk_socket->file) {
					spin_unlock(&files->file_lock);
					task_unlock(p);
					read_unlock(&tasklist_lock);
					printk("ipt_program: program name %s matched\n", prog_full_name);
					return 1;
				}
			}
			spin_unlock(&files->file_lock);
		}
		task_unlock(p);
	} while_each_thread(g, p);
	read_unlock(&tasklist_lock);
	return 0;
}


static int
match(const struct sk_buff *skb,
      const struct net_device *in,
      const struct net_device *out,
      const void *matchinfo,
      int offset,
      int *hotdrop)
{
	const struct ipt_program_info *info = matchinfo;

    printk("ipt_program...\n");

	if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
	{
    	printk("ipt_program: not enough info, no sk, no sk_socket, no file\n");
		return 0;
	}

	if (!match_inode(skb, info->full_exe_path) ^
		    !!info->invert)
		return 0;

	return 1;
}

static int
checkentry(const char *tablename,
           const struct ipt_ip *ip,
           void *matchinfo,
           unsigned int matchsize,
           unsigned int hook_mask)
{
        if (hook_mask
            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
                printk("ipt_program: warning - code based on ipt_owner, which is only valid for LOCAL_OUT or POST_ROUTING.  continuing at your own risk!\n");
                /*return 0;*/
        }

	if (matchsize != IPT_ALIGN(sizeof(struct ipt_program_info))) {
		printk("Matchsize %u != %Zu\n", matchsize,
		       IPT_ALIGN(sizeof(struct ipt_program_info)));
		return 0;
	}

	return 1;
}

static struct ipt_match program_match = {
	.name		= "program",
	.match		= &match,
	.checkentry	= &checkentry,
	.me		= THIS_MODULE,
};

static int __init init(void)
{
	return ipt_register_match(&program_match);
}

static void __exit fini(void)
{
	ipt_unregister_match(&program_match);
}

module_init(init);
module_exit(fini);

             reply	other threads:[~2004-09-11 12:30 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-09-11 12:41 Luke Kenneth Casson Leighton [this message]
2004-09-11 12:51 ` [PATCH 2.6 NETFILTER] new netfilter module ipt_program.c Patrick McHardy
2004-09-11 13:29   ` Luke Kenneth Casson Leighton
2004-09-11 13:34     ` Luke Kenneth Casson Leighton
2004-09-11 14:36       ` Patrick McHardy
2004-09-11 17:57         ` Luke Kenneth Casson Leighton
2004-09-11 14:49   ` Gianni Tedesco
2004-09-11 17:36     ` Luke Kenneth Casson Leighton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040911124106.GD24787@lkcl.net \
    --to=lkcl@lkcl.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox