Re: [PATCH x86_64] Live Patching Function on 2.6.11.7

Chris Wedgwood
2005-04-20T08:27:18Z

[-- Attachment #1: Type: text/plain, Size: 407 bytes --]

On Wed, Apr 20, 2005 at 04:57:31PM +0900, Takashi Ikebe wrote:

> hmm.. most internet base services will use TCPv4 TCPv6 SCTP...
> AF_UNIX can not use as inter-nodes communication.

You can send file descriptors (the actually file descriptors
themselves, not their contents) to another process over a socket.

A nearly ten-year old example is attached (ie. this isn't new or
magical or specific to Linux).

[-- Attachment #2: sendfd.c --]
[-- Type: text/x-csrc, Size: 2160 bytes --]

/* sendfd.c - v. crude example of passing fds */

/*
* I tested this on HPUX10 using gcc -D_XOPEN_SOURCE_EXTENDED sendfd.c -lxnet
*
* Expected output is "hello world"
*/

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

/* Note: msg_control may be msg_accrights, etc. */

int sendfd(int conn, int fd)
{
size_t len = sizeof(struct cmsghdr) + sizeof(int);
struct cmsghdr *hdr = (struct cmsghdr *)malloc(len);
struct msghdr msg;
int rc;

hdr->cmsg_len = len;
hdr->cmsg_level = SOL_SOCKET;
hdr->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(hdr) = fd;

msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = NULL;
msg.msg_iovlen = 0;
msg.msg_control = hdr;
msg.msg_controllen = len;

rc = sendmsg(conn, &msg, 0);
free(hdr);
return rc;
}

int recvfd(int conn)
{
size_t len = sizeof(struct cmsghdr) + sizeof(int);
struct cmsghdr *hdr = (struct cmsghdr *)malloc(len);
struct msghdr msg;
int rc;

msg.msg_iov = NULL;
msg.msg_iovlen = 0;
msg.msg_control = hdr;
msg.msg_controllen = len;

rc = recvmsg(conn, &msg, 0);

if (rc >= 0
&& hdr->cmsg_len == len
&& hdr->cmsg_level == SOL_SOCKET
&& hdr->cmsg_type == SCM_RIGHTS)
{
int fd = *(int *)CMSG_DATA(hdr);
free(hdr);
return fd;
}

free(hdr);
return -1;
}

int main()
{
int fds[2];
int fd = -1;
int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
pid_t pid;

if (rc)
{
perror("socketpair");
return 1;
}

/* punt */
system("echo hello world >testfile");

switch (pid = fork())
{
case 0:
// open this in the child proc
fd = open("testfile",O_RDONLY);
if (fd < 0)
perror("open(testfile)");
rc = sendfd(fds[1], fd);
if (rc)
perror("sendfd");
_exit(0);
case -1:
perror("fork");
return 1;
default:
waitpid(pid,NULL,0);
}

fd = recvfd(fds[0]);

if (fd < 0)
{
perror("recvfd");
return 1;
}

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

dup2(fd,0);
close(fd);
execl("/bin/cat","cat",NULL);
}