From 398b3c447d458db2a7972603b3c36ceb97eb976a Mon Sep 17 00:00:00 2001 From: James Morris Date: Sat, 8 May 2004 01:05:57 -0700 Subject: [PATCH] [NET]: Add sock_create_lite() The purpose of this is to allow sockets created by the kernel in this way to be passed through the LSM socket creation hooks and be labeled and mediated in the same manner as other sockets. This patches addresses a class of potential issues with LSMs, where such sockets will not be labeled correctly (if at all), or mediated during creation. Under SELinux, it fixes a specific bug where RPC sockets created by the kernel during TCP NFS serving are unlabeled. --- include/linux/net.h | 2 ++ net/bluetooth/rfcomm/core.c | 6 ++---- net/netlink/af_netlink.c | 4 +--- net/socket.c | 24 +++++++++++++++++++++++- net/sunrpc/svcsock.c | 10 ++++++---- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/include/linux/net.h b/include/linux/net.h index 6f7846c15e08..3d2cd0cec584 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -151,6 +151,8 @@ 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 int sock_create_lite(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); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 665564beee21..d9b4ce095b01 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1642,11 +1642,9 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) BT_DBG("session %p", s); - nsock = sock_alloc(); - if (!nsock) + if (sock_create_lite(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, &nsock)) return; - - nsock->type = sock->type; + nsock->ops = sock->ops; __module_get(nsock->ops->owner); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 95b8fbaf313f..9a77db793577 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -833,11 +833,9 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len)) if (unit<0 || unit>=MAX_LINKS) return NULL; - if (!(sock = sock_alloc())) + if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) return NULL; - sock->type = SOCK_RAW; - if (netlink_create(sock, unit) < 0) { sock_release(sock); return NULL; diff --git a/net/socket.c b/net/socket.c index f4ef38250280..f8d18942abd9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -457,7 +457,7 @@ struct socket *sockfd_lookup(int fd, int *err) * NULL is returned. */ -struct socket *sock_alloc(void) +static struct socket *sock_alloc(void) { struct inode * inode; struct socket * sock; @@ -840,6 +840,27 @@ static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return err; } +int sock_create_lite(int family, int type, int protocol, struct socket **res) +{ + int err; + struct socket *sock = NULL; + + err = security_socket_create(family, type, protocol, 1); + if (err) + goto out; + + sock = sock_alloc(); + if (!sock) { + err = -ENOMEM; + goto out; + } + + security_socket_post_create(sock, family, type, protocol, 1); + sock->type = type; +out: + *res = sock; + return err; +} /* No kernel lock held - perfect */ static unsigned int sock_poll(struct file *file, poll_table * wait) @@ -2001,6 +2022,7 @@ EXPORT_SYMBOL(sock_alloc); EXPORT_SYMBOL(sock_alloc_inode); EXPORT_SYMBOL(sock_create); EXPORT_SYMBOL(sock_create_kern); +EXPORT_SYMBOL(sock_create_lite); EXPORT_SYMBOL(sock_map_fd); EXPORT_SYMBOL(sock_recvmsg); EXPORT_SYMBOL(sock_register); diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index dd199ccbb78a..a8ac421d0be1 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -781,13 +781,15 @@ svc_tcp_accept(struct svc_sock *svsk) if (!sock) return; - if (!(newsock = sock_alloc())) { - printk(KERN_WARNING "%s: no more sockets!\n", serv->sv_name); + err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock); + if (err) { + if (err == -ENOMEM) + printk(KERN_WARNING "%s: no more sockets!\n", + serv->sv_name); return; } - dprintk("svc: tcp_accept %p allocated\n", newsock); - newsock->type = sock->type; + dprintk("svc: tcp_accept %p allocated\n", newsock); newsock->ops = ops = sock->ops; clear_bit(SK_CONN, &svsk->sk_flags); -- 2.39.5