]>
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
34 #include <sys/socket.h>
35 #include <sys/syscall.h>
43 #include "include/strlcpy.h"
46 lxc_log_define(af_unix
, lxc
);
48 static ssize_t
lxc_abstract_unix_set_sockaddr(struct sockaddr_un
*addr
,
58 /* Clear address structure */
59 memset(addr
, 0, sizeof(*addr
));
61 addr
->sun_family
= AF_UNIX
;
63 len
= strlen(&path
[1]);
65 /* do not enforce \0-termination */
66 if (len
>= INT_MAX
|| len
>= sizeof(addr
->sun_path
)) {
71 /* do not enforce \0-termination */
72 memcpy(&addr
->sun_path
[1], &path
[1], len
);
76 int lxc_abstract_unix_open(const char *path
, int type
, int flags
)
80 struct sockaddr_un addr
;
82 fd
= socket(PF_UNIX
, type
, 0);
89 len
= lxc_abstract_unix_set_sockaddr(&addr
, path
);
91 int saved_errno
= errno
;
97 ret
= bind(fd
, (struct sockaddr
*)&addr
,
98 offsetof(struct sockaddr_un
, sun_path
) + len
+ 1);
100 int saved_errno
= errno
;
106 if (type
== SOCK_STREAM
) {
107 ret
= listen(fd
, 100);
109 int saved_errno
= errno
;
119 void lxc_abstract_unix_close(int fd
)
124 int lxc_abstract_unix_connect(const char *path
)
128 struct sockaddr_un addr
;
130 fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
134 len
= lxc_abstract_unix_set_sockaddr(&addr
, path
);
136 int saved_errno
= errno
;
142 ret
= connect(fd
, (struct sockaddr
*)&addr
,
143 offsetof(struct sockaddr_un
, sun_path
) + len
+ 1);
145 int saved_errno
= errno
;
154 int lxc_abstract_unix_send_fds(int fd
, int *sendfds
, int num_sendfds
,
155 void *data
, size_t size
)
160 struct cmsghdr
*cmsg
= NULL
;
163 size_t cmsgbufsize
= CMSG_SPACE(num_sendfds
* sizeof(int));
165 memset(&msg
, 0, sizeof(msg
));
166 memset(&iov
, 0, sizeof(iov
));
168 cmsgbuf
= malloc(cmsgbufsize
);
174 msg
.msg_control
= cmsgbuf
;
175 msg
.msg_controllen
= cmsgbufsize
;
177 cmsg
= CMSG_FIRSTHDR(&msg
);
178 cmsg
->cmsg_level
= SOL_SOCKET
;
179 cmsg
->cmsg_type
= SCM_RIGHTS
;
180 cmsg
->cmsg_len
= CMSG_LEN(num_sendfds
* sizeof(int));
182 msg
.msg_controllen
= cmsg
->cmsg_len
;
184 memcpy(CMSG_DATA(cmsg
), sendfds
, num_sendfds
* sizeof(int));
186 iov
.iov_base
= data
? data
: buf
;
187 iov
.iov_len
= data
? size
: sizeof(buf
);
191 ret
= sendmsg(fd
, &msg
, MSG_NOSIGNAL
);
196 int lxc_abstract_unix_recv_fds(int fd
, int *recvfds
, int num_recvfds
,
197 void *data
, size_t size
)
202 struct cmsghdr
*cmsg
= NULL
;
205 size_t cmsgbufsize
= CMSG_SPACE(num_recvfds
* sizeof(int));
207 memset(&msg
, 0, sizeof(msg
));
208 memset(&iov
, 0, sizeof(iov
));
210 cmsgbuf
= malloc(cmsgbufsize
);
216 msg
.msg_control
= cmsgbuf
;
217 msg
.msg_controllen
= cmsgbufsize
;
219 iov
.iov_base
= data
? data
: buf
;
220 iov
.iov_len
= data
? size
: sizeof(buf
);
224 ret
= recvmsg(fd
, &msg
, 0);
228 cmsg
= CMSG_FIRSTHDR(&msg
);
230 memset(recvfds
, -1, num_recvfds
* sizeof(int));
231 if (cmsg
&& cmsg
->cmsg_len
== CMSG_LEN(num_recvfds
* sizeof(int)) &&
232 cmsg
->cmsg_level
== SOL_SOCKET
&& cmsg
->cmsg_type
== SCM_RIGHTS
)
233 memcpy(recvfds
, CMSG_DATA(cmsg
), num_recvfds
* sizeof(int));
240 int lxc_abstract_unix_send_credential(int fd
, void *data
, size_t size
)
242 struct msghdr msg
= {0};
244 struct cmsghdr
*cmsg
;
245 struct ucred cred
= {
246 .pid
= lxc_raw_getpid(), .uid
= getuid(), .gid
= getgid(),
248 char cmsgbuf
[CMSG_SPACE(sizeof(cred
))] = {0};
251 msg
.msg_control
= cmsgbuf
;
252 msg
.msg_controllen
= sizeof(cmsgbuf
);
254 cmsg
= CMSG_FIRSTHDR(&msg
);
255 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct ucred
));
256 cmsg
->cmsg_level
= SOL_SOCKET
;
257 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
258 memcpy(CMSG_DATA(cmsg
), &cred
, sizeof(cred
));
263 iov
.iov_base
= data
? data
: buf
;
264 iov
.iov_len
= data
? size
: sizeof(buf
);
268 return sendmsg(fd
, &msg
, MSG_NOSIGNAL
);
271 int lxc_abstract_unix_rcv_credential(int fd
, void *data
, size_t size
)
273 struct msghdr msg
= {0};
275 struct cmsghdr
*cmsg
;
278 char cmsgbuf
[CMSG_SPACE(sizeof(cred
))] = {0};
283 msg
.msg_control
= cmsgbuf
;
284 msg
.msg_controllen
= sizeof(cmsgbuf
);
286 iov
.iov_base
= data
? data
: buf
;
287 iov
.iov_len
= data
? size
: sizeof(buf
);
291 ret
= recvmsg(fd
, &msg
, 0);
295 cmsg
= CMSG_FIRSTHDR(&msg
);
297 if (cmsg
&& cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct ucred
)) &&
298 cmsg
->cmsg_level
== SOL_SOCKET
&&
299 cmsg
->cmsg_type
== SCM_CREDENTIALS
) {
300 memcpy(&cred
, CMSG_DATA(cmsg
), sizeof(cred
));
302 (cred
.uid
!= getuid() || cred
.gid
!= getgid())) {
303 INFO("Message denied for '%d/%d'", cred
.uid
, cred
.gid
);