Commit d1e13e50 authored by James Morris's avatar James Morris

[LSM]: Networking top-level socket operation hooks.

parent 3518172a
This diff is collapsed.
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/divert.h> #include <linux/divert.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/security.h>
#if defined(CONFIG_KMOD) && defined(CONFIG_NET) #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
#include <linux/kmod.h> #include <linux/kmod.h>
...@@ -527,6 +528,10 @@ static int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr ...@@ -527,6 +528,10 @@ static int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
si->msg = msg; si->msg = msg;
si->size = size; si->size = size;
err = security_socket_sendmsg(sock, msg, size);
if (err)
return err;
err = scm_send(sock, msg, si->scm); err = scm_send(sock, msg, si->scm);
if (err >= 0) { if (err >= 0) {
err = sock->ops->sendmsg(iocb, sock, msg, size, si->scm); err = sock->ops->sendmsg(iocb, sock, msg, size, si->scm);
...@@ -551,6 +556,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size) ...@@ -551,6 +556,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size)
int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags) int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags)
{ {
int err;
struct sock_iocb *si = kiocb_to_siocb(iocb); struct sock_iocb *si = kiocb_to_siocb(iocb);
si->sock = sock; si->sock = sock;
...@@ -560,6 +566,10 @@ int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, ...@@ -560,6 +566,10 @@ int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
si->size = size; si->size = size;
si->flags = flags; si->flags = flags;
err = security_socket_recvmsg(sock, msg, size, flags);
if (err)
return err;
memset(si->scm, 0, sizeof(*si->scm)); memset(si->scm, 0, sizeof(*si->scm));
size = sock->ops->recvmsg(iocb, sock, msg, size, flags, si->scm); size = sock->ops->recvmsg(iocb, sock, msg, size, flags, si->scm);
...@@ -963,6 +973,7 @@ int sock_wake_async(struct socket *sock, int how, int band) ...@@ -963,6 +973,7 @@ int sock_wake_async(struct socket *sock, int how, int band)
int sock_create(int family, int type, int protocol, struct socket **res) int sock_create(int family, int type, int protocol, struct socket **res)
{ {
int i; int i;
int err;
struct socket *sock; struct socket *sock;
/* /*
...@@ -986,6 +997,10 @@ int sock_create(int family, int type, int protocol, struct socket **res) ...@@ -986,6 +997,10 @@ int sock_create(int family, int type, int protocol, struct socket **res)
} }
family = PF_PACKET; family = PF_PACKET;
} }
err = security_socket_create(family, type, protocol);
if (err)
return err;
#if defined(CONFIG_KMOD) && defined(CONFIG_NET) #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
/* Attempt to load a protocol module if the find failed. /* Attempt to load a protocol module if the find failed.
...@@ -1031,6 +1046,7 @@ int sock_create(int family, int type, int protocol, struct socket **res) ...@@ -1031,6 +1046,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
} }
*res = sock; *res = sock;
security_socket_post_create(sock, family, type, protocol);
out: out:
net_family_read_unlock(); net_family_read_unlock();
...@@ -1141,8 +1157,14 @@ asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen) ...@@ -1141,8 +1157,14 @@ asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen)
if((sock = sockfd_lookup(fd,&err))!=NULL) if((sock = sockfd_lookup(fd,&err))!=NULL)
{ {
if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
if (err) {
sockfd_put(sock);
return err;
}
err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen); err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
}
sockfd_put(sock); sockfd_put(sock);
} }
return err; return err;
...@@ -1163,6 +1185,13 @@ asmlinkage long sys_listen(int fd, int backlog) ...@@ -1163,6 +1185,13 @@ asmlinkage long sys_listen(int fd, int backlog)
if ((sock = sockfd_lookup(fd, &err)) != NULL) { if ((sock = sockfd_lookup(fd, &err)) != NULL) {
if ((unsigned) backlog > SOMAXCONN) if ((unsigned) backlog > SOMAXCONN)
backlog = SOMAXCONN; backlog = SOMAXCONN;
err = security_socket_listen(sock, backlog);
if (err) {
sockfd_put(sock);
return err;
}
err=sock->ops->listen(sock, backlog); err=sock->ops->listen(sock, backlog);
sockfd_put(sock); sockfd_put(sock);
} }
...@@ -1199,6 +1228,10 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a ...@@ -1199,6 +1228,10 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
newsock->type = sock->type; newsock->type = sock->type;
newsock->ops = sock->ops; newsock->ops = sock->ops;
err = security_socket_accept(sock, newsock);
if (err)
goto out_release;
err = sock->ops->accept(sock, newsock, sock->file->f_flags); err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0) if (err < 0)
goto out_release; goto out_release;
...@@ -1218,6 +1251,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a ...@@ -1218,6 +1251,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
if ((err = sock_map_fd(newsock)) < 0) if ((err = sock_map_fd(newsock)) < 0)
goto out_release; goto out_release;
security_socket_post_accept(sock, newsock);
out_put: out_put:
sockfd_put(sock); sockfd_put(sock);
out: out:
...@@ -1253,6 +1288,11 @@ asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen) ...@@ -1253,6 +1288,11 @@ asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen)
err = move_addr_to_kernel(uservaddr, addrlen, address); err = move_addr_to_kernel(uservaddr, addrlen, address);
if (err < 0) if (err < 0)
goto out_put; goto out_put;
err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
if (err)
goto out_put;
err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
sock->file->f_flags); sock->file->f_flags);
out_put: out_put:
...@@ -1275,6 +1315,11 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockad ...@@ -1275,6 +1315,11 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockad
sock = sockfd_lookup(fd, &err); sock = sockfd_lookup(fd, &err);
if (!sock) if (!sock)
goto out; goto out;
err = security_socket_getsockname(sock);
if (err)
goto out_put;
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0); err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
if (err) if (err)
goto out_put; goto out_put;
...@@ -1299,6 +1344,12 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockad ...@@ -1299,6 +1344,12 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockad
if ((sock = sockfd_lookup(fd, &err))!=NULL) if ((sock = sockfd_lookup(fd, &err))!=NULL)
{ {
err = security_socket_getpeername(sock);
if (err) {
sockfd_put(sock);
return err;
}
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
if (!err) if (!err)
err=move_addr_to_user(address,len, usockaddr, usockaddr_len); err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
...@@ -1427,6 +1478,12 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char *optval, int ...@@ -1427,6 +1478,12 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char *optval, int
if ((sock = sockfd_lookup(fd, &err))!=NULL) if ((sock = sockfd_lookup(fd, &err))!=NULL)
{ {
err = security_socket_setsockopt(sock,level,optname);
if (err) {
sockfd_put(sock);
return err;
}
if (level == SOL_SOCKET) if (level == SOL_SOCKET)
err=sock_setsockopt(sock,level,optname,optval,optlen); err=sock_setsockopt(sock,level,optname,optval,optlen);
else else
...@@ -1448,6 +1505,13 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int ...@@ -1448,6 +1505,13 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int
if ((sock = sockfd_lookup(fd, &err))!=NULL) if ((sock = sockfd_lookup(fd, &err))!=NULL)
{ {
err = security_socket_getsockopt(sock, level,
optname);
if (err) {
sockfd_put(sock);
return err;
}
if (level == SOL_SOCKET) if (level == SOL_SOCKET)
err=sock_getsockopt(sock,level,optname,optval,optlen); err=sock_getsockopt(sock,level,optname,optval,optlen);
else else
...@@ -1469,6 +1533,12 @@ asmlinkage long sys_shutdown(int fd, int how) ...@@ -1469,6 +1533,12 @@ asmlinkage long sys_shutdown(int fd, int how)
if ((sock = sockfd_lookup(fd, &err))!=NULL) if ((sock = sockfd_lookup(fd, &err))!=NULL)
{ {
err = security_socket_shutdown(sock, how);
if (err) {
sockfd_put(sock);
return err;
}
err=sock->ops->shutdown(sock, how); err=sock->ops->shutdown(sock, how);
sockfd_put(sock); sockfd_put(sock);
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <net/sock.h>
static int dummy_ptrace (struct task_struct *parent, struct task_struct *child) static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
{ {
...@@ -598,6 +598,82 @@ static int dummy_sem_semop (struct sem_array *sma, ...@@ -598,6 +598,82 @@ static int dummy_sem_semop (struct sem_array *sma,
} }
#ifdef CONFIG_SECURITY_NETWORK #ifdef CONFIG_SECURITY_NETWORK
static int dummy_socket_create (int family, int type, int protocol)
{
return 0;
}
static void dummy_socket_post_create (struct socket *sock, int family, int type,
int protocol)
{
return;
}
static int dummy_socket_bind (struct socket *sock, struct sockaddr *address,
int addrlen)
{
return 0;
}
static int dummy_socket_connect (struct socket *sock, struct sockaddr *address,
int addrlen)
{
return 0;
}
static int dummy_socket_listen (struct socket *sock, int backlog)
{
return 0;
}
static int dummy_socket_accept (struct socket *sock, struct socket *newsock)
{
return 0;
}
static void dummy_socket_post_accept (struct socket *sock,
struct socket *newsock)
{
return;
}
static int dummy_socket_sendmsg (struct socket *sock, struct msghdr *msg,
int size)
{
return 0;
}
static int dummy_socket_recvmsg (struct socket *sock, struct msghdr *msg,
int size, int flags)
{
return 0;
}
static int dummy_socket_getsockname (struct socket *sock)
{
return 0;
}
static int dummy_socket_getpeername (struct socket *sock)
{
return 0;
}
static int dummy_socket_setsockopt (struct socket *sock, int level, int optname)
{
return 0;
}
static int dummy_socket_getsockopt (struct socket *sock, int level, int optname)
{
return 0;
}
static int dummy_socket_shutdown (struct socket *sock, int how)
{
return 0;
}
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
static int dummy_register_security (const char *name, struct security_operations *ops) static int dummy_register_security (const char *name, struct security_operations *ops)
...@@ -729,6 +805,20 @@ void security_fixup_ops (struct security_operations *ops) ...@@ -729,6 +805,20 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, register_security); set_to_dummy_if_null(ops, register_security);
set_to_dummy_if_null(ops, unregister_security); set_to_dummy_if_null(ops, unregister_security);
#ifdef CONFIG_SECURITY_NETWORK #ifdef CONFIG_SECURITY_NETWORK
set_to_dummy_if_null(ops, socket_create);
set_to_dummy_if_null(ops, socket_post_create);
set_to_dummy_if_null(ops, socket_bind);
set_to_dummy_if_null(ops, socket_connect);
set_to_dummy_if_null(ops, socket_listen);
set_to_dummy_if_null(ops, socket_accept);
set_to_dummy_if_null(ops, socket_post_accept);
set_to_dummy_if_null(ops, socket_sendmsg);
set_to_dummy_if_null(ops, socket_recvmsg);
set_to_dummy_if_null(ops, socket_getsockname);
set_to_dummy_if_null(ops, socket_getpeername);
set_to_dummy_if_null(ops, socket_setsockopt);
set_to_dummy_if_null(ops, socket_getsockopt);
set_to_dummy_if_null(ops, socket_shutdown);
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
} }
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