LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Kentaro Takeda <takedakn@nttdata.co.jp>
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	Kentaro Takeda <takedakn@nttdata.co.jp>,
	Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Subject: [TOMOYO #6 retry 05/21] Add packet filtering based on processs security context.
Date: Wed, 09 Jan 2008 09:53:25 +0900	[thread overview]
Message-ID: <20080109005419.951580769@nttdata.co.jp> (raw)
In-Reply-To: <20080109005320.323184643@nttdata.co.jp>

This patch allows LSM modules filter incoming connections/datagrams
based on the process's security context who is attempting to pick up.

There are already hooks to filter incoming connections/datagrams
based on the socket's security context, but these hooks are not
applicable when one wants to do TCP Wrapper-like filtering
(e.g. App1 is permitted to accept TCP connections from 192.168.0.0/16).

Precautions: This approach has a side effect which unlikely occurs.

If a socket is shared by multiple processes with differnt policy,
the process who should be able to accept this connection
will not be able to accept this connection
because socket_post_accept() aborts this connection.
But if socket_post_accept() doesn't abort this connection,
the process who must not be able to accept this connection
will repeat accept() forever, which is a worse side effect.

Similarly, if a socket is shared by multiple processes with differnt policy,
the process who should be able to pick up this datagram
will not be able to pick up this datagram
because socket_post_recv_datagram() discards this datagram.
But if socket_post_recv_datagram() doesn't discard this datagram,
the process who must not be able to pick up this datagram
will repeat recvmsg() forever, which is a worse side effect.

So, don't give different permissions between processes who shares one socket.
Otherwise, some connections/datagrams cannot be delivered to intended process.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 include/linux/security.h |   34 +++++++++++++++++++++++++++++-----
 net/core/datagram.c      |   29 ++++++++++++++++++++++++++++-
 net/socket.c             |    7 +++++--
 security/dummy.c         |   13 ++++++++++---
 security/security.c      |   10 ++++++++--
 5 files changed, 80 insertions(+), 13 deletions(-)

--- linux-2.6-mm.orig/include/linux/security.h
+++ linux-2.6-mm/include/linux/security.h
@@ -795,8 +795,12 @@ struct request_sock;
  * @socket_post_accept:
  *	This hook allows a security module to copy security
  *	information into the newly created socket's inode.
+ *	This hook also allows a security module to filter connections
+ *	from unwanted peers based on the process accepting this connection.
+ *	The connection will be aborted if this hook returns nonzero.
  *	@sock contains the listening socket structure.
  *	@newsock contains the newly created server socket for connection.
+ *	Return 0 if permission is granted.
  * @socket_sendmsg:
  *	Check permission before transmitting a message to another socket.
  *	@sock contains the socket structure.
@@ -810,6 +814,15 @@ struct request_sock;
  *	@size contains the size of message structure.
  *	@flags contains the operational flags.
  *	Return 0 if permission is granted.  
+ * @socket_post_recv_datagram:
+ *	Check permission after receiving a datagram.
+ *	This hook allows a security module to filter packets
+ *	from unwanted peers based on the process receiving this datagram.
+ *	The packet will be discarded if this hook returns nonzero.
+ *	@sk contains the socket.
+ *	@skb contains the socket buffer.
+ *	@flags contains the operational flags.
+ *	Return 0 if permission is granted.
  * @socket_getsockname:
  *	Check permission before the local address (name) of the socket object
  *	@sock is retrieved.
@@ -1417,12 +1430,13 @@ struct security_operations {
 			       struct sockaddr * address, int addrlen);
 	int (*socket_listen) (struct socket * sock, int backlog);
 	int (*socket_accept) (struct socket * sock, struct socket * newsock);
-	void (*socket_post_accept) (struct socket * sock,
-				    struct socket * newsock);
+	int (*socket_post_accept) (struct socket *sock, struct socket *newsock);
 	int (*socket_sendmsg) (struct socket * sock,
 			       struct msghdr * msg, int size);
 	int (*socket_recvmsg) (struct socket * sock,
 			       struct msghdr * msg, int size, int flags);
+	int (*socket_post_recv_datagram) (struct sock *sk, struct sk_buff *skb,
+					  unsigned int flags);
 	int (*socket_getsockname) (struct socket * sock);
 	int (*socket_getpeername) (struct socket * sock);
 	int (*socket_getsockopt) (struct socket * sock, int level, int optname);
@@ -2343,10 +2357,12 @@ int security_socket_bind(struct socket *
 int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen);
 int security_socket_listen(struct socket *sock, int backlog);
 int security_socket_accept(struct socket *sock, struct socket *newsock);
-void security_socket_post_accept(struct socket *sock, struct socket *newsock);
+int security_socket_post_accept(struct socket *sock, struct socket *newsock);
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size);
 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
 			    int size, int flags);
+int security_socket_post_recv_datagram(struct sock *sk, struct sk_buff *skb,
+				       unsigned int flags);
 int security_socket_getsockname(struct socket *sock);
 int security_socket_getpeername(struct socket *sock);
 int security_socket_getsockopt(struct socket *sock, int level, int optname);
@@ -2423,9 +2439,10 @@ static inline int security_socket_accept
 	return 0;
 }
 
-static inline void security_socket_post_accept(struct socket * sock, 
-					       struct socket * newsock)
+static inline int security_socket_post_accept(struct socket *sock,
+					      struct socket *newsock)
 {
+	return 0;
 }
 
 static inline int security_socket_sendmsg(struct socket * sock, 
@@ -2441,6 +2458,13 @@ static inline int security_socket_recvms
 	return 0;
 }
 
+static inline int security_socket_post_recv_datagram(struct sock *sk,
+						     struct sk_buff *skb,
+						     unsigned int flags)
+{
+	return 0;
+}
+
 static inline int security_socket_getsockname(struct socket * sock)
 {
 	return 0;
--- linux-2.6-mm.orig/net/socket.c
+++ linux-2.6-mm/net/socket.c
@@ -1454,13 +1454,16 @@ asmlinkage long sys_accept(int fd, struc
 			goto out_fd;
 	}
 
+	/* Filter connections from unwanted peers. */
+	err = security_socket_post_accept(sock, newsock);
+	if (err)
+		goto out_fd;
+
 	/* File flags are not inherited via accept() unlike another OSes. */
 
 	fd_install(newfd, newfile);
 	err = newfd;
 
-	security_socket_post_accept(sock, newsock);
-
 out_put:
 	fput_light(sock->file, fput_needed);
 out:
--- linux-2.6-mm.orig/security/dummy.c
+++ linux-2.6-mm/security/dummy.c
@@ -776,10 +776,10 @@ static int dummy_socket_accept (struct s
 	return 0;
 }
 
-static void dummy_socket_post_accept (struct socket *sock, 
-				      struct socket *newsock)
+static int dummy_socket_post_accept(struct socket *sock,
+				    struct socket *newsock)
 {
-	return;
+	return 0;
 }
 
 static int dummy_socket_sendmsg (struct socket *sock, struct msghdr *msg,
@@ -794,6 +794,12 @@ static int dummy_socket_recvmsg (struct 
 	return 0;
 }
 
+static int dummy_socket_post_recv_datagram(struct sock *sk, struct sk_buff *skb,
+					   unsigned int flags)
+{
+	return 0;
+}
+
 static int dummy_socket_getsockname (struct socket *sock)
 {
 	return 0;
@@ -1141,6 +1147,7 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, socket_post_accept);
 	set_to_dummy_if_null(ops, socket_sendmsg);
 	set_to_dummy_if_null(ops, socket_recvmsg);
+	set_to_dummy_if_null(ops, socket_post_recv_datagram);
 	set_to_dummy_if_null(ops, socket_getsockname);
 	set_to_dummy_if_null(ops, socket_getpeername);
 	set_to_dummy_if_null(ops, socket_setsockopt);
--- linux-2.6-mm.orig/net/core/datagram.c
+++ linux-2.6-mm/net/core/datagram.c
@@ -55,6 +55,7 @@
 #include <net/checksum.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
+#include <linux/security.h>
 
 /*
  *	Is a socket 'connection oriented' ?
@@ -148,6 +149,7 @@ struct sk_buff *__skb_recv_datagram(stru
 {
 	struct sk_buff *skb;
 	long timeo;
+	unsigned long cpu_flags;
 	/*
 	 * Caller is allowed not to check sk->sk_err before skb_recv_datagram()
 	 */
@@ -165,7 +167,6 @@ struct sk_buff *__skb_recv_datagram(stru
 		 * Look at current nfs client by the way...
 		 * However, this function was corrent in any case. 8)
 		 */
-		unsigned long cpu_flags;
 
 		spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
 		skb = skb_peek(&sk->sk_receive_queue);
@@ -179,6 +180,14 @@ struct sk_buff *__skb_recv_datagram(stru
 		}
 		spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
 
+		/* Filter packets from unwanted peers. */
+		if (skb) {
+			error = security_socket_post_recv_datagram(sk, skb,
+								   flags);
+			if (error)
+				goto force_dequeue;
+		}
+
 		if (skb)
 			return skb;
 
@@ -191,6 +200,24 @@ struct sk_buff *__skb_recv_datagram(stru
 
 	return NULL;
 
+force_dequeue:
+	/* Drop this packet because LSM says "Don't pass it to the caller". */
+	if (!(flags & MSG_PEEK))
+		goto no_peek;
+	/*
+	 * If this packet is MSG_PEEK'ed, dequeue it forcibly
+	 * so that this packet won't prevent the caller from picking up
+	 * next packet.
+	 */
+	spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
+	if (skb == skb_peek(&sk->sk_receive_queue)) {
+		__skb_unlink(skb, &sk->sk_receive_queue);
+		atomic_dec(&skb->users);
+		/* Do I have something to do with skb->peeked ? */
+	}
+	spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
+no_peek:
+	kfree_skb(skb);
 no_packet:
 	*err = error;
 	return NULL;
--- linux-2.6-mm.orig/security/security.c
+++ linux-2.6-mm/security/security.c
@@ -895,9 +895,9 @@ int security_socket_accept(struct socket
 	return security_ops->socket_accept(sock, newsock);
 }
 
-void security_socket_post_accept(struct socket *sock, struct socket *newsock)
+int security_socket_post_accept(struct socket *sock, struct socket *newsock)
 {
-	security_ops->socket_post_accept(sock, newsock);
+	return security_ops->socket_post_accept(sock, newsock);
 }
 
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
@@ -911,6 +911,12 @@ int security_socket_recvmsg(struct socke
 	return security_ops->socket_recvmsg(sock, msg, size, flags);
 }
 
+int security_socket_post_recv_datagram(struct sock *sk, struct sk_buff *skb,
+				       unsigned int flags)
+{
+	return security_ops->socket_post_recv_datagram(sk, skb, flags);
+}
+
 int security_socket_getsockname(struct socket *sock)
 {
 	return security_ops->socket_getsockname(sock);

-- 

  parent reply	other threads:[~2008-01-09  0:56 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-09  0:53 [TOMOYO #6 retry 00/21] TOMOYO Linux - MAC based on process invocation history Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 01/21] TOMOYO Linux documentation Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 02/21] Add struct vfsmount to struct task_struct Kentaro Takeda
2008-01-15 21:16   ` Serge E. Hallyn
2008-01-16  0:22     ` Kentaro Takeda
2008-01-16 14:39       ` Serge E. Hallyn
2008-01-17  4:55         ` Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 03/21] Add wrapper functions for VFS helper functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 04/21] Replace VFS with wrapper functions Kentaro Takeda
2008-01-09  0:53 ` Kentaro Takeda [this message]
2008-01-09  0:53 ` [TOMOYO #6 retry 06/21] Data structures and prototype defitions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 07/21] Memory and pathname management functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 08/21] Utility functions and policy manipulation interface Kentaro Takeda
2008-01-09  4:25   ` James Morris
2008-01-09  4:29     ` James Morris
2008-01-12  2:06       ` [TOMOYO #6 retry 08/21] Utility functions and policy manipulationinterface Tetsuo Handa
2008-01-12  3:06         ` James Morris
2008-01-12  4:45         ` Greg KH
2008-01-12  7:34           ` [TOMOYO #6 retry 08/21] Utility functions and policymanipulationinterface Tetsuo Handa
2008-01-09  4:31     ` [TOMOYO #6 retry 08/21] Utility functions and policy manipulation interface Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 09/21] Domain transition functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 10/21] Auditing interface Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 11/21] File access control functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 12/21] argv0 check functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 13/21] environment variable name " Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 14/21] Network access control functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 15/21] Namespace manipulation " Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 16/21] Signal " Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 17/21] Capability access " Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 18/21] LSM adapter functions Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 19/21] Conditional permission support Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 20/21] Kconfig and Makefile Kentaro Takeda
2008-01-09  0:53 ` [TOMOYO #6 retry 21/21] Add signal hooks at sleepable location Kentaro Takeda

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080109005419.951580769@nttdata.co.jp \
    --to=takedakn@nttdata.co.jp \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=penguin-kernel@I-love.SAKURA.ne.jp \
    --subject='Re: [TOMOYO #6 retry 05/21] Add packet filtering based on processs security context.' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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).