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,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
168 s->chr_read(s->handler_opaque, buf, len); 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 void qemu_chr_accept_input(CharDriverState *s) 176 void qemu_chr_accept_input(CharDriverState *s)
172 { 177 {
173 if (s->chr_accept_input) 178 if (s->chr_accept_input)
@@ -1832,6 +1837,7 @@ typedef struct { @@ -1832,6 +1837,7 @@ typedef struct {
1832 int do_telnetopt; 1837 int do_telnetopt;
1833 int do_nodelay; 1838 int do_nodelay;
1834 int is_unix; 1839 int is_unix;
  1840 + int msgfd;
1835 } TCPCharDriver; 1841 } TCPCharDriver;
1836 1842
1837 static void tcp_chr_accept(void *opaque); 1843 static void tcp_chr_accept(void *opaque);
@@ -1907,20 +1913,61 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, @@ -1907,20 +1913,61 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
1907 *size = j; 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 #ifndef WIN32 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 static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) 1947 static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
1912 { 1948 {
1913 TCPCharDriver *s = chr->opaque; 1949 TCPCharDriver *s = chr->opaque;
1914 struct msghdr msg = { 0, }; 1950 struct msghdr msg = { 0, };
1915 struct iovec iov[1]; 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 iov[0].iov_base = buf; 1958 iov[0].iov_base = buf;
1918 iov[0].iov_len = len; 1959 iov[0].iov_len = len;
1919 1960
1920 msg.msg_iov = iov; 1961 msg.msg_iov = iov;
1921 msg.msg_iovlen = 1; 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 #else 1972 #else
1926 static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) 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,6 +2004,10 @@ static void tcp_chr_read(void *opaque)
1957 tcp_chr_process_IAC_bytes(chr, s, buf, &size); 2004 tcp_chr_process_IAC_bytes(chr, s, buf, &size);
1958 if (size > 0) 2005 if (size > 0)
1959 qemu_chr_read(chr, buf, size); 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,12 +2169,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
2118 s->connected = 0; 2169 s->connected = 0;
2119 s->fd = -1; 2170 s->fd = -1;
2120 s->listen_fd = -1; 2171 s->listen_fd = -1;
  2172 + s->msgfd = -1;
2121 s->is_unix = is_unix; 2173 s->is_unix = is_unix;
2122 s->do_nodelay = do_nodelay && !is_unix; 2174 s->do_nodelay = do_nodelay && !is_unix;
2123 2175
2124 chr->opaque = s; 2176 chr->opaque = s;
2125 chr->chr_write = tcp_chr_write; 2177 chr->chr_write = tcp_chr_write;
2126 chr->chr_close = tcp_chr_close; 2178 chr->chr_close = tcp_chr_close;
  2179 + chr->get_msgfd = tcp_get_msgfd;
2127 2180
2128 if (is_listen) { 2181 if (is_listen) {
2129 s->listen_fd = fd; 2182 s->listen_fd = fd;
qemu-char.h
@@ -51,6 +51,7 @@ struct CharDriverState { @@ -51,6 +51,7 @@ struct CharDriverState {
51 int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); 51 int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
52 void (*chr_update_read_handler)(struct CharDriverState *s); 52 void (*chr_update_read_handler)(struct CharDriverState *s);
53 int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); 53 int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
  54 + int (*get_msgfd)(struct CharDriverState *s);
54 IOEventHandler *chr_event; 55 IOEventHandler *chr_event;
55 IOCanRWHandler *chr_can_read; 56 IOCanRWHandler *chr_can_read;
56 IOReadHandler *chr_read; 57 IOReadHandler *chr_read;
@@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s);
81 void qemu_chr_initial_reset(void); 82 void qemu_chr_initial_reset(void);
82 int qemu_chr_can_read(CharDriverState *s); 83 int qemu_chr_can_read(CharDriverState *s);
83 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); 84 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
  85 +int qemu_chr_get_msgfd(CharDriverState *s);
84 void qemu_chr_accept_input(CharDriverState *s); 86 void qemu_chr_accept_input(CharDriverState *s);
85 void qemu_chr_info(Monitor *mon); 87 void qemu_chr_info(Monitor *mon);
86 88