VMware 12.1.1 and 4.7.0-1

VMware 12.1.1 and 4.7.0-1 [openSUSE Tumbleweed (20160730) (x86_64)]:

1. VMware Virtual ethernet module:

/usr/lib/vmware/modules/source/vmnet-only/netif.c: In function ‘VNetNetifStartXmit’:
/usr/lib/vmware/modules/source/vmnet-only/netif.c:468:7: error: ‘struct net_device’ has no member named ‘trans_start’; did you mean ‘mem_start’?
    dev->trans_start = jiffies;
       ^~

Robert Gadsdon’s solution was to remove that line entirely:
http://rglinuxtech.com/?p=1746

Also virtualbox developers did basically the same:
https://www.virtualbox.org/ticket/15444
https://www.virtualbox.org/changeset/61429/vbox

VMware and 4.6.1-1

Today while trying to compile kernel modules for VMware Workstation 12.1.1 + 4.6.1-1-default [openSUSE Tumbleweed (20160422) (x86_64)] I got two compilation errors:

1. VMware Virtual ethernet module:

/usr/lib/vmware/modules/source/vmnet-only/userif.c:116:13: error: too many arguments to function ‘get_user_pages’
    retval = get_user_pages(current, current->mm, addr,
             ^

2. VMware Virtual machine monitor:

/usr/lib/vmware/modules/source/vmmon-only/linux/hostif.c:1165:13: error: too many arguments to function ‘get_user_pages’
    retval = get_user_pages(current, current->mm, (unsigned long)uvAddr,
             ^

VMware Community member alexsandr1981 has the correct answer in the discussion, which is to replace every get_user_pages call with get_user_pages_remote calls.
After replacing the original tar, the compilation succeeded for me.

VMware and linux 3.14.0-rc7

# vmware --version
VMware Workstation 10.0.1 build-1379776

#uname -a
Linux workstation 3.14.0-rc7-4-desktop #1 SMP PREEMPT Wed Mar 19 08:35:32 UTC 2014 (d1f1027) x86_64 x86_64 x86_64 GNU/Linux

# head -n1 /etc/SuSE-release
openSUSE 13.1 (x86_64)

#cd /usr/lib/vmware/modules/source/

#cp vmnet.tar vmnet.tar.original

#tar xvf vmnet.tar vmnet-only/filter.c
vmnet-only/filter.c

# patch vmnet-only/filter.c < /tmp/<a href="http://ferenc.homelinux.com/attachments/filter.c.diff">filter.c.diff</a>
patching file vmnet-only/filter.c

# tar -uvf vmnet.tar vmnet-only/filter.c
vmnet-only/filter.c

#rm -rf vmnet-only/

#vmware-modconfig --console --install-all

If something goes wrong then tail the logs:

tail -F /tmp/vmware-root/vmware-modconfig-16234.log

And don’t forget to validate kernel headers:

vmware-modconfig --console --validate-kernel-headers /usr/src/linux-3.14.0-rc7-4-obj/x86_64/desktop/include/

The dangers and sideffects of MACROS

This article is a collection of practical examples of unexpected behavior while using MACROS. I also collected a few general opinions on the usage of macros.

Dangerous situations:

// A macro that returns the absolute value of i
#define unsafe(i)  \
        ( (i) >= 0 ? (i) : -(i) )

// An inline function that returns the absolute value of i
inline
int safe(int i)
{
  return i >= 0 ? i : -i;
}

int f();

void userCode(int x)
{
  int ans;

  ans = unsafe(x++);   // Error! x is incremented twice
  ans = unsafe(f());   // Danger! f() is called twice

  ans = safe(x++);     // Correct! x is incremented once
  ans = safe(f());     // Correct! f() is called once
}

“Also unlike macros, argument types are checked, and necessary conversions are performed correctly.”
Source: C++FAQ

#include
#include
#define double(x) ((x)+(x))

int main()
{
    int x = 3;
    int y = double (++x);

    printf("y is %d\n",y);

    return 0;
}

Instead of the expected 8 this will yield 10!

y = (++x) + (++x);
/*
the stack is :
+
++x
++x

- the first '+' is unstacked
- the first '++x' is evaluated and unstacked => x = 4
- the second '++x'is evaluated and unstacked => x = 5
- then the '+' give x+x = 5+5 = 10*/

Source: Wikipedia

Using a macro instead of writing a function for max causes calling getValue() twice instead of just once, which may have negative sideffects.

#include

inline int max(const int a, const int b){ return (a>b)?a:b; }

#ifndef MAX
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

int getValue()
{
    printf("getValue has been called!\n");
    return 42;
}

int main(int argc, char** argv)
{
    int x=0;
    x=max(2,getValue());
    printf("X: %i\n",x);
    return 0;
}

 

ferenc@fileserver:~> gcc -Wall -o makrotest.o makrotest.c && ./makrotest.o
getValue has been called!
getValue has been called!
X: 42
ferenc@fileserver:~> gcc -Wall -DMAX -o makrotest.o makrotest.c && ./makrotest.o
getValue has been called!
X: 42
ferenc@fileserver:~>

Original Source: Robert Prouse

#define ASPECT_RATIO 1.653

vs

const double AspectRatio = 1.653;

What are legitimate uses of macros?

In C++ (Google Style Guide) for example to explicitly disallow copying and copy assignment.

DISALLOW_COPY_AND_ASSIGN(ClassName);

which would cause this:

private:
        ClassName(const ClassName&);
        void operator=(const ClassName&);

Google Style C++ Guide

In C, and in the Linux kernel it’s often used to fake iterators:

#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
     pos = n, n = pos->next)

In both languages, when you really need the preprocessor symbols like __LINE__, __FILE__, __func__, it is usually acceptable.

Macro rules

“Macros with multiple statements should be enclosed in a do – while block” Linux Kernel CodingStyle

Why? Consider this

if( something ) function1(); else function2();

If function1() is actually a macro, just using { } requires you to omit the semicolon at the point of use, but do { } while(0) lets you use exactly the same syntax as for a real function. Plus using return in a simple { } block would cause the calling function to return, but in a do { } while(0) you can use break to end the execution of your code in the macro.

Some general opinions:

“In addition, in the case of a floating point constant (such as in this example), use of the constant may yield smaller code than
using a #define. That’s because the preprocessor’s blind substitution of the macro name ASPECT_RATIO with 1.653 could
result in multiple copies of 1.653 in your object code, while the use of the constant AspectRatio should never result in more
than one copy.”

Source: Scott Meyers Effective C++ 3rd edition

“Rationale: The C preprocessor is a powerful obfuscation tool that can destroy code
clarity and befuddle many text based checkers. The effect of constructs in unrestricted
preprocessor code can be extremely hard to decipher, even with a formal language
definition in hand. In a new implementation of the C preprocessor, developers often
have to resort to using earlier implementations as the referee for interpreting complex
defining language in the C standard. The rationale for the caution against conditional
compilation is equally important. Note that with just ten conditional compilation
directives, there could be up to 210 possible versions of the code, each of which would
have to be tested– causing a huge increase in the required test effort.”

Gerard J.Holzmann NASA Jet Propulsion Laboratory

“Generally, inline functions are preferable to macros resembling functions.”
Linux Kernel CodingStyle

Minimal Chat server and client with POSIX socket

Server (to be continued…)

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>


typedef struct
{
    int socketid;
    pthread_t threadid;
} connection_t;

#define CONNECTION_LIMIT 100
connection_t connections[CONNECTION_LIMIT];

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *handle_connection(void *);


int main(int argc, char **argv)
{

#if 0
    /* Structure describing a UNIX socket address. sys/socket.h */
    struct sockaddr_un
    {
        sa_family_t sun_family; /* AF_UNIX */
        char sun_path[UNIX_PATH_MAX];   /* pathname */
    };

    /* Structure describing a generic socket address. bits/socket.h */
    struct sockaddr
    {
        __SOCKADDR_COMMON(sa_); /* Common data: address family and length.  */
        char sa_data[14];       /* Address data.  */
    };

#endif
    unsigned int i = 0;
    int sfd = 0;
    char *socket_path = "\0_something_hidden";
    struct sockaddr_un addr;

    /* This casting is necessary from sockaddr_un to sockaddr */

    struct sockaddr *address_pointer = (struct sockaddr *)&addr;
    int socket_listen_queue_length = 5;

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;  /* AF_UNIX and AF_LOCAL are the same */
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);


    if (-1 == (sfd = socket(AF_UNIX, SOCK_STREAM, 0)))
    {
        perror("SOCKET ERROR");
        exit(-1);
    }

    if (-1 == bind(sfd, address_pointer, sizeof(addr)))
    {
        perror("BIND ERROR");
        exit(-1);
    }

    if (-1 == listen(sfd, socket_listen_queue_length))
    {
        perror("LISTEN ERROR");
        exit(-1);
    }

    while (1)
    {
        int cl = 0;

        /* Waiting for incoming connections */
        if ((cl = accept(sfd, NULL, NULL)) == -1)
        {
            perror("ACCEPT ERROR");
            continue;
        }

        for (i = 0; i < CONNECTION_LIMIT; ++i)
        {
            if (0 == connections[i].socketid)
                break;
        }

        if (CONNECTION_LIMIT == i)
        {
            close(cl);
            fprintf(stderr, "CONNECTION LIMIT REACHED: connection closed");
            continue;
        }
        connections[i].socketid = cl;
        pthread_create(&(connections[i].threadid), 0, handle_connection,
                       (void *)&i);


    }
    return 0;

}

void send_to_everyone(char *buf)
{
    unsigned int i;
    pthread_mutex_lock(&mutex);
    /* 
       Here we want to iterate through all the accepted socket file
       descriptors and write the buffer */
    for (i = 0; i < CONNECTION_LIMIT; ++i)
    {
        if (0 != connections[i].socketid)
        {
            write(connections[i].socketid, buf, 256);
        }
    }
    pthread_mutex_unlock(&mutex);
}

void *handle_connection(void *ptr)
{
    unsigned int i = *(unsigned int *)ptr;
    int cl = connections[i].socketid;
    int rc = 0;
    char buf[256];
    char buf2[256];
    char name[16];

    /* Step 0 reading auth data */
    read(cl, name, sizeof(name));
    /* Step 1 send greeting */
    strcpy(buf, "Hello ");
    strcat(buf, name);
    strcat(buf, "!");
    write(cl, buf, sizeof(buf));
    printf("%s is connected!\n", name);

    /* Step 2 start chat */
    while ((rc = read(cl, buf, sizeof(buf))) > 0)
    {
        sprintf(buf2, "[%s] (%i bytes): %.*s", name, rc, rc, buf);
        printf(buf2);
        send_to_everyone(buf2);
    }
    if (-1 == rc)
    {
        perror("READ ERROR");
    }
    else if (0 == rc)
    {
        printf("%s disconnected EOF\n", name);
        close(cl);
    }

    connections[i].socketid = 0;

    return 0;
}

Client

#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>


void send_some_data(int, char *);

int main(int argc, char **argv)
{
    if (2 > argc)
    {
        printf("Usage:\n %s <name>\n", argv[0]);
        exit(-1);
    }


    int sfd = 0;
    char *socket_path = "\0_something_hidden";
    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
    struct sockaddr *address_pointer = (struct sockaddr *)&addr;

    if (-1 == (sfd = socket(AF_UNIX, SOCK_STREAM, 0)))
    {
        perror("SOCKET ERROR");
        exit(-1);
    }
    if (-1 == connect(sfd, address_pointer, sizeof(addr)))
    {
        perror("CONNECT ERROR");
        exit(-1);
    }

    send_some_data(sfd, argv[1]);

    return 0;
}

void *read_some_data(void *ptr)
{
    int sfd = *(int *)ptr;
    char buf[256];
    while (1)
    {
        read(sfd, buf, sizeof(buf));
        printf("%s", buf);
    }

}

void send_some_data(int sfd, char *name)
{
    int rc = 0;
    char buf[256];
    pthread_t reader_thread;

    // Step 0 sending auth data
    write(sfd, name, sizeof(name));

    // Step 1 wait for greeting
    read(sfd, buf, sizeof(buf));
    printf("\nServer says: %s\n", buf);

    // Step 2 start chat
    pthread_create(&reader_thread, 0, read_some_data, (void *)&sfd);
    while ((rc = read(STDIN_FILENO, buf, sizeof(buf))) > 0)
    {
        if (write(sfd, buf, rc) != rc)
        {
            if (rc > 0)
                fprintf(stderr, "partial write");
            else
            {
                perror("WRITE ERROR");
                exit(-1);
            }
        }
    }
}

Linux libc tunable free()

For those, who did not read

man free 

or at least not the part where MALLOC_CHECK_ is explained. Here is a little example.

 
//
// malloc_check_test.c
//
#include<stdlib.h>

int main(int argc, char* argv[])
{
	int *p =malloc(sizeof(int));
	*p=42;
	free(p);
	free(p);

	return 0;
}

And here are the result of running it with different MALLOCK_CHECK_ values:

ferenc@linux-3spa:~> gcc -Wall malloc_check_test.c
ferenc@linux-3spa:~> MALLOC_CHECK_=0 ./a.out 
ferenc@linux-3spa:~> MALLOC_CHECK_=1 ./a.out 
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0000000000602010 ***
ferenc@linux-3spa:~> MALLOC_CHECK_=2 ./a.out 
Aborted
ferenc@linux-3spa:~> MALLOC_CHECK_=3 ./a.out 
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0000000000602010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x766d6)[0x7fd87ad8b6d6]
./a.out[0x4005a3]
/lib64/libc.so.6(__libc_start_main+0xed)[0x7fd87ad3623d]
./a.out[0x4004a9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:04 9488                               /home/ferenc/a.out
00600000-00601000 r--p 00000000 08:04 9488                               /home/ferenc/a.out
00601000-00602000 rw-p 00001000 08:04 9488                               /home/ferenc/a.out
00602000-00623000 rw-p 00000000 00:00 0                                  [heap]
7fd87aaff000-7fd87ab14000 r-xp 00000000 08:03 1049                       /lib64/libgcc_s.so.1
7fd87ab14000-7fd87ad13000 ---p 00015000 08:03 1049                       /lib64/libgcc_s.so.1
7fd87ad13000-7fd87ad14000 r--p 00014000 08:03 1049                       /lib64/libgcc_s.so.1
7fd87ad14000-7fd87ad15000 rw-p 00015000 08:03 1049                       /lib64/libgcc_s.so.1
7fd87ad15000-7fd87ae9c000 r-xp 00000000 08:03 1656                       /lib64/libc-2.14.1.so
7fd87ae9c000-7fd87b09b000 ---p 00187000 08:03 1656                       /lib64/libc-2.14.1.so
7fd87b09b000-7fd87b09f000 r--p 00186000 08:03 1656                       /lib64/libc-2.14.1.so
7fd87b09f000-7fd87b0a0000 rw-p 0018a000 08:03 1656                       /lib64/libc-2.14.1.so
7fd87b0a0000-7fd87b0a5000 rw-p 00000000 00:00 0 
7fd87b0a5000-7fd87b0c5000 r-xp 00000000 08:03 82                         /lib64/ld-2.14.1.so
7fd87b296000-7fd87b299000 rw-p 00000000 00:00 0 
7fd87b2c3000-7fd87b2c5000 rw-p 00000000 00:00 0 
7fd87b2c5000-7fd87b2c6000 r--p 00020000 08:03 82                         /lib64/ld-2.14.1.so
7fd87b2c6000-7fd87b2c7000 rw-p 00021000 08:03 82                         /lib64/ld-2.14.1.so
7fd87b2c7000-7fd87b2c8000 rw-p 00000000 00:00 0 
7fff4cfaf000-7fff4cfd0000 rw-p 00000000 00:00 0                          [stack]
7fff4cfff000-7fff4d000000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted
ferenc@linux-3spa:~> 

By default (when MALLOCK_CHECK_ is not set) than MALLOC_CHECK_=3 is assumed.
Just for the record, I tried the above code with Microsoft’s msvcrt.dll -but the double free was silently ignored.