GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/syslogd/privsep_fdpass.c Lines: 22 53 41.5 %
Date: 2017-11-07 Branches: 4 18 22.2 %

Line Branch Exec Source
1
/*	$OpenBSD: privsep_fdpass.c,v 1.11 2015/07/09 20:16:04 bluhm Exp $	*/
2
3
/*
4
 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
5
 * All rights reserved.
6
 *
7
 * Copyright (c) 2002 Matthieu Herrb
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 *    - Redistributions of source code must retain the above copyright
15
 *      notice, this list of conditions and the following disclaimer.
16
 *    - Redistributions in binary form must reproduce the above
17
 *      copyright notice, this list of conditions and the following
18
 *      disclaimer in the documentation and/or other materials provided
19
 *      with the distribution.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 */
34
35
#include <err.h>
36
#include <errno.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <unistd.h>
41
42
#include "syslogd.h"
43
44
void
45
send_fd(int sock, int fd)
46
{
47
85138
	struct msghdr msg;
48
42569
	union {
49
		struct cmsghdr hdr;
50
		char buf[CMSG_SPACE(sizeof(int))];
51
	} cmsgbuf;
52
	struct cmsghdr *cmsg;
53
42569
	struct iovec vec;
54
42569
	int result = 0;
55
	ssize_t n;
56
57
42569
	memset(&msg, 0, sizeof(msg));
58
59
42569
	if (fd >= 0) {
60
42554
		msg.msg_control = (caddr_t)&cmsgbuf.buf;
61
42554
		msg.msg_controllen = sizeof(cmsgbuf.buf);
62
42554
		cmsg = CMSG_FIRSTHDR(&msg);
63
42554
		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
64
42554
		cmsg->cmsg_level = SOL_SOCKET;
65
42554
		cmsg->cmsg_type = SCM_RIGHTS;
66
42554
		*(int *)CMSG_DATA(cmsg) = fd;
67
42554
	} else {
68
15
		result = errno;
69
	}
70
71
42569
	vec.iov_base = &result;
72
42569
	vec.iov_len = sizeof(int);
73
42569
	msg.msg_iov = &vec;
74
42569
	msg.msg_iovlen = 1;
75
76
42569
	if ((n = sendmsg(sock, &msg, 0)) == -1)
77
		warn("%s: sendmsg(%d)", "send_fd", sock);
78
42569
	if (n != sizeof(int))
79
		warnx("%s: sendmsg: expected sent 1 got %ld",
80
		    "send_fd", (long)n);
81
42569
}
82
83
int
84
receive_fd(int sock)
85
{
86
	struct msghdr msg;
87
	union {
88
		struct cmsghdr hdr;
89
		char buf[CMSG_SPACE(sizeof(int))];
90
	} cmsgbuf;
91
	struct cmsghdr *cmsg;
92
	struct iovec vec;
93
	ssize_t n;
94
	int result;
95
	int fd;
96
97
	memset(&msg, 0, sizeof(msg));
98
	vec.iov_base = &result;
99
	vec.iov_len = sizeof(int);
100
	msg.msg_iov = &vec;
101
	msg.msg_iovlen = 1;
102
	msg.msg_control = &cmsgbuf.buf;
103
	msg.msg_controllen = sizeof(cmsgbuf.buf);
104
105
	if ((n = recvmsg(sock, &msg, 0)) == -1) {
106
		warn("%s: recvmsg", "receive_fd");
107
		/* receive message failed, but the result is in the socket */
108
		if (errno == EMSGSIZE)
109
			recv(sock, &result, sizeof(int), MSG_DONTWAIT);
110
		return -1;
111
	}
112
	if (n != sizeof(int))
113
		warnx("%s: recvmsg: expected received 1 got %ld",
114
		    "receive_fd", (long)n);
115
	if (result == 0) {
116
		cmsg = CMSG_FIRSTHDR(&msg);
117
		if (cmsg == NULL) {
118
			warnx("%s: no message header", "receive_fd");
119
			return (-1);
120
		}
121
		if (cmsg->cmsg_type != SCM_RIGHTS)
122
			warnx("%s: expected type %d got %d", "receive_fd",
123
			    SCM_RIGHTS, cmsg->cmsg_type);
124
		fd = (*(int *)CMSG_DATA(cmsg));
125
		return fd;
126
	} else {
127
		errno = result;
128
		return -1;
129
	}
130
}