ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libptytty/src/fdpass.C
Revision: 1.26
Committed: Thu Dec 29 14:06:26 2022 UTC (16 months, 2 weeks ago) by sf-exg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.25: +1 -1 lines
Log Message:
Fix typo

File Contents

# Content
1 /*----------------------------------------------------------------------*
2 * File: fdpass.C
3 *----------------------------------------------------------------------*
4 *
5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 2005-2006,2012 Marc Lehmann <schmorp@schmorp.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *----------------------------------------------------------------------*/
22
23 #include "config.h"
24
25 #include <stddef.h> // needed by broken bsds for NULL used in sys/uio.h
26 #include <stdlib.h>
27
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/uio.h>
31 #include <sys/socket.h>
32
33 #include "libptytty.h"
34
35 // CMSG_SPACE & CMSG_LEN are rfc2292 extensions to unix
36 #ifndef CMSG_SPACE
37 # define CMSG_SPACE(len) (sizeof (cmsghdr) + len)
38 #endif
39
40 #ifndef CMSG_LEN
41 # define CMSG_LEN(len) (sizeof (cmsghdr) + len)
42 #endif
43
44 bool
45 ptytty::send_fd (int socket, int fd)
46 {
47 void *buf = malloc (CMSG_SPACE (sizeof (int)));
48
49 if (!buf)
50 return 0;
51
52 msghdr msg;
53 iovec iov;
54 cmsghdr *cmsg;
55 char data = 0;
56
57 iov.iov_base = &data;
58 iov.iov_len = 1;
59
60 msg.msg_name = 0;
61 msg.msg_namelen = 0;
62 msg.msg_iov = &iov;
63 msg.msg_iovlen = 1;
64 msg.msg_control = buf;
65 msg.msg_controllen = CMSG_SPACE (sizeof (int));
66
67 cmsg = CMSG_FIRSTHDR (&msg);
68 cmsg->cmsg_level = SOL_SOCKET;
69 cmsg->cmsg_type = SCM_RIGHTS;
70 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
71
72 *(int *)CMSG_DATA (cmsg) = fd;
73
74 ssize_t result = sendmsg (socket, &msg, 0);
75
76 free (buf);
77
78 return result >= 0;
79 }
80
81 int
82 ptytty::recv_fd (int socket)
83 {
84 void *buf = malloc (CMSG_SPACE (sizeof (int)));
85
86 if (!buf)
87 return -1;
88
89 msghdr msg;
90 iovec iov;
91 char data = 1;
92
93 iov.iov_base = &data;
94 iov.iov_len = 1;
95
96 msg.msg_name = 0;
97 msg.msg_namelen = 0;
98 msg.msg_iov = &iov;
99 msg.msg_iovlen = 1;
100 msg.msg_control = buf;
101 msg.msg_controllen = CMSG_SPACE (sizeof (int));
102
103 int fd = -1;
104
105 if (recvmsg (socket, &msg, 0) > 0)
106 {
107 // there *should* be at most one cmsg, as more should not fit
108 // in the buffer, although this depends on somewhat sane
109 // alignment imposed by CMSG_SPACE.
110 cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
111
112 if (cmsg)
113 {
114 // some operating systems (i.e. osx) allow msg->cmsg_len to be larger than
115 // msg.msg_controllen, so limit the size here
116 if (cmsg->cmsg_len > CMSG_SPACE (sizeof (int)))
117 cmsg->cmsg_len = CMSG_SPACE (sizeof (int));
118
119 if ( cmsg->cmsg_level == SOL_SOCKET
120 && cmsg->cmsg_type == SCM_RIGHTS
121 && cmsg->cmsg_len >= CMSG_LEN (sizeof (int)))
122 {
123 // close any extra fds that might have been passed.
124 // this does not work around osx/freebsd bugs where a malicious sender
125 // can send us more fds than we can receive, leaking the extra fds,
126 // which must be fixed in the kernel, really.
127 for (fd = 1; cmsg->cmsg_len >= CMSG_LEN (sizeof (int) * (fd + 1)); ++fd)
128 close (((int *)CMSG_DATA (cmsg))[fd]);
129
130 // we are only interested in the first fd
131 fd = *(int *)CMSG_DATA (cmsg);
132 }
133 }
134 }
135
136 free (buf);
137
138 if (data != 0)
139 {
140 close (fd);
141 fd = -1;
142 }
143
144 return fd;
145 }
146