Signal handling different for root and others

From: jury gerold (gjury@grips.com)
Date: Mon Sep 11 2000 - 19:20:02 EST


I ran into a problem with 2.2.x kernels, posix signals and sockets.

I have a program that creates a serversocket, puts it into listen state,
attaches the socket to a realtime signal and simply waits for the signal.

When i create a connection (telnet a.b.c.d port) the signal is delivered depending
on the user that does the telnet.
If root creates the socket, then only root or another machine is able to trigger the signal
by connecting to the socket.
Normal users are only able to create a SIGIO signal when connecting.

If a normal user runs the program, then any user, as well as root is able to trigger the realtime signal.
No SIGIO is delivered.

The program is attached.

best regards

Gerold

/* compile with gcc -o rtsigsock rtsigsock.c -lpthread */
/* start it and do a telnet 127.0.0.1 20000 */

#define _GNU_SOURCE

#include <stdio.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>

#define SERVERPORT 20000

static int RT_DISPATCHSIG;

static void setAsync( int fd, int sig )
{
  int ret;

  // printf( "setasync %d %d\n", fd, sig );
  ret = fcntl( fd, F_SETOWN, getpid() );
  if( ret == -1 ) perror( "SETOWN" );
  ret = fcntl( fd, F_SETSIG, sig );
  if( ret == -1 ) perror( "SETSIG" );
  ret = fcntl( fd, F_SETFL, fcntl( fd, F_GETFL, 0) | FASYNC);
  if( ret == -1 ) perror("F_SETFL" );
}

int setPortReuse( int iSockFd )
{
  int ret;
  int iReuse = 1;

  ret = setsockopt( iSockFd, SOL_SOCKET, SO_REUSEADDR, (char *)&iReuse, sizeof( iReuse ) );
  if( ret == -1 ) perror( "SO_REUSEADDR" );
  return ret;
}

int main( int argc, char *argv[] )
{
  int iFd, ret, sig;
  struct sockaddr_in sa;
  sigset_t waitset;
  siginfo_t info;

  RT_DISPATCHSIG = (SIGRTMIN);

  sigemptyset( &waitset );
  sigaddset( &waitset, RT_DISPATCHSIG );
  sigaddset( &waitset, SIGIO );
#if 0
  sigprocmask( SIG_SETMASK, &waitset, NULL );
#else
  pthread_sigmask( SIG_BLOCK, &waitset, NULL );
#endif

  iFd = socket (AF_INET, SOCK_STREAM, 0);
  if( iFd == -1 ) {
    perror( "socket" );
    return 0;
  }

  sa.sin_family = AF_INET;
  sa.sin_port = htons( SERVERPORT );
  sa.sin_addr.s_addr = htonl( INADDR_ANY );
  setPortReuse( iFd );
  ret = bind( iFd, (struct sockaddr*)&sa, sizeof(sa) ); // connect to host
  if( ret == -1 ) {
    perror( "bind" );
    return 0;
  }
  ret = listen( iFd, 8 );
  if( ret == -1 ) {
    perror( "listen" );
    return 0;
  }
  setAsync( iFd, RT_DISPATCHSIG );
  for(;;) {
    sig = sigwaitinfo( &waitset, &info );
    if( sig == RT_DISPATCHSIG ) break;
  }
  printf( "got the signal %d\n", sig );
  return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Sep 15 2000 - 21:00:16 EST