Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-07 Thread Anselm R Garbe
Hi FRIGN,

we had this strlcpy pseudo-discussion years ago. And we concluded to
avoid adopting strlcpy.

The basic reason is, that the claim of strlcpy to be more secure than
strncpy is a myth. Roberto has pointed this out already. In either
case you should handle the retval for arbitrary source inputs,
_unless_ you are knowing what you are doing.

In case of dwm, we don't process arbitrary input apart from window
titles. And for those we exactly know what we do. Client structures
are always zero-allocated and c->name[sizeof c->name - 1] is never
touched and hence the last resort string terminator. For all other
uses of strcpy or strncpy the buffer sizes will suffice unless you
don't purposefully exceed the VERSION macro at compile time to be
longer than 251 chars -- and here it wouldn't be about arbitrary input
anyways and detected at compile time (if the compiler is smart
enough).

Also bare in mind, that there is a significant usage difference
between strlcpy and strncpy. strlcpy always requires that the size
argument contains space for the trailing 0, whereas the size argument
of strncpy does not require this. Our code is written to work well
with a non-null-terminated strncpy operation (last resort terminator),
so there is really no need to introduce strlcpy for pseudo security
reasons.

I think the same should apply for most suckless stuff as well.

BR,
Anselm



Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-07 Thread Hiltjo Posthuma
On Mon, Jun 06, 2016 at 08:50:31PM +0200, FRIGN wrote:
> On Mon, 6 Jun 2016 20:12:19 +0200
> k...@shike2.com wrote:
> 
>> ...
> 
> Nope, it's not. Keep in mind strlcpy fills the rest
> of the memory area with 0's.

No it doesn't, but strncpy does that.

> Also, I suspect you have not understood strlcpy()
> at all. Read the manpage!

Roberto wrote compilers before you were a baby.

> The size-argument of strlcpy is wrt to the size of
> the _destination_, not the _source_.
> Your example also hides the fact that "nsrc" has to
> be first determined with strlen().
> 

It depends, strlcpy copies the data regardless if truncation occurs, so it is
slower in some cases. It often does not matter though.

> > From my point of view the worst thing is that people believe
> > that using strlcpy the code magically becomes secure, and this
> > is a totally false security sensation. You have to check the
> > return code, and it means that the code is totally equivalent
> > to an explicit if. Look for example this case:
> > 
> > deluser(strlcpy(dst, "user15", 4));
> > 

Truncation needs to be checked regardless if strlcpy is used or not, imo the
pattern of using strlcpy is nice in alot (but not all) cases. It is usually:

if (strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))
...;

> You cannot possibly check these things by yourself. What
> strlcpy does is give you an insurance in case there is an
> overflow that the program doesn't pass pointers to
> unterminated strings around. Of course you have to check
> the return value anyway.
> I don't know why you are always riding the same horse
> here given that:
>   1) dwm used strcpy (!)
>   2) dwm used _unchecked_ strncpy (!)
> so you definitely should calm down a bit here.
> 

Dwm is not insecure in these cases, it is more a style issue. Some of the
strncpy cases can be replaced even with strcpy, it can't overflow unless
the user screws up his config.

-- 
Kind regards,
Hiltjo



Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-06 Thread FRIGN
On Mon, 6 Jun 2016 20:12:19 +0200
k...@shike2.com wrote:

Hey Roberto,

> What happens if you pass an incorrect size to strlcpy?. Please,
> stop of saying stupid things.

well, you don't pass invalid sizes to strlcpy. It's like if I
asked: Robert, what happens if I pass an invalid path to
unlink()? Huh, see, your world is crumbling into pieces.

>   if (strlcpy(dst, src, nsrc) >= nsrc)
>   error();
> 
> is equal to:
> 
>   if (nsrc >= ndst)
>   error();
>   memcpy(dst, src, nsrc);

Nope, it's not. Keep in mind strlcpy fills the rest
of the memory area with 0's.
Also, I suspect you have not understood strlcpy()
at all. Read the manpage!
The size-argument of strlcpy is wrt to the size of
the _destination_, not the _source_.
Your example also hides the fact that "nsrc" has to
be first determined with strlen().

> but the code with strlcpy is slower and not portable.

I give you a beer at the next slcon if you can show me
a solution which does the same as strlcpy and is faster.

> There is a reason why after 16 years strlcpy is not in any
> standard, no C11, no POSIX, and it is because it sucks a lot.

Well, this is up for debate. I respect your opinion though.

> From my point of view the worst thing is that people believe
> that using strlcpy the code magically becomes secure, and this
> is a totally false security sensation. You have to check the
> return code, and it means that the code is totally equivalent
> to an explicit if. Look for example this case:
> 
>   deluser(strlcpy(dst, "user15", 4));
> 
> Since you are not checking any return code there you are not
> deleting the correct user, and this kind of attacks can be very
> easy of attack, more easier than stack overflow.

Yes, this is a very good point. However, if you used strncpy,
the string would not even be terminated in case of an overflow.
It's funny to see how people wage holy war between strlcpy and
strncpy only to realize that of the two strlcpy is the safer
one.
Now, of course, you have to check the return value.

> In a previous mail you said that one of the reasons of using
> strlcpy was to avoid problems in the future due to modifications
> in the code. Did you think about it before writing it?. You
> can say that of _ANY_ operation in C, mainly with pointers and
> indexes, but strlcpy can not help at all in a situation like this:
> 
> 
>   #define LENA 5
>   #define LENB 6
> 
>   char sa[LENB];
> 
>   f(sa);
> 
>   f(char s[LENB])
>   {
>   strlcpy(s, "This is a very long string", LENB);
>   }
> 
> and now you have this patch:
> 
>   - char sa[LENB];
>   + char sa[LENA];
> 
> Do you see? strlcpy didn't help at all, and due to the
> false security sensation the programmer didn't dig to
> see all the side effects of changing the size of sa.
> C is a very low level language, and it is a language
> without support for strings, and the only way of writting
> correct code is to be very carefull and before doing any
> change check everything, and look for all the possible
> errors due to your change.

You cannot possibly check these things by yourself. What
strlcpy does is give you an insurance in case there is an
overflow that the program doesn't pass pointers to
unterminated strings around. Of course you have to check
the return value anyway.
I don't know why you are always riding the same horse
here given that:
1) dwm used strcpy (!)
2) dwm used _unchecked_ strncpy (!)
so you definitely should calm down a bit here.

> And of course, strlcpy is also totally useless because
> you can do the same work with snprintf.

I'm not sure if people want to involve the complex
mechanics of the *printf functions to do simple string
copying. You have to agree that on a decision between
strncpy and strlcpy, strncpy wins, no matter the context.

Of course, to use strlcpy safely, you have to check the
return code, because truncation is also yielding garbage.
However, at least this garbage won't blow up in your
face.

> PD: I don't want to begin a flame war, but please, stop
> of being a fan boy and think for yourself, try to find
> the strong points and what is propaganda.

Maybe you should evaluate your position a bit better
before going all grandpa here on this ml.
Your first code example is embarassing and shows that
despite your high skill in C you seem to be fighting
the wrong war here.

Cheers

FRIGN

-- 
FRIGN 



Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-06 Thread k0ga
> The only reason why strlcpy is "non-portable" is because the
> Posix-committee has sticks up their asses (same with the
> glibc guys).

Why is so difficult to accept that your idea is so bad?.
Why people like so much think in obscure conspiracions
instead of accepting the true?

Regards,




Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-06 Thread k0ga
> there is also another point here: strlcpy is safer than strcpy
> and strncpy because _if_ there is an overflow the string will

What happens if you pass an incorrect size to strlcpy?. Please,
stop of saying stupid things.

if (strlcpy(dst, src, nsrc) >= nsrc)
error();

is equal to:

if (nsrc >= ndst)
error();
memcpy(dst, src, nsrc);

but the code with strlcpy is slower and not portable.

There is a reason why after 16 years strlcpy is not in any
standard, no C11, no POSIX, and it is because it sucks a lot.
>From my point of view the worst thing is that people believe
that using strlcpy the code magically becomes secure, and this
is a totally false security sensation. You have to check the
return code, and it means that the code is totally equivalent
to an explicit if. Look for example this case:

deluser(strlcpy(dst, "user15", 4));

Since you are not checking any return code there you are not
deleting the correct user, and this kind of attacks can be very
easy of attack, more easier than stack overflow.

In a previous mail you said that one of the reasons of using
strlcpy was to avoid problems in the future due to modifications
in the code. Did you think about it before writing it?. You
can say that of _ANY_ operation in C, mainly with pointers and
indexes, but strlcpy can not help at all in a situation like this:


#define LENA 5
#define LENB 6

char sa[LENB];

f(sa);

f(char s[LENB])
{
strlcpy(s, "This is a very long string", LENB);
}

and now you have this patch:

- char sa[LENB];
+ char sa[LENA];

Do you see? strlcpy didn't help at all, and due to the
false security sensation the programmer didn't dig to
see all the side effects of changing the size of sa.
C is a very low level language, and it is a language
without support for strings, and the only way of writting
correct code is to be very carefull and before doing any
change check everything, and look for all the possible
errors due to your change.

And of course, strlcpy is also totally useless because
you can do the same work with snprintf.


Regards,

PD: I don't want to begin a flame war, but please, stop
of being a fan boy and think for yourself, try to find
the strong points and what is propaganda.




Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-05 Thread FRIGN
On Fri, 3 Jun 2016 17:58:12 +0200
k...@shike2.com wrote:

Hey Roberto,

> safe?. You are not checking any of the return codes. You are only
> moving the problem from some place to another place. Please add
> checks and stop using non portable functions. I don't want your
> shit, thanks.

there is also another point here: strlcpy is safer than strcpy
and strncpy because _if_ there is an overflow the string will
be 0-terminated. I'm not sure if there even should be an
error-out in case for instance we overflow writing the
"broken"-state-string to a client-name.

Cheers

FRIGN

-- 
FRIGN 



Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-05 Thread FRIGN
On Fri, 3 Jun 2016 17:58:12 +0200
k...@shike2.com wrote:

Hey k0ga,

> safe?. You are not checking any of the return codes. You are only
> moving the problem from some place to another place. Please add
> checks and stop using non portable functions. I don't want your
> shit, thanks.

I just saw that I forgot to amend this part of the patch to this
one here. Will push it later, like the following:

if (strlcpy(..., size) >= size)
...

The only reason why strlcpy is "non-portable" is because the
Posix-committee has sticks up their asses (same with the
glibc guys).

Cheers

FRIGN


-- 
FRIGN 



Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-03 Thread Hiltjo Posthuma
On Thu, Jun 02, 2016 at 09:57:01PM +0200, FRIGN wrote:
> Hello fellow hackers,
> 
> I'll drop this little patch here so we finally make the switch to the
> safe OpenBSD-functions for string copying.

A good compromise might be using snprintf(buf, sizeof(buf), "%s", text) this is
standard and functionally exactly the same as using strlcpy.

I agree the strncpy functions need to go, they don't make sense in this
context.

Some people forget strncpy has the following properties aswell, from the
OpenBSD man page:

"If src is less than len characters long, it fills the remaining buffer
with '\0' characters".

and

"strncpy() only NUL terminates the destination string when the length of
the source string is less than the length parameter."

-- 
Kind regards,
Hiltjo



Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-03 Thread k0ga
>> I'll drop this little patch here so we finally make the switch to the safe

safe?. You are not checking any of the return codes. You are only
moving the problem from some place to another place. Please add
checks and stop using non portable functions. I don't want your
shit, thanks.

Regards,




Re: [hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-03 Thread Markus Teich
FRIGN wrote:
> I'll drop this little patch here so we finally make the switch to the safe
> OpenBSD-functions for string copying.

Heyho,

please don't forget the drw unification patches from two weeks ago, when merging
this. Hiltjo seems to be busy right now and I don't know if anyone else but
Hiltjo and Anselm has authority for the dwm repo.

--Markus



[hackers] [dwm] [PATCH] Replace str[n]cpy with strlcpy

2016-06-02 Thread FRIGN
Hello fellow hackers,

I'll drop this little patch here so we finally make the switch to the
safe OpenBSD-functions for string copying.
Read the patch description for more info.

Cheers

FRIGN

-- 
FRIGN 
>From 849a7cbee0310beb7ea51986bf98aff8d3b7ff26 Mon Sep 17 00:00:00 2001
From: FRIGN 
Date: Thu, 2 Jun 2016 21:46:50 +0200
Subject: [PATCH] Replace str[n]cpy with strlcpy

Let's finally use this safe interface here! We've waited long
enough.
Even if a call to strcpy in some cases might be safe
(e.g. writing the broken string to c->name), we can never
assure that there might not be a code change in the future
that breaks this assumption.
Even though you might have had these side-effects in mind the
time you wrote the code, they definitely won't be a few days/
months/years later when the changes are made.
---
 dwm.c  | 16 +---
 util.c | 40 
 util.h |  3 +++
 3 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/dwm.c b/dwm.c
index ff7e096..d45916c 100644
--- a/dwm.c
+++ b/dwm.c
@@ -393,7 +393,7 @@ arrange(Monitor *m)
 void
 arrangemon(Monitor *m)
 {
-	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
+	strlcpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof(m->ltsymbol));
 	if (m->lt[m->sellt]->arrange)
 		m->lt[m->sellt]->arrange(m);
 }
@@ -654,7 +654,8 @@ createmon(void)
 	m->topbar = topbar;
 	m->lt[0] = &layouts[0];
 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
-	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+	strlcpy(m->ltsymbol, layouts[0].symbol, sizeof(m->ltsymbol));
+
 	return m;
 }
 
@@ -931,10 +932,10 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size)
 	if (!name.nitems)
 		return 0;
 	if (name.encoding == XA_STRING)
-		strncpy(text, (char *)name.value, size - 1);
+		strlcpy(text, (char *)name.value, size - 1);
 	else {
 		if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
-			strncpy(text, *list, size - 1);
+			strlcpy(text, *list, size - 1);
 			XFreeStringList(list);
 		}
 	}
@@ -1526,7 +1527,8 @@ setlayout(const Arg *arg)
 		selmon->sellt ^= 1;
 	if (arg && arg->v)
 		selmon->lt[selmon->sellt] = (Layout *)arg->v;
-	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
+	strlcpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol,
+	sizeof(selmon->ltsymbol));
 	if (selmon->sel)
 		arrange(selmon);
 	else
@@ -1991,14 +1993,14 @@ updatetitle(Client *c)
 	if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
 		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
 	if (c->name[0] == '\0') /* hack to mark broken clients */
-		strcpy(c->name, broken);
+		strlcpy(c->name, broken, sizeof(c->name));
 }
 
 void
 updatestatus(void)
 {
 	if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
-		strcpy(stext, "dwm-"VERSION);
+		strlcpy(stext, "dwm-"VERSION, sizeof(stext));
 	drawbar(selmon);
 }
 
diff --git a/util.c b/util.c
index 6b703e9..ac4372f 100644
--- a/util.c
+++ b/util.c
@@ -31,3 +31,43 @@ die(const char *fmt, ...) {
 
 	exit(1);
 }
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t dsize)
+{
+	const char *osrc = src;
+	size_t nleft = dsize;
+
+	/* Copy as many bytes as will fit. */
+	if (nleft != 0) {
+		while (--nleft != 0) {
+			if ((*dst++ = *src++) == '\0')
+break;
+		}
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src. */
+	if (nleft == 0) {
+		if (dsize != 0)
+			*dst = '\0';		/* NUL-terminate dst */
+		while (*src++)
+			;
+	}
+
+	return(src - osrc - 1);	/* count does not include NUL */
+}
diff --git a/util.h b/util.h
index cded043..ce29b77 100644
--- a/util.h
+++ b/util.h
@@ -1,4 +1,5 @@
 /* See LICENSE file for copyright and license details. */
+#include 
 
 #define MAX(A, B)   ((A) > (B) ? (A) : (B))
 #define MIN(A, B)   ((A) < (B) ? (A) : (B))
@@ -6,3 +7,5 @@
 
 void die(const char *errstr, ...);
 void *ecalloc(size_t, size_t);
+#undef strlcpy
+size_t strlcpy(char *, const char *, size_t);
-- 
2.4.10