summaryrefslogtreecommitdiff
path: root/qemu_patches/0003-slirp-add-disable_host_loopback-prohibit-connections.patch
blob: 819edeb7c9a4e0f1fe286ebd90a398321c442986 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
From 3e8a2a9a3a467e7ab02cc28f99bdcd5d2e30d217 Mon Sep 17 00:00:00 2001
From: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
Date: Wed, 6 Mar 2019 17:04:14 +0900
Subject: [PATCH 3/3] slirp: add disable_host_loopback (prohibit connections to
 127.0.0.1)

From slirp4netns project:
* https://github.com/rootless-containers/slirp4netns/commit/6325473781bb344c225f54e2d28800fb0619d7ee
* https://github.com/rootless-containers/slirp4netns/commit/13b24026867d4c30d5d1465ac82e3bb890bf4caa

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
---
 slirp/src/ip_icmp.c  |  6 +++-
 slirp/src/libslirp.h |  2 ++
 slirp/src/slirp.c    |  1 +
 slirp/src/slirp.h    |  2 ++
 slirp/src/socket.c   | 68 +++++++++++++++++++++++++-------------------
 slirp/src/socket.h   |  2 +-
 slirp/src/tcp_subr.c |  4 ++-
 7 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/slirp/src/ip_icmp.c b/slirp/src/ip_icmp.c
index 1aea18afa7..b0f116dd22 100644
--- a/slirp/src/ip_icmp.c
+++ b/slirp/src/ip_icmp.c
@@ -189,7 +189,11 @@ icmp_input(struct mbuf *m, int hlen)
 
       /* Send the packet */
       addr = so->fhost.ss;
-      sotranslate_out(so, &addr);
+      if (sotranslate_out(so, &addr) < 0) {
+          icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
+          udp_detach(so);
+          return;
+      }
 
       if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
 		(struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) {
diff --git a/slirp/src/libslirp.h b/slirp/src/libslirp.h
index 4e2d4ee6c7..d8e69828ba 100644
--- a/slirp/src/libslirp.h
+++ b/slirp/src/libslirp.h
@@ -87,6 +87,8 @@ typedef struct SlirpConfig{
     int if_mtu;
     /* Default: IF_MRU_DEFAULT */
     int if_mru;
+    /* Prohibit connecting to 127.0.0.1:* */
+    bool disable_host_loopback;
 } SlirpConfig;
 
 Slirp *slirp_initx(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque);
diff --git a/slirp/src/slirp.c b/slirp/src/slirp.c
index 8c02913769..cc1215d2dd 100644
--- a/slirp/src/slirp.c
+++ b/slirp/src/slirp.c
@@ -325,6 +325,7 @@ Slirp *slirp_initx(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaqu
     }
     slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu;
     slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru;
+    slirp->disable_host_loopback = cfg->disable_host_loopback;
 
     return slirp;
 }
diff --git a/slirp/src/slirp.h b/slirp/src/slirp.h
index 1c485be36f..fce6583f8a 100644
--- a/slirp/src/slirp.h
+++ b/slirp/src/slirp.h
@@ -149,6 +149,8 @@ struct Slirp {
     int if_mtu;
     int if_mru;
 
+    bool disable_host_loopback;
+
     /* mbuf states */
     struct quehead m_freelist;
     struct quehead m_usedlist;
diff --git a/slirp/src/socket.c b/slirp/src/socket.c
index 4a3c935e25..be27e523e6 100644
--- a/slirp/src/socket.c
+++ b/slirp/src/socket.c
@@ -659,7 +659,9 @@ sosendto(struct socket *so, struct mbuf *m)
 
 	addr = so->fhost.ss;
 	DEBUG_CALL(" sendto()ing)");
-	sotranslate_out(so, &addr);
+    if (sotranslate_out(so, &addr) < 0) {
+        return -1;
+    }
 
 	/* Don't care what port we get */
 	ret = sendto(so->s, m->m_data, m->m_len, 0,
@@ -825,49 +827,57 @@ sofwdrain(struct socket *so)
 /*
  * Translate addr in host addr when it is a virtual address
  */
-void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
+int sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
 {
+    int rc = 0;
     Slirp *slirp = so->slirp;
     struct sockaddr_in *sin = (struct sockaddr_in *)addr;
     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
     switch (addr->ss_family) {
-    case AF_INET:
-        if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
-                slirp->vnetwork_addr.s_addr) {
-            /* It's an alias */
-            if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
-                if (get_dns_addr(&sin->sin_addr) < 0) {
+        case AF_INET:
+            if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+                    slirp->vnetwork_addr.s_addr) {
+                /* It's an alias */
+                if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
+                    if (get_dns_addr(&sin->sin_addr) >= 0) {
+                        goto ret;
+                    }
+                }
+                if (slirp->disable_host_loopback) {
+                    rc = -1;
+                    errno = EPERM;
+                    goto ret;
+                } else {
                     sin->sin_addr = loopback_addr;
                 }
-            } else {
-                sin->sin_addr = loopback_addr;
             }
-        }
-
-        DEBUG_MISC(" addr.sin_port=%d, addr.sin_addr.s_addr=%.16s",
-                   ntohs(sin->sin_port), inet_ntoa(sin->sin_addr));
-        break;
-
-    case AF_INET6:
-        if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
-                    slirp->vprefix_len)) {
-            if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) {
-                uint32_t scope_id;
-                if (get_dns6_addr(&sin6->sin6_addr, &scope_id) >= 0) {
-                    sin6->sin6_scope_id = scope_id;
+            break;
+        case AF_INET6:
+            if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
+                        slirp->vprefix_len)) {
+                if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) {
+                    uint32_t scope_id;
+                    if (get_dns6_addr(&sin6->sin6_addr, &scope_id) >= 0) {
+                        sin6->sin6_scope_id = scope_id;
+                        goto ret;
+                    }
+                }
+                if (slirp->disable_host_loopback){
+                    rc = -1;
+                    errno = EPERM;
+                    goto ret;
                 } else {
                     sin6->sin6_addr = in6addr_loopback;
                 }
-            } else {
-                sin6->sin6_addr = in6addr_loopback;
             }
-        }
-        break;
+            break;
 
-    default:
-        break;
+        default:
+            break;
     }
+ret:
+    return rc;
 }
 
 void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
diff --git a/slirp/src/socket.h b/slirp/src/socket.h
index 25403898cd..791ae9482c 100644
--- a/slirp/src/socket.h
+++ b/slirp/src/socket.h
@@ -151,7 +151,7 @@ struct iovec; /* For win32 */
 size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
 int soreadbuf(struct socket *so, const char *buf, int size);
 
-void sotranslate_out(struct socket *, struct sockaddr_storage *);
+int sotranslate_out(struct socket *, struct sockaddr_storage *);
 void sotranslate_in(struct socket *, struct sockaddr_storage *);
 void sotranslate_accept(struct socket *);
 void sodrop(struct socket *, int num);
diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c
index e88e51e39c..4224213c14 100644
--- a/slirp/src/tcp_subr.c
+++ b/slirp/src/tcp_subr.c
@@ -420,7 +420,9 @@ int tcp_fconnect(struct socket *so, unsigned short af)
 
     addr = so->fhost.ss;
     DEBUG_CALL(" connect()ing");
-    sotranslate_out(so, &addr);
+    if (sotranslate_out(so, &addr) < 0) {
+        return -1;
+    }
 
     /* We don't care what port we get */
     ret = connect(s, (struct sockaddr *)&addr, sockaddr_size(&addr));
-- 
2.20.1