[PATCH] IPVS: Replace several unchecked strcpy() with strncpy() (PaX team)

Linux Kernel Mailing List <[email protected]> Tue, 31 May 2005 11:32:10 +0000
Newsgroups gmane.linux.kernel.commits.2-4
Message-ID <[email protected]>
ChangeSet 1.1564, 2005/05/31 08:32:10-03:00, [email protected]

	[PATCH] IPVS: Replace several unchecked strcpy() with strncpy() (PaX team)
	
	strcpy() is exploitable from the root but we can expect some user
	interface running with root privileges which pass user information
	to the kernel and exploit the bug.



 ip_vs_ctl.c   |   21 ++++++++++++++-------
 ip_vs_sched.c |    2 +-
 ip_vs_sync.c  |    6 ++++--
 3 files changed, 19 insertions(+), 10 deletions(-)


diff -Nru a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
--- a/net/ipv4/ipvs/ip_vs_ctl.c	2005-05-31 13:01:46 -07:00
+++ b/net/ipv4/ipvs/ip_vs_ctl.c	2005-05-31 13:01:46 -07:00
@@ -1842,7 +1842,8 @@
 			entry.addr = svc->addr;
 			entry.port = svc->port;
 			entry.fwmark = svc->fwmark;
-			strcpy(entry.sched_name, svc->scheduler->name);
+			strncpy(entry.sched_name, svc->scheduler->name, sizeof(entry.sched_name));
+			entry.sched_name[sizeof(entry.sched_name) - 1] = 0;
 			entry.flags = svc->flags;
 			entry.timeout = svc->timeout / HZ;
 			entry.netmask = svc->netmask;
@@ -1866,7 +1867,8 @@
 			entry.addr = svc->addr;
 			entry.port = svc->port;
 			entry.fwmark = svc->fwmark;
-			strcpy(entry.sched_name, svc->scheduler->name);
+			strncpy(entry.sched_name, svc->scheduler->name, sizeof(entry.sched_name));
+			entry.sched_name[sizeof(entry.sched_name) - 1] = 0;
 			entry.flags = svc->flags;
 			entry.timeout = svc->timeout / HZ;
 			entry.netmask = svc->netmask;
@@ -2020,7 +2022,8 @@
 			svc = __ip_vs_service_get(get.protocol,
 						  get.addr, get.port);
 		if (svc) {
-			strcpy(get.sched_name, svc->scheduler->name);
+			strncpy(get.sched_name, svc->scheduler->name, sizeof(get.sched_name));
+			get.sched_name[sizeof(get.sched_name) - 1] = 0;
 			get.flags = svc->flags;
 			get.timeout = svc->timeout / HZ;
 			get.netmask = svc->netmask;
@@ -2083,10 +2086,14 @@
 			goto out;
 		}
 		u.state = ip_vs_sync_state;
-		if (ip_vs_sync_state & IP_VS_STATE_MASTER)
-			strcpy(u.mcast_master_ifn, ip_vs_mcast_master_ifn);
-		if (ip_vs_sync_state & IP_VS_STATE_BACKUP)
-			strcpy(u.mcast_backup_ifn, ip_vs_mcast_backup_ifn);
+		if (ip_vs_sync_state & IP_VS_STATE_MASTER) {
+			strncpy(u.mcast_master_ifn, ip_vs_mcast_master_ifn, sizeof(u.mcast_master_ifn));
+			u.mcast_master_ifn[sizeof(u.mcast_master_ifn) - 1] = 0;
+		}
+		if (ip_vs_sync_state & IP_VS_STATE_BACKUP) {
+			strncpy(u.mcast_backup_ifn, ip_vs_mcast_backup_ifn, sizeof(u.mcast_backup_ifn));
+			u.mcast_backup_ifn[sizeof(u.mcast_backup_ifn) - 1] = 0;
+		}
 		if (copy_to_user(user, &u, sizeof(u)) != 0)
 			ret = -EFAULT;
 	}
diff -Nru a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c
--- a/net/ipv4/ipvs/ip_vs_sched.c	2005-05-31 13:01:46 -07:00
+++ b/net/ipv4/ipvs/ip_vs_sched.c	2005-05-31 13:01:46 -07:00
@@ -156,7 +156,7 @@
 	 */
 	if (sched == NULL) {
 		char module_name[IP_VS_SCHEDNAME_MAXLEN+8];
-		sprintf(module_name,"ip_vs_%s", sched_name);
+		snprintf(module_name, sizeof(module_name), "ip_vs_%s", sched_name);
 		request_module(module_name);
 		sched = ip_vs_sched_getbyname(sched_name);
 	}
diff -Nru a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
--- a/net/ipv4/ipvs/ip_vs_sync.c	2005-05-31 13:01:46 -07:00
+++ b/net/ipv4/ipvs/ip_vs_sync.c	2005-05-31 13:01:46 -07:00
@@ -808,10 +808,12 @@
 
 	ip_vs_sync_state |= state;
 	if (state == IP_VS_STATE_MASTER) {
-		strcpy(ip_vs_mcast_master_ifn, mcast_ifn);
+		strncpy(ip_vs_mcast_master_ifn, mcast_ifn, sizeof(ip_vs_mcast_master_ifn));
+		ip_vs_mcast_master_ifn[sizeof(ip_vs_mcast_master_ifn) - 1] = 0;
 		ip_vs_master_syncid = syncid;
 	} else {
-		strcpy(ip_vs_mcast_backup_ifn, mcast_ifn);
+		strncpy(ip_vs_mcast_backup_ifn, mcast_ifn, sizeof(ip_vs_mcast_backup_ifn));
+		ip_vs_mcast_backup_ifn[sizeof(ip_vs_mcast_backup_ifn) - 1] = 0;
 		ip_vs_backup_syncid = syncid;
 	}