aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2016-03-03 08:20:42 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-06 22:54:57 -0500
commitddb3712552c8807c75576fb4fbdbb16f0d48b161 (patch)
treed412f143ca686dc52c2acf5380d0d45af916eb38 /net/tipc
parent2837f39c7cdbd209ab04d1c1f4eca015a40d5cd6 (diff)
tipc: safely copy UDP netlink data from user
The netlink policy for TIPC_NLA_UDP_LOCAL and TIPC_NLA_UDP_REMOTE is of type binary with a defined length. This causes the policy framework to threat the defined length as maximum length. There is however no protection against a user sending a smaller amount of data. Prior to this patch this wasn't handled which could result in a partially incomplete sockaddr_storage struct containing uninitialized data. In this patch we use nla_memcpy() when copying the user data. This ensures a potential gap at the end is cleared out properly. This was found by Julia with Coccinelle tool. Reported-by: Daniel Borkmann <daniel@iogearbox.net> Reported-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Richard Alpe <richard.alpe@ericsson.com> Acked-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/udp_media.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index f22a5bb169c9..6fe8740a226f 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -276,7 +276,7 @@ static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub,
276 struct udp_media_addr *remote) 276 struct udp_media_addr *remote)
277{ 277{
278 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; 278 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
279 struct sockaddr_storage *sa_local, *sa_remote; 279 struct sockaddr_storage sa_local, sa_remote;
280 280
281 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) 281 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
282 goto err; 282 goto err;
@@ -285,41 +285,43 @@ static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub,
285 tipc_nl_udp_policy)) 285 tipc_nl_udp_policy))
286 goto err; 286 goto err;
287 if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { 287 if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) {
288 sa_local = nla_data(opts[TIPC_NLA_UDP_LOCAL]); 288 nla_memcpy(&sa_local, opts[TIPC_NLA_UDP_LOCAL],
289 sa_remote = nla_data(opts[TIPC_NLA_UDP_REMOTE]); 289 sizeof(sa_local));
290 nla_memcpy(&sa_remote, opts[TIPC_NLA_UDP_REMOTE],
291 sizeof(sa_remote));
290 } else { 292 } else {
291err: 293err:
292 pr_err("Invalid UDP bearer configuration"); 294 pr_err("Invalid UDP bearer configuration");
293 return -EINVAL; 295 return -EINVAL;
294 } 296 }
295 if ((sa_local->ss_family & sa_remote->ss_family) == AF_INET) { 297 if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET) {
296 struct sockaddr_in *ip4; 298 struct sockaddr_in *ip4;
297 299
298 ip4 = (struct sockaddr_in *)sa_local; 300 ip4 = (struct sockaddr_in *)&sa_local;
299 local->proto = htons(ETH_P_IP); 301 local->proto = htons(ETH_P_IP);
300 local->udp_port = ip4->sin_port; 302 local->udp_port = ip4->sin_port;
301 local->ipv4.s_addr = ip4->sin_addr.s_addr; 303 local->ipv4.s_addr = ip4->sin_addr.s_addr;
302 304
303 ip4 = (struct sockaddr_in *)sa_remote; 305 ip4 = (struct sockaddr_in *)&sa_remote;
304 remote->proto = htons(ETH_P_IP); 306 remote->proto = htons(ETH_P_IP);
305 remote->udp_port = ip4->sin_port; 307 remote->udp_port = ip4->sin_port;
306 remote->ipv4.s_addr = ip4->sin_addr.s_addr; 308 remote->ipv4.s_addr = ip4->sin_addr.s_addr;
307 return 0; 309 return 0;
308 310
309#if IS_ENABLED(CONFIG_IPV6) 311#if IS_ENABLED(CONFIG_IPV6)
310 } else if ((sa_local->ss_family & sa_remote->ss_family) == AF_INET6) { 312 } else if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET6) {
311 struct sockaddr_in6 *ip6; 313 struct sockaddr_in6 *ip6;
312 314
313 ip6 = (struct sockaddr_in6 *)sa_local; 315 ip6 = (struct sockaddr_in6 *)&sa_local;
314 local->proto = htons(ETH_P_IPV6); 316 local->proto = htons(ETH_P_IPV6);
315 local->udp_port = ip6->sin6_port; 317 local->udp_port = ip6->sin6_port;
316 local->ipv6 = ip6->sin6_addr; 318 memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
317 ub->ifindex = ip6->sin6_scope_id; 319 ub->ifindex = ip6->sin6_scope_id;
318 320
319 ip6 = (struct sockaddr_in6 *)sa_remote; 321 ip6 = (struct sockaddr_in6 *)&sa_remote;
320 remote->proto = htons(ETH_P_IPV6); 322 remote->proto = htons(ETH_P_IPV6);
321 remote->udp_port = ip6->sin6_port; 323 remote->udp_port = ip6->sin6_port;
322 remote->ipv6 = ip6->sin6_addr; 324 memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr));
323 return 0; 325 return 0;
324#endif 326#endif
325 } 327 }