linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] accessfs v0.5 ported to LSM - 1/2
@ 2002-09-24 15:39 Olaf Dietsche
  2002-09-26 20:37 ` Greg KH
  0 siblings, 1 reply; 9+ messages in thread
From: Olaf Dietsche @ 2002-09-24 15:39 UTC (permalink / raw)
  To: linux-kernel, linux-security-module

Hi,

Accessfs is a new file system to control access to system resources.
For further information see the help text.

Changes:
- ported to LSM
- support capabilities
- merged ipv4/ipv6 into ip

This part (1/2) adds a hook to LSM to enable control based on the port
number.

The patch is attached below. It is also available at:
<http://home.t-online.de/home/olaf.dietsche/linux/accessfs-2.5.34-0.5-1_2.patch.gz>

It applies to 2.5.3[5-8] as well.

I did minimal testing using uml 0.58-2.5.34.

Regards, Olaf.

diff -urN v2.5.34/include/linux/security.h v2.5.34-accessfs/include/linux/security.h
--- v2.5.34/include/linux/security.h	Sun Sep  1 00:04:51 2002
+++ v2.5.34-accessfs/include/linux/security.h	Tue Sep 24 13:25:50 2002
@@ -642,6 +642,13 @@
  *	@args contains the call arguments (user space pointer).
  *	The module should return -ENOSYS if it does not implement any new
  *	system calls.
+ * @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.
+ *	@port contains the requested port
+ *	The module should return true if port is a protected port (e.g. < 1024),
+ *	false otherwise.
  *
  * @register_security:
  * 	allow module stacking.
@@ -785,6 +792,7 @@
 			   unsigned long arg5);
 	void (*task_kmod_set_label) (void);
 	void (*task_reparent_to_init) (struct task_struct * p);
+	int (*ip_prot_sock) (int port);
 
 	/* allow module stacking */
 	int (*register_security) (const char *name,
diff -urN v2.5.34/net/ipv4/af_inet.c v2.5.34-accessfs/net/ipv4/af_inet.c
--- v2.5.34/net/ipv4/af_inet.c	Tue Sep 24 11:52:15 2002
+++ v2.5.34-accessfs/net/ipv4/af_inet.c	Tue Sep 24 13:21:29 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(snum) && !capable(CAP_NET_BIND_SERVICE))
 		goto out;
 
 	/*      We keep a pair of addresses. rcv_saddr is the one
diff -urN v2.5.34/net/ipv6/af_inet6.c v2.5.34-accessfs/net/ipv6/af_inet6.c
--- v2.5.34/net/ipv6/af_inet6.c	Tue Sep 24 11:52:15 2002
+++ v2.5.34-accessfs/net/ipv6/af_inet6.c	Tue Sep 24 13:21:56 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(snum) && !capable(CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
 	lock_sock(sk);
diff -urN v2.5.34/security/capability.c v2.5.34-accessfs/security/capability.c
--- v2.5.34/security/capability.c	Sun Sep  1 00:04:55 2002
+++ v2.5.34-accessfs/security/capability.c	Tue Sep 24 13:20:08 2002
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 /* flag to keep track of how we were registered */
 static int secondary;
@@ -679,6 +680,11 @@
 	return;
 }
 
+static int cap_ip_prot_sock (int port)
+{
+	return port && port < PROT_SOCK;
+}
+
 static int cap_register (const char *name, struct security_operations *ops)
 {
 	return -EINVAL;
@@ -781,6 +787,8 @@
 	.task_prctl =			cap_task_prctl,
 	.task_kmod_set_label =		cap_task_kmod_set_label,
 	.task_reparent_to_init =	cap_task_reparent_to_init,
+
+	.ip_prot_sock =	cap_ip_prot_sock,
 
 	.register_security =		cap_register,
 	.unregister_security =		cap_unregister,
diff -urN v2.5.34/security/dummy.c v2.5.34-accessfs/security/dummy.c
--- v2.5.34/security/dummy.c	Sun Sep  1 00:04:52 2002
+++ v2.5.34-accessfs/security/dummy.c	Tue Sep 24 13:19:21 2002
@@ -18,6 +18,7 @@
 #include <linux/security.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
 {
@@ -493,6 +494,11 @@
 	return;
 }
 
+static int dummy_ip_prot_sock (int port)
+{
+	return port && port < PROT_SOCK;
+}
+
 static int dummy_register (const char *name, struct security_operations *ops)
 {
 	return -EINVAL;
@@ -595,6 +601,8 @@
 	.task_prctl =			dummy_task_prctl,
 	.task_kmod_set_label =		dummy_task_kmod_set_label,
 	.task_reparent_to_init =	dummy_task_reparent_to_init,
+
+	.ip_prot_sock =	dummy_ip_prot_sock,
 
 	.register_security =		dummy_register,
 	.unregister_security =		dummy_unregister,

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.5 ported to LSM - 1/2
  2002-09-24 15:39 [PATCH] accessfs v0.5 ported to LSM - 1/2 Olaf Dietsche
@ 2002-09-26 20:37 ` Greg KH
  2002-09-27 18:55   ` [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 " Olaf Dietsche
  0 siblings, 1 reply; 9+ messages in thread
From: Greg KH @ 2002-09-26 20:37 UTC (permalink / raw)
  To: Olaf Dietsche; +Cc: linux-kernel, linux-security-module

On Tue, Sep 24, 2002 at 05:39:43PM +0200, Olaf Dietsche wrote:
> Hi,
> 
> Accessfs is a new file system to control access to system resources.
> For further information see the help text.
> 
> Changes:
> - ported to LSM
> - support capabilities
> - merged ipv4/ipv6 into ip
> 
> This part (1/2) adds a hook to LSM to enable control based on the port
> number.

I like this, it looks quite nice.

You might want to provide a patch against the development LSM tree
(available at lsm.immunix.org) as that tree already has a lot of ip_*
hooks that have not been submitted to the networking group yet.  If you
do this, I would be glad to add this patch to the LSM tree, which will
keep you from having to do the forward port for all new kernel versions
that come out, if you want.  A number of other security related projects
are already in this tree (SELinux, DTE, LIDS, and others.)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-26 20:37 ` Greg KH
@ 2002-09-27 18:55   ` Olaf Dietsche
  2002-09-27 21:46     ` Greg KH
  0 siblings, 1 reply; 9+ messages in thread
From: Olaf Dietsche @ 2002-09-27 18:55 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, linux-security-module

Hi Greg,

Greg KH <greg@kroah.com> writes:

> You might want to provide a patch against the development LSM tree
> (available at lsm.immunix.org) as that tree already has a lot of ip_*
> hooks that have not been submitted to the networking group yet.  If you
> do this, I would be glad to add this patch to the LSM tree, which will
> keep you from having to do the forward port for all new kernel versions
> that come out, if you want.  A number of other security related projects
> are already in this tree (SELinux, DTE, LIDS, and others.)

That would be great, thanks.
The patch against 2.5.35-lsm1 is below.

I'm not entirely sure about the other security modules. If this needs
tweaking, please let me know.

Do you want part 2 move below ./security?

Regards, Olaf.

diff -urN a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Fri Sep 27 17:10:26 2002
+++ b/include/linux/security.h	Fri Sep 27 17:55:55 2002
@@ -784,6 +784,13 @@
  *	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.
+ *	@port contains the requested port
+ *	The module should return 0, if permission to access this port is
+ *	granted, -EACCES otherwise.
  *
  * Security hooks for network devices.
  * @netdev_unregister:
@@ -1351,6 +1358,7 @@
 	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) (int port);
 
 	void (*netdev_unregister) (struct net_device * dev);
 
diff -urN a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Tue Sep 24 11:52:15 2002
+++ b/net/ipv4/af_inet.c	Fri Sep 27 17:55:55 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(snum))
 		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	Tue Sep 24 11:52:15 2002
+++ b/net/ipv6/af_inet6.c	Fri Sep 27 17:55:55 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(snum))
 		return -EACCES;
 
 	lock_sock(sk);
diff -urN a/security/capability.c b/security/capability.c
--- a/security/capability.c	Fri Sep 27 17:10:26 2002
+++ b/security/capability.c	Fri Sep 27 17:55:55 2002
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 /* flag to keep track of how we were registered */
 static int secondary;
@@ -773,6 +774,14 @@
 	return 0;
 }
 
+static int cap_ip_prot_sock (int port)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void cap_netdev_unregister (struct net_device *dev)
 {
 	return;
@@ -1189,6 +1198,7 @@
 	.ip_encapsulate =		cap_ip_encapsulate,
 	.ip_decapsulate =		cap_ip_decapsulate,
 	.ip_decode_options =		cap_ip_decode_options,
+	.ip_prot_sock =			cap_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	Fri Sep 27 17:10:27 2002
+++ b/security/dte/dte.c	Fri Sep 27 18:20:21 2002
@@ -25,6 +25,7 @@
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 
 extern int dte_initialized;
@@ -609,6 +610,14 @@
 	return 0;
 }
 
+static int dte_ip_prot_sock (int port)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void dte_netdev_unregister (struct net_device *dev)
 {
 	return;
@@ -1053,6 +1062,7 @@
 	ip_encapsulate:			dte_ip_encapsulate,
 	ip_decapsulate:			dte_ip_decapsulate,
 	ip_decode_options:		dte_ip_decode_options,
+	ip_prot_sock:			dte_ip_prot_sock,
 	
 	netdev_unregister:		dte_netdev_unregister,
 	
diff -urN a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Fri Sep 27 17:10:27 2002
+++ b/security/dummy.c	Fri Sep 27 17:55:55 2002
@@ -18,6 +18,7 @@
 #include <linux/security.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 static int dummy_sethostname (char *hostname)
 {
@@ -590,6 +591,14 @@
 	return 0;
 }
 
+static int dummy_ip_prot_sock (int 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 +1018,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,
diff -urN a/security/lids/lids_lsm.c b/security/lids/lids_lsm.c
--- a/security/lids/lids_lsm.c	Fri Sep 27 17:10:27 2002
+++ b/security/lids/lids_lsm.c	Fri Sep 27 18:38:27 2002
@@ -22,6 +22,7 @@
 #include <linux/lids.h>
 #include <linux/lidsext.h>
 #include <linux/lidsif.h>
+#include <net/sock.h>
 
 struct security_operations *lids_secondary_ops;
 
@@ -767,6 +768,14 @@
 	return 0;
 }
 
+static int lids_ip_prot_sock (int port)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void lids_netdev_unregister (struct net_device *dev)
 {
 	return;
@@ -1208,6 +1217,7 @@
 	ip_encapsulate:			lids_ip_encapsulate,
 	ip_decapsulate:			lids_ip_decapsulate,
 	ip_decode_options:		lids_ip_decode_options,
+	ip_prot_sock:			lids_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	Fri Sep 27 17:10:27 2002
+++ b/security/owlsm.c	Fri Sep 27 18:19:44 2002
@@ -23,6 +23,7 @@
 #include <linux/netlink.h>
 #include <linux/ctype.h>
 #include <linux/file.h>
+#include <net/sock.h>
 
 #include "owlsm.h"
 
@@ -607,6 +608,14 @@
 	return 0;
 }
 
+static int owlsm_ip_prot_sock (int port)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void owlsm_netdev_unregister (struct net_device *dev) 
 {
 	return;
@@ -1005,6 +1014,7 @@
 	ip_encapsulate:			owlsm_ip_encapsulate,
 	ip_decapsulate:			owlsm_ip_decapsulate,
 	ip_decode_options:		owlsm_decode_options,
+	ip_prot_sock:			owlsm_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	Fri Sep 27 17:10:27 2002
+++ b/security/selinux/hooks.c	Fri Sep 27 18:01:35 2002
@@ -3218,6 +3218,14 @@
 	return nsid_ip_decode_options(skb, optptr, pp_ptr);
 }
 
+static int selinux_ip_prot_sock(int port)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void selinux_netdev_unregister(struct net_device *dev)
 {
 	netdev_free_security(dev);
@@ -4814,6 +4822,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,
 	

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-27 18:55   ` [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 " Olaf Dietsche
@ 2002-09-27 21:46     ` Greg KH
  2002-09-27 23:02       ` Olaf Dietsche
  2002-09-29 12:56       ` James Morris
  0 siblings, 2 replies; 9+ messages in thread
From: Greg KH @ 2002-09-27 21:46 UTC (permalink / raw)
  To: Olaf Dietsche; +Cc: linux-kernel, linux-security-module

On Fri, Sep 27, 2002 at 08:55:52PM +0200, Olaf Dietsche wrote:
>  
> +static int cap_ip_prot_sock (int port)
> +{
> +	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
> +		return -EACCES;
> +
> +	return 0;
> +}
> +

Do we really want to force all of the security modules to implement this
logic (yes, it's the same discussion again...)

As for the ip_prot_sock hook in general, does it look ok to the other
developers?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-27 21:46     ` Greg KH
@ 2002-09-27 23:02       ` Olaf Dietsche
  2002-09-29 12:56       ` James Morris
  1 sibling, 0 replies; 9+ messages in thread
From: Olaf Dietsche @ 2002-09-27 23:02 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, linux-security-module

Greg KH <greg@kroah.com> writes:

> On Fri, Sep 27, 2002 at 08:55:52PM +0200, Olaf Dietsche wrote:
>>  
>> +static int cap_ip_prot_sock (int port)
>> +{
>> +	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
>> +		return -EACCES;
>> +
>> +	return 0;
>> +}
>> +
>
> Do we really want to force all of the security modules to implement this
> logic (yes, it's the same discussion again...)

I don't understand what you mean. There must be _some_ implementation
for this hook. Of course, everybody's free to do his own.

Regards, Olaf.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-27 21:46     ` Greg KH
  2002-09-27 23:02       ` Olaf Dietsche
@ 2002-09-29 12:56       ` James Morris
  2002-09-29 14:49         ` Olaf Dietsche
  2002-09-30  8:22         ` Chris Wright
  1 sibling, 2 replies; 9+ messages in thread
From: James Morris @ 2002-09-29 12:56 UTC (permalink / raw)
  To: Greg KH; +Cc: Olaf Dietsche, linux-kernel, linux-security-module

On Fri, 27 Sep 2002, Greg KH wrote:

> On Fri, Sep 27, 2002 at 08:55:52PM +0200, Olaf Dietsche wrote:
> >  
> > +static int cap_ip_prot_sock (int port)
> > +{
> > +	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
> > +		return -EACCES;
> > +
> > +	return 0;
> > +}
> > +
> 
> Do we really want to force all of the security modules to implement this
> logic (yes, it's the same discussion again...)
> 
> As for the ip_prot_sock hook in general, does it look ok to the other
> developers?
> 

This hook is not necessary: any related access control decision can be
made via the more generic and flexible socket_bind() hook (like SELinux).


- James
-- 
James Morris
<jmorris@intercode.com.au>



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-29 12:56       ` James Morris
@ 2002-09-29 14:49         ` Olaf Dietsche
  2002-09-30 13:14           ` Olaf Dietsche
  2002-09-30  8:22         ` Chris Wright
  1 sibling, 1 reply; 9+ messages in thread
From: Olaf Dietsche @ 2002-09-29 14:49 UTC (permalink / raw)
  To: James Morris; +Cc: Greg KH, linux-kernel, linux-security-module

James Morris <jmorris@intercode.com.au> writes:

> On Fri, 27 Sep 2002, Greg KH wrote:
>
>> As for the ip_prot_sock hook in general, does it look ok to the other
>> developers?
>> 
>
> This hook is not necessary: any related access control decision can be
> made via the more generic and flexible socket_bind() hook (like SELinux).

AFAICS, it looks like you can make _additional_ checks only. You still
have to grant CAP_NET_BIND_SERVICE for binding to ports below PROT_SOCK.
So, this doesn't look like a viable solution for me.

Anyway, thanks for this pointer, I'll look into socket_bind().

Regards, Olaf.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-29 12:56       ` James Morris
  2002-09-29 14:49         ` Olaf Dietsche
@ 2002-09-30  8:22         ` Chris Wright
  1 sibling, 0 replies; 9+ messages in thread
From: Chris Wright @ 2002-09-30  8:22 UTC (permalink / raw)
  To: James Morris; +Cc: Greg KH, Olaf Dietsche, linux-kernel, linux-security-module

* James Morris (jmorris@intercode.com.au) wrote:
> > 
> > As for the ip_prot_sock hook in general, does it look ok to the other
> > developers?
> 
> This hook is not necessary: any related access control decision can be
> made via the more generic and flexible socket_bind() hook (like SELinux).

Yes, I had the same impression.
thanks,
-chris
-- 
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 - 1/2
  2002-09-29 14:49         ` Olaf Dietsche
@ 2002-09-30 13:14           ` Olaf Dietsche
  0 siblings, 0 replies; 9+ messages in thread
From: Olaf Dietsche @ 2002-09-30 13:14 UTC (permalink / raw)
  To: James Morris; +Cc: Greg KH, linux-kernel, linux-security-module, Chris Wright

Olaf Dietsche <olaf.dietsche--list.linux-security-module@exmail.de> writes:

> James Morris <jmorris@intercode.com.au> writes:
>
>> On Fri, 27 Sep 2002, Greg KH wrote:
>>
>>> As for the ip_prot_sock hook in general, does it look ok to the other
>>> developers?
>>> 
>>
>> This hook is not necessary: any related access control decision can be
>> made via the more generic and flexible socket_bind() hook (like SELinux).
>
> AFAICS, it looks like you can make _additional_ checks only. You still
> have to grant CAP_NET_BIND_SERVICE for binding to ports below PROT_SOCK.
> So, this doesn't look like a viable solution for me.
>
> Anyway, thanks for this pointer, I'll look into socket_bind().

Seems like my first impression was correct. You can augment the
existing checks only.

For this particular case it means, without CAP_NET_BIND_SERVICE the
hook is effectively useless for ports below PROT_SOCK. Quite the
contrary, since you must grant this capability, it leaves the door
wide open to other net protocols.

Even SELinux would benefit from this new hook, since they could move
the protocol specific part away from socket_bind() to ip_prot_sock().
Thus, they could gain _real_ fine grained control over who has access
and who has not.

Regards, Olaf.

diff -urN a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Fri Sep 27 19:09:00 2002
+++ b/include/linux/security.h	Mon Sep 30 13:50:33 2002
@@ -784,6 +784,16 @@
  *	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.
+ *	@port contains the requested port
+ *	@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 +1361,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) (int port, struct socket *sock,
+			     struct sockaddr *address, int addrlen);
 
 	void (*netdev_unregister) (struct net_device * dev);
 
diff -urN a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Fri Sep 27 19:07:38 2002
+++ b/net/ipv4/af_inet.c	Mon Sep 30 13:50:33 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(snum, 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	Fri Sep 27 19:07:38 2002
+++ b/net/ipv6/af_inet6.c	Mon Sep 30 13:50:33 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(snum, sock, uaddr, addr_len))
 		return -EACCES;
 
 	lock_sock(sk);
diff -urN a/security/capability.c b/security/capability.c
--- a/security/capability.c	Fri Sep 27 19:09:01 2002
+++ b/security/capability.c	Mon Sep 30 13:50:33 2002
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 /* flag to keep track of how we were registered */
 static int secondary;
@@ -773,6 +774,15 @@
 	return 0;
 }
 
+static int cap_ip_prot_sock (int port, struct socket *sock,
+			     struct sockaddr *address, int addrlen)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void cap_netdev_unregister (struct net_device *dev)
 {
 	return;
@@ -1189,6 +1199,7 @@
 	.ip_encapsulate =		cap_ip_encapsulate,
 	.ip_decapsulate =		cap_ip_decapsulate,
 	.ip_decode_options =		cap_ip_decode_options,
+	.ip_prot_sock =			cap_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	Fri Sep 27 19:09:01 2002
+++ b/security/dte/dte.c	Mon Sep 30 13:50:33 2002
@@ -25,6 +25,7 @@
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 
 extern int dte_initialized;
@@ -609,6 +610,15 @@
 	return 0;
 }
 
+static int dte_ip_prot_sock (int port, struct socket *sock,
+			     struct sockaddr *address, int addrlen)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void dte_netdev_unregister (struct net_device *dev)
 {
 	return;
@@ -1053,6 +1063,7 @@
 	ip_encapsulate:			dte_ip_encapsulate,
 	ip_decapsulate:			dte_ip_decapsulate,
 	ip_decode_options:		dte_ip_decode_options,
+	ip_prot_sock:			dte_ip_prot_sock,
 	
 	netdev_unregister:		dte_netdev_unregister,
 	
diff -urN a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Fri Sep 27 19:09:01 2002
+++ b/security/dummy.c	Mon Sep 30 13:50:33 2002
@@ -18,6 +18,7 @@
 #include <linux/security.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <net/sock.h>
 
 static int dummy_sethostname (char *hostname)
 {
@@ -590,6 +591,15 @@
 	return 0;
 }
 
+static int dummy_ip_prot_sock (int port, struct socket *sock,
+			       struct sockaddr *address, int addrlen)
+{
+	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 +1019,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,
diff -urN a/security/lids/lids_lsm.c b/security/lids/lids_lsm.c
--- a/security/lids/lids_lsm.c	Fri Sep 27 19:09:01 2002
+++ b/security/lids/lids_lsm.c	Mon Sep 30 13:50:33 2002
@@ -22,6 +22,7 @@
 #include <linux/lids.h>
 #include <linux/lidsext.h>
 #include <linux/lidsif.h>
+#include <net/sock.h>
 
 struct security_operations *lids_secondary_ops;
 
@@ -767,6 +768,15 @@
 	return 0;
 }
 
+static int lids_ip_prot_sock (int port, struct socket *sock,
+			      struct sockaddr *address, int addrlen)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void lids_netdev_unregister (struct net_device *dev)
 {
 	return;
@@ -1208,6 +1218,7 @@
 	ip_encapsulate:			lids_ip_encapsulate,
 	ip_decapsulate:			lids_ip_decapsulate,
 	ip_decode_options:		lids_ip_decode_options,
+	ip_prot_sock:			lids_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	Fri Sep 27 19:09:01 2002
+++ b/security/owlsm.c	Mon Sep 30 13:50:33 2002
@@ -23,6 +23,7 @@
 #include <linux/netlink.h>
 #include <linux/ctype.h>
 #include <linux/file.h>
+#include <net/sock.h>
 
 #include "owlsm.h"
 
@@ -607,6 +608,15 @@
 	return 0;
 }
 
+static int owlsm_ip_prot_sock (int port, struct socket *sock,
+			       struct sockaddr *address, int addrlen)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	return 0;
+}
+
 static void owlsm_netdev_unregister (struct net_device *dev) 
 {
 	return;
@@ -1005,6 +1015,7 @@
 	ip_encapsulate:			owlsm_ip_encapsulate,
 	ip_decapsulate:			owlsm_ip_decapsulate,
 	ip_decode_options:		owlsm_decode_options,
+	ip_prot_sock:			owlsm_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	Fri Sep 27 19:09:01 2002
+++ b/security/selinux/hooks.c	Mon Sep 30 13:50:33 2002
@@ -3218,6 +3218,52 @@
 	return nsid_ip_decode_options(skb, optptr, pp_ptr);
 }
 
+static int selinux_ip_prot_sock(int port, struct socket *sock,
+				struct sockaddr *address, int addrlen)
+{
+	if (port && port < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	/*
+	 * 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;
+		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 (port&&(port < max(PROT_SOCK,ip_local_port_range_0) ||
+			   port > ip_local_port_range_1)) {
+			err = security_port_sid(sk->family, sk->type,
+						sk->protocol, port, &sid);
+			if (err)
+				return err;
+			AVC_AUDIT_DATA_INIT(&ad,NET);
+			ad.u.net.port = port;
+			err = avc_has_perm_audit(isec->sid, sid,
+						 isec->sclass,
+						 SOCKET__NAME_BIND, &ad);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
 static void selinux_netdev_unregister(struct net_device *dev)
 {
 	netdev_free_security(dev);
@@ -3313,43 +3359,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 +4823,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,
 	

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2002-09-30 13:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-24 15:39 [PATCH] accessfs v0.5 ported to LSM - 1/2 Olaf Dietsche
2002-09-26 20:37 ` Greg KH
2002-09-27 18:55   ` [PATCH] accessfs v0.6 ported to 2.5.35-lsm1 " Olaf Dietsche
2002-09-27 21:46     ` Greg KH
2002-09-27 23:02       ` Olaf Dietsche
2002-09-29 12:56       ` James Morris
2002-09-29 14:49         ` Olaf Dietsche
2002-09-30 13:14           ` Olaf Dietsche
2002-09-30  8:22         ` Chris Wright

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).