Discussion:
is ut_user[] in struct utmpx NUL terminated?
Don Lewis
2016-05-15 23:07:16 UTC
Permalink
There is a lot of code that expects ut_user[] to be NUL terminated.
There is also a lot of code that sets ut_user[] using strncmp(), which
will not guarantee NUL termination of this field if the name is
sufficiently long.

This doesn't matter as long as user names are kept short enough, but
there doesn't seem to be any limit enforced by the passwd file format or
getpwent().
Ed Schouten
2016-05-16 18:10:26 UTC
Permalink
Hi Don,
Post by Don Lewis
There is a lot of code that expects ut_user[] to be NUL terminated.
Our implementation of utmpx should be pretty friendly to use:

- You can call pututxline() with strings that are not null terminated.
- The getutx*() functions return entries in which all strings are null
terminated.

Keep in mind that ut_id is not a string, but a binary identifier,
meaning it is not null terminated.

Best regards,
--
Ed Schouten <***@nuxi.nl>
Nuxi, 's-Hertogenbosch, the Netherlands
KvK-nr.: 62051717
Don Lewis
2016-05-25 21:14:01 UTC
Permalink
Post by Ed Schouten
Hi Don,
Post by Don Lewis
There is a lot of code that expects ut_user[] to be NUL terminated.
- You can call pututxline() with strings that are not null terminated.
- The getutx*() functions return entries in which all strings are null
terminated.
The latter doesn't appear to be true. If I stuff a non-NUL terminated
32 character user name into ut_user and then call pututxline(), it calls
utx_to_futx(), which uses the UTOF_STRING() macro, which in turn uses
snprintf() to copy the data to the corresponding field in a struct futx
before saving the latter. Going in the other direction, getutxent()
calls futx_to_utx(), which uses the FTOU_STRING() macro, which in turn
uses strncpy() to copy the data back out. If the original name was 32
characters, then the ut_user value in the returned struct utmpx will not
be NUL terminated.
Ed Schouten
2016-05-25 21:26:03 UTC
Permalink
Hi Don,
Post by Don Lewis
Going in the other direction, getutxent()
calls futx_to_utx(), which uses the FTOU_STRING() macro, which in turn
uses strncpy() to copy the data back out.
Keep in mind that strcpy() is called with a size that is at most one
less than sizeof(ut->ut_user). The final byte in the array is never
overwritten.
--
Ed Schouten <***@nuxi.nl>
Nuxi, 's-Hertogenbosch, the Netherlands
KvK-nr.: 62051717
Ed Schouten
2016-05-25 21:26:49 UTC
Permalink
Post by Ed Schouten
Keep in mind that strcpy() is called with a size that is at most one
less than sizeof(ut->ut_user). The final byte in the array is never
overwritten.
Sorry; strncpy() of course.
--
Ed Schouten <***@nuxi.nl>
Nuxi, 's-Hertogenbosch, the Netherlands
KvK-nr.: 62051717
Don Lewis
2016-05-25 21:49:36 UTC
Permalink
Post by Ed Schouten
Hi Don,
Post by Don Lewis
Going in the other direction, getutxent()
calls futx_to_utx(), which uses the FTOU_STRING() macro, which in turn
uses strncpy() to copy the data back out.
Keep in mind that strcpy() is called with a size that is at most one
less than sizeof(ut->ut_user). The final byte in the array is never
overwritten.
It looks like it is using sizeof() and not sizeof()-1 in both
directions:

Ah, it's using sizeof() going in, but I now see that there is a
carefully hidden -1 adjustment coming out:

#define FTOU_STRING(fu, ut, field) do { \
strncpy((ut)->ut_ ## field, (fu)->fu_ ## field, \
MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \
} while (0)

We should probably document this in the man page. The Linux man page
that I found online says that the string fields are NUL terminated only
if there is room. The Mac OS X man page and Open Group documentation
are silent on this, which would lead one to think these fields are NUL
terminated.

Code also has be careful to not make the assumption that these fields
are NUL terminated if the struct utmpx has not been laundered through
pututxline() and getutx*(), though this should be rare.
Ed Schouten
2016-05-26 06:30:34 UTC
Permalink
Post by Don Lewis
We should probably document this in the man page.
This specific aspect is already documented in the man page:

The ut_user, ut_line and ut_host fields of the structure returned by the
library functions are also guaranteed to be null-terminated in this
implementation.

Be sure to send me a code review if you can think of ways to improve
the man page.
--
Ed Schouten <***@nuxi.nl>
Nuxi, 's-Hertogenbosch, the Netherlands
KvK-nr.: 62051717
Loading...