Commit 7d1740590b6550b2b8ab4901e4f0b704d9733383

Authored by Mark McLoughlin
Committed by Anthony Liguori
1 parent 9977c894

Add SCM_RIGHTS support to unix socket character devices

If a file descriptor is passed via a message with SCM_RIGHTS ancillary
data on a unix socket, store the file descriptor for use in the
chr_read() handler. Close the file descriptor if it was not used.

The qemu_chr_get_msgfd() API provides access to the passed descriptor.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 2 changed files with 56 additions and 1 deletions
qemu-char.c
... ... @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
168 168 s->chr_read(s->handler_opaque, buf, len);
169 169 }
170 170  
  171 +int qemu_chr_get_msgfd(CharDriverState *s)
  172 +{
  173 + return s->get_msgfd ? s->get_msgfd(s) : -1;
  174 +}
  175 +
171 176 void qemu_chr_accept_input(CharDriverState *s)
172 177 {
173 178 if (s->chr_accept_input)
... ... @@ -1832,6 +1837,7 @@ typedef struct {
1832 1837 int do_telnetopt;
1833 1838 int do_nodelay;
1834 1839 int is_unix;
  1840 + int msgfd;
1835 1841 } TCPCharDriver;
1836 1842  
1837 1843 static void tcp_chr_accept(void *opaque);
... ... @@ -1907,20 +1913,61 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
1907 1913 *size = j;
1908 1914 }
1909 1915  
  1916 +static int tcp_get_msgfd(CharDriverState *chr)
  1917 +{
  1918 + TCPCharDriver *s = chr->opaque;
  1919 +
  1920 + return s->msgfd;
  1921 +}
  1922 +
1910 1923 #ifndef WIN32
  1924 +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
  1925 +{
  1926 + TCPCharDriver *s = chr->opaque;
  1927 + struct cmsghdr *cmsg;
  1928 +
  1929 + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
  1930 + int fd;
  1931 +
  1932 + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
  1933 + cmsg->cmsg_level != SOL_SOCKET ||
  1934 + cmsg->cmsg_type != SCM_RIGHTS)
  1935 + continue;
  1936 +
  1937 + fd = *((int *)CMSG_DATA(cmsg));
  1938 + if (fd < 0)
  1939 + continue;
  1940 +
  1941 + if (s->msgfd != -1)
  1942 + close(s->msgfd);
  1943 + s->msgfd = fd;
  1944 + }
  1945 +}
  1946 +
1911 1947 static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
1912 1948 {
1913 1949 TCPCharDriver *s = chr->opaque;
1914 1950 struct msghdr msg = { 0, };
1915 1951 struct iovec iov[1];
  1952 + union {
  1953 + struct cmsghdr cmsg;
  1954 + char control[CMSG_SPACE(sizeof(int))];
  1955 + } msg_control;
  1956 + ssize_t ret;
1916 1957  
1917 1958 iov[0].iov_base = buf;
1918 1959 iov[0].iov_len = len;
1919 1960  
1920 1961 msg.msg_iov = iov;
1921 1962 msg.msg_iovlen = 1;
  1963 + msg.msg_control = &msg_control;
  1964 + msg.msg_controllen = sizeof(msg_control);
  1965 +
  1966 + ret = recvmsg(s->fd, &msg, 0);
  1967 + if (ret > 0 && s->is_unix)
  1968 + unix_process_msgfd(chr, &msg);
1922 1969  
1923   - return recvmsg(s->fd, &msg, 0);
  1970 + return ret;
1924 1971 }
1925 1972 #else
1926 1973 static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
... ... @@ -1957,6 +2004,10 @@ static void tcp_chr_read(void *opaque)
1957 2004 tcp_chr_process_IAC_bytes(chr, s, buf, &size);
1958 2005 if (size > 0)
1959 2006 qemu_chr_read(chr, buf, size);
  2007 + if (s->msgfd != -1) {
  2008 + close(s->msgfd);
  2009 + s->msgfd = -1;
  2010 + }
1960 2011 }
1961 2012 }
1962 2013  
... ... @@ -2118,12 +2169,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
2118 2169 s->connected = 0;
2119 2170 s->fd = -1;
2120 2171 s->listen_fd = -1;
  2172 + s->msgfd = -1;
2121 2173 s->is_unix = is_unix;
2122 2174 s->do_nodelay = do_nodelay && !is_unix;
2123 2175  
2124 2176 chr->opaque = s;
2125 2177 chr->chr_write = tcp_chr_write;
2126 2178 chr->chr_close = tcp_chr_close;
  2179 + chr->get_msgfd = tcp_get_msgfd;
2127 2180  
2128 2181 if (is_listen) {
2129 2182 s->listen_fd = fd;
... ...
qemu-char.h
... ... @@ -51,6 +51,7 @@ struct CharDriverState {
51 51 int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
52 52 void (*chr_update_read_handler)(struct CharDriverState *s);
53 53 int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
  54 + int (*get_msgfd)(struct CharDriverState *s);
54 55 IOEventHandler *chr_event;
55 56 IOCanRWHandler *chr_can_read;
56 57 IOReadHandler *chr_read;
... ... @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s);
81 82 void qemu_chr_initial_reset(void);
82 83 int qemu_chr_can_read(CharDriverState *s);
83 84 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
  85 +int qemu_chr_get_msgfd(CharDriverState *s);
84 86 void qemu_chr_accept_input(CharDriverState *s);
85 87 void qemu_chr_info(Monitor *mon);
86 88  
... ...