[RFC,v3,02/10] Revert "lsm: Remove the socket_post_accept() hook"

Message ID 1304432663-1575-3-git-send-email-sam@synack.fr
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Samir Bellabes May 3, 2011, 2:24 p.m.
snet needs to reintroduce this hook, as it was designed to be: a hook for
updating security informations on objects.

Originally, This was a direct revert of commit
8651d5c0b1f874c5b8307ae2b858bc40f9f02482.

But from the comment of Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> :

> Please move security_socket_post_accept() to before fd_install().
> Otherwise, other threads which share fd tables can use
> security-informations-not-yet-updated accept()ed sockets.

Signed-off-by: Samir Bellabes <sam@synack.fr>
Acked-by: Serge Hallyn <serue@us.ibm.com>

snet needs to reintroduce this hook, as it was designed to be: a hook for
updating security informations on objects.

Signed-off-by: Samir Bellabes <sam@synack.fr>
---
 include/linux/security.h |   13 +++++++++++++
 net/socket.c             |    2 ++
 security/capability.c    |    5 +++++
 security/security.c      |    5 +++++
 4 files changed, 25 insertions(+), 0 deletions(-)

Comments

Paul Moore May 3, 2011, 10:02 p.m. | #1
On Tuesday, May 03, 2011 10:24:15 AM Samir Bellabes wrote:
> snet needs to reintroduce this hook, as it was designed to be: a hook for
> updating security informations on objects.

Looking at this and 5/10 again, it seems that you should be able to do what 
you need with the sock_graft() hook.  Am I missing something?

My apologies if we've already discussed this approach previously ...

> Originally, This was a direct revert of commit
> 8651d5c0b1f874c5b8307ae2b858bc40f9f02482.
> 
> But from the comment of Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> :
> > Please move security_socket_post_accept() to before fd_install().
> > Otherwise, other threads which share fd tables can use
> > security-informations-not-yet-updated accept()ed sockets.
> 
> Signed-off-by: Samir Bellabes <sam@synack.fr>
> Acked-by: Serge Hallyn <serue@us.ibm.com>
> 
> snet needs to reintroduce this hook, as it was designed to be: a hook for
> updating security informations on objects.
> 
> Signed-off-by: Samir Bellabes <sam@synack.fr>
> ---
>  include/linux/security.h |   13 +++++++++++++
>  net/socket.c             |    2 ++
>  security/capability.c    |    5 +++++
>  security/security.c      |    5 +++++
>  4 files changed, 25 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/security.h b/include/linux/security.h
> index da0d59e..02effe5 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -875,6 +875,11 @@ static inline void security_free_mnt_opts(struct
> security_mnt_opts *opts) *	@sock contains the listening socket structure.
>   *	@newsock contains the newly created server socket for connection.
>   *	Return 0 if permission is granted.
> + * @socket_post_accept:
> + *	This hook allows a security module to copy security
> + *	information into the newly created socket's inode.
> + *	@sock contains the listening socket structure.
> + *	@newsock contains the newly created server socket for connection.
>   * @socket_sendmsg:
>   *	Check permission before transmitting a message to another socket.
>   *	@sock contains the socket structure.
> @@ -1587,6 +1592,8 @@ 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_sendmsg) (struct socket *sock,
>  			       struct msghdr *msg, int size);
>  	int (*socket_recvmsg) (struct socket *sock,
> @@ -2555,6 +2562,7 @@ int security_socket_bind(struct socket *sock, struct
> sockaddr *address, int addr 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_sendmsg(struct socket *sock, struct msghdr
> *msg, int size); int security_socket_recvmsg(struct socket *sock, struct
> msghdr *msg, int size, int flags);
> @@ -2640,6 +2648,11 @@ static inline int security_socket_accept(struct
> socket *sock, return 0;
>  }
> 
> +static inline void security_socket_post_accept(struct socket *sock,
> +					       struct socket *newsock)
> +{
> +}
> +
>  static inline int security_socket_sendmsg(struct socket *sock,
>  					  struct msghdr *msg, int size)
>  {
> diff --git a/net/socket.c b/net/socket.c
> index d588e9e..7807904 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -1535,6 +1535,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr
> __user *, upeer_sockaddr, goto out_fd;
>  	}
> 
> +	security_socket_post_accept(sock, newsock);
> +
>  	/* File flags are not inherited via accept() unlike another OSes. */
> 
>  	fd_install(newfd, newfile);
> diff --git a/security/capability.c b/security/capability.c
> index 1f8bbe2..da68c60 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -593,6 +593,10 @@ static int cap_socket_accept(struct socket *sock,
> struct socket *newsock) return 0;
>  }
> 
> +static void cap_socket_post_accept(struct socket *sock, struct socket
> *newsock) +{
> +}
> +
>  static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int
> size) {
>  	return 0;
> @@ -1022,6 +1026,7 @@ void __init security_fixup_ops(struct
> security_operations *ops) set_to_cap_if_null(ops, socket_connect);
>  	set_to_cap_if_null(ops, socket_listen);
>  	set_to_cap_if_null(ops, socket_accept);
> +	set_to_cap_if_null(ops, socket_post_accept);
>  	set_to_cap_if_null(ops, socket_sendmsg);
>  	set_to_cap_if_null(ops, socket_recvmsg);
>  	set_to_cap_if_null(ops, socket_getsockname);
> diff --git a/security/security.c b/security/security.c
> index 84187d8..eda2b75 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1038,6 +1038,11 @@ int security_socket_accept(struct socket *sock,
> struct socket *newsock) return security_ops->socket_accept(sock, newsock);
>  }
> 
> +void security_socket_post_accept(struct socket *sock, struct socket
> *newsock) +{
> +	security_ops->socket_post_accept(sock, newsock);
> +}
> +
>  int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int
> size) {
>  	return security_ops->socket_sendmsg(sock, msg, size);


--
paul moore
linux @ hp
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tetsuo Handa May 4, 2011, 2:28 a.m. | #2
Paul Moore wrote:
> On Tuesday, May 03, 2011 10:24:15 AM Samir Bellabes wrote:
> > snet needs to reintroduce this hook, as it was designed to be: a hook for
> > updating security informations on objects.
> 
> Looking at this and 5/10 again, it seems that you should be able to do what 
> you need with the sock_graft() hook.  Am I missing something?
> 
> My apologies if we've already discussed this approach previously ...

static void snet_socket_post_accept(struct socket *sock, struct socket *newsock)
{
	static void snet_do_send_event(struct snet_info *info)
	{
		int snet_nl_send_event(struct snet_info *info)
		{
			skb_rsp = genlmsg_new(size, GFP_KERNEL);
			genlmsg_unicast()
		}
	}
}

First problem with using snet_do_send_event() from security_sock_graft() is
that we have to use GFP_ATOMIC rather than GFP_KERNEL because we are inside
write_lock_bh()/write_unlock_bh().

static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 pid)
{
	static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32 pid)
	{
		int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
			u32 pid, MSG_DONTWAIT)
		{
			int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
				      long *timeo, struct sock *ssk)
			{
				if (!*timeo) {
					return -EAGAIN;
			}
		}
	}
}

Second problem is that genlmsg_unicast() might return -EAGAIN because we can't
sleep inside write_lock_bh()/write_unlock_bh().

Third problem (though independent with security_sock_graft()) is that
snet_do_send_event() ignores snet_nl_send_event() failure.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Samir Bellabes May 4, 2011, 8:50 a.m. | #3
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> writes:

> Paul Moore wrote:
>> On Tuesday, May 03, 2011 10:24:15 AM Samir Bellabes wrote:
>> > snet needs to reintroduce this hook, as it was designed to be: a hook for
>> > updating security informations on objects.
>> 
>> Looking at this and 5/10 again, it seems that you should be able to do what 
>> you need with the sock_graft() hook.  Am I missing something?
>> 
>> My apologies if we've already discussed this approach previously ...
>
> Third problem (though independent with security_sock_graft()) is that
> snet_do_send_event() ignores snet_nl_send_event() failure.

using snet_do_send_event() means that system is sending data to
userspace. the system is not waiting for a verdict from userspace.

If error occurs, we actually loose the information data.
I may be able to write a solution which try to send the data again, but
we need a exit solution for this loop (a number of try ?).
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Moore May 5, 2011, 2:11 p.m. | #4
On Tuesday, May 03, 2011 10:28:24 PM Tetsuo Handa wrote:
> Paul Moore wrote:
> > On Tuesday, May 03, 2011 10:24:15 AM Samir Bellabes wrote:
> > > snet needs to reintroduce this hook, as it was designed to be: a hook
> > > for updating security informations on objects.
> > 
> > Looking at this and 5/10 again, it seems that you should be able to do
> > what you need with the sock_graft() hook.  Am I missing something?
> > 
> > My apologies if we've already discussed this approach previously ...
> 
> static void snet_socket_post_accept(struct socket *sock, struct socket
> *newsock) {
> 	static void snet_do_send_event(struct snet_info *info)
> 	{
> 		int snet_nl_send_event(struct snet_info *info)
> 		{
> 			skb_rsp = genlmsg_new(size, GFP_KERNEL);
> 			genlmsg_unicast()
> 		}
> 	}
> }
> 
> First problem with using snet_do_send_event() from security_sock_graft() is
> that we have to use GFP_ATOMIC rather than GFP_KERNEL because we are inside
> write_lock_bh()/write_unlock_bh().

I guess I don't see that as being a blocker ...

> static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32
> pid) {
> 	static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32
> pid) {
> 		int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
> 			u32 pid, MSG_DONTWAIT)
> 		{
> 			int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
> 				      long *timeo, struct sock *ssk)
> 			{
> 				if (!*timeo) {
> 					return -EAGAIN;
> 			}
> 		}
> 	}
> }
> 
> Second problem is that genlmsg_unicast() might return -EAGAIN because we
> can't sleep inside write_lock_bh()/write_unlock_bh().

Ah yes, the real problem.  I forgot that snet relied on a user space tool.  I 
tend to agree with others who have suggested this is not the right approach, 
but I understand why you want the post_accept() hook; thanks for reminding me.

--
paul moore
linux @ hp
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tetsuo Handa May 5, 2011, 9:43 p.m. | #5
Paul Moore wrote:
> On Tuesday, May 03, 2011 10:28:24 PM Tetsuo Handa wrote:
> > Paul Moore wrote:
> > > On Tuesday, May 03, 2011 10:24:15 AM Samir Bellabes wrote:
> > > > snet needs to reintroduce this hook, as it was designed to be: a hook
> > > > for updating security informations on objects.
> > > 
> > > Looking at this and 5/10 again, it seems that you should be able to do
> > > what you need with the sock_graft() hook.  Am I missing something?
> > > 
> > > My apologies if we've already discussed this approach previously ...
> > 
> > Second problem is that genlmsg_unicast() might return -EAGAIN because we
> > can't sleep inside write_lock_bh()/write_unlock_bh().
> 
> Ah yes, the real problem.  I forgot that snet relied on a user space tool.  I 
> tend to agree with others who have suggested this is not the right approach, 
> but I understand why you want the post_accept() hook; thanks for reminding me.
> 
However, it sounds that Samir says genlmsg_unicast() failure is not fatal.

Samir Bellabes wrote:
> using snet_do_send_event() means that system is sending data to
> userspace. the system is not waiting for a verdict from userspace.
> 
> If error occurs, we actually loose the information data.
> I may be able to write a solution which try to send the data again, but
> we need a exit solution for this loop (a number of try ?).

If genlmsg_unicast() failure is not fatal, snet doesn't need the
socket_post_accept hook. Samir, is genlmsg_unicast() failure fatal for snet?
(Although, I'd like to ask for revival of the hook for TOMOYO anyway.)
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/include/linux/security.h b/include/linux/security.h
index da0d59e..02effe5 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -875,6 +875,11 @@  static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@sock contains the listening socket structure.
  *	@newsock contains the newly created server socket for connection.
  *	Return 0 if permission is granted.
+ * @socket_post_accept:
+ *	This hook allows a security module to copy security
+ *	information into the newly created socket's inode.
+ *	@sock contains the listening socket structure.
+ *	@newsock contains the newly created server socket for connection.
  * @socket_sendmsg:
  *	Check permission before transmitting a message to another socket.
  *	@sock contains the socket structure.
@@ -1587,6 +1592,8 @@  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_sendmsg) (struct socket *sock,
 			       struct msghdr *msg, int size);
 	int (*socket_recvmsg) (struct socket *sock,
@@ -2555,6 +2562,7 @@  int security_socket_bind(struct socket *sock, struct sockaddr *address, int addr
 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_sendmsg(struct socket *sock, struct msghdr *msg, int size);
 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
 			    int size, int flags);
@@ -2640,6 +2648,11 @@  static inline int security_socket_accept(struct socket *sock,
 	return 0;
 }
 
+static inline void security_socket_post_accept(struct socket *sock,
+					       struct socket *newsock)
+{
+}
+
 static inline int security_socket_sendmsg(struct socket *sock,
 					  struct msghdr *msg, int size)
 {
diff --git a/net/socket.c b/net/socket.c
index d588e9e..7807904 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1535,6 +1535,8 @@  SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
 			goto out_fd;
 	}
 
+	security_socket_post_accept(sock, newsock);
+
 	/* File flags are not inherited via accept() unlike another OSes. */
 
 	fd_install(newfd, newfile);
diff --git a/security/capability.c b/security/capability.c
index 1f8bbe2..da68c60 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -593,6 +593,10 @@  static int cap_socket_accept(struct socket *sock, struct socket *newsock)
 	return 0;
 }
 
+static void cap_socket_post_accept(struct socket *sock, struct socket *newsock)
+{
+}
+
 static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
 	return 0;
@@ -1022,6 +1026,7 @@  void __init security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, socket_connect);
 	set_to_cap_if_null(ops, socket_listen);
 	set_to_cap_if_null(ops, socket_accept);
+	set_to_cap_if_null(ops, socket_post_accept);
 	set_to_cap_if_null(ops, socket_sendmsg);
 	set_to_cap_if_null(ops, socket_recvmsg);
 	set_to_cap_if_null(ops, socket_getsockname);
diff --git a/security/security.c b/security/security.c
index 84187d8..eda2b75 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1038,6 +1038,11 @@  int security_socket_accept(struct socket *sock, struct socket *newsock)
 	return security_ops->socket_accept(sock, newsock);
 }
 
+void security_socket_post_accept(struct socket *sock, struct socket *newsock)
+{
+	security_ops->socket_post_accept(sock, newsock);
+}
+
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
 	return security_ops->socket_sendmsg(sock, msg, size);