linux/include
Ulrich Drepper 4a19542e5f O_CLOEXEC for SCM_RIGHTS
Part two in the O_CLOEXEC saga: adding support for file descriptors received
through Unix domain sockets.

The patch is once again pretty minimal, it introduces a new flag for recvmsg
and passes it just like the existing MSG_CMSG_COMPAT flag.  I think this bit
is not used otherwise but the networking people will know better.

This new flag is not recognized by recvfrom and recv.  These functions cannot
be used for that purpose and the asymmetry this introduces is not worse than
the already existing MSG_CMSG_COMPAT situations.

The patch must be applied on the patch which introduced O_CLOEXEC.  It has to
remove static from the new get_unused_fd_flags function but since scm.c cannot
live in a module the function still hasn't to be exported.

Here's a test program to make sure the code works.  It's so much longer than
the actual patch...

#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#ifndef O_CLOEXEC
# define O_CLOEXEC 02000000
#endif
#ifndef MSG_CMSG_CLOEXEC
# define MSG_CMSG_CLOEXEC 0x40000000
#endif

int
main (int argc, char *argv[])
{
  if (argc > 1)
    {
      int fd = atol (argv[1]);
      printf ("child: fd = %d\n", fd);
      if (fcntl (fd, F_GETFD) == 0 || errno != EBADF)
        {
          puts ("file descriptor valid in child");
          return 1;
        }
      return 0;

    }

  struct sockaddr_un sun;
  strcpy (sun.sun_path, "./testsocket");
  sun.sun_family = AF_UNIX;

  char databuf[] = "hello";
  struct iovec iov[1];
  iov[0].iov_base = databuf;
  iov[0].iov_len = sizeof (databuf);

  union
  {
    struct cmsghdr hdr;
    char bytes[CMSG_SPACE (sizeof (int))];
  } buf;
  struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
                        .msg_control = buf.bytes,
                        .msg_controllen = sizeof (buf) };
  struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);

  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;
  cmsg->cmsg_len = CMSG_LEN (sizeof (int));

  msg.msg_controllen = cmsg->cmsg_len;

  pid_t child = fork ();
  if (child == -1)
    error (1, errno, "fork");
  if (child == 0)
    {
      int sock = socket (PF_UNIX, SOCK_STREAM, 0);
      if (sock < 0)
        error (1, errno, "socket");

      if (bind (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0)
        error (1, errno, "bind");
      if (listen (sock, SOMAXCONN) < 0)
        error (1, errno, "listen");

      int conn = accept (sock, NULL, NULL);
      if (conn == -1)
        error (1, errno, "accept");

      *(int *) CMSG_DATA (cmsg) = sock;
      if (sendmsg (conn, &msg, MSG_NOSIGNAL) < 0)
        error (1, errno, "sendmsg");

      return 0;
    }

  /* For a test suite this should be more robust like a
     barrier in shared memory.  */
  sleep (1);

  int sock = socket (PF_UNIX, SOCK_STREAM, 0);
  if (sock < 0)
    error (1, errno, "socket");

  if (connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0)
    error (1, errno, "connect");
  unlink (sun.sun_path);

  *(int *) CMSG_DATA (cmsg) = -1;

  if (recvmsg (sock, &msg, MSG_CMSG_CLOEXEC) < 0)
    error (1, errno, "recvmsg");

  int fd = *(int *) CMSG_DATA (cmsg);
  if (fd == -1)
    error (1, 0, "no descriptor received");

  char fdname[20];
  snprintf (fdname, sizeof (fdname), "%d", fd);
  execl ("/proc/self/exe", argv[0], fdname, NULL);
  puts ("execl failed");
  return 1;
}

[akpm@linux-foundation.org: Fix fastcall inconsistency noted by Michael Buesch]
[akpm@linux-foundation.org: build fix]
Signed-off-by: Ulrich Drepper <drepper@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Michael Buesch <mb@bu3sch.de>
Cc: Michael Kerrisk <mtk-manpages@gmx.net>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-16 09:05:45 -07:00
..
acpi
asm-alpha fix alpha ISA support 2007-07-16 09:05:37 -07:00
asm-arm page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-arm26 dma-mapping: prevent dma dependent code from linking on !HAS_DMA archs 2007-07-16 09:05:45 -07:00
asm-avr32 page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-blackfin Blackfin arch: Add peripheral io API to gpio header file 2007-07-12 17:06:45 +08:00
asm-cris etrax: enable arbitary speed setting on tty ports 2007-07-16 09:05:38 -07:00
asm-frv FRV: Connect up new syscalls 2007-07-16 09:05:37 -07:00
asm-generic Introduce O_CLOEXEC 2007-07-16 09:05:45 -07:00
asm-h8300 dma-mapping: prevent dma dependent code from linking on !HAS_DMA archs 2007-07-16 09:05:45 -07:00
asm-i386 fix jvc cdrom drive lockup 2007-07-16 09:05:40 -07:00
asm-ia64 page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-m32r dma-mapping: prevent dma dependent code from linking on !HAS_DMA archs 2007-07-16 09:05:45 -07:00
asm-m68k page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-m68knommu PCI: remove pci_dac_dma_... APIs 2007-07-11 16:02:11 -07:00
asm-mips page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-parisc Introduce O_CLOEXEC 2007-07-16 09:05:45 -07:00
asm-powerpc page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-ppc page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-s390 dma-mapping: prevent dma dependent code from linking on !HAS_DMA archs 2007-07-16 09:05:45 -07:00
asm-sh page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-sh64 page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-sparc page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-sparc64 page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-um Add generic exit-time stack-depth checking to CONFIG_DEBUG_STACK_USAGE 2007-07-16 09:05:38 -07:00
asm-v850 v850: enable arbitary speed tty ioctls 2007-07-16 09:05:39 -07:00
asm-x86_64 page table handling cleanup 2007-07-16 09:05:36 -07:00
asm-xtensa page table handling cleanup 2007-07-16 09:05:36 -07:00
crypto
keys
linux O_CLOEXEC for SCM_RIGHTS 2007-07-16 09:05:45 -07:00
math-emu
media
mtd
net Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2007-07-15 16:50:46 -07:00
pcmcia
rdma
rxrpc
scsi [SCSI] Remove unused method scsi_device_cancel 2007-07-14 16:01:16 -05:00
sound
video
Kbuild