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