[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Bug with fcntl(n, F_SETOWN, getpid) with NPTL 0.34



I searched to see if this was a known issue but found nothing.

Using RH9 out-of-the-box with the NPTL 0.34 update applied.

The test program (attached) tries to do fcntl(fd, F_SETOWN, getpid()) on a 
socket descriptor. If it does this in the main thread then it works fine. 
If it does this in a separate pthread then it fails with EPERM.

Looking into the bowels of sock.c sock_no_fcntl does this:
   case F_SETOWN:
	if (current->pgrp != -arg &&
            current->pid != arg &&
	    !capable(CAP_KILL)) return(-EPERM);

Running as root provides the CAP_KILL capability and the test passes. So
it seems that there is a discrepancy between the value returned by
getpid() and the value used internally (current->pid).

This only fails with NPTL. If I use LD_ASSUME_KERNEL the test passes 
threaded and non-threaded.

Thanks.

David Holmes
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>


#define CHECK(func, msg) \
   if ((func) != 0) { \
      fprintf(stderr, "Error: %s - %s\n", msg, strerror(errno)); \
      exit(1); \
   }

#define CHECKP(func) \
   do { \
    int rc = (func); \
    if (rc!= 0) { \
      fprintf(stderr, "Error: " #func " - %s\n", strerror(rc)); \
      exit(1); \
    } \
   } while(0)


int fds[] = { -1, -1 };

static int fcntlSetFlag(int fd,int flag) {
	int flags=fcntl(fd,F_GETFL,0);
	if (flags<0) {
		return -1;
	}
	return fcntl(fd,F_SETFL,flags|flag);
}

static void test() {
    int fd;

    CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds), "socketpair");
    fd = fds[0];

    if (fcntlSetFlag(fd, O_ASYNC)<0) {
        fprintf(stderr, "error setting O_ASYNC flag on %d: %s\n",
               fd, strerror(errno));
        exit(1);
    }

    if (fcntl(fd, F_SETOWN, getpid())<0) {
        fprintf(stderr, "error fcntl(%d, F_SETOWN, %d): %s\n",fd, getpid(), strerror(errno));
        exit(1);
    }
    
    printf("Managed to set up socket %d ok\n", fd);

    close(fds[0]);
    close(fds[1]);
}



static void* threadRun(void* arg) {
    test();
    pthread_detach(pthread_self()); /* ensure detached to release resources */
    pthread_exit(NULL);
}

static void threadedTest() {
    pthread_t thread; 
    pthread_attr_t attr;


    /* we take default status:
       - joinable
       - default contention scope  ??
       - default stack attributes
    */
    CHECKP(pthread_attr_init(&attr));

    /* always set this so that the thread uses the attr object we pass in */
    CHECKP(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED));
    
    CHECKP(pthread_create(&thread, &attr, threadRun, 0));
    
}

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

    if (argc > 1) {
        printf("Doing threaded test\n");
        threadedTest();
        pthread_exit(0);
    }
    else {
        printf("Doing normal test\n");
        test();
    }
    return 0;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]