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, ...@@ -151,6 +151,8 @@ extern int sock_create(int family, int type, int proto,
struct socket **res); struct socket **res);
extern int sock_create_kern(int family, int type, int proto, extern int sock_create_kern(int family, int type, int proto,
struct socket **res); 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 void sock_release(struct socket *sock);
extern int sock_sendmsg(struct socket *sock, struct msghdr *msg, extern int sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len); size_t len);
......
...@@ -1642,11 +1642,9 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) ...@@ -1642,11 +1642,9 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
BT_DBG("session %p", s); BT_DBG("session %p", s);
nsock = sock_alloc(); if (sock_create_lite(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, &nsock))
if (!nsock)
return; return;
nsock->type = sock->type;
nsock->ops = sock->ops; nsock->ops = sock->ops;
__module_get(nsock->ops->owner); __module_get(nsock->ops->owner);
......
...@@ -833,11 +833,9 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len)) ...@@ -833,11 +833,9 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
if (unit<0 || unit>=MAX_LINKS) if (unit<0 || unit>=MAX_LINKS)
return NULL; return NULL;
if (!(sock = sock_alloc())) if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
return NULL; return NULL;
sock->type = SOCK_RAW;
if (netlink_create(sock, unit) < 0) { if (netlink_create(sock, unit) < 0) {
sock_release(sock); sock_release(sock);
return NULL; return NULL;
......
...@@ -457,7 +457,7 @@ struct socket *sockfd_lookup(int fd, int *err) ...@@ -457,7 +457,7 @@ struct socket *sockfd_lookup(int fd, int *err)
* NULL is returned. * NULL is returned.
*/ */
struct socket *sock_alloc(void) static struct socket *sock_alloc(void)
{ {
struct inode * inode; struct inode * inode;
struct socket * sock; struct socket * sock;
...@@ -840,6 +840,27 @@ static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -840,6 +840,27 @@ static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return err; 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 */ /* No kernel lock held - perfect */
static unsigned int sock_poll(struct file *file, poll_table * wait) static unsigned int sock_poll(struct file *file, poll_table * wait)
...@@ -2001,6 +2022,7 @@ EXPORT_SYMBOL(sock_alloc); ...@@ -2001,6 +2022,7 @@ EXPORT_SYMBOL(sock_alloc);
EXPORT_SYMBOL(sock_alloc_inode); EXPORT_SYMBOL(sock_alloc_inode);
EXPORT_SYMBOL(sock_create); EXPORT_SYMBOL(sock_create);
EXPORT_SYMBOL(sock_create_kern); EXPORT_SYMBOL(sock_create_kern);
EXPORT_SYMBOL(sock_create_lite);
EXPORT_SYMBOL(sock_map_fd); EXPORT_SYMBOL(sock_map_fd);
EXPORT_SYMBOL(sock_recvmsg); EXPORT_SYMBOL(sock_recvmsg);
EXPORT_SYMBOL(sock_register); EXPORT_SYMBOL(sock_register);
......
...@@ -781,13 +781,15 @@ svc_tcp_accept(struct svc_sock *svsk) ...@@ -781,13 +781,15 @@ svc_tcp_accept(struct svc_sock *svsk)
if (!sock) if (!sock)
return; return;
if (!(newsock = sock_alloc())) { err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
printk(KERN_WARNING "%s: no more sockets!\n", serv->sv_name); if (err) {
if (err == -ENOMEM)
printk(KERN_WARNING "%s: no more sockets!\n",
serv->sv_name);
return; 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; newsock->ops = ops = sock->ops;
clear_bit(SK_CONN, &svsk->sk_flags); 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