[stgt] [PATCH 2/4] using concat_printf() in tgtadm

Alexander Nezhinsky alexandern at mellanox.com
Sat Nov 26 12:23:42 CET 2011


Using struct concat_buf and its associated concat_printf() variant 
of snprintf(), replacing shprintf() macro.
This spares explicit checkguards against buffer overflow.

Signed-off-by: Alexander Nezhinsky <alexandern at mellanox.com>
---
 usr/tgtadm.c |   83 ++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 49 insertions(+), 34 deletions(-)

diff --git a/usr/tgtadm.c b/usr/tgtadm.c
index 41e9e99..f6b8342 100644
--- a/usr/tgtadm.c
+++ b/usr/tgtadm.c
@@ -415,6 +415,32 @@ static int str_to_op(char *str)
 	}
 }
 
+int concat_printf(struct concat_buf *b, const char *format, ...)
+{
+	va_list args;
+	int rest = b->size - b->used;
+	int nprinted;
+
+	if (b->err)
+		return b->err;
+	if (!rest)
+		return (b->err = -ENOSPC);
+
+	va_start(args, format);
+	nprinted = vsnprintf(b->buf + b->used, rest, format, args);
+	va_end(args);
+
+	if (nprinted < 0)
+		return (b->err = nprinted);
+
+	if (nprinted >= rest) {
+		nprinted = rest;
+		b->err = -ENOSPC;
+	}
+	b->used += nprinted;
+	return b->err;
+}
+
 static void bad_optarg(int ret, int ch, char *optarg)
 {
 	if (ret == ERANGE)
@@ -445,26 +471,26 @@ static int verify_mode_params(int argc, char **argv, char *allowed)
 int main(int argc, char **argv)
 {
 	int ch, longindex, rc;
-	int op, total, tid, rest, mode, dev_type, ac_dir;
+	int op, tid, mode, dev_type, ac_dir;
 	uint32_t cid, hostno;
 	uint64_t sid, lun, force;
-	char *name, *value, *path, *targetname, *params, *address, *iqnname, *targetOps;
+	char *name, *value, *path, *targetname, *address, *iqnname, *targetOps;
 	char *portalOps, *bstype;
 	char *bsoflags;
 	char *blocksize;
 	char *user, *password;
 	char *buf;
 	size_t bufsz = BUFSIZE + sizeof(struct tgtadm_req);
+	struct concat_buf b;
 	struct tgtadm_req *req;
 
 	op = tid = mode = -1;
-	total = cid = hostno = sid = 0;
+	cid = hostno = sid = 0;
 	lun = UINT64_MAX;
 
 	rc = 0;
 	dev_type = TYPE_DISK;
 	ac_dir = ACCOUNT_TYPE_INCOMING;
-	rest = BUFSIZE;
 	name = value = path = targetname = address = iqnname = NULL;
 	targetOps = portalOps = bstype = NULL;
 	bsoflags = blocksize = user = password = NULL;
@@ -864,53 +890,42 @@ int main(int argc, char **argv)
 	req->ac_dir = ac_dir;
 	req->force = force;
 
-	params = buf + sizeof(*req);
+	concat_buf_init(&b, buf + sizeof(*req), bufsz - sizeof(*req));
 
 	if (name)
-		shprintf(total, params, rest, "%s=%s", name, value);
+		concat_printf(&b, "%s=%s", name, value);
 	if (path)
-		shprintf(total, params, rest, "%spath=%s",
-			 rest == BUFSIZE ? "" : ",", path);
+		concat_printf(&b, "%spath=%s", concat_delim(&b,","), path);
 
 	if (req->device_type == TYPE_TAPE)
-		shprintf(total, params, rest, "%sbstype=%s",
-			 rest == BUFSIZE ? "" : ",", "ssc");
+		concat_printf(&b, "%sbstype=%s", concat_delim(&b,","), "ssc");
 	else if (bstype)
-		shprintf(total, params, rest, "%sbstype=%s",
-			 rest == BUFSIZE ? "" : ",", bstype);
+		concat_printf(&b, "%sbstype=%s", concat_delim(&b,","), bstype);
 	if (bsoflags)
-		shprintf(total, params, rest, "%sbsoflags=%s",
-			 rest == BUFSIZE ? "" : ",", bsoflags);
+		concat_printf(&b, "%sbsoflags=%s", concat_delim(&b,","), bsoflags);
 	if (blocksize)
-		shprintf(total, params, rest, "%sblocksize=%s",
-			 rest == BUFSIZE ? "" : ",", blocksize);
+		concat_printf(&b, "%sblocksize=%s", concat_delim(&b,","), blocksize);
 	if (targetname)
-		shprintf(total, params, rest, "%stargetname=%s",
-			 rest == BUFSIZE ? "" : ",", targetname);
+		concat_printf(&b, "%stargetname=%s", concat_delim(&b,","), targetname);
 	if (address)
-		shprintf(total, params, rest, "%sinitiator-address=%s",
-			 rest == BUFSIZE ? "" : ",", address);
+		concat_printf(&b, "%sinitiator-address=%s", concat_delim(&b,","), address);
 	if (iqnname)
-		shprintf(total, params, rest, "%sinitiator-name=%s",
-			 rest == BUFSIZE ? "" : ",", iqnname);
+		concat_printf(&b, "%sinitiator-name=%s", concat_delim(&b,","), iqnname);
 	if (user)
-		shprintf(total, params, rest, "%suser=%s",
-			 rest == BUFSIZE ? "" : ",", user);
+		concat_printf(&b, "%suser=%s", concat_delim(&b,","), user);
 	if (password)
-		shprintf(total, params, rest, "%spassword=%s",
-			 rest == BUFSIZE ? "" : ",", password);
+		concat_printf(&b, "%spassword=%s", concat_delim(&b,","), password);
 	/* Trailing ',' makes parsing params in modules easier.. */
 	if (targetOps)
-		shprintf(total, params, rest, "%stargetOps %s,",
-			 rest == BUFSIZE ? "" : ",", targetOps);
+		concat_printf(&b, "%stargetOps %s,", concat_delim(&b,","), targetOps);
 	if (portalOps)
-		shprintf(total, params, rest, "%sportalOps %s,",
-			 rest == BUFSIZE ? "" : ",", portalOps);
+		concat_printf(&b, "%sportalOps %s,", concat_delim(&b,","), portalOps);
 
-	req->len = sizeof(*req) + total;
+	if (b.err) {
+		eprintf("BUFSIZE (%d bytes) isn't long enough\n", BUFSIZE);
+		return EINVAL;
+	}
 
+	req->len = sizeof(*req) + b.used;
 	return ipc_mgmt_req(req);
-overflow:
-	eprintf("BUFSIZE (%d bytes) isn't long enough\n", BUFSIZE);
-	return EINVAL;
 }
--
1.7.1
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list