bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bug#187391: PortingIssues sockaddr_un


From: Ognyan Kulev
Subject: Re: Bug#187391: PortingIssues sockaddr_un
Date: Sat, 19 Apr 2003 15:41:55 +0300
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.3b) Gecko/20030408 Minotaur/0.1a

Robert Millan wrote:
On Mon, Apr 14, 2003 at 04:19:03PM +0300, Ognyan Kulev wrote:

This arbitrary limit (108) is just for *nix compatibility -- programs expect to be able to do something like:

struct sockaddr_un su;
su.sun_family = AF_LOCAL;
strcpy (su.sun_path, "/path/to/socket"); /* for constant strings!  */


no, the initial allocated size is 108. you're right in that you _should_
be able to reallocate it in the pointer, but for some reason you can't.

2- assuming there's no limitation on GNU, which is wrong and will lead
to overflows.

This is exactly the case. All we need to do is to alloca sockaddr_un with the correct size (that can be of any length) and fill it.

you mean alloca sockaddr_un or alloca sockaddr_un.sun_path?

because sockaddr_un.sun_path has that nasty bug that prevents you from
assigning a pointer to it.

of course, a better solution could be to allow the pointer in
sockaddr_un.sun_path to be replaced by a const char * for GNU. then we
wouldn't have to fix anything else.

I have a question for you: how do you interpret RMS's suggestion to use `alloca'? Nowhere he mentions that alloca is for sun_path, and I think that it is about the whole sockaddr_un.

RMS's suggestion refers to sun_path, and is based on the assumption that
there isn't a weird bug that prevents you from assigning new pointers to
a sockaddr_un.sun_path

aside from that, i agree it's much better to assign a dynamicaly allocated
string to sun_path rather than strncpy'ing a 108-limited string to it.

however, strncpy'ing a 108-limited string is still the only solution that
adheres to the API docs. but the GNU implementation doesn't match the
API docs anyway so... oh well (i'm getting a headache).

Again, there is no such limit in GNU, exactly like not having PATH_MAX.

not when we can allocate it manualy..

I've almost forgotten this thread :-) Here I`ll try to make it clearer why alloca must be used in GNU systems.

What does classic *nix kernel expect from a sockaddr_un structure? It expects the following sequence of bytes (let's forget sun_len in some BSDs -- this is irrelevant):

|..........|.....................................|
 sun_family sun_path

Where sun_family is some integer and sun_path is array of characters with length that is _not_ fixed and the last character is _not_ NUL. The length of this array of characters is calculated from the `socklen_t length' of bind (or whatever function is used). To be precise, the formula is something like (where `length' is the parameter passed to `bind'):

length - offsetof (struct sockaddr_un, sun_path)

What happens in practice?  People do things like this:

struct sockaddr_un sun;
sun.sun_family = AF_LOCAL;
strcpy (sun.sun_path, "/tmp/my-socket");
... bind (sock, (struct sockaddr *)&sun, sizeof sun) ...
                                         ^^^^^^^^^^
You see, the `length' parameter is "not correct" because it represents sun_path as having more characters that it has in reality. To cope with such cases when kernel wants sun_path it stops on the first NUL when there is such character.

Conclusion: In this cases it's better to use SUN_LEN to pass the correct `length' parameter, as this will give correct sockaddr size.

Now to the harder part: when you want to pass path name longer than roughly 100 characters. This is possible. See the above picture what kernels expect. _I'm not talking about assigning pointer to sun_path._ I'm talking about seeing sun_path as it is array with a different length. When you use alloca as this:

socklen_t su_len = offsetof (struct sockaddr_un, sun_path)
                   + strlen (filename);
struct sockaddr_un *su = alloca (su_len);
su->sun_family = AF_LOCAL;
memcpy (su->sun_path, filename, strlen (filename));
... bind (sock, (struct sockaddr *)su, su_len) ...

your definition of `su' is like this:

|............|.................................|
| sun_family | sun_path                        |

but in reality, when strlen (filename) is greater than 108 and when the above code is used, it is something like this:

|............|....................................................|
| sun_family | sun_path                                           |

and it's OK by the kernel to get such (sctruct sockaddr_un *).

Classic *nix kernels will refuse such larger sockaddr_un when they look at the `length' parameter to bind, but GNU`s Not Unix.

I hope this clears up why alloca should be used in GNU. And, again, I never talked about assigning pointer to sun_path, but about allocating struct sockaddr_un with custom size.

http://hurd.gnufans.org/bin/view/Distrib/PortingIssues is updated.

Regards
--
Ognyan Kulev <ogi@fmi.uni-sofia.bg>, "\"Programmer\""





reply via email to

[Prev in Thread] Current Thread [Next in Thread]