Linux bare system calls, not glibc

I’m reading an article that explains how to call bare syscalls without passing through glibc. To call chmod and exit, use:

#include <linux/unistd.h>
_syscall2(int,chmod,char*,f,int,m)
_syscall1(int,exit,int,r)

My gcc complains about them. What are their use, how do they work?

$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0
$ gcc e.c 
e.c:2:15: error: unknown type name ‘setresuid’; did you mean ‘__NR_setresuid’?
 _syscall3(int,setresuid,int,r,int,e,int,s)
               ^~~~~~~~~
               __NR_setresuid
e.c:2:29: error: unknown type name ‘r’
 _syscall3(int,setresuid,int,r,int,e,int,s)
                             ^
e.c:2:35: error: unknown type name ‘e’
 _syscall3(int,setresuid,int,r,int,e,int,s)
                                   ^
e.c:2:41: error: unknown type name ‘s’
 _syscall3(int,setresuid,int,r,int,e,int,s)
                                         ^

Solution:

Your article is probably obsolete.

If you code in C, there is no reason to avoid using the syscalls(2) (notice the plural) as documented. Be also aware of the vdso(7). You could use some other C standard library than the glibc (e.g. musl-libc, dietlibc, etc…) and you might (but that is not recommended) statically link it.

You might use syscall(2) (notice the singular) instead. I see no reason to do that, e.g. use read(2) or mmap(2) without syscall.

The Assembly HowTo might be an interesting read (beware, it might be too 32 bits centric, most Linux PCs today are 64 bits x86-64).

See also osdev.org

BTW, some old Unixes (e.g. Solaris) had a libsys providing just the syscalls, and their libc linked to it. I would like a libsys too! But on current Linux systems, it does not really matter, since almost every process (running some dynamically linked ELF executable) is mmap(2)-ing, after ld-linux.so(8), several segments and sections of your libc.so.6; for details, read Drepper’s How to write a shared library (since it also explains in details how shared libraries actually work). Use also pmap(1) on some running process (e.g. pmap $$ in a shell).

Some rare syscalls (e.g. userfaultfd(2) today 2Q2019) are not known by the glibc. They are an exception, because most system calls are wrapped by your libc (the wrapping usually just deals with errno(3) setting on failure). Be aware of strace(1).

And you also should read Operating Systems: Three Easy Pieces (it is a freely downloadable book, explaining the role of, and reason for, system calls)

Child process read from pipe failed and seemed to be out of order

I have the following code with output:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>

#define PIPE_STDIN  0
#define PIPE_STDOUT 1

#define msg "hello world"

int main()
{
   int fd_pipe[2];

   int ret = fork();
   if (ret < 0)
   {
       printf("Failed to fork\n");
       return -1;
   }
   else if (ret == 0)
   {
       printf("Parent with PID %d\n", getpid());    fflush(stdout);
       //sleep(3);
       ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg));   fflush(stdout);
       printf("Parent wrote string %d\n", ret);     fflush(stdout);
       wait( NULL );
       printf("Parent done wait\n");    fflush(stdout);
   }
   else
   {
       char buf[80];
       printf("Child with PID %d whose parent PID %d\n", getpid(), ret);    fflush(stdout);
       ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
       printf("Child read %s %d\n", buf, ret);  fflush(stdout);
   }
}

Output:

Child with PID 1130 whose parent PID 1131
Child read   -1
Parent with PID 1131
hello world Parent wrote string 12
Parent done wait

From the output, why would child failed to read from pipe (returned -1) and then later on message “hello world” was printed ? Please explain the execution order that gives the above log.

Solution:

  1. You should call pipe before fork to init file descriptor.
  2. fork() == 0 means child process.

The follow code could work:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>

#define PIPE_STDIN  0
#define PIPE_STDOUT 1

#define msg "hello world"

int main()
{
   int fd_pipe[2];
   int ret;

   if (pipe(fd_pipe) == -1) {
       perror("pipe");
       return -1;
   }
   ret = fork();
   if (ret < 0)
   {
       printf("Failed to fork\n");
       return -1;
   }
   else if (ret != 0)
   {
       printf("Parent with PID %d\n", getpid());    fflush(stdout);
       //sleep(3);
       ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg));   fflush(stdout);
       printf("Parent wrote string %d\n", ret);     fflush(stdout);
       wait( NULL );
       printf("Parent done wait\n");    fflush(stdout);
   }
   else
   {
       char buf[80];
       printf("Child with PID %d whose parent PID %d\n", getpid(), getppid());    fflush(stdout);
       ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
       printf("Child read %s %d\n", buf, ret);  fflush(stdout);
   }
}

Use two pipes in C or one pipe for more than 2 read/writes? And how?

I have the following simplified code template:

pid_t pid;
int pipe1[2], pipe2[2];
pid = fork();
pipe(pipe1); pipe(pipe2)
if(pid == 0)  //child
{
    read(pipe1[0],...);
    write(pipe1[1],...);
    close(pipe1[0]);
    close(pipe1[1]);

    close(pipe2[1]);
    read(pipe2[0]...);
}
else //parent
{
    write(pipe1[1],...);
    wait(NULL);
    read(pipe1[0]...);
    close(pipe1[0]);
    close(pipe1[1]);

    close(pipe2[0]);
    write(pipe2[1]...);
}

If I am not using the pipe2 in parent and child, the code works perfectly, but if I do, it seems like the child has nothing to read(the program does nothing until I intrerrupt it). Also, is there a way to use only one pipe for more than 2 read/writes? I tried using wait(NULL) more than once but that didn’t work.

Solution:

Simply put, your code template is garbage. Let me explain why.

  1. Each pipe is unidirectional.

    If you use a pipe to send data from the child to the parent, close the read end in the child, and the write end in the parent. This allows the parent to see when the child (write end) closes the pipe or exits, as read() will then return -1 with errno == EPIPE.

    If you use a pipe to send data from the parent to the child, close the read end in the parent, and the write end in the child. This allows the parent to detect if the child exits prematurely, as write() will then return with -1 with errno == EPIPE and a SIGPIPE signal gets raised in the parent.
     

  2. If you need bidirectional “pipe” between the parent and a child, use an Unix domain stream socket pair via socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair).

    Such a socket pair works very much like a pipe, except that the socket pair is bidirectional. You can also use send(descriptor, buffer, length, MSG_NOSIGNAL) instead of write(descriptor, buffer, length); in the former case, no SIGPIPE signal is raised if the other end of the socket is already closed.

    Use one of the descriptors in the parent, and the other in the child. Both parent and child should close the other descriptor. Otherwise, one end cannot detect when the other end has closed its descriptor.

    In some cases, an Unix Domain datagram socket pair may be preferable. Each send() generates a separate datagram, that is received using a single recv(). (That is, message boundaries are retained.) If the receiving end knows the maximum size of a datagram the sending side might send, this is an extremely robust and simple way to implement bidirectional communications between a parent and a child process; I personally use it a lot.
     

  3. read() and write() to pipes and sockets may be short.

    (POSIX states that you should always be able to stuff at least 512 bytes into a pipe, though; Linux supports that at least up to a full page, if I recall correctly.)

    This means that rather than a single call, you need to do a loop until you have as much data as you need.

    With sockets, send() either sends all the data, or fails with -1 (with errno == EMSGSIZE, or some other error code).

    For datagram sockets (Unix domain datagram sockets, UDP sockets), if the buffer is large enough, recv() either receives the entire datagram, or fails with -1 (with errno set). Receiving zero-length datagrams is iffy, so don’t try to do that.

    For stream sockets, recv() may return only some of the data (i.e. short, or partial receive).
     

  4. When two processes both send and receive, or read and write, data to/from each other, deadlock is a serious, common problem.

    Simply put, both ends may end up waiting for the other end to read/write at the same time, with nothing at all happening.

    There are three typical solutions to avoid a deadlock in such situations:

    1. Use a query – response protocol, so that one endpoint always initiates communications, and then waits for the other endpoint to respond. At most one endpoint is transferring data at any given time.

    2. Use nonblocking/asynchronous I/O. That is, before trying to write()/send(), each endpoint does a read()/recv() to see if the other end has already sent something. This supports full duplex communications (information can flow both ways at the same time).

    3. Use a separate thread to continuously read()/recv(), while another does write()/send(). This essentially separates each socket into two unidirectional “lanes”, with one thread handling their direction only. This is useful for protocols where one end produces a lot of data, and the other end sends occasional commands.
       

Combining all the above, we’ll find that there is no single template one should use. There are variants with significant differences, making them better in some use cases but harder/worse in others. One should pick one depending on the situation at hand. If OP wants to see a better example (“template”), they should describe an actual problem case, including the desired behaviour.

Memory Leak Valgrind

I wrote a program to chunk a string five by five. This is my program.

struct list
{
    char *str;
    struct list* next;
};

struct list* head = NULL;

void insert(char *cont)
{
    struct list* temp = (struct list*)malloc(sizeof(struct list));

    size_t len = strlen(cont);
    char *heapString = (char*)malloc(len);
    strcpy(heapString,cont);

    temp->str = heapString;
    temp->next = NULL;

    if(head == NULL)
    {
        head = temp;
        return ;
    }

    temp->next = head;
    head = temp;
}
void print()
{
    struct list* temp = head;
    while(temp != NULL)
    {
        printf("%s\n",temp->str);
        temp = temp->next;
    }
}
void clearmem()
{
    struct list* temp = head;
    while(temp != NULL)
    {
        free(temp->str);
        free(temp);
        temp = temp->next;
    }
}
int main()
{
    char text[] = "abcdefghijklmno";
    size_t len = strlen(text);
    while(len !=0)
    {
        char *temp;
        temp = text ;
        temp = temp + len - 5;

        insert(temp);
        *(text+len-5) = '\0';
        len = strlen(text);
        free(temp);
    }
    print();
    clearmem();
}

My program is working fine. But when I try to run this program through Valgrind, I got the following messages. It says there are 12 errors.

==2055== Invalid write of size 1
==2055==    at 0x4C32E0D: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x10888C: insert (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x1089BD: main (in /home/infant/Documents/Sample_codes/a.out)
==2055==  Address 0x522d095 is 0 bytes after a block of size 5 alloc'd
==2055==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x108875: insert (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x1089BD: main (in /home/infant/Documents/Sample_codes/a.out)
==2055== 
==2055== Invalid free() / delete / delete[] / realloc()
==2055==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x1089EB: main (in /home/infant/Documents/Sample_codes/a.out)
==2055==  Address 0x1fff00030a is on thread 1's stack
==2055==  in frame #1, created by main (???:)
==2055== 
==2055== Invalid read of size 1
==2055==    at 0x4C32D44: __strlen_sse2 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x4EBC9D1: puts (ioputs.c:35)
==2055==    by 0x1088FC: print (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x1089FC: main (in /home/infant/Documents/Sample_codes/a.out)
==2055==  Address 0x522d1d5 is 0 bytes after a block of size 5 alloc'd
==2055==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x108875: insert (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x1089BD: main (in /home/infant/Documents/Sample_codes/a.out)
==2055== 
abcde
fghij
klmno
==2055== Invalid read of size 8
==2055==    at 0x108947: clearmem (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x108A06: main (in /home/infant/Documents/Sample_codes/a.out)
==2055==  Address 0x522d188 is 8 bytes inside a block of size 16 free'd
==2055==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x108942: clearmem (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x108A06: main (in /home/infant/Documents/Sample_codes/a.out)
==2055==  Block was alloc'd at
==2055==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2055==    by 0x108855: insert (in /home/infant/Documents/Sample_codes/a.out)
==2055==    by 0x1089BD: main (in /home/infant/Documents/Sample_codes/a.out)
==2055== 
==2055== 
==2055== HEAP SUMMARY:
==2055==     in use at exit: 0 bytes in 0 blocks
==2055==   total heap usage: 7 allocs, 10 frees, 1,087 bytes allocated
==2055== 
==2055== All heap blocks were freed -- no leaks are possible
==2055== 
==2055== For counts of detected and suppressed errors, rerun with: -v
==2055== ERROR SUMMARY: 12 errors from 4 contexts (suppressed: 0 from 0)

Even though I cleared all the Memory in the Heap, I am getting 12 errors from 4 contexts. What is my error here?

Solution:

Step by step.

Invalid write of size 1

Your malloc() does not allocate space for the string terminator, but strcpy() tries to write it. Use

char *heapString = malloc(len + 1);

instead. (Note: no need to cast void* to char*!). For simplicity, you may also try to use the (non-standard) strdup(cont).

Invalid free() / delete / delete[] / realloc()

Your temp points to a char in text. It makes no sense to use free(), as there’s nothing allocated there. Remove that call.

Invalid read of size 1

This should be related with the first error. It is interesting to note how, in print(), at compile time printf("%s\n",temp->str) is translated to a (faster) puts(temp->str). That’s why Valgrind is complaining about a call to puts.

Invalid read of size 8

In

free(temp);
temp = temp->next;

you read temp after it has been freed.

How to test user namespace with clone system call with CLONE_NEWUSER flag

Testing the sample from Containerization with LXC to demonstrate User namespace.

It is supposed to print both outputs from the child process in a new user namespace and outputs from the parent process.

# ./user_namespace
UID outside the namespace is 0
GID outside the namespace is 0
UID inside the namespace is 65534
GID inside the namespace is 65534

However, it only show parent outputs.

UID outside the namespace is 1000
GID outside the namespace is 1000

Please help to understand why the child process is not printing.

Code

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <signal.h>

static int childFunc(void *arg)
{
    printf("UID inside the namespace is %ld\n", (long)geteuid());
    printf("GID inside the namespace is %ld\n", (long)getegid());
}

static char child_stack[1024*1024];

int main(int argc, char *argv[])
{
    pid_t child_pid;

    /* child_pid = clone(childFunc, child_stack + (1024*1024), CLONE_NEWUSER, 0);*/

    child_pid = clone(&childFunc, child_stack + (1024*1024), CLONE_NEWUSER, 0);

    printf("UID outside the namespace is %ld\n", (long)geteuid());
    printf("GID outside the namespace is %ld\n", (long)getegid());
    waitpid(child_pid, NULL, 0);
    exit(EXIT_SUCCESS);
}

Environment

$ uname -r
3.10.0-693.21.1.el7.x86_64

$ cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
CPE_NAME="cpe:/o:centos:centos:7"

References


Update

As per the answer from thejonny, it was to enable user namespace. For RHEL/CentOS 7, Is it safe to enable user namespaces in CentOS 7.4 and how to do it?

By default, the new 7.4 kernel restricts the number of user namespaces to 0. To work around this, increase the user namespace limit:
echo 15000 > /proc/sys/user/max_user_namespaces

Solution:

Unprivileged user namespaces are probably disabled. As you don’t check the return value of clone, you won’t notice. Running through strace on my system prints:

.... startup stuff ...
clone(child_stack=0x55b41f2a4070, flags=CLONE_NEWUSER) = -1 EPERM (Operation not permitted)
geteuid()                               = 1000
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 6), ...}) = 0
brk(NULL)                               = 0x55b4200b8000
brk(0x55b4200d9000)                     = 0x55b4200d9000
write(1, "UID outside the namespace is 100"..., 34UID outside the namespace is 1000
) = 34
getegid()                               = 1000
write(1, "GID outside the namespace is 100"..., 34GID outside the namespace is 1000
) = 34
wait4(-1, NULL, 0, NULL)                = -1 ECHILD (No child processes)
exit_group(0)   = ?

So clone and therefor waitpid fail, there is no child process.

See here to enable user privileges: https://superuser.com/questions/1094597/enable-user-namespaces-in-debian-kernel

How can "plugins" loaded by libdl refer to symbols in the program which loaded them?

Imagine that you have an application with a plugin based architecture, where each plugin is a *.so file that is dynamically loaded with dlopen().

The main application can refer to symbols via dlsym(), and so it may call functions of the plugin. How can the plugin call functions of the main application?

I know that the main application could provide a struct full of function pointers, which the plugin could use to call into the application. Is there any easier way than that?

Edit: here’s a minimal working example to show what I mean:

app.h:

#ifndef APP_H
#define APP_H
void app_utility(void);
#endif

app.c:

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

#include "app.h"

void app_utility(void)
{
    printf("app_utility()\n");
}

int main(int argc, char **argv)
{
    void *handle;
    void (*plugin_function)(void);
    if (argc < 2) {
        fprintf(stderr, "usage: ./app plugin.so\n");
        exit(1);
    }

    handle = dlopen(argv[1], RTLD_NOW | RTLD_LOCAL);
    if (!handle) {
        fprintf(stderr, "error loading plugin: %s\n", dlerror());
        exit(1);
    }

    plugin_function = dlsym(handle, "doit");
    if (!plugin_function) {
        fprintf(stderr, "error loading symbol: %s\n", dlerror());
        dlclose(handle);
        exit(1);
    }

    plugin_function();

    dlclose(handle);
    return 0;
}

plugin.c:

#include <stdio.h>

#include "app.h"

void doit(void)
{
    printf("doit()\n");
    app_utility();
    printf("did it!\n");
}

Example usage:

$ gcc -o app app.c -ldl
$ gcc -shared -o plugin.so
$ ./app ./plugin.so
error loading plugin: ./plugin.so: undefined symbol: app_utility

Solution:

There is a option you can pass to when you invoke it to create the executable for the main application: -rdynamic

$ gcc -rdynamic -o app app.c -ldl

The GCC documentation for -rdynamic:

Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol table. This option is needed for some uses of dlopen or to allow obtaining backtraces from within a program.

The ld manual page for --export-dynamic includes this paragraph:

If you use “dlopen” to load a dynamic object which needs to refer
back to the symbols defined by the program, rather than some
other dynamic object, then you will probably need to use this
option when linking the program itself.

Why does the following C code skip the read() system call to execute the next write() system call?

My question is regarding Linux Systems Programming, specifically about the read and write APIs.

I am writing a program that replicates a shell. It takes a string argument and tokenizes it with a space delimiter. Depending on the command of the first token, it performs an operation using the remaining tokens as parameters. So far I have only implemented this for an ‘add’ command. The code runs in a loop until the user enters ‘n’ for ‘continue? [y/n]’. However, after the first iteration, my program skips the read() after the first write() call to enter command, and ends up at the ‘continue?’ write() call. Why does it skip the read() call immediately following the first write()?

int main (int argc, char *argv[]) {
int true=0;
while (true==0) {
    char buff1[]="Please enter your command\n";
    int count1= strlen(buff1);
    write (STDOUT_FILENO, buff1, count1);
    char buff2[100];
    int count2=read (STDIN_FILENO, buff2, 100);
    buff2[count2-1]='\0';
    char *list[30]; //This creates an array of character pointers (strings)
    /*
    * Begin tokenization and entering tokens in list
    */
    const char delim[]=" ";
    char *token;
    token=strtok(buff2, delim);
    const char newline[]="\n";
    int i=0;
    while (token!= NULL) {
        write (STDOUT_FILENO, newline, strlen(newline));
        list[i]=token;
        write (STDOUT_FILENO, list[i], strlen(list[i]));
        i++;
        token=strtok(NULL,delim);
    }
    /*
    * End tokenization
    */

    /*
    * Begin Addition operation
    */
    const char add[]="add";
    if (strcmp(list[0], add)==0) {
        int result=0;
        for (int j=1; j<i; j++) {
            result+=atoi(list[j]);
        }
        char sum[50];
        int sumcount=sprintf(sum, "%d", result);
        write (STDOUT_FILENO, newline, strlen(newline));
        write (STDOUT_FILENO, sum, sumcount);
    }
    /*
    * End Addition operation
    */


    char *truefalse;
    char endmessage[]="Continue: [y/n]\n";
    write (STDOUT_FILENO, endmessage, strlen(endmessage));
    read (STDIN_FILENO, truefalse, 1);
    if (*truefalse=='n') {
        true=1;
    }

}
return 0;
}

As this output image shows, in the second iteration, after asking me
to enter a command, the code skips to asking me to continue rather than
actually reading my command

Solution:

Your program has undefined behavior.

You use a pointer that has not been initialized to point to anything valid.

The line

char *truefalse;

declares a pointer but it has not been initialized to point to anything valid. You go on to use it in the line

read (STDIN_FILENO, truefalse, 1);

Instead of

char *truefalse;
char endmessage[]="Continue: [y/n]\n";
write (STDOUT_FILENO, endmessage, strlen(endmessage));
read (STDIN_FILENO, truefalse, 1);

Use

char truefalse; // Make it an object instead of a pointer.
char endmessage[]="Continue: [y/n]\n";
write (STDOUT_FILENO, endmessage, strlen(endmessage));
read (STDIN_FILENO, &truefalse, 1); // Use the address of the variable.

Update

The reason your code does not wait for you to enter anything in the second iteration is that the newline character is still left in the input stream. The second call just reads the newline character.

You’ll need code to skip the rest of the line after reading the answer to the question.

The simplest way would be to use:

int c;
while ((c = fgetc(stdin)) != EOF && c != '\n');

Why the address of the pointer variable printed differently between two printf statements without any modification to the variable?

In below simple c test program two printf statements return different values. ( check last four printf statements).

int main ()
{
    char c, *cc;
    int i;
    long l;
    float f;
    c = 'Z';
    i = 15;
    l = 7777;
    f = 9999999312;
    cc = &c;
    printf("\nc = %c, cc= %u", *cc, cc);
    cc = &i;
    printf("\nc = %d, cc= %u", *cc, cc);
    cc = &l;
    printf("\nc = %ld, cc= %u", *( long* )cc, cc);
    printf("\nc = %ld, cc= %u", *cc, cc);
    cc = &f;
    printf("\nc = %f, cc= %u", *(float *)cc, cc);
    printf("\n cc= %u", cc);
    printf("\nc = %f, cc= %u", *cc, cc);
    printf("\nc = %f, cc= %u", *(float *)cc, cc);

    printf("\nc = %f, cc using pointer  = %p", *(float *)cc, cc);
    printf("\nc = %f, cc using pointer  =%p", *cc, cc);

    return 0;
}

output : –

c = Z, cc= 755585903
c = 15, cc= 755585904
c = 7777, cc= 755585912
c = 97, cc= 755585912
c = 9999998976.000000, cc= 755585908
cc= 755585908
c = 9999998976.000000, cc= 4294967288
c = 9999998976.000000, cc= 755585908
c = 9999998976.000000, cc using pointer  = 0x7ffc37f4ace4
c = 9999998976.000000, cc using pointer  =0xfffffff8

I am running it in eclipse ide and using Ubuntu Linux.

Why does it behave differently?

Solution:

In several places you are using the wrong format specifier to printf. In particular, on this line:

printf("\nc = %f, cc= %u", *cc, cc);

The first parameter has type char, but you use %f which expects a double. Also, the second parameter has type char * but %u is expecting an unsigned int. Using the wrong format specifiers invokes undefined behavior.

That being said, here is what is most likely happening under the hood:

On most hosted implementations, floating point numbers are not pushed onto the stack the way integer types and pointers are, but are instead stored in a floating point register.

When you run the above printf command, both *cc and cc are pushed onto the stack because neither of them are floating point numbers. When printf then looks for the first parameter it sees %f, so it retrieves a value from a floating point register. Since you did actually pass a floating point value the prior time you called printf that value is still there, and that value happens to be the value you actually wanted to print, so that’s what gets printed.

Then when printf goes to print the next parameter, it sees %u in the format so the value is pulled from the stack. That value is *cc, which points to the first byte in the representation of f.

Assuming a float is a IEEE754 single precision floating point number, the value it contains is represented as 0xf8021550. The first byte of that is 0xf8. Since cc points to a char, which in your case appears to be signed, it is interpreted as a negative value. When passed to printf the value is promoted to type int, so the actual value passed in is 0xfffffff8, which is what you see being printed.

To reiterate however, the output you’re seeing is undefined behavior. The output could change if you build it on a different machine, use a different compiler, or just use a different optimization setting.

Server tries to accept a connection and fail with "Socket operation on non-socket" ever though there is no connect operation from the client

I am doing a very simple application using TCP client-server protocol. First I set up the socket for server and start listening to the client requests. After the connection is established the client sends me a file and I read the file but after I close the connection another accept() call happen on the server-side and it fails. I am only doing connect() once on the client side. And I see the socket descriptor value on the second accept is different from the first one.

Thank you.

EDIT: It seems like I’m overwriting the value of the socket descriptor with the call to Readline() function in utility.c. My guess is that some lin in function might have overwritten the value above its stack.

server.c

#include <sys/socket.h>       /*  socket definitions        */
#include <sys/types.h>        /*  socket types              */
#include <arpa/inet.h>        /*  inet (3) funtions         */
#include <errno.h>
#include <unistd.h>           /*  misc. UNIX functions      */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>

#include "utility.h"           /*  our own utility functions  */


/*  Global constants  */

#define ECHO_PORT          (2002)
#define MAX_LINE           (1000)


int main(int argc, char *argv[]) {
    int       list_s;                /*  listening socket          */
    int       conn_s;                /*  connection socket         */
    short int port;                  /*  port number               */
    struct    sockaddr_in servaddr;  /*  socket address structure  */
    struct    sockaddr_in incoming_addr;
    char*     endptr;                /*  for strtol()              */


    /*  Get port number from the command line, and
        set to default port if no arguments were supplied  */

    if ( argc == 2 ) {
    port = strtol(argv[1], &endptr, 0);
    if ( *endptr ) {
        fprintf(stderr, "ECHOSERV: Invalid port number.\n");
        exit(EXIT_FAILURE);
    }
    }
    else if ( argc < 2 ) {
    port = ECHO_PORT;
    }
    else {
    fprintf(stderr, "ECHOSERV: Invalid arguments.\n");
    exit(EXIT_FAILURE);
    }


    /*  Create the listening socket  */

    list_s = socket(AF_INET, SOCK_STREAM, 0);
    if (list_s < 0) {
    fprintf(stderr, "ECHOSERV: Error creating listening socket.\n");
    exit(EXIT_FAILURE);
    }
    else {
        fprintf(stdout, "Socket successfully created.\n");
    }


    /*  Set all bytes in socket address structure to
        zero, and fill in the relevant data members   */

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(port);


    /* Bind the socket descriptor "list_s" to the servaddr which defines the port number. */

    if ( bind(list_s, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
    fprintf(stderr, "ECHOSERV: Error calling bind()\n");
    exit(EXIT_FAILURE);
    }
    else {
        fprintf(stdout, "Socket successfully binded to port no %d.\n", port);
    }

    if ( listen(list_s, 1) < 0 ) {
    fprintf(stderr, "ECHOSERV: Error calling listen()\n");
    exit(EXIT_FAILURE);
    }
    else {
        fprintf(stdout, "Now listening to port: %d.\n", port);
    }


    /*  Enter an infinite loop to respond
        to client requests and echo input  */

    while (1) {
    /*  Wait for a connection, then accept() it  */
        socklen_t incoming_addr_len = sizeof(incoming_addr);
        int server_socket = list_s;
        printf("The value of list_s is: %d.\n", list_s);
        conn_s = accept(server_socket, (struct sockaddr*)(&incoming_addr), &incoming_addr_len);
    if ( conn_s < 0 ) {
        fprintf(stderr, "ECHOSERV: Error calling accept(): %s.\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

        /* Read the data from the socket descriptor which in this case  */
        /* is the size of the file that is to be received. */

        int data_size;
        Readline(conn_s, &data_size, sizeof(data_size));


        /* Read data from the given socket descriptor conn_s and then
         * write the same data to the descriptor again to be sent as
         * a response. */

        char buffer[data_size];
        Readline(conn_s, buffer, data_size);
        printFile(buffer, data_size);


    /*  Close the connected socket  */

    if ( close(conn_s) < 0 ) {
        fprintf(stderr, "ECHOSERV: Error calling close()\n");
        exit(EXIT_FAILURE);
    }
    }
}

Client.c

#include <sys/socket.h>       /*  socket definitions        */
#include <sys/types.h>        /*  socket types              */
#include <arpa/inet.h>        /*  inet (3) funtions         */
#include <unistd.h>           /*  misc. UNIX functions      */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include "utility.h"           /*  Our own utility functions  */


/*  Global constants  */

#define MAX_LINE           (1000)
#define DATA_IN_FILE       (4)

static const char* const kFileName = "/home/pb/Desktop/workspace/Networking/practice_project/practice_project_test_file_1";

/*  Function declarations  */

int ParseCmdLine(int argc, char *argv[], char **szAddress, char **szPort);


/*  main()  */

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

    int       conn_s;                /*  connection socket         */
    short int port;                  /*  port number               */
    struct    sockaddr_in servaddr;  /*  socket address structure  */
    char      buffer[MAX_LINE];      /*  character buffer          */
    char     *szAddress;             /*  Holds remote IP address   */
    char     *szPort;                /*  Holds remote port         */
    char     *endptr;                /*  for strtol()              */


    /*  Get command line arguments  */

    ParseCmdLine(argc, argv, &szAddress, &szPort);


    /*  Set the remote port  */

    port = strtol(szPort, &endptr, 0);
    if ( *endptr ) {
    printf("ECHOCLNT: Invalid port supplied.\n");
    exit(EXIT_FAILURE);
    }


    /*  Create the listening socket  */

    if ( (conn_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
    fprintf(stderr, "ECHOCLNT: Error creating listening socket.\n");
    exit(EXIT_FAILURE);
    }


    /*  Set all bytes in socket address structure to
        zero, and fill in the relevant data members   */

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_port        = htons(port);


    /*  Set the remote IP address  */

    if ( inet_aton(szAddress, &servaddr.sin_addr) <= 0 ) {
    printf("ECHOCLNT: Invalid remote IP address.\n");
    exit(EXIT_FAILURE);
    }


    /*  connect() to the remote echo server  */
    if ( connect(conn_s, (struct sockaddr *) &servaddr, sizeof(servaddr) ) < 0 ) {
    printf("ECHOCLNT: Error calling connect()\n");
    exit(EXIT_FAILURE);
    }

    FILE* f = fopen(kFileName, "rb");
    if (f == NULL) {
        perror("Error ");
        return -1;
    }
    fseek(f, 0, SEEK_END);
    int size_of_file = ftell(f);
    rewind(f);
    char file_buffer[size_of_file];
    int items_read = fread(file_buffer, 1, size_of_file, f);
    if (items_read != size_of_file) {
        printf("Read the rest.\n");
    }

    /* First sending to the server the size of the data in the  */
    /* file in bytes as an integer. */

    sendData(conn_s, &size_of_file, sizeof(int));

    /* This is the actual file now that we have let the server  */
    /* know the size of the file to be send. */
    sendData(conn_s, file_buffer, size_of_file);

    return EXIT_SUCCESS;
}


int ParseCmdLine(int argc, char *argv[], char **szAddress, char **szPort) {

    int n = 1;

    while ( n < argc ) {
    if ( !strncmp(argv[n], "-a", 2) || !strncmp(argv[n], "-A", 2) ) {
        *szAddress = argv[++n];
    }
    else if ( !strncmp(argv[n], "-p", 2) || !strncmp(argv[n], "-P", 2) ) {
        *szPort = argv[++n];
    }
    else if ( !strncmp(argv[n], "-h", 2) || !strncmp(argv[n], "-H", 2) ) {
        printf("Usage:\n\n");
        printf("    timeclnt -a (remote IP) -p (remote port)\n\n");
        exit(EXIT_SUCCESS);
    }
    ++n;
    }

    return 0;
}

utility.c

#include "utility.h"

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>


int printFile(char *binary_buffer, int buffer_size) {
    int current_position = 0;
    while (current_position < buffer_size) {
        if(binary_buffer[current_position] == 0) {
            printf("\n");
            printf("Type 1.\n");
            current_position = read_first_type(binary_buffer, current_position);
        }
        else if(binary_buffer[current_position] == 1) {
            printf("\n");
            printf("Type 2.\n");
            current_position = read_second_type(binary_buffer, current_position);
        }
    }
    return 0;
}


int read_first_type(const char* binary, const int offset) {
    int size_of_units = 2;
    int no_of_units;
    short unit_buffer[1];

    // current position is always Type and no_of_units is amount which is a byte off of Type.
    no_of_units = binary[offset+1]; 
    printf("No of units is %d.\n", no_of_units);
    for (int i=0; i<no_of_units; ++i) {
        // This is a Big-endian system so the values will bit off.
        memcpy(unit_buffer, (binary+offset+2)+i*size_of_units, 2);
        printf("Type 1 unit has number: %d.\n", unit_buffer[0]);
    }
    return (offset + no_of_units*size_of_units + 2); 
}


int read_second_type(const char* binary, const int offset) {
    int no_of_units;
    int current_position = 4;
    char amount[4];
    memcpy(amount, binary+offset+1, 3);
    amount[3] = '\0';
    no_of_units = atoi(amount);
    printf("No of units is %d.\n", no_of_units);
    char unit_buffer[5];
    int count;
    for(int i=0; i<no_of_units; ++i) {
        count = 0;
        while(1) {
            memcpy(unit_buffer+count, binary+offset+current_position+count, 1);
            if (unit_buffer[count] == 44) {
                unit_buffer[count] = '\0';
                current_position += count+1;
                break;
            }
            if (unit_buffer[count] == 0 || unit_buffer[count] == 1) {
                unit_buffer[count] = '\0';
                printf("Type 2 unit has number: %d.\n",atoi(unit_buffer));
                return (offset+current_position+count);
            }
            count++;
        }
        printf("Type 2 unit has number: %d.\n",atoi(unit_buffer));
    }
    return offset+current_position+count;
}

/*  Read a line from a socket  */

ssize_t Readline(int sockd, void *vptr, size_t maxlen) {
    ssize_t n, rc;
    char    c, *buffer;

    buffer = vptr;

    for ( n = 0; n < maxlen; n++ ) {
    if ( (rc = read(sockd, &c, 1)) == 1 ) {
        *buffer++ = c;
        if ( c == '\n' )
        break;
    }
    else if ( rc == 0 ) {
        if ( n == 0 )
        return 0;
        else
        break;
    }
    else {
        if ( errno == EINTR )
        continue;
        return -1;
    }
    }

    *buffer = 0;
    return n;
}


/*  Write a line to a socket  */

ssize_t sendData(int sockd, const void *vptr, size_t n) {
    size_t      nleft;
    ssize_t     nwritten;
    const char *buffer;

    buffer = vptr;
    nleft  = n;

    while ( nleft > 0 ) {
    if ( (nwritten = write(sockd, buffer, nleft)) <= 0 ) {
        if ( errno == EINTR )
        nwritten = 0;
        else
        return -1;
    }
    nleft  -= nwritten;
    buffer += nwritten;
    }

    return n;
}

Solution:

If the full buffer was read in ReadLine (i.e. maxlen reached in loop) then you will still write a 0x0 after the last character read, thus causing an out of buffer:

ssize_t Readline(int sockd, void *vptr, size_t maxlen) {
 ...
    for ( n = 0; n < maxlen; n++ ) {
        if ( (rc = read(sockd, &c, 1)) == 1 ) {
           *buffer++ = c;
 ...
    *buffer = 0;         <<<<<<<<<<<< might be vptr[maxlen+1], i.e. buffer overflow
    return n;

And this will almost always occur when doing

  Readline(conn_s, &data_size, sizeof(data_size));

Only if the
octets making up data_size contain an \n before the end of the buffer it will not occur but then you will read the wrong number.

This buffer overflow might cause a corruption of adjacent memory which might lead to the problem you see.

I am receiving "shmat: permission denied" when attempting to attach to shared memory. Why?

I’m having a little trouble with shared memory, and could use a little guidance if someone could point me in the right direction.

// Allocate Shared Memory
key_t key = 56789;
int shmid;
char* shm_address;
int* value;

// Reserve the memory
if (shmid = shmget(key, sizeof(int), IPC_CREAT | 0777) < 0)
{
    perror("shmget was unsuccessful");
    exit(1);
}   
else
{
    printf("\nMemory created successfully:%d\n", shmid);
}

// Attach to memory address
if ( (shm_address = shmat(shmid, NULL, 0)) == (char *)-1 )
{

    perror("shmat was unsuccessful");
    exit(1);

}
else
{
    printf ("shared memory attached at address %p\n", shm_address);
}

I then do some process management, call shmdt(shm_address), and finally cleanup with shmctl. But I never reach that part of the code.

I get this as output:

Memory created successfully:0

shmat was unsuccessful: Permission denied

I just don’t understand why shmat is failing to attach? When I call the ipcs command after execution, my memory is allocated, so I’m fairly confident that shmget is working. Could anyone point me in the right direction? Thanks.

Solution:

Precedence error:

if (shmid = shmget(key, sizeof(int), IPC_CREAT | 0777) < 0)

This assigns shmget(key, sizeof(int), IPC_CREAT | 0777) < 0 (i.e. 0 or 1) to shmid. You want

if ((shmid = shmget(key, sizeof(int), IPC_CREAT | 0777)) < 0)