diff -r --unidirectional-new-file -u linux/arch/i386/kernel/entry.S linux-acl-2.4.19/arch/i386/kernel/entry.S --- linux/arch/i386/kernel/entry.S 2002-08-26 14:50:42.000000000 +0200 +++ linux-acl-2.4.19/arch/i386/kernel/entry.S 2002-08-26 13:55:41.000000000 +0200 @@ -618,6 +618,7 @@ .long SYMBOL_NAME(sys_madvise) .long SYMBOL_NAME(sys_getdents64) /* 220 */ .long SYMBOL_NAME(sys_fcntl64) + .long SYMBOL_NAME(sys_port_acl_set) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */ .long SYMBOL_NAME(sys_gettid) diff -r --unidirectional-new-file -u linux/include/asm-i386/unistd.h linux-acl-2.4.19/include/asm-i386/unistd.h --- linux/include/asm-i386/unistd.h 2002-08-26 14:51:24.000000000 +0200 +++ linux-acl-2.4.19/include/asm-i386/unistd.h 2002-08-26 13:55:41.000000000 +0200 @@ -227,6 +227,7 @@ #define __NR_madvise1 219 /* delete when C lib stub is removed */ #define __NR_getdents64 220 #define __NR_fcntl64 221 +#define __NR_port_acl_set 222 #define __NR_security 223 /* syscall for security modules */ #define __NR_gettid 224 #define __NR_readahead 225 diff -r --unidirectional-new-file -u linux/include/net/port_acl.h linux-acl-2.4.19/include/net/port_acl.h --- linux/include/net/port_acl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-acl-2.4.19/include/net/port_acl.h 2002-08-26 13:55:41.000000000 +0200 @@ -0,0 +1,14 @@ +#include + +struct port_acl { + uid_t uid; + struct port_acl *next; +}; + +#ifdef __PORT_ACL__ + struct port_acl *port_acl_list[1024]; +#else + extern struct port_acl *port_acl_list[1024]; +#endif + +extern int port_acl(short int); diff -r --unidirectional-new-file -u linux/kernel/sys.c linux-acl-2.4.19/kernel/sys.c --- linux/kernel/sys.c 2002-08-26 14:51:36.000000000 +0200 +++ linux-acl-2.4.19/kernel/sys.c 2002-08-26 13:55:41.000000000 +0200 @@ -18,6 +18,9 @@ #include #include +#define __PORT_ACL__ +#include + /* * this is where the system-wide overflow UID and GID are defined, for * architectures that now have 32-bit UID/GID but didn't in the past @@ -1279,6 +1282,90 @@ return error; } +/* + * The following lines were added to implement port_acl secured + * mecanism : + * port_acl_add - add to a user the authorisation to acces a particular port + * port_acl_remove - remove to a user that authorisation + * sys_port_acl_set - front end for port_acl_add and port_acl_remove + */ +int port_acl_add(short int snum, uid_t uid) +{ + struct port_acl *ptr, *new; + + /* we verify if the permition is already set for that user */ + ptr = port_acl_list[snum]; + + while (ptr != NULL) { + if (ptr->uid == uid) + return -EBUSY; + if (ptr->next == NULL) + break; + ptr = ptr->next; + } + + /* ok, we haven't found the user and ptr is a pointer on the + last structure */ + new = kmalloc( sizeof(struct port_acl), GFP_KERNEL); + new->next = NULL; + new->uid = uid; + + if(ptr == NULL) + port_acl_list[snum] = new; + else + ptr->next = new; + + return 0; +} + +int port_acl_remove(short int snum, uid_t uid) +{ + struct port_acl *ptr, *prev = 0; + + /* we verify if the permition is already set for that user */ + ptr = port_acl_list[snum]; + + while (ptr != NULL) { + /* we found the user */ + if (ptr->uid == uid) { + if (ptr == port_acl_list[snum]) { + port_acl_list[snum] = ptr->next; + } + else { + prev->next = ptr->next; + } + kfree(ptr); + return 0; + } + prev = ptr; + ptr = ptr->next; + } + + return -ENODATA; +} + +asmlinkage int sys_port_acl_set(short int snum, uid_t uid, int act) +{ + /* the owner of the process must be root */ + if (current->uid != 0) + return -EACCES; + + /* we verify that the port is valid */ + if (snum<0 || snum>1023) + return -EINVAL; + + if (uid<1 || uid>65534) + return -EINVAL; + + if (act == 0) + return port_acl_remove(snum, uid); + else if (act == 1) + return port_acl_add(snum, uid); + else + return -EPERM; +} + + EXPORT_SYMBOL(notifier_chain_register); EXPORT_SYMBOL(notifier_chain_unregister); EXPORT_SYMBOL(notifier_call_chain); diff -r --unidirectional-new-file -u linux/net/ipv4/Makefile linux-acl-2.4.19/net/ipv4/Makefile --- linux/net/ipv4/Makefile 2001-12-21 18:42:05.000000000 +0100 +++ linux-acl-2.4.19/net/ipv4/Makefile 2002-08-26 13:55:41.000000000 +0200 @@ -16,7 +16,7 @@ ip_output.o ip_sockglue.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o \ tcp_diag.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ - sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o + sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o port_acl.o obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o obj-$(CONFIG_IP_ROUTE_NAT) += ip_nat_dumb.o diff -r --unidirectional-new-file -u linux/net/ipv4/af_inet.c linux-acl-2.4.19/net/ipv4/af_inet.c --- linux/net/ipv4/af_inet.c 2002-08-26 14:51:37.000000000 +0200 +++ linux-acl-2.4.19/net/ipv4/af_inet.c 2002-08-26 13:55:42.000000000 +0200 @@ -103,6 +103,7 @@ #include #include #include +#include #ifdef CONFIG_IP_MROUTE #include #endif @@ -130,6 +131,7 @@ extern int tcp_get_info(char *, char **, off_t, int); extern int udp_get_info(char *, char **, off_t, int); extern void ip_mc_drop_socket(struct sock *sk); +extern int port_acl_get_info(char *, char **, off_t, int, int); #ifdef CONFIG_DLCI extern int dlci_ioctl(unsigned int, void*); @@ -503,7 +505,7 @@ return -EADDRNOTAVAIL; snum = ntohs(addr->sin_port); - if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE) && !port_acl(snum)) return -EACCES; /* We keep a pair of addresses. rcv_saddr is the one @@ -1189,6 +1191,7 @@ proc_net_create ("sockstat", 0, afinet_get_info); proc_net_create ("tcp", 0, tcp_get_info); proc_net_create ("udp", 0, udp_get_info); + proc_net_create ("port_acl", 0, port_acl_get_info); #endif /* CONFIG_PROC_FS */ return 0; } diff -r --unidirectional-new-file -u linux/net/ipv4/port_acl.c linux-acl-2.4.19/net/ipv4/port_acl.c --- linux/net/ipv4/port_acl.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-acl-2.4.19/net/ipv4/port_acl.c 2002-08-26 13:55:42.000000000 +0200 @@ -0,0 +1,27 @@ +/* + * This is an implementation of acces list applied + * to privileged ports. + * Authors: Arnauld Michelizza, + */ +#include +#include +#include +#include + +/* + * yields 1 if the owner of the current process is authorized to + * bind the port given in argument + */ +int port_acl(short int snum) +{ + struct port_acl *ptr; + ptr = port_acl_list[snum]; + + while (ptr != NULL) { + if (ptr->uid == current->uid) + return 1; + ptr = ptr->next; + } + + return 0; +} diff -r --unidirectional-new-file -u linux/net/ipv4/proc.c linux-acl-2.4.19/net/ipv4/proc.c --- linux/net/ipv4/proc.c 2001-05-16 19:21:45.000000000 +0200 +++ linux-acl-2.4.19/net/ipv4/proc.c 2002-08-26 13:55:42.000000000 +0200 @@ -49,6 +49,7 @@ #include #include #include +#include static int fold_prot_inuse(struct proto *proto) { @@ -212,3 +213,41 @@ len = 0; return len; } + +/* + * Report privileged port authorization + */ +int port_acl_get_info(char *buffer, char **start, off_t offset, int length, int dummy) +{ + int index; + int len = 0; + struct port_acl *ptr; + + /* for every port below 1024, we search privileged uid */ + for (index=0;index<1024;index++) { + ptr = port_acl_list[index]; + if (ptr != NULL) { + len += sprintf(buffer+len,"%d:", index); + do { + len += sprintf(buffer+len," %d", ptr->uid); + ptr = ptr->next; + } while (ptr != NULL); + len += sprintf(buffer+len,"\n"); + } + } + + if (offset >= len) + { + *start = buffer; + return 0; + } + *start = buffer + offset; + len -= offset; + if (len > length) + len = length; + if (len < 0) + len = 0; + return len; +} + +