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

[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.
parent e2943dca
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
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