How to fix invalid conversion error when including linux cn_proc.h header in C++ code

75 views Asked by At

Since 23 July 2023 the cn_proc.h linux header contains the following:

#define PROC_EVENT_ALL (PROC_EVENT_FORK | PROC_EVENT_EXEC | PROC_EVENT_UID |  \
            PROC_EVENT_GID | PROC_EVENT_SID | PROC_EVENT_PTRACE | \
            PROC_EVENT_COMM | PROC_EVENT_NONZERO_EXIT |           \
            PROC_EVENT_COREDUMP | PROC_EVENT_EXIT)

/*
 * If you add an entry in proc_cn_event, make sure you add it in
 * PROC_EVENT_ALL above as well.
 */
enum proc_cn_event {
    /* Use successive bits so the enums can be used to record
     * sets of events as well
     */
    PROC_EVENT_NONE = 0x00000000,
    PROC_EVENT_FORK = 0x00000001,
    PROC_EVENT_EXEC = 0x00000002,
    PROC_EVENT_UID  = 0x00000004,
    PROC_EVENT_GID  = 0x00000040,
    PROC_EVENT_SID  = 0x00000080,
    PROC_EVENT_PTRACE = 0x00000100,
    PROC_EVENT_COMM = 0x00000200,
    /* "next" should be 0x00000400 */
    /* "last" is the last process event: exit,
     * while "next to last" is coredumping event
     * before that is report only if process dies
     * with non-zero exit status
     */
    PROC_EVENT_NONZERO_EXIT = 0x20000000,
    PROC_EVENT_COREDUMP = 0x40000000,
    PROC_EVENT_EXIT = 0x80000000
};

/* [some unrelated code removed] */

static inline enum proc_cn_event valid_event(enum proc_cn_event ev_type)
{
    ev_type &= PROC_EVENT_ALL;
    return ev_type;
}

This means that if you’re compiling the following minimal breaking example on kernel 6.5.6:

#include <iostream>

#include <linux/cn_proc.h>

int main()
{
    std::cout << "Hello World\n";
    return 0;
}

Compilation fails with the following error:

/usr/include/linux/cn_proc.h: In function ‘proc_cn_event valid_event(proc_cn_event)’:
/usr/include/linux/cn_proc.h:72:17: error: invalid conversion from ‘unsigned int’ to ‘proc_cn_event’ [-fpermissive]
   72 |         ev_type &= PROC_EVENT_ALL;
      |                 ^
      |                 |
      |                 unsigned int

It seems the |-aggregate of enum proc_cn_event values that is PROC_EVENT_ALL is considered, in C++, as an unsigned int and not an enum proc_cn_event, nor an int which seems to be the underlying type for enum proc_cn_event.

(Tested on g++ 13.1 and clang++ 17.0)

Note that:

  • The header compiles fine as C code
  • Wrapping the include statement in extern "C" { … } does not fix this issue
  • Prepending a forward declaration enum proc_cn_event : unsigned int; to the include to force the underlying type to be unsigned int fails with:
    /usr/include/linux/cn_proc.h:42:6: error: enumeration previously declared with fixed underlying type
        42 | enum proc_cn_event {
           |      ^
    test.cpp:3:6: note: previous declaration is here
         3 | enum proc_cn_event : unsigned int;
           |      ^
    

I’m not sure whether I am doing this wrong and there is a proper way to include that header in C++ code, or whether I should not be trying to include it in C++ code at all (seems a bit drastic).

So how can I make this compile, without using -fpermissive? Can I maybe add something to my C++ code to make this compile (maybe something implicitly converting unsigned int to enum proc_cn_event values?)

0

There are 0 answers