Commit 4da62fc7 authored by pageexec's avatar pageexec Committed by David S. Miller

[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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d470e3b4
...@@ -2059,7 +2059,7 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) ...@@ -2059,7 +2059,7 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
dst->addr = src->addr; dst->addr = src->addr;
dst->port = src->port; dst->port = src->port;
dst->fwmark = src->fwmark; dst->fwmark = src->fwmark;
strcpy(dst->sched_name, src->scheduler->name); strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name));
dst->flags = src->flags; dst->flags = src->flags;
dst->timeout = src->timeout / HZ; dst->timeout = src->timeout / HZ;
dst->netmask = src->netmask; dst->netmask = src->netmask;
...@@ -2080,6 +2080,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, ...@@ -2080,6 +2080,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
if (count >= get->num_services) if (count >= get->num_services)
goto out; goto out;
memset(&entry, 0, sizeof(entry));
ip_vs_copy_service(&entry, svc); ip_vs_copy_service(&entry, svc);
if (copy_to_user(&uptr->entrytable[count], if (copy_to_user(&uptr->entrytable[count],
&entry, sizeof(entry))) { &entry, sizeof(entry))) {
...@@ -2094,6 +2095,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, ...@@ -2094,6 +2095,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
if (count >= get->num_services) if (count >= get->num_services)
goto out; goto out;
memset(&entry, 0, sizeof(entry));
ip_vs_copy_service(&entry, svc); ip_vs_copy_service(&entry, svc);
if (copy_to_user(&uptr->entrytable[count], if (copy_to_user(&uptr->entrytable[count],
&entry, sizeof(entry))) { &entry, sizeof(entry))) {
...@@ -2304,12 +2306,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ...@@ -2304,12 +2306,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
memset(&d, 0, sizeof(d)); memset(&d, 0, sizeof(d));
if (ip_vs_sync_state & IP_VS_STATE_MASTER) { if (ip_vs_sync_state & IP_VS_STATE_MASTER) {
d[0].state = IP_VS_STATE_MASTER; d[0].state = IP_VS_STATE_MASTER;
strcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn); strlcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn, sizeof(d[0].mcast_ifn));
d[0].syncid = ip_vs_master_syncid; d[0].syncid = ip_vs_master_syncid;
} }
if (ip_vs_sync_state & IP_VS_STATE_BACKUP) { if (ip_vs_sync_state & IP_VS_STATE_BACKUP) {
d[1].state = IP_VS_STATE_BACKUP; d[1].state = IP_VS_STATE_BACKUP;
strcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn); strlcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn, sizeof(d[1].mcast_ifn));
d[1].syncid = ip_vs_backup_syncid; d[1].syncid = ip_vs_backup_syncid;
} }
if (copy_to_user(user, &d, sizeof(d)) != 0) if (copy_to_user(user, &d, sizeof(d)) != 0)
......
...@@ -839,10 +839,10 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) ...@@ -839,10 +839,10 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
ip_vs_sync_state |= state; ip_vs_sync_state |= state;
if (state == IP_VS_STATE_MASTER) { if (state == IP_VS_STATE_MASTER) {
strcpy(ip_vs_master_mcast_ifn, mcast_ifn); strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn));
ip_vs_master_syncid = syncid; ip_vs_master_syncid = syncid;
} else { } else {
strcpy(ip_vs_backup_mcast_ifn, mcast_ifn); strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn));
ip_vs_backup_syncid = syncid; ip_vs_backup_syncid = syncid;
} }
......
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