[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>

authored by pageexec and committed by David S. Miller 4da62fc7 d470e3b4

+7 -5
+5 -3
net/ipv4/ipvs/ip_vs_ctl.c
··· 2059 dst->addr = src->addr; 2060 dst->port = src->port; 2061 dst->fwmark = src->fwmark; 2062 - strcpy(dst->sched_name, src->scheduler->name); 2063 dst->flags = src->flags; 2064 dst->timeout = src->timeout / HZ; 2065 dst->netmask = src->netmask; ··· 2080 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { 2081 if (count >= get->num_services) 2082 goto out; 2083 ip_vs_copy_service(&entry, svc); 2084 if (copy_to_user(&uptr->entrytable[count], 2085 &entry, sizeof(entry))) { ··· 2095 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { 2096 if (count >= get->num_services) 2097 goto out; 2098 ip_vs_copy_service(&entry, svc); 2099 if (copy_to_user(&uptr->entrytable[count], 2100 &entry, sizeof(entry))) { ··· 2306 memset(&d, 0, sizeof(d)); 2307 if (ip_vs_sync_state & IP_VS_STATE_MASTER) { 2308 d[0].state = IP_VS_STATE_MASTER; 2309 - strcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn); 2310 d[0].syncid = ip_vs_master_syncid; 2311 } 2312 if (ip_vs_sync_state & IP_VS_STATE_BACKUP) { 2313 d[1].state = IP_VS_STATE_BACKUP; 2314 - strcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn); 2315 d[1].syncid = ip_vs_backup_syncid; 2316 } 2317 if (copy_to_user(user, &d, sizeof(d)) != 0)
··· 2059 dst->addr = src->addr; 2060 dst->port = src->port; 2061 dst->fwmark = src->fwmark; 2062 + strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name)); 2063 dst->flags = src->flags; 2064 dst->timeout = src->timeout / HZ; 2065 dst->netmask = src->netmask; ··· 2080 list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { 2081 if (count >= get->num_services) 2082 goto out; 2083 + memset(&entry, 0, sizeof(entry)); 2084 ip_vs_copy_service(&entry, svc); 2085 if (copy_to_user(&uptr->entrytable[count], 2086 &entry, sizeof(entry))) { ··· 2094 list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { 2095 if (count >= get->num_services) 2096 goto out; 2097 + memset(&entry, 0, sizeof(entry)); 2098 ip_vs_copy_service(&entry, svc); 2099 if (copy_to_user(&uptr->entrytable[count], 2100 &entry, sizeof(entry))) { ··· 2304 memset(&d, 0, sizeof(d)); 2305 if (ip_vs_sync_state & IP_VS_STATE_MASTER) { 2306 d[0].state = IP_VS_STATE_MASTER; 2307 + strlcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn, sizeof(d[0].mcast_ifn)); 2308 d[0].syncid = ip_vs_master_syncid; 2309 } 2310 if (ip_vs_sync_state & IP_VS_STATE_BACKUP) { 2311 d[1].state = IP_VS_STATE_BACKUP; 2312 + strlcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn, sizeof(d[1].mcast_ifn)); 2313 d[1].syncid = ip_vs_backup_syncid; 2314 } 2315 if (copy_to_user(user, &d, sizeof(d)) != 0)
+2 -2
net/ipv4/ipvs/ip_vs_sync.c
··· 839 840 ip_vs_sync_state |= state; 841 if (state == IP_VS_STATE_MASTER) { 842 - strcpy(ip_vs_master_mcast_ifn, mcast_ifn); 843 ip_vs_master_syncid = syncid; 844 } else { 845 - strcpy(ip_vs_backup_mcast_ifn, mcast_ifn); 846 ip_vs_backup_syncid = syncid; 847 } 848
··· 839 840 ip_vs_sync_state |= state; 841 if (state == IP_VS_STATE_MASTER) { 842 + strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn)); 843 ip_vs_master_syncid = syncid; 844 } else { 845 + strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn)); 846 ip_vs_backup_syncid = syncid; 847 } 848