Stephen Smalley <sdsat_private> writes: > However, I understand your point and don't object to your hook, except to > suggest that you not pass both the port and the (address, addrlen) pair > to it. You could drop the latter without harm to SELinux, but it would be > more general to drop the port and pass the full address. My only other Here is the new patch with your suggested interface change. > concern is whether the kernel developers will object to having a LSM hook > in both sys_bind and inet_bind. Well, we'll never know until we try :-). Besides that, sys_bind() and inet_bind() are on an entirely different level. Regards, Olaf. diff -urN a/include/linux/security.h b/include/linux/security.h --- a/include/linux/security.h Mon Sep 30 21:57:14 2002 +++ b/include/linux/security.h Mon Sep 30 22:10:07 2002 @@ -784,6 +784,15 @@ * A non-zero return value will cause an ICMP parameter problem message to * be generated and transmitted to the sender. The @pp_ptr parameter may * be used to point to the offending option parameter. + * @ip_prot_sock: + * Check, whether this is a protected port. + * Security modules may use this hook to implement fine grained control + * based on the port number. + * @sock contains the socket structure. + * @address contains the address to bind to. + * @addrlen contains the length of address. + * The module should return 0, if permission to access this port is + * granted, -EACCES otherwise. * * Security hooks for network devices. * @netdev_unregister: @@ -1351,6 +1360,8 @@ void (*ip_decapsulate) (struct sk_buff * skb); int (*ip_decode_options) (struct sk_buff * skb, const char *optptr, unsigned char **pp_ptr); + int (*ip_prot_sock) (struct socket *sock, + struct sockaddr *address, int addrlen); void (*netdev_unregister) (struct net_device * dev); @@ -1405,6 +1416,10 @@ extern int mod_reg_security (const char *name, struct security_operations *ops); extern int mod_unreg_security (const char *name, struct security_operations *ops); extern int capable (int cap); + +/* default implementations for use by other security modules */ +extern int dummy_ip_prot_sock (struct socket *sock, + struct sockaddr *address, int addrlen); /* global variables */ extern struct security_operations *security_ops; diff -urN a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c --- a/net/ipv4/af_inet.c Wed Sep 18 02:58:46 2002 +++ b/net/ipv4/af_inet.c Mon Sep 30 22:00:18 2002 @@ -531,7 +531,7 @@ snum = ntohs(addr->sin_port); err = -EACCES; - if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + if (security_ops->ip_prot_sock(sock, uaddr, addr_len)) goto out; /* We keep a pair of addresses. rcv_saddr is the one diff -urN a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c --- a/net/ipv6/af_inet6.c Wed Sep 18 02:58:59 2002 +++ b/net/ipv6/af_inet6.c Mon Sep 30 22:00:32 2002 @@ -313,7 +313,7 @@ } snum = ntohs(addr->sin6_port); - if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + if (security_ops->ip_prot_sock(sock, uaddr, addr_len)) return -EACCES; lock_sock(sk); diff -urN a/security/Makefile b/security/Makefile --- a/security/Makefile Mon Sep 30 21:57:14 2002 +++ b/security/Makefile Mon Sep 30 22:10:53 2002 @@ -9,7 +9,7 @@ subdir-$(CONFIG_LIDS) += lids # Objects that export symbols -export-objs := security.o +export-objs := security.o dummy.o # Object file lists obj-y := security.o dummy.o diff -urN a/security/capability.c b/security/capability.c --- a/security/capability.c Mon Sep 30 21:57:14 2002 +++ b/security/capability.c Mon Sep 30 22:11:29 2002 @@ -1189,6 +1189,7 @@ .ip_encapsulate = cap_ip_encapsulate, .ip_decapsulate = cap_ip_decapsulate, .ip_decode_options = cap_ip_decode_options, + .ip_prot_sock = dummy_ip_prot_sock, .netdev_unregister = cap_netdev_unregister, diff -urN a/security/dte/dte.c b/security/dte/dte.c --- a/security/dte/dte.c Mon Sep 30 21:57:14 2002 +++ b/security/dte/dte.c Mon Sep 30 22:12:06 2002 @@ -1053,6 +1053,7 @@ ip_encapsulate: dte_ip_encapsulate, ip_decapsulate: dte_ip_decapsulate, ip_decode_options: dte_ip_decode_options, + ip_prot_sock: dummy_ip_prot_sock, netdev_unregister: dte_netdev_unregister, diff -urN a/security/dummy.c b/security/dummy.c --- a/security/dummy.c Mon Sep 30 21:57:14 2002 +++ b/security/dummy.c Tue Oct 1 11:19:04 2002 @@ -18,6 +18,8 @@ #include <linux/security.h> #include <linux/skbuff.h> #include <linux/netlink.h> +#include <linux/in.h> +#include <net/sock.h> static int dummy_sethostname (char *hostname) { @@ -590,6 +592,18 @@ return 0; } +int dummy_ip_prot_sock (struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sockaddr_in *addr = (struct sockaddr_in *) address; + unsigned short port = ntohs(addr->sin_port); + + if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + return -EACCES; + + return 0; +} + static void dummy_netdev_unregister (struct net_device *dev) { return; @@ -1009,6 +1023,7 @@ .ip_encapsulate = dummy_ip_encapsulate, .ip_decapsulate = dummy_ip_decapsulate, .ip_decode_options = dummy_ip_decode_options, + .ip_prot_sock = dummy_ip_prot_sock, .ipc_permission = dummy_ipc_permission, .ipc_getinfo = dummy_ipc_getinfo, @@ -1045,3 +1060,4 @@ .unregister_security = dummy_unregister, }; +EXPORT_SYMBOL (dummy_ip_prot_sock); diff -urN a/security/lids/lids_lsm.c b/security/lids/lids_lsm.c --- a/security/lids/lids_lsm.c Mon Sep 30 21:57:14 2002 +++ b/security/lids/lids_lsm.c Mon Sep 30 22:12:33 2002 @@ -1208,6 +1208,7 @@ ip_encapsulate: lids_ip_encapsulate, ip_decapsulate: lids_ip_decapsulate, ip_decode_options: lids_ip_decode_options, + ip_prot_sock: dummy_ip_prot_sock, ipc_permission: lids_ipc_permission, ipc_getinfo: lids_ipc_getinfo, diff -urN a/security/owlsm.c b/security/owlsm.c --- a/security/owlsm.c Mon Sep 30 21:57:14 2002 +++ b/security/owlsm.c Mon Sep 30 22:13:01 2002 @@ -1005,6 +1005,7 @@ ip_encapsulate: owlsm_ip_encapsulate, ip_decapsulate: owlsm_ip_decapsulate, ip_decode_options: owlsm_decode_options, + ip_prot_sock: dummy_ip_prot_sock, netdev_unregister: owlsm_netdev_unregister, diff -urN a/security/selinux/hooks.c b/security/selinux/hooks.c --- a/security/selinux/hooks.c Mon Sep 30 21:57:14 2002 +++ b/security/selinux/hooks.c Tue Oct 1 00:02:20 2002 @@ -3218,6 +3218,54 @@ return nsid_ip_decode_options(skb, optptr, pp_ptr); } +static int selinux_ip_prot_sock(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sockaddr_in *addr = (struct sockaddr_in *)address; + unsigned short snum = ntohs(addr->sin_port); + + /* + * If PF_INET, check name_bind permission for the port. + */ + if (sock->sk->family == PF_INET) { + struct inode_security_struct *isec; + struct task_security_struct *tsec; + avc_audit_data_t ad; + struct sock *sk = sock->sk; + security_id_t sid; + int err; + + err = task_precondition(current); + if (err <= 0) + return err; + tsec = current->security; + err = inode_precondition(SOCK_INODE(sock)); + if (err <= 0) + return err; + isec = SOCK_INODE(sock)->i_security; + + if (snum&&(snum < max(PROT_SOCK,ip_local_port_range_0) || + snum > ip_local_port_range_1)) { + err = security_port_sid(sk->family, sk->type, + sk->protocol, snum, &sid); + if (err) + return err; + AVC_AUDIT_DATA_INIT(&ad,NET); + ad.u.net.port = snum; + err = avc_has_perm_audit(isec->sid, sid, + isec->sclass, + SOCKET__NAME_BIND, &ad); + if (err) + return err; + } + } + + if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + return -EACCES; + + return 0; +} + static void selinux_netdev_unregister(struct net_device *dev) { netdev_free_security(dev); @@ -3313,43 +3361,6 @@ if (err) return err; - /* - * If PF_INET, check name_bind permission for the port. - */ - if (sock->sk->family == PF_INET) { - struct inode_security_struct *isec; - struct task_security_struct *tsec; - avc_audit_data_t ad; - struct sockaddr_in *addr = (struct sockaddr_in *)address; - unsigned short snum = ntohs(addr->sin_port); - struct sock *sk = sock->sk; - security_id_t sid; - - err = task_precondition(current); - if (err <= 0) - return err; - tsec = current->security; - err = inode_precondition(SOCK_INODE(sock)); - if (err <= 0) - return err; - isec = SOCK_INODE(sock)->i_security; - - if (snum&&(snum < max(PROT_SOCK,ip_local_port_range_0) || - snum > ip_local_port_range_1)) { - err = security_port_sid(sk->family, sk->type, - sk->protocol, snum, &sid); - if (err) - return err; - AVC_AUDIT_DATA_INIT(&ad,NET); - ad.u.net.port = snum; - err = avc_has_perm_audit(isec->sid, sid, - isec->sclass, - SOCKET__NAME_BIND, &ad); - if (err) - return err; - } - } - return 0; } @@ -4814,6 +4825,7 @@ ip_encapsulate: selinux_ip_encapsulate, ip_decapsulate: selinux_ip_decapsulate, ip_decode_options: selinux_ip_decode_options, + ip_prot_sock: selinux_ip_prot_sock, netdev_unregister: selinux_netdev_unregister, _______________________________________________ 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 : Tue Oct 01 2002 - 02:43:31 PDT