Description: switch all sprintfs which can overrun to snprintfs
 This will be forwarded upstream
Author: Serge Hallyn <serge.hallyn@ubuntu.com>
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/988918
Forwarded: no

Index: lxc-0.7.5/src/lxc/commands.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/commands.c	2012-04-26 16:18:15.000000000 +0000
+++ lxc-0.7.5/src/lxc/commands.c	2012-04-26 17:09:39.562283058 +0000
@@ -75,8 +75,14 @@
 	int sock, ret = -1;
 	char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
 	char *offset = &path[1];
+	int rc, len;
 
-	sprintf(offset, abstractname, name);
+	len = sizeof(path)-1;
+	rc = snprintf(offset, len, abstractname, name);
+	if (rc < 0 || rc >= len) {
+		ERROR("Name too long");
+		return -1;
+	}
 
 	sock = lxc_af_unix_connect(path);
 	if (sock < 0 && errno == ECONNREFUSED) {
@@ -268,8 +274,14 @@
 	int ret, fd;
 	char path[sizeof(((struct sockaddr_un *)0)->sun_path)] = { 0 };
 	char *offset = &path[1];
+	int rc, len;
 
-	sprintf(offset, abstractname, name);
+	len = sizeof(path)-1;
+	rc = snprintf(offset, len, abstractname, name);
+	if (rc < 0 || rc >= len) {
+		ERROR("Name too long");
+		return -1;
+	}
 
 	fd = lxc_af_unix_open(path, SOCK_STREAM, 0);
 	if (fd < 0) {
Index: lxc-0.7.5/src/lxc/lxc_monitor.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/lxc_monitor.c	2012-04-26 16:18:15.000000000 +0000
+++ lxc-0.7.5/src/lxc/lxc_monitor.c	2012-04-26 16:18:15.000000000 +0000
@@ -71,6 +71,7 @@
 	struct lxc_msg msg;
 	regex_t preg;
 	int fd;
+	int len, rc;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
 		return -1;
@@ -79,12 +80,18 @@
 			 my_args.progname, my_args.quiet))
 		return -1;
 
-	regexp = malloc(strlen(my_args.name) + 3);
+	len = strlen(my_args.name) + 3;
+	regexp = malloc(len + 3);
 	if (!regexp) {
 		ERROR("failed to allocate memory");
 		return -1;
 	}
-	sprintf(regexp, "^%s$", my_args.name);
+	rc = snprintf(regexp, len, "^%s$", my_args.name);
+	if (rc < 0 || rc >= len) {
+		ERROR("Name too long");
+		free(regexp);
+		return -1;
+	}
 
 	if (regcomp(&preg, regexp, REG_NOSUB|REG_EXTENDED)) {
 		ERROR("failed to compile the regex '%s'", my_args.name);
Index: lxc-0.7.5/src/lxc/conf.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/conf.c	2012-04-26 16:18:15.000000000 +0000
+++ lxc-0.7.5/src/lxc/conf.c	2012-04-26 17:08:52.866279000 +0000
@@ -234,11 +234,25 @@
 		return -1;
 	}
 
-	ret = sprintf(buffer, "%s %s %s", script, name, section);
+	ret = snprintf(buffer, size, "%s %s %s", script, name, section);
+	if (ret < 0 || ret >= size) {
+		ERROR("Script name too long");
+		free(buffer);
+		return -1;
+	}
 
 	va_start(ap, script);
-	while ((p = va_arg(ap, char *)))
-		ret += sprintf(buffer + ret, " %s", p);
+	while ((p = va_arg(ap, char *))) {
+		int len = size-ret;
+		int rc;
+		rc = snprintf(buffer + ret, len, " %s", p);
+		if (rc < 0 || rc >= len) {
+			free(buffer);
+			ERROR("Script args too long");
+			return -1;
+		}
+		ret += rc;
+	}
 	va_end(ap);
 
 	f = popen(buffer, "r");
@@ -384,7 +398,7 @@
 {
 	struct dirent dirent, *direntp;
 	struct loop_info64 loinfo;
-	int ret = -1, fd = -1;
+	int ret = -1, fd = -1, rc;
 	DIR *dir;
 	char path[MAXPATHLEN];
 
@@ -408,7 +422,10 @@
 		if (strncmp(direntp->d_name, "loop", 4))
 			continue;
 
-		sprintf(path, "/dev/%s", direntp->d_name);
+		rc = snprintf(path, MAXPATHLEN, "/dev/%s", direntp->d_name);
+		if (rc < 0 || rc >= MAXPATHLEN)
+			continue;
+
 		fd = open(path, O_RDWR);
 		if (fd < 0)
 			continue;
@@ -570,7 +587,7 @@
 		}
 		if (ttydir) {
 			/* create dev/lxc/tty%d" */
-			snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
+			ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
 				 rootfs->mount, ttydir, i + 1);
 			if (ret >= sizeof(lxcpath)) {
 				ERROR("pathname too long for ttys");
@@ -594,7 +611,11 @@
 				continue;
 			}
 
-			snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
+			ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
+			if (ret >= sizeof(lxcpath)) {
+				ERROR("tty pathname too long");
+				return -1;
+			}
 			ret = symlink(lxcpath, path);
 			if (ret) {
 				SYSERROR("failed to create symlink for tty %d\n", i+1);
@@ -675,12 +696,17 @@
 	void *cbparm[2];
 	struct lxc_list mountlist, *iterator;
 	int ok, still_mounted, last_still_mounted;
+	int rc;
 
 	/* read and parse /proc/mounts in old root fs */
 	lxc_list_init(&mountlist);
 
 	/* oldrootfs is on the top tree directory now */
-	snprintf(path, sizeof(path), "/%s", oldrootfs);
+	rc = snprintf(path, sizeof(path), "/%s", oldrootfs);
+	if (rc >= sizeof(path)) {
+		ERROR("rootfs name too long");
+		return -1;
+	}
 	cbparm[0] = &mountlist;
 
 	cbparm[1] = strdup(path);
@@ -689,7 +715,11 @@
 		return -1;
 	}
 
-	snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
+	rc = snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
+	if (rc >= sizeof(path)) {
+		ERROR("container proc/mounts name too long");
+		return -1;
+	}
 
 	ok = lxc_file_for_each_line(path,
 				    setup_rootfs_pivot_root_cb, &cbparm);
@@ -743,6 +773,7 @@
 {
 	char path[MAXPATHLEN];
 	int remove_pivotdir = 0;
+	int rc;
 
 	/* change into new root fs */
 	if (chdir(rootfs)) {
@@ -754,7 +785,11 @@
 		pivotdir = "mnt";
 
 	/* compute the full path to pivotdir under rootfs */
-	snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
+	rc = snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
+	if (rc >= sizeof(path)) {
+		ERROR("pivot dir name too long");
+		return -1;
+	}
 
 	if (access(path, F_OK)) {
 
@@ -977,7 +1012,11 @@
 	}
 
 	/* create symlink from rootfs/dev/console to 'lxc/console' */
-	snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
+	ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
+	if (ret >= sizeof(lxcpath)) {
+		ERROR("lxc/console path too long");
+		return -1;
+	}
 	ret = symlink(lxcpath, path);
 	if (ret) {
 		SYSERROR("failed to create symlink for console");
@@ -1171,7 +1210,7 @@
 
 skipabs:
 
-	snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
+	r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
 		 aux + offset);
 	if (r < 0 || r >= MAXPATHLEN) {
 		WARN("pathnme too long for '%s'", mntent->mnt_dir);
@@ -1202,7 +1241,11 @@
 	}
 
         /* relative to root mount point */
-	snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
+	ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
+	if (ret >= sizeof(path)) {
+		ERROR("path name too long");
+		return -1;
+	}
 
 	ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
 			  mntflags, mntdata);
@@ -1564,7 +1607,11 @@
 	if (netdev->priv.veth_attr.pair)
 		veth1 = netdev->priv.veth_attr.pair;
 	else {
-		snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
+		err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
+		if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
+			ERROR("veth1 name too long");
+			return -1;
+		}
 		veth1 = mktemp(veth1buf);
 	}
 
@@ -1642,7 +1689,9 @@
 		return -1;
 	}
 
-	snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
+	err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
+	if (err >= sizeof(peerbuf))
+		return -1;
 
 	peer = mktemp(peerbuf);
 	if (!strlen(peer)) {
@@ -1689,7 +1738,11 @@
 		return -1;
 	}
 
-	snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
+	err = snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
+	if (err >= sizeof(peer)) {
+		ERROR("peer name too long");
+		return -1;
+	}
 
 	err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
 	if (err) {
Index: lxc-0.7.5/src/lxc/namespace.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/namespace.c	2011-08-11 16:59:44.000000000 +0000
+++ lxc-0.7.5/src/lxc/namespace.c	2012-04-26 16:18:15.000000000 +0000
@@ -90,6 +90,7 @@
 	int fd[size];
 	int i;
 
+	/* pid is pid_t, can't be > MAXPATHLEN */
 	sprintf(path, "/proc/%d/ns", pid);
 	if (access(path, X_OK)) {
 		ERROR("Does this kernel version support 'attach' ?");
Index: lxc-0.7.5/src/lxc/network.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/network.c	2011-07-24 22:27:10.000000000 +0000
+++ lxc-0.7.5/src/lxc/network.c	2012-04-26 16:18:15.000000000 +0000
@@ -576,12 +576,15 @@
 static int ip_forward_set(const char *ifname, int family, int flag)
 {
 	char path[MAXPATHLEN];
+	int rc;
 
 	if (family != AF_INET && family != AF_INET6)
 		return -EINVAL;
 
-	snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
+	rc = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
 		 family == AF_INET?"ipv4":"ipv6" , ifname);
+	if (rc >= MAXPATHLEN)
+		return -E2BIG;
 
 	return proc_sys_net_write(path, flag?"1":"0");
 }
@@ -599,13 +602,16 @@
 static int neigh_proxy_set(const char *ifname, int family, int flag)
 {
 	char path[MAXPATHLEN];
+	int ret;
 
 	if (family != AF_INET && family != AF_INET6)
 		return -EINVAL;
 
-	sprintf(path, "/proc/sys/net/%s/conf/%s/%s",
+	ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
 		family == AF_INET?"ipv4":"ipv6" , ifname,
 		family == AF_INET?"proxy_arp":"proxy_ndp");
+	if (ret < 0 || ret >= MAXPATHLEN)
+		return -E2BIG;
 
 	return proc_sys_net_write(path, flag?"1":"0");
 }
Index: lxc-0.7.5/src/lxc/cgroup.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/cgroup.c	2012-04-26 16:18:15.000000000 +0000
+++ lxc-0.7.5/src/lxc/cgroup.c	2012-04-26 16:18:15.000000000 +0000
@@ -169,8 +169,13 @@
 static int cgroup_rename_nsgroup(const char *mnt, const char *name, pid_t pid)
 {
 	char oldname[MAXPATHLEN];
+	int ret;
 
-	snprintf(oldname, MAXPATHLEN, "%s/%d", mnt, pid);
+	ret = snprintf(oldname, MAXPATHLEN, "%s/%d", mnt, pid);
+	if (ret < 0 || ret >= MAXPATHLEN) {
+		ERROR("Name too long");
+		return -1;
+	}
 
 	if (rename(oldname, name)) {
 		SYSERROR("failed to rename cgroup %s->%s", oldname, name);
@@ -208,8 +213,11 @@
 	FILE *f;
 	char tasks[MAXPATHLEN];
 	int ret = 0;
+	int rc;
 
-	snprintf(tasks, MAXPATHLEN, "%s/tasks", path);
+	rc = snprintf(tasks, MAXPATHLEN, "%s/tasks", path);
+	if (rc < 0 || rc >= MAXPATHLEN)
+		return -1;
 
 	f = fopen(tasks, "w");
 	if (!f) {
@@ -400,6 +408,7 @@
 
 	while (!readdir_r(dir, &dirent, &direntp)) {
 		struct stat mystat;
+		int rc;
 
 		if (!direntp)
 			break;
@@ -408,7 +417,9 @@
 		    !strcmp(direntp->d_name, ".."))
 			continue;
 
-		snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name);
+		rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name);
+		if (rc < 0 || rc >= MAXPATHLEN)
+			continue;
 		ret = stat(pathname, &mystat);
 		if (ret)
 			continue;
@@ -429,9 +440,14 @@
 {
 	char cgname[MAXPATHLEN], initcgroup[MAXPATHLEN];
 	char *cgmnt = mntent->mnt_dir;
+	int rc;
 
-	snprintf(cgname, MAXPATHLEN, "%s%s/lxc/%s", cgmnt,
+	rc = snprintf(cgname, MAXPATHLEN, "%s%s/lxc/%s", cgmnt,
 		get_init_cgroup(NULL, mntent, initcgroup), name);
+	if (rc < 0 || rc >= MAXPATHLEN) {
+		ERROR("name too long");
+		return -1;
+	}
 	DEBUG("destroying %s\n", cgname);
 	if (recursive_rmdir(cgname)) {
 		SYSERROR("failed to remove cgroup '%s'", cgname);
@@ -482,11 +498,16 @@
 {
 	static char        buf[MAXPATHLEN];
 	static char        retbuf[MAXPATHLEN];
+	int rc;
 
 	/* what lxc_cgroup_set calls subsystem is actually the filename, i.e.
 	   'devices.allow'.  So for our purposee we trim it */
 	if (subsystem) {
-		snprintf(retbuf, MAXPATHLEN, "%s", subsystem);
+		rc = snprintf(retbuf, MAXPATHLEN, "%s", subsystem);
+		if (rc < 0 || rc >= MAXPATHLEN) {
+			ERROR("subsystem name too long");
+			return -1;
+		}
 		char *s = index(retbuf, '.');
 		if (s)
 			*s = '\0';
@@ -497,7 +518,11 @@
 		return -1;
 	}
 
-	snprintf(retbuf, MAXPATHLEN, "%s/%s", buf, name);
+	rc = snprintf(retbuf, MAXPATHLEN, "%s/%s", buf, name);
+	if (rc < 0 || rc >= MAXPATHLEN) {
+		ERROR("name too long");
+		return -1;
+	}
 
 	DEBUG("%s: returning %s for subsystem %s", __func__, retbuf, subsystem);
 
@@ -510,12 +535,15 @@
 	int fd, ret;
 	char *dirpath;
 	char path[MAXPATHLEN];
+	int rc;
 
 	ret = lxc_cgroup_path_get(&dirpath, filename, name);
 	if (ret)
 		return -1;
 
-	snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
+	rc = snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
+	if (rc < 0 || rc >= MAXPATHLEN)
+		return -1;
 
 	fd = open(path, O_WRONLY);
 	if (fd < 0) {
@@ -541,12 +569,15 @@
 	int fd, ret = -1;
 	char *dirpath;
 	char path[MAXPATHLEN];
+	int rc;
 
 	ret = lxc_cgroup_path_get(&dirpath, filename, name);
 	if (ret)
 		return -1;
 
-	snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
+	rc = snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
+	if (rc < 0 || rc >= MAXPATHLEN)
+		return -1;
 
 	fd = open(path, O_RDONLY);
 	if (fd < 0) {
@@ -568,12 +599,15 @@
 	char path[MAXPATHLEN];
 	int pid, ret, count = 0;
 	FILE *file;
+	int rc;
 
 	ret = lxc_cgroup_path_get(&dpath, NULL, name);
 	if (ret)
 		return -1;
 
-	snprintf(path, MAXPATHLEN, "%s/tasks", dpath);
+	rc = snprintf(path, MAXPATHLEN, "%s/tasks", dpath);
+	if (rc < 0 || rc >= MAXPATHLEN)
+		return -1;
 
 	file = fopen(path, "r");
 	if (!file) {
Index: lxc-0.7.5/src/lxc/state.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/state.c	2011-07-24 22:27:10.000000000 +0000
+++ lxc-0.7.5/src/lxc/state.c	2012-04-26 16:18:15.000000000 +0000
@@ -75,7 +75,9 @@
 	if (err)
 		return -1;
 
-	snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
+	err = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
+	if (err < 0 || err >= MAXPATHLEN)
+		return -1;
 
 	file = fopen(freezer, "r");
 	if (!file)
Index: lxc-0.7.5/src/lxc/freezer.c
===================================================================
--- lxc-0.7.5.orig/src/lxc/freezer.c	2011-07-24 22:27:10.000000000 +0000
+++ lxc-0.7.5/src/lxc/freezer.c	2012-04-26 16:30:20.918284521 +0000
@@ -49,7 +49,11 @@
 	if (ret)
 		return -1;
 
-	snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
+	ret = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
+	if (ret >= MAXPATHLEN) {
+		ERROR("freezer.state name too long");
+		return -1;
+	}
 
 	fd = open(freezer, O_RDWR);
 	if (fd < 0) {
