Commit e2943dca authored by James Morris's avatar James Morris Committed by David S. Miller

[NET]: Add sock_create_kern()

Under SELinux, and potentially other LSMs, we need to be able to
distinguish between user sockets and kernel sockets.  For SELinux
specifically, kernel sockets need to be specially labeled during creation,
then bypass access control checks (they are controlled by the kernel
itself and not subject to SELinux mediation).

This addresses a class of potential issues in SELinux where, for example, 
a TCP NFS session times out, then the kernel re-establishes an RPC 
connection upon further user activity.  We do not want such kernel 
created sockets to be labeled with user security contexts.

sock_create() and sock_create_kern() are wrapper functions, which seems 
semantically clearer to me than e.g. adding a flag to sock_create().  If 
you prefer the latter, then let me know.

The patch also adds an argument to the LSM socket creation functions
indicating whether the socket being created is a kernel socket or not.
parent 49a1f4d4
......@@ -900,7 +900,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
unsigned short int orig_port = 0;
if(*csocket == NULL) {
rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) {
cERROR(1, ("Error %d creating socket",rc));
*csocket = NULL;
......@@ -1007,7 +1007,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
int connected = 0;
if(*csocket == NULL) {
rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) {
cERROR(1, ("Error %d creating ipv6 socket",rc));
*csocket = NULL;
......
......@@ -149,6 +149,8 @@ extern int sock_unregister(int family);
extern struct socket *sock_alloc(void);
extern int sock_create(int family, int type, int proto,
struct socket **res);
extern int sock_create_kern(int family, int type, int proto,
struct socket **res);
extern void sock_release(struct socket *sock);
extern int sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len);
......
......@@ -680,6 +680,7 @@ struct swap_info_struct;
* @family contains the requested protocol family.
* @type contains the requested communications type.
* @protocol contains the requested protocol.
* @kern set to 1 if a kernel socket.
* Return 0 if permission is granted.
* @socket_post_create:
* This hook allows a module to update or allocate a per-socket security
......@@ -694,6 +695,7 @@ struct swap_info_struct;
* @family contains the requested protocol family.
* @type contains the requested communications type.
* @protocol contains the requested protocol.
* @kern set to 1 if a kernel socket.
* @socket_bind:
* Check permission before socket protocol layer bind operation is
* performed and the socket @sock is bound to the address specified in the
......@@ -1198,9 +1200,9 @@ struct security_operations {
struct socket * other, struct sock * newsk);
int (*unix_may_send) (struct socket * sock, struct socket * other);
int (*socket_create) (int family, int type, int protocol);
int (*socket_create) (int family, int type, int protocol, int kern);
void (*socket_post_create) (struct socket * sock, int family,
int type, int protocol);
int type, int protocol, int kern);
int (*socket_bind) (struct socket * sock,
struct sockaddr * address, int addrlen);
int (*socket_connect) (struct socket * sock,
......@@ -2526,17 +2528,19 @@ static inline int security_unix_may_send(struct socket * sock,
return security_ops->unix_may_send(sock, other);
}
static inline int security_socket_create (int family, int type, int protocol)
static inline int security_socket_create (int family, int type,
int protocol, int kern)
{
return security_ops->socket_create(family, type, protocol);
return security_ops->socket_create(family, type, protocol, kern);
}
static inline void security_socket_post_create(struct socket * sock,
int family,
int type,
int protocol)
int protocol, int kern)
{
security_ops->socket_post_create(sock, family, type, protocol);
security_ops->socket_post_create(sock, family, type,
protocol, kern);
}
static inline int security_socket_bind(struct socket * sock,
......@@ -2645,7 +2649,8 @@ static inline int security_unix_may_send(struct socket * sock,
return 0;
}
static inline int security_socket_create (int family, int type, int protocol)
static inline int security_socket_create (int family, int type,
int protocol, int kern)
{
return 0;
}
......@@ -2653,7 +2658,7 @@ static inline int security_socket_create (int family, int type, int protocol)
static inline void security_socket_post_create(struct socket * sock,
int family,
int type,
int protocol)
int protocol, int kern)
{
}
......
......@@ -158,7 +158,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
BT_DBG("");
err = sock_create(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, sock);
err = sock_create_kern(PF_BLUETOOTH, SOCK_SEQPACKET,
BTPROTO_L2CAP, sock);
if (!err) {
struct sock *sk = (*sock)->sk;
sk->sk_data_ready = rfcomm_l2data_ready;
......
......@@ -976,7 +976,7 @@ static int __init aun_udp_initialise(void)
/* We can count ourselves lucky Acorn machines are too dim to
speak IPv6. :-) */
if ((error = sock_create(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
if ((error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
{
printk("AUN: socket error %d\n", -error);
return error;
......
......@@ -1108,8 +1108,8 @@ void __init icmp_init(struct net_proto_family *ops)
if (!cpu_possible(i))
continue;
err = sock_create(PF_INET, SOCK_RAW, IPPROTO_ICMP,
&per_cpu(__icmp_socket, i));
err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
&per_cpu(__icmp_socket, i));
if (err < 0)
panic("Failed to create the ICMP control socket.\n");
......
......@@ -480,7 +480,7 @@ static struct socket * make_send_sock(void)
struct socket *sock;
/* First create a socket */
if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
IP_VS_ERR("Error during creation of socket; terminating\n");
return NULL;
}
......@@ -521,7 +521,7 @@ static struct socket * make_receive_sock(void)
struct socket *sock;
/* First create a socket */
if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
IP_VS_ERR("Error during creation of socket; terminating\n");
return NULL;
}
......
......@@ -2609,7 +2609,7 @@ struct proto tcp_prot = {
void __init tcp_v4_init(struct net_proto_family *ops)
{
int err = sock_create(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);
int err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);
if (err < 0)
panic("Failed to create the TCP control socket.\n");
tcp_socket->sk->sk_allocation = GFP_ATOMIC;
......
......@@ -682,8 +682,8 @@ int __init icmpv6_init(struct net_proto_family *ops)
if (!cpu_possible(i))
continue;
err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
&per_cpu(__icmpv6_socket, i));
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
&per_cpu(__icmpv6_socket, i));
if (err < 0) {
printk(KERN_ERR
"Failed to initialize the ICMP6 control socket "
......
......@@ -2452,7 +2452,7 @@ int __init igmp6_init(struct net_proto_family *ops)
struct sock *sk;
int err;
err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
if (err < 0) {
printk(KERN_ERR
"Failed to initialize the IGMP6 control socket (err %d).\n",
......
......@@ -1443,7 +1443,7 @@ int __init ndisc_init(struct net_proto_family *ops)
struct sock *sk;
int err;
err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
if (err < 0) {
ND_PRINTK0(KERN_ERR
"ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
......
......@@ -112,7 +112,7 @@ static int netlink_open(struct inode * inode, struct file * file)
if (test_and_set_bit(minor, &open_map))
return -EBUSY;
err = sock_create(PF_NETLINK, SOCK_RAW, minor, &sock);
err = sock_create_kern(PF_NETLINK, SOCK_RAW, minor, &sock);
if (err < 0)
goto out;
......
......@@ -86,7 +86,7 @@ int rxrpc_create_transport(unsigned short port,
trans->port = port;
/* create a UDP socket to be my actual transport endpoint */
ret = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &trans->socket);
ret = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &trans->socket);
if (ret < 0)
goto error;
......
......@@ -653,8 +653,8 @@ int sctp_ctl_sock_init(void)
else
family = PF_INET;
err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP,
&sctp_ctl_socket);
err = sock_create_kern(family, SOCK_SEQPACKET, IPPROTO_SCTP,
&sctp_ctl_socket);
if (err < 0) {
printk(KERN_ERR
"SCTP: Failed to create the SCTP control socket.\n");
......
......@@ -983,8 +983,7 @@ int sock_wake_async(struct socket *sock, int how, int band)
return 0;
}
int sock_create(int family, int type, int protocol, struct socket **res)
static int __sock_create(int family, int type, int protocol, struct socket **res, int kern)
{
int i;
int err;
......@@ -1012,7 +1011,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
family = PF_PACKET;
}
err = security_socket_create(family, type, protocol);
err = security_socket_create(family, type, protocol, kern);
if (err)
return err;
......@@ -1075,7 +1074,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
*/
module_put(net_families[family]->owner);
*res = sock;
security_socket_post_create(sock, family, type, protocol);
security_socket_post_create(sock, family, type, protocol, kern);
out:
net_family_read_unlock();
......@@ -1087,6 +1086,16 @@ int sock_create(int family, int type, int protocol, struct socket **res)
goto out;
}
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(family, type, protocol, res, 0);
}
int sock_create_kern(int family, int type, int protocol, struct socket **res)
{
return __sock_create(family, type, protocol, res, 1);
}
asmlinkage long sys_socket(int family, int type, int protocol)
{
int retval;
......@@ -1991,6 +2000,7 @@ EXPORT_SYMBOL(move_addr_to_user);
EXPORT_SYMBOL(sock_alloc);
EXPORT_SYMBOL(sock_alloc_inode);
EXPORT_SYMBOL(sock_create);
EXPORT_SYMBOL(sock_create_kern);
EXPORT_SYMBOL(sock_map_fd);
EXPORT_SYMBOL(sock_recvmsg);
EXPORT_SYMBOL(sock_register);
......
......@@ -1413,7 +1413,7 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
}
type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
if ((error = sock_create(PF_INET, type, protocol, &sock)) < 0)
if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
return error;
if (sin != NULL) {
......
......@@ -1567,7 +1567,7 @@ static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int
type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
if ((err = sock_create(PF_INET, type, proto, &sock)) < 0) {
if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
printk("RPC: can't create socket (%d).\n", -err);
return NULL;
}
......
......@@ -750,13 +750,14 @@ static int dummy_unix_may_send (struct socket *sock,
return 0;
}
static int dummy_socket_create (int family, int type, int protocol)
static int dummy_socket_create (int family, int type,
int protocol, int kern)
{
return 0;
}
static void dummy_socket_post_create (struct socket *sock, int family, int type,
int protocol)
int protocol, int kern)
{
return;
}
......
......@@ -2810,34 +2810,43 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
struct inode_security_struct *isec;
struct task_security_struct *tsec;
struct avc_audit_data ad;
int err;
int err = 0;
tsec = task->security;
isec = SOCK_INODE(sock)->i_security;
if (isec->sid == SECINITSID_KERNEL)
goto out;
AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.sk = sock->sk;
err = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
perms, &isec->avcr, &ad);
out:
return err;
}
static int selinux_socket_create(int family, int type, int protocol)
static int selinux_socket_create(int family, int type,
int protocol, int kern)
{
int err;
int err = 0;
struct task_security_struct *tsec;
tsec = current->security;
if (kern)
goto out;
tsec = current->security;
err = avc_has_perm(tsec->sid, tsec->sid,
socket_type_to_security_class(family, type),
SOCKET__CREATE, NULL, NULL);
out:
return err;
}
static void selinux_socket_post_create(struct socket *sock, int family, int type, int protocol)
static void selinux_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
int err;
struct inode_security_struct *isec;
......@@ -2850,7 +2859,7 @@ static void selinux_socket_post_create(struct socket *sock, int family, int type
tsec = current->security;
isec->sclass = socket_type_to_security_class(family, type);
isec->sid = tsec->sid;
isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
return;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment