All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduardo Silva <eduardo.silva@oracle.com>
To: Olaf van der Spek <olafvdspek@gmail.com>
Cc: Jeremy Sanders <jeremy@jeremysanders.net>, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH] Btrfs-progs use safe string manipulation functions
Date: Thu, 10 Feb 2011 10:29:45 -0300	[thread overview]
Message-ID: <1297344585.28159.12.camel@monotop> (raw)
In-Reply-To: <AANLkTi=7B1FLtSrcJ88zgitCBiRctwveRhLzt_2yAHZL@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1015 bytes --]

On Thu, 2011-02-10 at 12:39 +0100, Olaf van der Spek wrote:
> On Thu, Feb 10, 2011 at 12:37 PM, Jeremy Sanders
> <jeremy@jeremysanders.net> wrote:
> > Olaf van der Spek wrote:
> >
> >> On Thu, Feb 10, 2011 at 12:08 PM, Thomas Bellman <bellman@nsc.liu.se>
> >> wrote:
> >>> strncpy(args.name, source, BTRFS_PATH_NAME_MAX);
> >>> args.name[BTRFS_PATH_NAME_MAX] = '\0';
> >>
> >> That's silly. Isn't there a sane safe variant of strcpy?
> >
> > There's strlcpy, but it's not in glibc because of possible truncation
> > errors!
> 
> Then use a private wrapper.
> 

Here's the new patch:

----
[PATCH] Add safe string manipulation functions

Deprecate direct use of strcpy(3)
The following string manipulation function has been added:

   - string_copy() : wrapper of strcpy(3)
   - string_ncopy(): wrapper of strncpy(3)

both function compose safe NULL terminated strings.
----

I check that the code most of the time raise an error if the path is too
long, so the new wrappers should be ok...

best, 

Eduardo Silva
 

[-- Attachment #2: 0001-Add-safe-string-manipulation-functions.patch --]
[-- Type: text/x-patch, Size: 8559 bytes --]

>From 6e551f4d9482a438beb336c4ec3a54735a15b76c Mon Sep 17 00:00:00 2001
From: Eduardo Silva <eduardo.silva@oracle.com>
Date: Thu, 10 Feb 2011 10:25:15 -0300
Subject: [PATCH] Add safe string manipulation functions

Deprecate direct use of strcpy(3)
The following string manipulation function has been added:

   - string_copy() : wrapper of strcpy(3)
   - string_ncopy(): wrapper of strncpy(3)

both function compose safe NULL terminated strings.

Signed-off-by: Eduardo Silva <eduardo.silva@oracle.com>
---
 btrfs-list.c |    4 ++--
 btrfs-vol.c  |    2 +-
 btrfs.c      |    3 ++-
 btrfs_cmds.c |   14 +++++++-------
 btrfsctl.c   |    2 +-
 convert.c    |    4 ++--
 utils.c      |   38 ++++++++++++++++++++++++++++++++------
 utils.h      |    5 +++++
 8 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/btrfs-list.c b/btrfs-list.c
index 93766a8..ede51a4 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -291,7 +291,7 @@ static int lookup_ino_path(int fd, struct root_info *ri)
 			perror("malloc failed");
 			exit(1);
 		}
-		strcpy(ri->path, args.name);
+		string_copy(ri->path, args.name);
 		strcat(ri->path, ri->name);
 	} else {
 		/* we're at the root of ref_tree */
@@ -448,7 +448,7 @@ char *build_name(char *dirid, char *name)
 	full = malloc(strlen(dirid) + strlen(name) + 1);
 	if (!full)
 		return NULL;
-	strcpy(full, dirid);
+	string_copy(full, dirid);
 	strcat(full, name);
 	return full;
 }
diff --git a/btrfs-vol.c b/btrfs-vol.c
index 4ed799d..60361f6 100644
--- a/btrfs-vol.c
+++ b/btrfs-vol.c
@@ -151,7 +151,7 @@ int main(int ac, char **av)
 	}
 	fd = dirfd(dirstream);
 	if (device)
-		strcpy(args.name, device);
+		string_copy(args.name, device);
 	else
 		args.name[0] = '\0';
 
diff --git a/btrfs.c b/btrfs.c
index 46314cf..ddf4960 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -21,6 +21,7 @@
 
 #include "kerncompat.h"
 #include "btrfs_cmds.h"
+#include "utils.h"
 #include "version.h"
 
 typedef int (*CommandFunction)(int argc, char **argv);
@@ -241,7 +242,7 @@ static int prepare_args(int *ac, char ***av, char *prgname, struct Command *cmd
 	for(i=0; i < *ac ; i++ )
 		ret[i+1] = (*av)[i];
 
-	strcpy(newname, prgname);
+	string_copy(newname, prgname);
 	strcat(newname, " ");
 	strcat(newname, cmd->verb);
 
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index 8031c58..f4be8c2 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -375,7 +375,7 @@ int do_clone(int argc, char **argv)
 	printf("Create a snapshot of '%s' in '%s/%s'\n",
 	       subvol, dstdir, newname);
 	args.fd = fd;
-	strcpy(args.name, newname);
+	string_ncopy(args.name, newname, BTRFS_PATH_NAME_MAX);
 	res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE, &args);
 
 	close(fd);
@@ -436,7 +436,7 @@ int do_delete_subvolume(int argc, char **argv)
 	}
 
 	printf("Delete subvolume '%s/%s'\n", dname, vname);
-	strcpy(args.name, vname);
+	string_ncopy(args.name, vname, BTRFS_PATH_NAME_MAX);
 	res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
 
 	close(fd);
@@ -490,7 +490,7 @@ int do_create_subvol(int argc, char **argv)
 	}
 
 	printf("Create subvolume '%s/%s'\n", dstdir, newname);
-	strcpy(args.name, newname);
+	string_ncopy(args.name, newname, BTRFS_PATH_NAME_MAX);
 	res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args);
 
 	close(fddst);
@@ -553,7 +553,7 @@ int do_scan(int argc, char **argv)
 
 		printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]);
 
-		strcpy(args.name, argv[i]);
+		string_ncopy(args.name, argv[i], BTRFS_PATH_NAME_MAX);
 		/*
 		 * FIXME: which are the error code returned by this ioctl ?
 		 * it seems that is impossible to understand if there no is
@@ -593,7 +593,7 @@ int do_resize(int argc, char **argv)
 	}
 
 	printf("Resize '%s' of '%s'\n", path, amount);
-	strcpy(args.name, amount);
+	string_ncopy(args.name, amount, BTRFS_VOL_NAME_MAX);
 	res = ioctl(fd, BTRFS_IOC_RESIZE, &args);
 	close(fd);
 	if( res < 0 ){
@@ -736,7 +736,7 @@ int do_add_volume(int nargs, char **args)
 		}
 		close(devfd);
 
-		strcpy(ioctl_args.name, args[i]);
+		string_ncopy(ioctl_args.name, args[i], BTRFS_PATH_NAME_MAX);
 		res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
 		if(res<0){
 			fprintf(stderr, "ERROR: error adding the device '%s'\n", args[i]);
@@ -792,7 +792,7 @@ int do_remove_volume(int nargs, char **args)
 		struct	btrfs_ioctl_vol_args arg;
 		int	res;
 
-		strcpy(arg.name, args[i]);
+		string_ncopy(arg.name, args[i], BTRFS_PATH_NAME_MAX);
 		res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
 		if(res<0){
 			fprintf(stderr, "ERROR: error removing the device '%s'\n", args[i]);
diff --git a/btrfsctl.c b/btrfsctl.c
index 92bdf39..adfa519 100644
--- a/btrfsctl.c
+++ b/btrfsctl.c
@@ -237,7 +237,7 @@ int main(int ac, char **av)
 	 }
 
 	if (name)
-		strcpy(args.name, name);
+                strncpy(args.name, name, BTRFS_PATH_NAME_MAX + 1);
 	else
 		args.name[0] = '\0';
 
diff --git a/convert.c b/convert.c
index d037c98..67706f3 100644
--- a/convert.c
+++ b/convert.c
@@ -857,7 +857,7 @@ static int copy_single_xattr(struct btrfs_trans_handle *trans,
 		data = databuf;
 		datalen = bufsize;
 	}
-	strcpy(namebuf, xattr_prefix_table[name_index]);
+	strncpy(namebuf, xattr_prefix_table[name_index], XATTR_NAME_MAX);
 	strncat(namebuf, EXT2_EXT_ATTR_NAME(entry), entry->e_name_len);
 	if (name_len + datalen > BTRFS_LEAF_DATA_SIZE(root) -
 	    sizeof(struct btrfs_item) - sizeof(struct btrfs_dir_item)) {
@@ -1465,7 +1465,7 @@ struct btrfs_root *link_subvol(struct btrfs_root *root, const char *base,
 	key.offset = (u64)-1;
 	key.type = BTRFS_ROOT_ITEM_KEY;
 
-	strcpy(buf, base);
+	string_copy(buf, base);
 	for (i = 0; i < 1024; i++) {
 		ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf),
 					    dirid, &key, BTRFS_FT_DIR, index);
diff --git a/utils.c b/utils.c
index fd894f3..0c052c1 100644
--- a/utils.c
+++ b/utils.c
@@ -108,7 +108,7 @@ int make_btrfs(int fd, const char *device, const char *label,
 	btrfs_set_super_csum_type(&super, BTRFS_CSUM_TYPE_CRC32);
 	btrfs_set_super_chunk_root_generation(&super, 1);
 	if (label)
-		strcpy(super.label, label);
+		strncpy(super.label, label, BTRFS_LABEL_SIZE - 1);
 
 	buf = malloc(sizeof(*buf) + max(sectorsize, leafsize));
 
@@ -828,7 +828,7 @@ void btrfs_register_one_device(char *fname)
 			"skipping device registration\n");
 		return;
 	}
-	strcpy(args.name, fname);
+	strncpy(args.name, fname, BTRFS_PATH_NAME_MAX);
 	ret = ioctl(fd, BTRFS_IOC_SCAN_DEV, &args);
 	close(fd);
 }
@@ -853,7 +853,7 @@ int btrfs_scan_one_dir(char *dirname, int run_ioctl)
 	pending = malloc(sizeof(*pending));
 	if (!pending)
 		return -ENOMEM;
-	strcpy(pending->name, dirname);
+	string_copy(pending->name, dirname);
 
 again:
 	dirname_len = strlen(pending->name);
@@ -894,7 +894,7 @@ again:
 				ret = -ENOMEM;
 				goto fail;
 			}
-			strcpy(next->name, fullpath);
+			string_copy(next->name, fullpath);
 			list_add_tail(&next->list, &pending_list);
 		}
 		if (!S_ISBLK(st.st_mode)) {
@@ -971,6 +971,7 @@ static char *size_strs[] = { "", "KB", "MB", "GB", "TB",
 char *pretty_sizes(u64 size)
 {
 	int num_divs = 0;
+        int pretty_len = 16;
 	u64 last_size = size;
 	u64 fract_size = size;
 	float fraction;
@@ -988,8 +989,33 @@ char *pretty_sizes(u64 size)
 		return NULL;
 
 	fraction = (float)fract_size / 1024;
-	pretty = malloc(16);
-	sprintf(pretty, "%.2f%s", fraction, size_strs[num_divs-1]);
+	pretty = malloc(pretty_len);
+	snprintf(pretty, pretty_len, "%.2f%s", fraction, size_strs[num_divs-1]);
 	return pretty;
 }
 
+char *string_copy(char *dest, const char *src)
+{
+	if (!dest || !src) {
+		fprintf(stderr, "ERROR: invalid string_copy() parameters");
+		exit(EXIT_FAILURE);
+	}
+
+	memset(dest, '\0', sizeof(dest));
+	return strcpy(dest, src);
+}
+
+char *string_ncopy(char *dest, const char *src, size_t n)
+{
+	/* Just a basic test to avoid silly bugs */
+	if (!dest || !src || n <= 0) {
+		fprintf(stderr, "ERROR: invalid string_ncopy() parameters\n");
+		exit(EXIT_FAILURE);
+	}
+
+	strncpy(dest, src, n);
+	dest[n] = '\0';
+	
+	return dest;
+}
+
diff --git a/utils.h b/utils.h
index 9dce5b0..39c8455 100644
--- a/utils.h
+++ b/utils.h
@@ -19,6 +19,8 @@
 #ifndef __UTILS__
 #define __UTILS__
 
+#include "ctree.h"
+
 #define BTRFS_MKFS_SYSTEM_GROUP_SIZE (4 * 1024 * 1024)
 
 int make_btrfs(int fd, const char *device, const char *label,
@@ -40,4 +42,7 @@ int check_mounted(const char *devicename);
 int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
 				 int super_offset);
 char *pretty_sizes(u64 size);
+
+char *string_copy(char *dest, const char *src);
+char *string_ncopy(char *dest, const char *src, size_t n);
 #endif
-- 
1.7.1


  reply	other threads:[~2011-02-10 13:29 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-07 12:22 [PATCH] Btrfs-progs use safe string manipulation functions Eduardo Silva
2011-02-07 18:17 ` Goffredo Baroncelli
2011-02-10 11:08 ` Thomas Bellman
2011-02-10 11:21   ` Olaf van der Spek
2011-02-10 11:37     ` Jeremy Sanders
2011-02-10 11:39       ` Olaf van der Spek
2011-02-10 13:29         ` Eduardo Silva [this message]
2011-02-10 13:34           ` Olaf van der Spek
2011-02-10 13:41             ` Eduardo Silva
     [not found]             ` <1297345079.28159.14.camel@monotop>
2011-02-10 13:52               ` Olaf van der Spek
2011-02-10 14:00                 ` Eduardo Silva
2011-02-10 14:05                   ` Olaf van der Spek
2011-02-10 18:39           ` Goffredo Baroncelli
2011-02-11 12:41           ` Lars Wirzenius
2011-02-10 11:54       ` Lars Wirzenius
2011-02-10 12:27         ` Olaf van der Spek
2011-02-10 12:41           ` Thomas Bellman
2011-02-10 15:17       ` Olaf van der Spek
2011-02-10 11:49   ` Eduardo Silva

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1297344585.28159.12.camel@monotop \
    --to=eduardo.silva@oracle.com \
    --cc=jeremy@jeremysanders.net \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=olafvdspek@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.