Introduce LSM-hook for socketpair(2)
Subsystems (6)
v2 cover Introduce LSM-hook for socketpair(2)
Hi
This is v2 of the socketpair(2) LSM hook introduction. Changes since v1 are:
- Added ACKs from previous series.
- Moved the hook into generic socketpair(2) handling. The hook is now called security_socket_socketpair(), just like the other hooks on the socket layer.
There is no AF_UNIX specific code, anymore.
- Added SMACK support.
- Still *NO* AppArmor support, since upstream AppArmor lacks SO_PEERSEC support and requires downstream patches (in particular, the apparmor_unix_stream_connect() function is mostly a stub and was never synced with Ubuntu downstream modifications).
Old cover letter follows (only trivial changes).
Thanks
David
This series adds a new LSM hook for the socketpair(2) syscall. The idea is to allow SO_PEERSEC to be called on AF_UNIX sockets created via socketpair(2), and return the same information as if you emulated socketpair(2) via a temporary listener socket. Right now SO_PEERSEC will return the unlabeled credentials for a socketpair, rather than the actual credentials of the creating process.
A simple call to:
socketpair(AF_UNIX, SOCK_STREAM, 0, out);
can be emulated via a temporary listener socket bound to a unique, random name in the abstract namespace. By connecting to this listener socket, accept(2) will return the second part of the pair. If SO_PEERSEC is queried on these, the correct credentials of the creating process are returned. A simple comparison between the behavior of SO_PEERSEC on socketpair(2) and an emulated socketpair is included in the dbus-broker test-suite [1].
This patch series tries to close this gap and makes both behave the same. A new LSM-hook is added which allows LSMs to cache the correct peer information on newly created socket-pairs.
Apart from fixing this behavioral difference, the dbus-broker project actually needs to query the credentials of socketpairs, and currently must resort to racy procfs(2) queries to get the LSM credentials of its controller socket. Several parts of the dbus-broker project allow you to pass in a socket during execve(2), which will be used by the child process to accept control-commands from its parent. One natural way to create this communication channel is to use socketpair(2). However, right now SO_PEERSEC does not return any useful information, hence, the child-process would need other means to retrieve this information. By avoiding socketpair(2) and using the hacky-emulated version, this is not an issue.
There was a previous discussion on this matter [2] roughly a year ago. Back then there was the suspicion that proper SO_PEERSEC would confuse applications. However, we could not find any evidence backing this suspicion. Furthermore, we now actually see the contrary. Lack of SO_PEERSEC makes it a hassle to use socketpairs with LSM credentials. Hence, we propose to implement full SO_PEERSEC for socketpairs.
Thanks
David
[1] https://github.com/bus1/dbus-broker/blob/master/src/util/test-peersec.c
[2] https://www.spinics.net/lists/selinux/msg22674.html
David Herrmann (3):
security: add hook for socketpair()
net: hook socketpair() into LSM
selinux: provide socketpair callback
Tom Gundersen (1):
smack: provide socketpair callback
include/linux/lsm_hooks.h | 7 +++++++ include/linux/security.h | 7 +++++++ net/socket.c | 7 +++++++ security/security.c | 6 ++++++ security/selinux/hooks.c | 13 +++++++++++++ security/smack/smack_lsm.c | 22 ++++++++++++++++++++++ 6 files changed, 62 insertions(+)
Signature · 6 lines
2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 1/4 security: add hook for socketpair()
Right now the LSM labels for socketpairs are always uninitialized, since there is no security hook for the socketpair() syscall. This patch adds the required hooks so LSMs can properly label socketpairs. This allows SO_PEERSEC to return useful information on those sockets.
Note that the behavior of socketpair() can be emulated by creating a listener socket, connecting to it, and then discarding the initial listener socket. With this workaround, SO_PEERSEC would return the caller's security context. However, with socketpair(), the uninitialized context is returned unconditionally. This is unexpected and makes socketpair() less useful in situations where the security context is crucial to the application.
With the new socketpair-hook this disparity can be solved by making socketpair() return the expected security context.
--- include/linux/lsm_hooks.h | 7 +++++++ include/linux/security.h | 7 +++++++ security/security.c | 6 ++++++ 3 files changed, 20 insertions(+)
include/linux/lsm_hooks.h +7 -0
@@ -757,6 +757,11 @@* @type contains the requested communications type. * @protocol contains the requested protocol. * @kern set to 1 if a kernel socket. +* @socket_socketpair: +* Check permissions before creating a fresh pair of sockets. +* @socka contains the first socket structure. +* @sockb contains the second socket structure. +* Return 0 if permission is granted and the connection was established. * @socket_bind: * Check permission before socket protocol layer bind operation is * performed and the socket @sock is bound to the address specified in the
@@ -1656,6 +1661,7 @@ union security_list_options {int (*socket_create)(int family,int type,int protocol,int kern);int (*socket_post_create)(struct socket *sock,int family,int type,int protocol,int kern); +int (*socket_socketpair)(struct socket *socka,struct socket *sockb);int (*socket_bind)(struct socket *sock,struct sockaddr *address,int addrlen); int (*socket_connect)(struct socket *sock, struct sockaddr *address,
@@ -1922,6 +1928,7 @@ struct security_hook_heads {struct hlist_head unix_may_send;struct hlist_head socket_create;struct hlist_head socket_post_create; +struct hlist_head socket_socketpair;struct hlist_head socket_bind;struct hlist_head socket_connect;struct hlist_head socket_listen;
include/linux/security.h +7 -0
@@ -1191,6 +1191,7 @@ int security_unix_may_send(struct socket *sock, struct socket *other);int security_socket_create (int family,int type,int protocol,int kern);int security_socket_post_create (struct socket *sock,int family,int type,int protocol,int kern); +int security_socket_socketpair (struct socket *socka,struct socket *sockb);int security_socket_bind (struct socket *sock,struct sockaddr *address,int addrlen);int security_socket_connect (struct socket *sock,struct sockaddr *address,int addrlen);int security_socket_listen (struct socket *sock,int backlog);
@@ -1262,6 +1263,12 @@ static inline int security_socket_post_create(struct socket *sock,return 0 ; } +static inline int security_socket_socketpair (struct socket *socka, +struct socket *sockb) +{ +return 0 ; +} +static inline int security_socket_bind (struct socket *sock,struct sockaddr *address,int addrlen)
security/security.c +6 -0
@@ -1358,6 +1358,12 @@ int security_socket_post_create(struct socket *sock, int family, protocol, kern); } +int security_socket_socketpair (struct socket *socka,struct socket *sockb) +{ +return call_int_hook (socket_socketpair,0 , socka, sockb); +} +EXPORT_SYMBOL (security_socket_socketpair); +int security_socket_bind (struct socket *sock,struct sockaddr *address,int addrlen) {return call_int_hook (socket_bind,0 , sock, address, addrlen);
Signature · 6 lines
2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 2/4 net: hook socketpair() into LSM
In reply to David HerrmannUse the newly created LSM-hook for socketpair(). The default hook return-value is 0, so behavior stays the same unless LSMs start using this hook.
--- net/socket.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/socket.c +7 -0
@@ -1420,6 +1420,13 @@ int __sys_socketpair(int family, int type, int protocol, int __user *usockvec) goto out; } + err =security_socket_socketpair (sock1, sock2); +if (unlikely (err)) { +sock_release (sock2); +sock_release (sock1); + goto out; + } + err = sock1->ops->socketpair (sock1, sock2);if (unlikely (err <0 )) {sock_release (sock2);
Signature · 6 lines
2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org More majordomo info@ http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/4] net: hook socketpair() into LSM
From: David Herrmann <[email protected]>
Date: Fri, 4 May 2018 16:28:20 +0200
Quoted 7 lines
Use the newly created LSM-hook for
socketpair(). The default hook return-value is 0, so behavior stays the same unless LSMs start using this hook.Acked-by Serge Hallyn <[email protected]>Signed-off-by Tom Gundersen <[email protected]>Signed-off-by David Herrmann <[email protected]>
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 3/4 selinux: provide socketpair callback
In reply to David HerrmannMake sure to implement the new socketpair callback so the SO_PEERSEC call on socketpair(2)s will return correct information.
--- security/selinux/hooks.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
security/selinux/hooks.c +13 -0
@@ -4569,6 +4569,18 @@ static int selinux_socket_post_create(struct socket *sock, int family,return err; } +static int selinux_socket_socketpair (struct socket *socka, +struct socket *sockb) +{ +struct sk_security_struct *sksec_a = socka->sk->sk_security; +struct sk_security_struct *sksec_b = sockb->sk->sk_security; + + sksec_a->peer_sid = sksec_b->sid; + sksec_b->peer_sid = sksec_a->sid; + +return 0 ; +} +/* Range of port numbers used to automatically bind. Need to determine whether we should perform a name_bind permission check between the socket and the port number. */
@@ -6999,6 +7011,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {LSM_HOOK_INIT (socket_create, selinux_socket_create),LSM_HOOK_INIT (socket_post_create, selinux_socket_post_create), +LSM_HOOK_INIT (socket_socketpair, selinux_socket_socketpair),LSM_HOOK_INIT (socket_bind, selinux_socket_bind),LSM_HOOK_INIT (socket_connect, selinux_socket_connect), LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
Signature · 6 lines
2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 4/4 smack: provide socketpair callback
In reply to David HerrmannFrom: Tom Gundersen <[email protected]>
Make sure to implement the new socketpair callback so the SO_PEERSEC call on socketpair(2)s will return correct information.
--- security/smack/smack_lsm.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
security/smack/smack_lsm.c +22 -0
@@ -2842,6 +2842,27 @@ static int smack_socket_post_create(struct socket *sock, int family,return smack_netlabel (sock->sk,SMACK_CIPSO_SOCKET ); } +/** +* smack_socket_socketpair - create socket pair +* @socka: one socket +* @sockb: another socket +* +* Cross reference the peer labels for SO_PEERSEC +* +* Returns 0 on success, and error code otherwise +*/ +static int smack_socket_socketpair (struct socket *socka, +struct socket *sockb) +{ +struct socket_smack *asp = socka->sk->sk_security; +struct socket_smack *bsp = sockb->sk->sk_security; + + asp->smk_packet = bsp->smk_out; + bsp->smk_packet = asp->smk_out; + +return 0 ; +} +#ifdef SMACK_IPV6_PORT_LABELING /** * smack_socket_bind - record port binding information.
@@ -4724,6 +4745,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {LSM_HOOK_INIT (unix_may_send, smack_unix_may_send),LSM_HOOK_INIT (socket_post_create, smack_socket_post_create), +LSM_HOOK_INIT (socket_socketpair, smack_socket_socketpair), #ifdef SMACK_IPV6_PORT_LABELING LSM_HOOK_INIT(socket_bind, smack_socket_bind), #endif
Signature · 6 lines
2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 4/4] smack: provide socketpair callback
Quoted 7 lines · David Herrmann
From: Tom Gundersen <[email protected]>
Make sure to implement the new socketpair callback so the
SO_PEERSECcall on socketpair(2)s will return correct information.Signed-off-by Tom Gundersen <[email protected]>Signed-off-by David Herrmann <[email protected]>
This doesn't look like it will cause any problems. I've only been able to test it in a general way. I haven't created specific tests, but it passes the usual Smack use cases.
Quoted 37 lines
--- security/smack/smack_lsm.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)security/smack/smack_lsm.c +21
-0@@ -2842,6 +2842,27 @@ static int smack_socket_post_create(struct socket *sock, int family,return smack_netlabel (sock->sk,SMACK_CIPSO_SOCKET ); } +/** +* smack_socket_socketpair - create socket pair +* @socka: one socket +* @sockb: another socket +* +* Cross reference the peer labels for SO_PEERSEC +* +* Returns 0 on success, and error code otherwise +*/ +static int smack_socket_socketpair (struct socket *socka, +struct socket *sockb) +{ +struct socket_smack *asp = socka->sk->sk_security; +struct socket_smack *bsp = sockb->sk->sk_security; + + asp->smk_packet = bsp->smk_out; + bsp->smk_packet = asp->smk_out; + +return 0 ; +} +#ifdef SMACK_IPV6_PORT_LABELING /** * smack_socket_bind - record port binding information.
security/smack/smack_lsm.c static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { · line 4751
Quoted 7 lines
security/smack/smack_lsm.c +1
-0@@ -4724,6 +4745,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {LSM_HOOK_INIT (unix_may_send, smack_unix_may_send),LSM_HOOK_INIT (socket_post_create, smack_socket_post_create), +LSM_HOOK_INIT (socket_socketpair, smack_socket_socketpair), #ifdef SMACK_IPV6_PORT_LABELING LSM_HOOK_INIT(socket_bind, smack_socket_bind), #endif
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
James Morris
maintainerQuoted 3 lines · David Herrmann
Hi
This is v2 of the socketpair(2) LSM hook introduction.
Thanks, all applied togit://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next-general
Signature · 7 lines
James Morris <[email protected]> -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html