lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Sat, 21 Jul 2007 00:11:04 +0900
From:	Tetsuo Handa <from-netdev@...ove.SAKURA.ne.jp>
To:	jmorris@...ei.org, shemminger@...ux-foundation.org
Cc:	netdev@...r.kernel.org, linux-security-module@...r.kernel.org
Subject: [PATCH 1/1] Allow LSM to use IP address/port number.

Hello.

> > Isn't it better to hook into existing netfilter infrastructure somehow?
> Yes, it has been suggested several times.
I want to use a process's context who issued
accept()/recv()/recvfrom()/recvmsg()/read() requests.

But Stephen Smalley said at http://marc.info/?l=linux-security-module&m=118459899017487&w=2 that
> The socket can be inherited by a child task or passed via local IPC to
> an unrelated task, and then used by those other tasks.  It isn't tied to
> the original allocating task's lifecycle in any way, nor is it
> guaranteed to only be used by that original allocating task.  It can
> exist in zero, one or many tasks' file tables and still be receiving
> data, and can go from completely disassociated (i.e. not present in any
> tasks' file tables) to being associated.
I can't use netfilter infrastructure because
it is too early to know who the recipant process of the packet is.
The only chance to perform ip/port based filtering
using ACLs associated with the recipant process of the packet
is post-accept() and post-recvmsg().

Therefore, I re-post my patch again.

Regards.

Signed-off-by: Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
---
 include/linux/security.h |   44 +++++++++++++++++++++++++++++++++++++-------
 net/socket.c             |   42 ++++++++++++++++++++++++++++++++++++------
 security/dummy.c         |   13 ++++++++++---
 3 files changed, 83 insertions(+), 16 deletions(-)

diff -upr a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	2007-07-20 22:55:38.000000000 +0900
+++ b/include/linux/security.h	2007-07-20 23:15:58.000000000 +0900
@@ -749,8 +749,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.
+ *	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.
@@ -764,6 +768,15 @@ struct request_sock;
  *	@size contains the size of message structure.
  *	@flags contains the operational flags.
  *	Return 0 if permission is granted.  
+ * @socket_post_recvmsg:
+ *	Check peer's address after receiving a message from a socket.
+ *	This hook allows a security module to filter messages
+ *	from unwanted peers.
+ *	@sock contains the socket structure.
+ *	@msg contains the message structure.
+ *	@size contains the size of message structure.
+ *	@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.
@@ -1345,12 +1358,14 @@ 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_recvmsg) (struct socket *sock, struct msghdr *msg,
+				    int size, int flags);
 	int (*socket_getsockname) (struct socket * sock);
 	int (*socket_getpeername) (struct socket * sock);
 	int (*socket_getsockopt) (struct socket * sock, int level, int optname);
@@ -2860,10 +2875,10 @@ static inline int security_socket_accept
 	return security_ops->socket_accept(sock, newsock);
 }
 
-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)
 {
-	security_ops->socket_post_accept(sock, newsock);
+	return security_ops->socket_post_accept(sock, newsock);
 }
 
 static inline int security_socket_sendmsg(struct socket * sock, 
@@ -2879,6 +2894,13 @@ static inline int security_socket_recvms
 	return security_ops->socket_recvmsg(sock, msg, size, flags);
 }
 
+static inline int security_socket_post_recvmsg(struct socket *sock,
+					       struct msghdr *msg,
+					       int size, int flags)
+{
+	return security_ops->socket_post_recvmsg(sock, msg, size, flags);
+}
+
 static inline int security_socket_getsockname(struct socket * sock)
 {
 	return security_ops->socket_getsockname(sock);
@@ -3023,9 +3045,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, 
@@ -3041,6 +3064,13 @@ static inline int security_socket_recvms
 	return 0;
 }
 
+static inline int security_socket_post_recvmsg(struct socket *sock,
+					       struct msghdr *msg,
+					       int size, int flags)
+{
+	return 0;
+}
+
 static inline int security_socket_getsockname(struct socket * sock)
 {
 	return 0;
diff -upr a/net/socket.c b/net/socket.c
--- a/net/socket.c	2007-07-20 22:55:53.000000000 +0900
+++ b/net/socket.c	2007-07-21 00:05:18.000000000 +0900
@@ -635,7 +635,19 @@ static inline int __sock_recvmsg(struct 
 	if (err)
 		return err;
 
-	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
+	err = sock->ops->recvmsg(iocb, sock, msg, size, flags);
+	/*
+	 * Filter messages from unwanted peers.
+	 * To be exact, this hook can't filter messages,
+	 * this hook just returns an error code.
+	 */
+	if (err >= 0) {
+		int ret;
+		ret = security_socket_post_recvmsg(sock, msg, size, flags);
+		if (ret)
+			err = ret;
+	}
+	return err;
 }
 
 int sock_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -648,8 +660,17 @@ int sock_recvmsg(struct socket *sock, st
 	init_sync_kiocb(&iocb, NULL);
 	iocb.private = &siocb;
 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
-	if (-EIOCBQUEUED == ret)
+	if (-EIOCBQUEUED == ret) {
 		ret = wait_on_sync_kiocb(&iocb);
+		/* I can now check security_socket_post_recvmsg(). */
+		if (ret >= 0) {
+			int err;
+			err = security_socket_post_recvmsg(sock, msg, size,
+							   flags);
+			if (err)
+				ret = err;
+		}
+	}
 	return ret;
 }
 
@@ -712,12 +733,14 @@ static ssize_t do_sock_read(struct msghd
 	struct socket *sock = file->private_data;
 	size_t size = 0;
 	int i;
+	/* only for security_socket_post_recvmsg() */
+	char address[MAX_SOCK_ADDR];
 
 	for (i = 0; i < nr_segs; i++)
 		size += iov[i].iov_len;
 
-	msg->msg_name = NULL;
-	msg->msg_namelen = 0;
+	msg->msg_name = address;
+	msg->msg_namelen = sizeof(address);
 	msg->msg_control = NULL;
 	msg->msg_controllen = 0;
 	msg->msg_iov = (struct iovec *)iov;
@@ -1437,13 +1460,16 @@ asmlinkage long sys_accept(int fd, struc
 			goto out_fd;
 	}
 
+	/* Filter connections from unwanted peers like TCP Wrapper. */
+	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:
@@ -1937,6 +1963,10 @@ asmlinkage long sys_recvmsg(int fd, stru
 		goto out_freeiov;
 	total_len = err;
 
+	/* only for security_socket_post_recvmsg() */
+	msg_sys.msg_name = addr;
+	msg_sys.msg_namelen = sizeof(addr);
+
 	cmsg_ptr = (unsigned long)msg_sys.msg_control;
 	msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
 
diff -upr a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	2007-07-20 22:55:54.000000000 +0900
+++ b/security/dummy.c	2007-07-20 23:15:22.000000000 +0900
@@ -741,10 +741,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,
@@ -759,6 +759,12 @@ static int dummy_socket_recvmsg (struct 
 	return 0;
 }
 
+static int dummy_socket_post_recvmsg(struct socket *sock, struct msghdr *msg,
+				     int size, int flags)
+{
+	return 0;
+}
+
 static int dummy_socket_getsockname (struct socket *sock)
 {
 	return 0;
@@ -1096,6 +1102,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_recvmsg);
 	set_to_dummy_if_null(ops, socket_getsockname);
 	set_to_dummy_if_null(ops, socket_getpeername);
 	set_to_dummy_if_null(ops, socket_setsockopt);
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ