1/* Kernel module to match various things tied to sockets associated with 2 locally generated outgoing packets. 3 4 Copyright (C) 2000,2001 Marc Boucher 5 */ 6#include <linux/module.h> 7#include <linux/skbuff.h> 8#include <linux/file.h> 9#include <net/sock.h> 10 11#include <linux/netfilter_ipv6/ip6t_owner.h> 12#include <linux/netfilter_ipv6/ip6_tables.h> 13 14MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 15MODULE_DESCRIPTION("IP6 tables owner matching module"); 16MODULE_LICENSE("GPL"); 17 18static int 19match_pid(const struct sk_buff *skb, pid_t pid) 20{ 21 struct task_struct *p; 22 struct files_struct *files; 23 int i; 24 25 read_lock(&tasklist_lock); 26 p = find_task_by_pid(pid); 27 if (!p) 28 goto out; 29 task_lock(p); 30 files = p->files; 31 if(files) { 32 read_lock(&files->file_lock); 33 for (i=0; i < files->max_fds; i++) { 34 if (fcheck_files(files, i) == skb->sk->socket->file) { 35 read_unlock(&files->file_lock); 36 task_unlock(p); 37 read_unlock(&tasklist_lock); 38 return 1; 39 } 40 } 41 read_unlock(&files->file_lock); 42 } 43 task_unlock(p); 44out: 45 read_unlock(&tasklist_lock); 46 return 0; 47} 48 49static int 50match_sid(const struct sk_buff *skb, pid_t sid) 51{ 52 struct task_struct *p; 53 struct file *file = skb->sk->socket->file; 54 int i, found=0; 55 56 read_lock(&tasklist_lock); 57 for_each_task(p) { 58 struct files_struct *files; 59 if (p->session != sid) 60 continue; 61 62 task_lock(p); 63 files = p->files; 64 if (files) { 65 read_lock(&files->file_lock); 66 for (i=0; i < files->max_fds; i++) { 67 if (fcheck_files(files, i) == file) { 68 found = 1; 69 break; 70 } 71 } 72 read_unlock(&files->file_lock); 73 } 74 task_unlock(p); 75 if(found) 76 break; 77 } 78 read_unlock(&tasklist_lock); 79 80 return found; 81} 82 83static int 84match(const struct sk_buff *skb, 85 const struct net_device *in, 86 const struct net_device *out, 87 const void *matchinfo, 88 int offset, 89 const void *hdr, 90 u_int16_t datalen, 91 int *hotdrop) 92{ 93 const struct ip6t_owner_info *info = matchinfo; 94 95 if (!skb->sk || !skb->sk->socket || !skb->sk->socket->file) 96 return 0; 97 98 if(info->match & IP6T_OWNER_UID) { 99 if((skb->sk->socket->file->f_uid != info->uid) ^ 100 !!(info->invert & IP6T_OWNER_UID)) 101 return 0; 102 } 103 104 if(info->match & IP6T_OWNER_GID) { 105 if((skb->sk->socket->file->f_gid != info->gid) ^ 106 !!(info->invert & IP6T_OWNER_GID)) 107 return 0; 108 } 109 110 if(info->match & IP6T_OWNER_PID) { 111 if (!match_pid(skb, info->pid) ^ 112 !!(info->invert & IP6T_OWNER_PID)) 113 return 0; 114 } 115 116 if(info->match & IP6T_OWNER_SID) { 117 if (!match_sid(skb, info->sid) ^ 118 !!(info->invert & IP6T_OWNER_SID)) 119 return 0; 120 } 121 122 return 1; 123} 124 125static int 126checkentry(const char *tablename, 127 const struct ip6t_ip6 *ip, 128 void *matchinfo, 129 unsigned int matchsize, 130 unsigned int hook_mask) 131{ 132 if (hook_mask 133 & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) { 134 printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n"); 135 return 0; 136 } 137 138 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info))) 139 return 0; 140 141 return 1; 142} 143 144static struct ip6t_match owner_match 145= { { NULL, NULL }, "owner", &match, &checkentry, NULL, THIS_MODULE }; 146 147static int __init init(void) 148{ 149 return ip6t_register_match(&owner_match); 150} 151 152static void __exit fini(void) 153{ 154 ip6t_unregister_match(&owner_match); 155} 156 157module_init(init); 158module_exit(fini); 159