Re: Patch: Socket hooks

From: Chris Vance (cvanceat_private)
Date: Mon Jul 23 2001 - 10:10:00 PDT

  • Next message: Casey Schaufler: "Re: Changes to LSM phase 1 for audit."

    Attached is a patch that is identical to the first, with the exception
    that the extra user-space parameters have been removed from the accept and
    setsockopt hooks.  This new patch should replace the previously posted
    one. 
    
    chris.
    
    On Fri, 20 Jul 2001, Greg KH wrote:
    
    > On Fri, Jul 20, 2001 at 04:09:31PM -0400, Chris Vance wrote:
    > > 
    > > Something escaped my first pass.  Note that two of these hooks have
    > > parameters that are user-space variables - accept and setsockopt.  In the
    > > first case, accept, they should be removed. In the second case,
    > > setsockopt, it's not clear whether an LSM module would care precisely what
    > > value is being set.  It would need to be copied into kernel memory and the
    > > possibly of a race condition exists. 
    > > 
    > > Perhaps removing these paramters would be the safest thing to do.
    > 
    > I agree.  Keeping lsm modules from having to handle userspace variables
    > is a good thing.  Where ever possible I think we should try to avoid it.
    > 
    > Other than that, the patch looks nice.  However I don't profess to know
    > anything about the network stack code :)
    > 
    > Anyone else want to comment if these hooks will work out for their
    > projects?
    > 
    > thanks,
    > 
    > greg k-h
    > 
    
    
    Index: include/linux/netdevice.h
    ===================================================================
    RCS file: /cvs/lsm/lsm/include/linux/netdevice.h,v
    retrieving revision 1.1.1.1
    diff -u -r1.1.1.1 netdevice.h
    --- include/linux/netdevice.h	2001/06/11 18:19:59	1.1.1.1
    +++ include/linux/netdevice.h	2001/07/23 15:43:03
    @@ -291,6 +291,7 @@
     	unsigned short		type;	/* interface hardware type	*/
     	unsigned short		hard_header_len;	/* hardware hdr length	*/
     	void			*priv;	/* pointer to private data	*/
    +	void			*d_security; /* device security block   */
     
     	struct net_device	*master; /* Pointer to master device of a group,
     					  * which this device is member of.
    Index: include/linux/security.h
    ===================================================================
    RCS file: /cvs/lsm/lsm/include/linux/security.h,v
    retrieving revision 1.19
    diff -u -r1.19 security.h
    --- include/linux/security.h	2001/07/06 19:39:42	1.19
    +++ include/linux/security.h	2001/07/23 15:43:03
    @@ -121,6 +121,19 @@
     };
     
     struct socket_security_ops {
    +	int (* create)			(int family, int type, int protocol);
    +	void (* post_create)		(struct socket *sock, int family, int type, int protocol);
    +	int (* bind)			(struct socket *sock, struct sockaddr *address, int addrlen);
    +	int (* connect)			(struct socket *sock, struct sockaddr *address, int addrlen);
    +	int (* listen)			(struct socket *sock, int backlog);
    +	int (* accept)			(struct socket *sock, struct socket *newsock);
    +	int (* sendmsg)			(struct socket *sock, struct msghdr *msg, int size);
    +	int (* recvmsg)			(struct socket *sock, struct msghdr *msg, int size, int flags);
    +	int (* getsockname)		(struct socket *sock);
    +	int (* getpeername)		(struct socket *sock);
    +	int (* getsockopt)		(struct socket *sock, int level, int optname);
    +	int (* setsockopt)		(struct socket *sock, int level, int optname);
    +	int (* shutdown)		(struct socket *sock, int how);
     };
     
     struct module_security_ops {
    Index: kernel/capability_plug.c
    ===================================================================
    RCS file: /cvs/lsm/lsm/kernel/capability_plug.c,v
    retrieving revision 1.7
    diff -u -r1.7 capability_plug.c
    --- kernel/capability_plug.c	2001/07/06 19:39:42	1.7
    +++ kernel/capability_plug.c	2001/07/23 15:43:04
    @@ -56,6 +56,7 @@
     
     static int cap_setcapablity	(void)	{return 0;}
     static int cap_acct		(struct file *file) {return 0;}
    +static int cap_sysctl		(ctl_table * table, int op) {return 0;}
     
     static int cap_binprm_alloc_security(struct linux_binprm *bprm)
     {
    @@ -290,6 +291,20 @@
     	return;
     }
     
    +static int cap_socket_create	(int family, int type, int protocol) {return 0;}
    +static void cap_socket_post_create	(struct socket *sock, int family, int type, int protocol) {return;}
    +static int cap_socket_bind	(struct socket *sock, struct sockaddr *address, int addrlen) {return 0;}
    +static int cap_socket_connect	(struct socket *sock, struct sockaddr *address, int addrlen) {return 0;}
    +static int cap_socket_listen	(struct socket *sock, int backlog) {return 0;}
    +static int cap_socket_accept(	struct socket *sock, struct socket *newsock) {return 0;}
    +static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) {return 0;}
    +static int cap_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) {return 0;}
    +static int cap_socket_getsockname	(struct socket *sock) {return 0;}
    +static int cap_socket_getpeername	(struct socket *sock) {return 0;}
    +static int cap_socket_setsockopt	(struct socket *sock, int level, int optname) {return 0;}
    +static int cap_socket_getsockopt	(struct socket *sock, int level, int optname) {return 0;}
    +static int cap_socket_shutdown	(struct socket *sock, int how) {return 0;}
    +
     static int cap_module_create_module	(const char *name_user, size_t size)			{return 0;}
     static int cap_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
     static int cap_module_delete_module	(const char *name_user)					{return 0;}
    @@ -396,7 +411,21 @@
     	kmod_set_label:	cap_task_kmod_set_label,
     };
     
    -static struct socket_security_ops cap_socket_ops = {};
    +static struct socket_security_ops cap_socket_ops = {
    +	create:		cap_socket_create,
    +	post_create:	cap_socket_post_create,
    +	bind:		cap_socket_bind,
    +	connect:	cap_socket_connect,
    +	listen:		cap_socket_listen,
    +	accept:		cap_socket_accept,
    +	sendmsg:	cap_socket_sendmsg,
    +	recvmsg:	cap_socket_recvmsg,
    +	getsockname:	cap_socket_getsockname,
    +	getpeername:	cap_socket_getpeername,
    +	getsockopt:	cap_socket_getsockopt,
    +	setsockopt:	cap_socket_setsockopt,
    +	shutdown:	cap_socket_shutdown,
    +};
     
     static struct module_security_ops cap_module_ops = {
     	create_module:	cap_module_create_module,
    @@ -458,6 +487,7 @@
     	ptrace:			cap_ptrace,
     	setcapability:		cap_setcapablity,
     	acct:			cap_acct,
    +	sysctl:			cap_sysctl,
     	capable:		cap_capable,
     
     	bprm_ops:		&cap_binprm_ops,
    Index: kernel/security.c
    ===================================================================
    RCS file: /cvs/lsm/lsm/kernel/security.c,v
    retrieving revision 1.20
    diff -u -r1.20 security.c
    --- kernel/security.c	2001/07/06 19:39:42	1.20
    +++ kernel/security.c	2001/07/23 15:43:04
    @@ -127,6 +127,21 @@
     
     static void dummy_task_kmod_set_label	(void)	                {return;}
     
    +static int dummy_socket_create(int family, int type, int protocol) {return 0;}
    +static void dummy_socket_post_create(struct socket *sock, int family, int type, int protocol) {return;} 
    +static int dummy_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) {return 0;}
    +static int dummy_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) {return 0;}
    +static int dummy_socket_listen(struct socket *sock, int backlog) {return 0;}
    +static int dummy_socket_accept(struct socket *sock, struct socket *newsock) {return 0;}
    +static int dummy_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) {return 0;}
    +static int dummy_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) {return 0;}
    +static int dummy_socket_getsockname(struct socket *sock) {return 0;}
    +static int dummy_socket_getpeername(struct socket *sock) {return 0;}
    +static int dummy_socket_setsockopt(struct socket *sock, int level, int optname) {return 0;}
    +static int dummy_socket_getsockopt(struct socket *sock, int level, int optname) {return 0;}
    +static int dummy_socket_shutdown(struct socket *sock, int how) {return 0;}
    +
    +
     static int dummy_module_create_module	(const char *name_user, size_t size)			{return 0;}
     static int dummy_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
     static int dummy_module_delete_module	(const char *name_user)					{return 0;}
    @@ -233,7 +248,21 @@
     	kmod_set_label:	dummy_task_kmod_set_label,
     };
     
    -static struct socket_security_ops dummy_socket_ops = {};
    +static struct socket_security_ops dummy_socket_ops = {
    +	create:			dummy_socket_create,
    +	post_create:		dummy_socket_post_create,
    +	bind:			dummy_socket_bind,
    +	connect:		dummy_socket_connect,
    +	listen:			dummy_socket_listen,
    +	accept:			dummy_socket_accept,
    +	sendmsg:		dummy_socket_sendmsg,
    +	recvmsg:		dummy_socket_recvmsg,
    +	getsockname:		dummy_socket_getsockname,
    +	getpeername:		dummy_socket_getpeername,
    +	getsockopt:		dummy_socket_getsockopt,
    +	setsockopt:		dummy_socket_setsockopt,
    +	shutdown:		dummy_socket_shutdown,
    +};
     
     static struct module_security_ops dummy_module_ops = {
     	create_module:	dummy_module_create_module,
    Index: mm/mmap.c
    ===================================================================
    RCS file: /cvs/lsm/lsm/mm/mmap.c,v
    retrieving revision 1.3
    retrieving revision 1.4
    diff -u -r1.3 -r1.4
    --- mm/mmap.c	2001/06/21 15:46:47	1.3
    +++ mm/mmap.c	2001/07/12 17:23:47	1.4
    @@ -292,7 +292,7 @@
     		}
     	}
     
    -	error = security_ops->file_ops->mmap(file, flags, prot);
    +	error = security_ops->file_ops->mmap(file, prot, flags);
     	if (error)
     		return error;
     		
    Index: net/socket.c
    ===================================================================
    RCS file: /cvs/lsm/lsm/net/socket.c,v
    retrieving revision 1.1.1.2
    diff -u -r1.1.1.2 socket.c
    --- net/socket.c	2001/06/18 19:26:34	1.1.1.2
    +++ net/socket.c	2001/07/23 15:43:04
    @@ -507,6 +507,10 @@
     	int err;
     	struct scm_cookie scm;
     
    +	err = security_ops->socket_ops->sendmsg(sock, msg, size);
    +	if (err)
    +		return err;
    +
     	err = scm_send(sock, msg, &scm);
     	if (err >= 0) {
     		err = sock->ops->sendmsg(sock, msg, size, &scm);
    @@ -518,6 +522,11 @@
     int sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags)
     {
     	struct scm_cookie scm;
    +	int err;
    +
    +	err = security_ops->socket_ops->recvmsg(sock, msg, size, flags);
    +	if (err)
    +		return err;
     
     	memset(&scm, 0, sizeof(scm));
     
    @@ -836,6 +845,7 @@
     int sock_create(int family, int type, int protocol, struct socket **res)
     {
     	int i;
    +	int err;
     	struct socket *sock;
     
     	/*
    @@ -857,6 +867,13 @@
     		}
     		family = PF_PACKET;
     	}
    +
    +	/*
    +	 * Don't even allow modules to be loaded if this fails.
    +	 */
    +	err = security_ops->socket_ops->create(family, type, protocol);
    +	if (err)
    +		return err;
     		
     #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
     	/* Attempt to load a protocol module if the find failed. 
    @@ -903,6 +920,8 @@
     
     	*res = sock;
     
    +	security_ops->socket_ops->post_create(sock, family, type, protocol);
    +
     out:
     	net_family_read_unlock();
     	return i;
    @@ -1012,8 +1031,14 @@
     
     	if((sock = sockfd_lookup(fd,&err))!=NULL)
     	{
    -		if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0)
    +		if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
    +			err = security_ops->socket_ops->bind(sock, (struct sockaddr *)address, addrlen);
    +			if (err) {
    +				sockfd_put(sock);
    +				return err;
    +			}
     			err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
    +		}
     		sockfd_put(sock);
     	}			
     	return err;
    @@ -1034,6 +1059,13 @@
     	if ((sock = sockfd_lookup(fd, &err)) != NULL) {
     		if ((unsigned) backlog > SOMAXCONN)
     			backlog = SOMAXCONN;
    +
    +		err = security_ops->socket_ops->listen(sock, backlog);
    +		if (err) {
    +			sockfd_put(sock);
    +			return err;
    +		}
    +
     		err=sock->ops->listen(sock, backlog);
     		sockfd_put(sock);
     	}
    @@ -1070,6 +1102,10 @@
     	newsock->type = sock->type;
     	newsock->ops = sock->ops;
     
    +	err = security_ops->socket_ops->accept(sock, newsock);
    +	if (err)
    +		goto out_release;
    +
     	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
     	if (err < 0)
     		goto out_release;
    @@ -1124,8 +1160,14 @@
     	err = move_addr_to_kernel(uservaddr, addrlen, address);
     	if (err < 0)
     		goto out_put;
    +
    +	err = security_ops->socket_ops->connect(sock, (struct sockaddr *)address, addrlen);
    +	if (err)
    +		goto out_put;
    +
     	err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
     				 sock->file->f_flags);
    +
     out_put:
     	sockfd_put(sock);
     out:
    @@ -1146,6 +1188,11 @@
     	sock = sockfd_lookup(fd, &err);
     	if (!sock)
     		goto out;
    +
    +	err = security_ops->socket_ops->getsockname(sock);
    +	if (err)
    +		goto out_put;
    +
     	err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
     	if (err)
     		goto out_put;
    @@ -1170,6 +1217,12 @@
     
     	if ((sock = sockfd_lookup(fd, &err))!=NULL)
     	{
    +		err = security_ops->socket_ops->getpeername(sock);
    +		if (err) {
    +			sockfd_put(sock);
    +			return err;
    +		}
    +
     		err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
     		if (!err)
     			err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
    @@ -1297,6 +1350,12 @@
     			
     	if ((sock = sockfd_lookup(fd, &err))!=NULL)
     	{
    +		err = security_ops->socket_ops->setsockopt(sock,level,optname);
    +		if (err) {
    +			sockfd_put(sock);
    +			return err;
    +		}
    +
     		if (level == SOL_SOCKET)
     			err=sock_setsockopt(sock,level,optname,optval,optlen);
     		else
    @@ -1318,6 +1377,13 @@
     
     	if ((sock = sockfd_lookup(fd, &err))!=NULL)
     	{
    +		err = security_ops->socket_ops->getsockopt(sock, level, 
    +							   optname);
    +		if (err) {
    +			sockfd_put(sock);
    +			return err;
    +		}
    +
     		if (level == SOL_SOCKET)
     			err=sock_getsockopt(sock,level,optname,optval,optlen);
     		else
    @@ -1339,6 +1405,12 @@
     
     	if ((sock = sockfd_lookup(fd, &err))!=NULL)
     	{
    +		err = security_ops->socket_ops->shutdown(sock, how);
    +		if (err) {
    +			sockfd_put(sock);
    +			return err;
    +		}
    +				
     		err=sock->ops->shutdown(sock, how);
     		sockfd_put(sock);
     	}
    
    _______________________________________________
    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 : Mon Jul 23 2001 - 10:17:08 PDT