]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/af_unix.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <sys/socket.h>
37 lxc_log_define(lxc_af_unix
, lxc
);
39 int lxc_abstract_unix_open(const char *path
, int type
, int flags
)
43 struct sockaddr_un addr
;
48 fd
= socket(PF_UNIX
, type
, 0);
52 /* Clear address structure */
53 memset(&addr
, 0, sizeof(addr
));
58 addr
.sun_family
= AF_UNIX
;
60 len
= strlen(&path
[1]);
61 /* do not enforce \0-termination */
62 if (len
>= sizeof(addr
.sun_path
)) {
67 /* addr.sun_path[0] has already been set to 0 by memset() */
68 strncpy(&addr
.sun_path
[1], &path
[1], strlen(&path
[1]));
70 if (bind(fd
, (struct sockaddr
*)&addr
, offsetof(struct sockaddr_un
, sun_path
) + len
+ 1)) {
77 if (type
== SOCK_STREAM
&& listen(fd
, 100)) {
87 int lxc_abstract_unix_close(int fd
)
89 struct sockaddr_un addr
;
90 socklen_t addrlen
= sizeof(addr
);
92 if (!getsockname(fd
, (struct sockaddr
*)&addr
, &addrlen
) &&
94 unlink(addr
.sun_path
);
101 int lxc_abstract_unix_connect(const char *path
)
105 struct sockaddr_un addr
;
107 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
111 memset(&addr
, 0, sizeof(addr
));
113 addr
.sun_family
= AF_UNIX
;
115 len
= strlen(&path
[1]);
116 /* do not enforce \0-termination */
117 if (len
>= sizeof(addr
.sun_path
)) {
119 errno
= ENAMETOOLONG
;
122 /* addr.sun_path[0] has already been set to 0 by memset() */
123 strncpy(&addr
.sun_path
[1], &path
[1], strlen(&path
[1]));
125 if (connect(fd
, (struct sockaddr
*)&addr
, offsetof(struct sockaddr_un
, sun_path
) + len
+ 1)) {
127 /* special case to connect to older containers */
128 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)) == 0)
138 int lxc_abstract_unix_send_fds(int fd
, int *sendfds
, int num_sendfds
,
139 void *data
, size_t size
)
144 struct cmsghdr
*cmsg
= NULL
;
147 size_t cmsgbufsize
= CMSG_SPACE(num_sendfds
* sizeof(int));
149 memset(&msg
, 0, sizeof(msg
));
150 memset(&iov
, 0, sizeof(iov
));
152 cmsgbuf
= malloc(cmsgbufsize
);
156 msg
.msg_control
= cmsgbuf
;
157 msg
.msg_controllen
= cmsgbufsize
;
159 cmsg
= CMSG_FIRSTHDR(&msg
);
160 cmsg
->cmsg_level
= SOL_SOCKET
;
161 cmsg
->cmsg_type
= SCM_RIGHTS
;
162 cmsg
->cmsg_len
= CMSG_LEN(num_sendfds
* sizeof(int));
164 msg
.msg_controllen
= cmsg
->cmsg_len
;
166 memcpy(CMSG_DATA(cmsg
), sendfds
, num_sendfds
* sizeof(int));
168 iov
.iov_base
= data
? data
: buf
;
169 iov
.iov_len
= data
? size
: sizeof(buf
);
173 ret
= sendmsg(fd
, &msg
, MSG_NOSIGNAL
);
178 int lxc_abstract_unix_recv_fds(int fd
, int *recvfds
, int num_recvfds
,
179 void *data
, size_t size
)
184 struct cmsghdr
*cmsg
= NULL
;
187 size_t cmsgbufsize
= CMSG_SPACE(num_recvfds
* sizeof(int));
189 memset(&msg
, 0, sizeof(msg
));
190 memset(&iov
, 0, sizeof(iov
));
192 cmsgbuf
= malloc(cmsgbufsize
);
196 msg
.msg_control
= cmsgbuf
;
197 msg
.msg_controllen
= cmsgbufsize
;
199 iov
.iov_base
= data
? data
: buf
;
200 iov
.iov_len
= data
? size
: sizeof(buf
);
204 ret
= recvmsg(fd
, &msg
, 0);
208 cmsg
= CMSG_FIRSTHDR(&msg
);
210 memset(recvfds
, -1, num_recvfds
* sizeof(int));
211 if (cmsg
&& cmsg
->cmsg_len
== CMSG_LEN(num_recvfds
* sizeof(int)) &&
212 cmsg
->cmsg_level
== SOL_SOCKET
&& cmsg
->cmsg_type
== SCM_RIGHTS
) {
213 memcpy(recvfds
, CMSG_DATA(cmsg
), num_recvfds
* sizeof(int));
221 int lxc_abstract_unix_send_credential(int fd
, void *data
, size_t size
)
223 struct msghdr msg
= { 0 };
225 struct cmsghdr
*cmsg
;
226 struct ucred cred
= {
231 char cmsgbuf
[CMSG_SPACE(sizeof(cred
))] = {0};
234 msg
.msg_control
= cmsgbuf
;
235 msg
.msg_controllen
= sizeof(cmsgbuf
);
237 cmsg
= CMSG_FIRSTHDR(&msg
);
238 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct ucred
));
239 cmsg
->cmsg_level
= SOL_SOCKET
;
240 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
241 memcpy(CMSG_DATA(cmsg
), &cred
, sizeof(cred
));
246 iov
.iov_base
= data
? data
: buf
;
247 iov
.iov_len
= data
? size
: sizeof(buf
);
251 return sendmsg(fd
, &msg
, MSG_NOSIGNAL
);
254 int lxc_abstract_unix_rcv_credential(int fd
, void *data
, size_t size
)
256 struct msghdr msg
= { 0 };
258 struct cmsghdr
*cmsg
;
261 char cmsgbuf
[CMSG_SPACE(sizeof(cred
))] = {0};
266 msg
.msg_control
= cmsgbuf
;
267 msg
.msg_controllen
= sizeof(cmsgbuf
);
269 iov
.iov_base
= data
? data
: buf
;
270 iov
.iov_len
= data
? size
: sizeof(buf
);
274 ret
= recvmsg(fd
, &msg
, 0);
278 cmsg
= CMSG_FIRSTHDR(&msg
);
280 if (cmsg
&& cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct ucred
)) &&
281 cmsg
->cmsg_level
== SOL_SOCKET
&&
282 cmsg
->cmsg_type
== SCM_CREDENTIALS
) {
283 memcpy(&cred
, CMSG_DATA(cmsg
), sizeof(cred
));
284 if (cred
.uid
&& (cred
.uid
!= getuid() || cred
.gid
!= getgid())) {
285 INFO("message denied for '%d/%d'", cred
.uid
, cred
.gid
);