diff -Nru linux-2.4.22.orig/include/linux/if.h linux-2.4.22/include/linux/if.h --- linux-2.4.22.orig/include/linux/if.h 2003-06-13 10:51:38.000000000 -0400 +++ linux-2.4.22/include/linux/if.h 2003-10-25 00:45:32.000000000 -0400 @@ -138,6 +138,7 @@ struct ifmap ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; + int ifru_gid; char * ifru_data; struct if_settings ifru_settings; } ifr_ifru; @@ -146,6 +147,7 @@ #define ifr_name ifr_ifrn.ifrn_name /* interface name */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ #define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_gid ifr_ifru.ifru_gid /* gid of interface */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ diff -Nru linux-2.4.22.orig/include/linux/inetdevice.h linux-2.4.22/include/linux/inetdevice.h --- linux-2.4.22.orig/include/linux/inetdevice.h 2003-08-25 07:44:44.000000000 -0400 +++ linux-2.4.22/include/linux/inetdevice.h 2003-10-25 00:45:32.000000000 -0400 @@ -68,6 +68,7 @@ (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects))) #define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter) +#define MAX_GID 100 struct in_ifaddr { @@ -82,7 +83,10 @@ unsigned char ifa_flags; unsigned char ifa_prefixlen; char ifa_label[IFNAMSIZ]; + int ifa_gid; }; +extern struct in_ifaddr *ip_dev_find_alias(u32 addr); +extern int check_bind_perm(u32 addr); extern int register_inetaddr_notifier(struct notifier_block *nb); extern int unregister_inetaddr_notifier(struct notifier_block *nb); diff -Nru linux-2.4.22.orig/include/linux/sockios.h linux-2.4.22/include/linux/sockios.h --- linux-2.4.22.orig/include/linux/sockios.h 2003-06-13 10:51:39.000000000 -0400 +++ linux-2.4.22/include/linux/sockios.h 2003-10-25 00:45:32.000000000 -0400 @@ -129,6 +129,10 @@ #define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ +/* Device GID information */ +#define SIOCGIFGID 0x89F2 +#define SIOCSIFGID 0x89F3 + /* * These 16 ioctl calls are protocol private */ diff -Nru linux-2.4.22.orig/net/ipv4/Config.in linux-2.4.22/net/ipv4/Config.in --- linux-2.4.22.orig/net/ipv4/Config.in 2003-08-25 07:44:44.000000000 -0400 +++ linux-2.4.22/net/ipv4/Config.in 2003-10-25 00:45:32.000000000 -0400 @@ -1,6 +1,7 @@ # # IP configuration # +bool ' IP: GID Property' CONFIG_IP_GID_PROPERTY bool ' IP: multicasting' CONFIG_IP_MULTICAST bool ' IP: advanced router' CONFIG_IP_ADVANCED_ROUTER if [ "$CONFIG_IP_ADVANCED_ROUTER" = "y" ]; then diff -Nru linux-2.4.22.orig/net/ipv4/af_inet.c linux-2.4.22/net/ipv4/af_inet.c --- linux-2.4.22.orig/net/ipv4/af_inet.c 2003-06-13 10:51:39.000000000 -0400 +++ linux-2.4.22/net/ipv4/af_inet.c 2003-10-25 00:45:32.000000000 -0400 @@ -257,6 +257,20 @@ return sk->prot->getsockopt(sk,level,optname,optval,optlen); } +#ifdef CONFIG_IP_GID_PROPERTY +int check_bind_perm(u32 addr) { + struct in_ifaddr *ifa = ip_dev_find_alias(addr); + + /* the first MAX_GID gid's are for daemons etc... */ + if (ifa && ifa->ifa_gid && current->gid > MAX_GID && + current->gid != ifa->ifa_gid) { + printk("[%s]: bind denied for user UID(%d) GID(%d) PID(%d)\n", + ifa->ifa_label, current->uid, current->gid, current->pid); + return -EACCES; + } + return 0; +} +#endif /* * Automatically bind an unbound socket. */ @@ -266,6 +280,12 @@ /* We may need to bind the socket. */ lock_sock(sk); if (sk->num == 0) { +#ifdef CONFIG_IP_GID_PROPERTY + if (check_bind_perm(0)) { + release_sock(sk); + return -EACCES; + } +#endif if (sk->prot->get_port(sk, 0) != 0) { release_sock(sk); return -EAGAIN; @@ -481,7 +501,10 @@ /* If the socket has its own bind function then use it. (RAW) */ if(sk->prot->bind) return sk->prot->bind(sk, uaddr, addr_len); - +#ifdef CONFIG_IP_GID_PROPERTY + if (check_bind_perm((u32)addr->sin_addr.s_addr)) + return -EACCES; +#endif if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; @@ -855,6 +878,10 @@ case SIOCGARP: case SIOCSARP: return(arp_ioctl(cmd,(void *) arg)); +#ifdef CONFIG_IP_GID_PROPERTY + case SIOCGIFGID: + case SIOCSIFGID: +#endif case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFBRDADDR: diff -Nru linux-2.4.22.orig/net/ipv4/devinet.c linux-2.4.22/net/ipv4/devinet.c --- linux-2.4.22.orig/net/ipv4/devinet.c 2003-06-13 10:51:39.000000000 -0400 +++ linux-2.4.22/net/ipv4/devinet.c 2003-10-25 00:45:32.000000000 -0400 @@ -501,7 +501,11 @@ memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; break; - +#ifdef CONFIG_IP_GID_PROPERTY + case SIOCGIFGID: /* Get interface gid */ + break; + case SIOCSIFGID: /* Set interface gid */ +#endif case SIOCSIFFLAGS: if (!capable(CAP_NET_ADMIN)) return -EACCES; @@ -560,6 +564,11 @@ } switch(cmd) { +#ifdef CONFIG_IP_GID_PROPERTY + case SIOCGIFGID: /* Get interface gid */ + ifr.ifr_gid = ifa->ifa_gid; + goto rarok; +#endif case SIOCGIFADDR: /* Get interface address */ sin->sin_addr.s_addr = ifa->ifa_local; goto rarok; @@ -588,7 +597,14 @@ } ret = dev_change_flags(dev, ifr.ifr_flags); break; - + +#ifdef CONFIG_IP_GID_PROPERTY + case SIOCSIFGID: /* Set interface gid */ + ifa->ifa_gid = ifr.ifr_gid; + printk("new gid for %s : %d\n", ifr.ifr_name, ifa->ifa_gid); + break; +#endif + case SIOCSIFADDR: /* Set interface address (and family) */ if (inet_abc_len(sin->sin_addr.s_addr) < 0) { ret = -EINVAL; diff -Nru linux-2.4.22.orig/net/ipv4/fib_frontend.c linux-2.4.22/net/ipv4/fib_frontend.c --- linux-2.4.22.orig/net/ipv4/fib_frontend.c 2003-08-25 07:44:44.000000000 -0400 +++ linux-2.4.22/net/ipv4/fib_frontend.c 2003-10-25 00:45:32.000000000 -0400 @@ -168,6 +168,27 @@ return dev; } +#ifdef CONFIG_IP_GID_PROPERTY +/* + * Find the first exactly device with a given source address, when its + * an alias it returns for example the eth0:0 device not the eth0 device. + * if the source adress is INADDR_ANY the gid from the first net device + * will be used. + */ +struct in_ifaddr * ip_dev_find_alias(u32 addr) { + struct net_device *dev = NULL; + + for (dev = dev_base; dev; dev = dev->next) { + if (dev->ip_ptr) + for_ifa((struct in_device *) dev->ip_ptr) { + if (addr == ifa->ifa_local || addr == INADDR_ANY) + return ifa; + } endfor_ifa(in_dev); + } + return NULL; +} +#endif + unsigned inet_addr_type(u32 addr) { struct rt_key key;