Re: [PATCH 2/3] Security: Implement disablenetwork semantics. (v4)

From: Serge E. Hallyn
Date: Wed Dec 30 2009 - 13:51:07 EST


Quoting Michael Stone (michael@xxxxxxxxxx):
> Implement security_* hooks for socket_create, socket_bind, socket_connect,
> socket_sendmsg, and ptrace_access_check which return -EPERM when called from a
> process with networking restrictions. Exempt AF_UNIX sockets.
>
> Signed-off-by: Michael Stone <michael@xxxxxxxxxx>

Acked-by: Serge Hallyn <serue@xxxxxxxxxx>

> ---
> include/linux/disablenetwork.h | 22 +++++++++++
> security/Makefile | 1 +
> security/disablenetwork.c | 73 ++++++++++++++++++++++++++++++++++++++
> security/security.c | 76 +++++++++++++++++++++++++++++++++++++---
> 4 files changed, 167 insertions(+), 5 deletions(-)
> create mode 100644 include/linux/disablenetwork.h
> create mode 100644 security/disablenetwork.c
>
> diff --git a/include/linux/disablenetwork.h b/include/linux/disablenetwork.h
> new file mode 100644
> index 0000000..8a7bcc2
> --- /dev/null
> +++ b/include/linux/disablenetwork.h
> @@ -0,0 +1,22 @@
> +#ifndef __LINUX_DISABLENETWORK_H
> +#define __LINUX_DISABLENETWORK_H
> +
> +#ifdef CONFIG_SECURITY_DISABLENETWORK
> +
> +int disablenetwork_security_socket_create(int family, int type,
> + int protocol, int kern);

Bleh, I think disablenetwork_socket_create() is long enough :)

> +int disablenetwork_security_socket_bind(struct socket *sock,
> + struct sockaddr *address,
> + int addrlen);
> +int disablenetwork_security_socket_connect(struct socket *sock,
> + struct sockaddr *address,
> + int addrlen);
> +int disablenetwork_security_socket_sendmsg(struct socket *sock,
> + struct msghdr *msg,
> + int size);
> +int disablenetwork_security_ptrace_access_check(struct task_struct *child,
> + unsigned int mode);
> +
> +#endif /* CONFIG_SECURITY_DISABLENETWORK */
> +
> +#endif /* ! __LINUX_DISABLENETWORK_H */
> diff --git a/security/Makefile b/security/Makefile
> index da20a19..2f23b60 100644
> --- a/security/Makefile
> +++ b/security/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
> obj-$(CONFIG_AUDIT) += lsm_audit.o
> obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
> obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
> +obj-$(CONFIG_SECURITY_DISABLENETWORK) += disablenetwork.o
>
> # Object integrity file lists
> subdir-$(CONFIG_IMA) += integrity/ima
> diff --git a/security/disablenetwork.c b/security/disablenetwork.c
> new file mode 100644
> index 0000000..f45ddfc
> --- /dev/null
> +++ b/security/disablenetwork.c
> @@ -0,0 +1,73 @@
> +/*
> + * disablenetwork security hooks.
> + *
> + * Copyright (C) 2008-2009 Michael Stone <michael@xxxxxxxxxx>
> + *
> + * Implements the disablenetwork discretionary access control logic underlying
> + * the prctl(PRCTL_SET_NETWORK, PR_NETWORK_OFF) interface.
> + *
> + * See Documentation/disablenetwork.txt for more information.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation, version 2 of the
> + * License.
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/sched.h>
> +#include <net/sock.h>
> +#include <linux/socket.h>
> +#include <linux/disablenetwork.h>
> +
> +static inline int maybe_allow(void)
> +{
> + if (current->network)
> + return -EPERM;
> + return 0;
> +}
> +
> +int disablenetwork_security_socket_create(int family, int type,
> + int protocol, int kern)
> +{
> + if (family == AF_UNIX)
> + return 0;
> + return maybe_allow();
> +}
> +
> +int disablenetwork_security_socket_bind(struct socket * sock,
> + struct sockaddr * address,
> + int addrlen)
> +{
> + if (address->sa_family == AF_UNIX)
> + return 0;
> + return maybe_allow();
> +}
> +
> +int disablenetwork_security_socket_connect(struct socket * sock,
> + struct sockaddr * address,
> + int addrlen)
> +{
> + if (address->sa_family == AF_UNIX)
> + return 0;
> + return maybe_allow();
> +}
> +
> +int disablenetwork_security_socket_sendmsg(struct socket * sock,
> + struct msghdr * msg, int size)
> +{
> + if (sock->sk->sk_family != PF_UNIX &&
> + current->network &&
> + (msg->msg_name != NULL || msg->msg_namelen != 0))
> + return -EPERM;
> + return 0;
> +}
> +
> +int disablenetwork_security_ptrace_access_check(struct task_struct *child,
> + unsigned int mode)
> +{
> + /* does current have networking restrictions not shared by child? */
> + if (current->network & ~child->network)
> + return -EPERM;
> + return 0;
> +}
> diff --git a/security/security.c b/security/security.c
> index 24e060b..40ac615 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -17,6 +17,7 @@
> #include <linux/kernel.h>
> #include <linux/security.h>
> #include <linux/ima.h>
> +#include <linux/disablenetwork.h>
>
> /* Boot-time LSM user choice */
> static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
> @@ -130,7 +131,20 @@ int register_security(struct security_operations *ops)
>
> int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
> {
> - return security_ops->ptrace_access_check(child, mode);
> + int ret = 0;
> +
> + ret = security_ops->ptrace_access_check(child, mode);
> + if (ret)
> + goto out;
> +
> +#ifdef CONFIG_SECURITY_DISABLENETWORK
> + ret = disablenetwork_security_ptrace_access_check(child, mode);
> + if (ret)
> + goto out;
> +#endif
> +
> +out:
> + return ret;
> }
>
> int security_ptrace_traceme(struct task_struct *parent)
> @@ -1054,7 +1068,20 @@ EXPORT_SYMBOL(security_unix_may_send);
>
> int security_socket_create(int family, int type, int protocol, int kern)
> {
> - return security_ops->socket_create(family, type, protocol, kern);
> + int ret = 0;
> +
> + ret = security_ops->socket_create(family, type, protocol, kern);
> + if (ret)
> + goto out;
> +
> +#ifdef CONFIG_SECURITY_DISABLENETWORK
> + ret = disablenetwork_security_socket_create(family, type, protocol, kern);
> + if (ret)
> + goto out;
> +#endif
> +
> +out:
> + return ret;
> }
>
> int security_socket_post_create(struct socket *sock, int family,
> @@ -1066,12 +1093,38 @@ int security_socket_post_create(struct socket *sock, int family,
>
> int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
> {
> - return security_ops->socket_bind(sock, address, addrlen);
> + int ret = 0;
> +
> + ret = security_ops->socket_bind(sock, address, addrlen);
> + if (ret)
> + goto out;
> +
> +#ifdef CONFIG_SECURITY_DISABLENETWORK
> + ret = disablenetwork_security_socket_bind(sock, address, addrlen);
> + if (ret)
> + goto out;
> +#endif
> +
> +out:
> + return ret;
> }
>
> int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
> {
> - return security_ops->socket_connect(sock, address, addrlen);
> + int ret = 0;
> +
> + ret = security_ops->socket_connect(sock, address, addrlen);
> + if (ret)
> + goto out;
> +
> +#ifdef CONFIG_SECURITY_DISABLENETWORK
> + ret = disablenetwork_security_socket_connect(sock, address, addrlen);
> + if (ret)
> + goto out;
> +#endif
> +
> +out:
> + return ret;
> }
>
> int security_socket_listen(struct socket *sock, int backlog)
> @@ -1086,7 +1139,20 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
>
> int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
> {
> - return security_ops->socket_sendmsg(sock, msg, size);
> + int ret = 0;
> +
> + ret = security_ops->socket_sendmsg(sock, msg, size);
> + if (ret)
> + goto out;
> +
> +#ifdef CONFIG_SECURITY_DISABLENETWORK
> + ret = disablenetwork_security_socket_sendmsg(sock, msg, size);
> + if (ret)
> + goto out;
> +#endif
> +
> +out:
> + return ret;
> }
>
> int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
> --
> 1.6.6.rc2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/