diff options
author | pageexec <pageexec@freemail.hu> | 2005-06-26 19:00:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-26 19:00:19 -0400 |
commit | 4da62fc70d7cbcf8fa606a8c806d9dc8faa0ceae (patch) | |
tree | c15f61c9c0a1b1e88990eab47ebc89a4a83b3a4e /net/ipv4/ipvs | |
parent | d470e3b483dcf79c16463bc740738dca76a035a9 (diff) |
[IPVS]: Fix for overflows
From: <pageexec@freemail.hu>
$subject was fixed in 2.4 already, 2.6 needs it as well.
The impact of the bugs is a kernel stack overflow and privilege escalation
from CAP_NET_ADMIN via the IP_VS_SO_SET_STARTDAEMON/IP_VS_SO_GET_DAEMON
ioctls. People running with 'root=all caps' (i.e., most users) are not
really affected (there's nothing to escalate), but SELinux and similar
users should take it seriously if they grant CAP_NET_ADMIN to other users.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipvs')
-rw-r--r-- | net/ipv4/ipvs/ip_vs_ctl.c | 8 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_sync.c | 4 |
2 files changed, 7 insertions, 5 deletions
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 218d9701036e..12a82e91d22a 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c | |||
@@ -2059,7 +2059,7 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) | |||
2059 | dst->addr = src->addr; | 2059 | dst->addr = src->addr; |
2060 | dst->port = src->port; | 2060 | dst->port = src->port; |
2061 | dst->fwmark = src->fwmark; | 2061 | dst->fwmark = src->fwmark; |
2062 | strcpy(dst->sched_name, src->scheduler->name); | 2062 | strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name)); |
2063 | dst->flags = src->flags; | 2063 | dst->flags = src->flags; |
2064 | dst->timeout = src->timeout / HZ; | 2064 | dst->timeout = src->timeout / HZ; |
2065 | dst->netmask = src->netmask; | 2065 | dst->netmask = src->netmask; |
@@ -2080,6 +2080,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, | |||
2080 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | 2080 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { |
2081 | if (count >= get->num_services) | 2081 | if (count >= get->num_services) |
2082 | goto out; | 2082 | goto out; |
2083 | memset(&entry, 0, sizeof(entry)); | ||
2083 | ip_vs_copy_service(&entry, svc); | 2084 | ip_vs_copy_service(&entry, svc); |
2084 | if (copy_to_user(&uptr->entrytable[count], | 2085 | if (copy_to_user(&uptr->entrytable[count], |
2085 | &entry, sizeof(entry))) { | 2086 | &entry, sizeof(entry))) { |
@@ -2094,6 +2095,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, | |||
2094 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | 2095 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { |
2095 | if (count >= get->num_services) | 2096 | if (count >= get->num_services) |
2096 | goto out; | 2097 | goto out; |
2098 | memset(&entry, 0, sizeof(entry)); | ||
2097 | ip_vs_copy_service(&entry, svc); | 2099 | ip_vs_copy_service(&entry, svc); |
2098 | if (copy_to_user(&uptr->entrytable[count], | 2100 | if (copy_to_user(&uptr->entrytable[count], |
2099 | &entry, sizeof(entry))) { | 2101 | &entry, sizeof(entry))) { |
@@ -2304,12 +2306,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2304 | memset(&d, 0, sizeof(d)); | 2306 | memset(&d, 0, sizeof(d)); |
2305 | if (ip_vs_sync_state & IP_VS_STATE_MASTER) { | 2307 | if (ip_vs_sync_state & IP_VS_STATE_MASTER) { |
2306 | d[0].state = IP_VS_STATE_MASTER; | 2308 | d[0].state = IP_VS_STATE_MASTER; |
2307 | strcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn); | 2309 | strlcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn, sizeof(d[0].mcast_ifn)); |
2308 | d[0].syncid = ip_vs_master_syncid; | 2310 | d[0].syncid = ip_vs_master_syncid; |
2309 | } | 2311 | } |
2310 | if (ip_vs_sync_state & IP_VS_STATE_BACKUP) { | 2312 | if (ip_vs_sync_state & IP_VS_STATE_BACKUP) { |
2311 | d[1].state = IP_VS_STATE_BACKUP; | 2313 | d[1].state = IP_VS_STATE_BACKUP; |
2312 | strcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn); | 2314 | strlcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn, sizeof(d[1].mcast_ifn)); |
2313 | d[1].syncid = ip_vs_backup_syncid; | 2315 | d[1].syncid = ip_vs_backup_syncid; |
2314 | } | 2316 | } |
2315 | if (copy_to_user(user, &d, sizeof(d)) != 0) | 2317 | if (copy_to_user(user, &d, sizeof(d)) != 0) |
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 25c479550a32..574d1f509b46 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c | |||
@@ -839,10 +839,10 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) | |||
839 | 839 | ||
840 | ip_vs_sync_state |= state; | 840 | ip_vs_sync_state |= state; |
841 | if (state == IP_VS_STATE_MASTER) { | 841 | if (state == IP_VS_STATE_MASTER) { |
842 | strcpy(ip_vs_master_mcast_ifn, mcast_ifn); | 842 | strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn)); |
843 | ip_vs_master_syncid = syncid; | 843 | ip_vs_master_syncid = syncid; |
844 | } else { | 844 | } else { |
845 | strcpy(ip_vs_backup_mcast_ifn, mcast_ifn); | 845 | strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn)); |
846 | ip_vs_backup_syncid = syncid; | 846 | ip_vs_backup_syncid = syncid; |
847 | } | 847 | } |
848 | 848 | ||