Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000978 [1003.1(2008)/Issue 7] Base Definitions and Headers Editorial Enhancement Request 2015-08-21 20:54 2020-06-04 13:45
Reporter EdSchouten View Status public  
Assigned To ajosey
Priority normal Resolution Accepted As Marked  
Status Applied  
Name Ed Schouten
Organization Nuxi
User Reference
Section <sys/socket.h>
Page Number n/a
Line Number n/a
Interp Status ---
Final Accepted Text Note: 0003242
Summary 0000978: Please add CMSG_LEN() and CMSG_SPACE().
Description Most implementations provide the macros CMSG_LEN() and CMSG_SPACE(). These are quite important when constructing space to store control messages. This is why they are part of RFC 2292:

https://tools.ietf.org/html/rfc2292#section-4.3 [^]

POSIX issue 7 only seems to standardize CMSG_DATA(), CMSG_NXTHDR() and CMSG_FIRSTHDR().

Would it make sense to sync up with RFC 2292?
Desired Action Add CMSG_LEN() and CMSG_SPACE(). This will allow programmers to finally construct buffers for control messages in a portable way.
Tags issue8
Attached Files

- Relationships
related to 0001056Appliedajosey CMSG_NXTHDR(): under what criteria may NULL be returned? 

-  Notes
(0002805)
wahern (reporter)
2015-09-01 18:09

My porting notes show that CMSG_SPACE expanded to a non-constant expression on NetBSD 5.1.2 and OS X 10.7. But, notably, in the latest NetBSD and OS X releases it now expands to a constant expression.

I ran into this issue because I was originally using CMSG_SPACE to define a C99 compound literal. It would be useful if these were defined to expand to constant expressions.

Another interesting issue I have documented is the type of .msg_iovlen in struct msghdr. It's defined as size_t in glibc and RFC2292, unsigned on OpenBSD, and int everywhere else I checked. The POSIX standard defines it as int, although I guess it's not entirely clear that the language mandates the type as well as the member.

I mention this because it might be worthwhile to consider specifying the type of the CMSG_SPACE and CMSG_LEN expressions (e.g. socklen_t to match .msg_controllen and .cmsg_len), especially if they're not required to expand to constant expressions. Otherwise compilers might emit conversion warnings, as the obvious implementations will result in a type of size_t.
(0002807)
shware_systems (reporter)
2015-09-03 07:11

For msg_iovlen, I read it as the count of members in the array msg_iov points to, so int is appropriate. The description is missing "count of", though, so some implementers may construe it being the total size of the array, with count being derived via msg_iovlen/sizeof(struct iovec), and would be consistent with the definition of the iovec structure. The use of size_t as the type of iovec.iovlen in <uio.h> is appropriate as it references the size allocated to the buffer pointed to by each entry.

The use of signed int is normative, however, so bug reports should be filed with glibc and OpenBSD alerting them to it, imo.
-
As I read the RFC and C99TC3, CMSG_LEN is superfluous. The C standard explicitly requires sizeof() to account for any implicit tail padding of structures the compiler may generate, so CMSG_LEN() and CMSG_SPACE() should return equal values when based on sizeof(struct cmsg_hdr). CMSG_SPACE is not, to account for the different methods a conforming compiler may use to allocate a char array without attempting an allocation of the array as an automatic variable. I can see them evaluating to a compile time constant expression only if cmsg_data is declared a static array size, not a variable sized one or left undefined. I concur with it be explicit socklen_t is used as return type, similar to CMSG_DATA requiring (unsigned char*).
(0002808)
philip-guenther (reporter)
2015-09-03 08:38

> As I read the RFC and C99TC3, CMSG_LEN is superfluous. The C standard explicitly requires
> sizeof() to account for any implicit tail padding of structures the compiler may generate,
> so CMSG_LEN() and CMSG_SPACE() should return equal values when based on sizeof(struct cmsg_hdr).

At least on traditional BSD implementations, if the buffer holding the control msg is allocated with, e.g., malloc(), then the pointer returned by CMSG_DATA() will be sufficiently aligned for any control data passed by the system. This matters when the alignment required by cmsghdr is less than the system's maximum alignment.

For example, consider a system where
 * cmsghdr only requires 4 byte alignment,
 * sizeof(struct cmsghdr) == 12,
 * long long objects require 8 byte alignment, and
 * there's a control message containing a long long.
 
In order for CMSG_DATA() to return a pointer that is aligned for accessing a long long, there must be 4 bytes of padding between the cmsghdr and the actual data, and CMSG_DATA() and CMSG_ALIGN() must round up sizeof(struct cmsgmdr) to a multiple of the max alignment required by a control message. This exact situation occurs on OpenBSD on most archs with the SCM_TIMESTAMP cmsg which passes a struct timeval, since time_t is long long on OpenBSD.


If the spec doesn't currently require the pointer returned by CMSG_DATA() to be aligned sufficiently for all the cmsg structures supported by the system, then I would argue that's a defect in the standard: the code I've seen seems to assume that and does *not* copy the CMSG_DATA() to an aligned buffer before accessing it. e.g, ntp.org's ntpd, ISC bind
(0003241)
shware_systems (reporter)
2016-06-02 15:48

Re: 2808
Alignment issues with casting to another structure the unsigned char array CMSG_DATA() points to, it is up to the implementation to prefix a dummy field to that structure, nominally via an #ifdef that references the compilation environment #defines, that would force the alignment. It is not the compiler's job, or the standard's imo, to require a larger alignment than char as a result.
(0003242)
geoffclare (manager)
2016-06-02 16:40
edited on: 2016-06-09 15:07

On page 386 line 12945 section <sys/socket.h> add to CMSG_NXTHDR:
If the first argument is a pointer to a msghdr structure and the second argument is a null pointer, this macro shall be equivalent to CMSG_FIRSTHDR(mhdr).

On page 386 line 12949 section <sys/socket.h> add to the list of macros:

CMSG_SPACE(length)
If the argument has a type such that its value can be assigned to an object of type socklen_t, this macro shall return the space required by an ancillary data object of the specified length and its cmsghdr structure, including any padding needed to satisfy alignment requirements. This macro can be used, for example, to allocate space dynamically for the ancillary data. This macro should not be used to initialize the cmsg_len member of a cmsghdr structure. If the argument is an integer constant expression, this macro shall expand to an integer constant expression.
CMSG_LEN(length)
If the argument has a type such that its value can be assigned to an object of type socklen_t, this macro shall return the value to store in the cmsg_len member of the cmsghdr structure for an ancillary data object of the specified length, taking into account any padding needed to satisfy alignment requirements. If the argument is an integer constant expression, this macro shall expand to an integer constant expression.


(0003243)
EdSchouten (updater)
2016-06-03 08:04

In response to comment 2808:

An in my opinion elegant way of solving that problem would be to declare struct cmsghdr as follows:

struct cmsghdr {
  socklen_t cmsg_len;
  int cmsg_level;
  int cmsg_type;
  _Alignas(max_align_t) unsigned char __cmsg_data[];
};

That way you can be certain that any properly aligned cmsghdr is also capable of storing any piece of data with the correct alignment.
(0003244)
EdSchouten (updater)
2016-06-03 09:08

Quick question in response comment 3242:

I can understand why CMSG_LEN() should return a socklen_t, as it needs to be assignable to cmsg_len. For CMSG_SPACE(), however, wouldn't it make more sense to return size_t? That's a value that is typically used for array sizes, or to be passed to malloc().
(0003245)
shware_systems (reporter)
2016-06-03 13:10

It's for consistency, and the range of socklen_t can be less than that of size_t. It avoids potential overflow casting a size_t set arbitrarily large to other socklen_t parameters, iow.
(0004884)
eblake (manager)
2020-06-04 12:38

This is an interesting thread on a portability pitfall between Linux and OmniOS handling message length differently: https://gitlab.freedesktop.org/dbus/dbus/-/issues/304 [^]
Among other things, the thread suggests that perhaps we need to change wording along the lines:
CMSG_DATA(cmsg): If the argument is a pointer to a cmsghdr structure, this macro shall return an unsigned character pointer to the data array associated with the cmsghdr structure. The data array has length cmsg->cmsg_len - CMSG_LEN (0).
(0004885)
geoffclare (manager)
2020-06-04 13:45

Re: Note: 0004884, since this bug has already been applied, any additional changes will need to be done via a separate bug (either against the current standard or against Issue 8 draft 1 once it is out).

- Issue History
Date Modified Username Field Change
2015-08-21 20:54 EdSchouten New Issue
2015-08-21 20:54 EdSchouten Status New => Under Review
2015-08-21 20:54 EdSchouten Assigned To => ajosey
2015-08-21 20:54 EdSchouten Name => Ed Schouten
2015-08-21 20:54 EdSchouten Organization => Nuxi
2015-08-21 20:54 EdSchouten Section => <sys/socket.h>
2015-08-21 20:54 EdSchouten Page Number => n/a
2015-08-21 20:54 EdSchouten Line Number => n/a
2015-08-25 22:01 shware_systems Issue Monitored: shware_systems
2015-08-25 22:06 shware_systems Issue End Monitor: shware_systems
2015-09-01 18:09 wahern Note Added: 0002805
2015-09-03 07:11 shware_systems Note Added: 0002807
2015-09-03 08:38 philip-guenther Note Added: 0002808
2016-06-02 15:48 shware_systems Note Added: 0003241
2016-06-02 16:40 geoffclare Note Added: 0003242
2016-06-03 08:04 EdSchouten Note Added: 0003243
2016-06-03 09:08 EdSchouten Note Added: 0003244
2016-06-03 13:10 shware_systems Note Added: 0003245
2016-06-09 15:07 nick Interp Status => ---
2016-06-09 15:07 nick Final Accepted Text => bugnote: 3242
2016-06-09 15:07 nick Status Under Review => Resolved
2016-06-09 15:07 nick Resolution Open => Accepted As Marked
2016-06-09 15:07 geoffclare Note Edited: 0003242
2016-06-09 15:08 nick Final Accepted Text bugnote: 3242 => Note: 0003242
2016-06-09 15:08 nick Tag Attached: issue8
2020-04-08 15:35 geoffclare Status Resolved => Applied
2020-04-16 09:04 geoffclare Relationship added related to 0001056
2020-06-04 12:38 eblake Note Added: 0004884
2020-06-04 13:45 geoffclare Note Added: 0004885


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker