2
* Userspace side of netlink communications with eCryptfs kernel
5
* Copyright (C) 2004-2007 International Business Machines Corp.
6
* Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
7
* Tyler Hicks <tyhicks@ou.edu>
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public License as
11
* published by the Free Software Foundation; either version 2 of the
12
* License, or (at your option) any later version.
14
* This program is distributed in the hope that it will be useful, but
15
* WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34
#include <sys/socket.h>
36
#include "../include/ecryptfs.h"
38
int ecryptfs_send_netlink(struct ecryptfs_nl_ctx *nl_ctx,
39
struct ecryptfs_message *emsg, uint8_t msg_type,
40
uint16_t msg_flags, uint32_t msg_seq)
42
struct nlmsghdr *nlh = NULL;
43
struct sockaddr_nl dst_addr;
47
payload_len = emsg ? sizeof(*emsg) + emsg->data_len : 0;
48
nlh = malloc(NLMSG_SPACE(payload_len));
50
ecryptfs_syslog(LOG_ERR, "Failed to allocate memory for "
51
"netlink header: %m\n");
55
memset(&dst_addr, 0, sizeof(dst_addr));
56
dst_addr.nl_family = AF_NETLINK;
58
dst_addr.nl_groups = 0;
59
nlh->nlmsg_len = NLMSG_LENGTH(payload_len);
60
nlh->nlmsg_seq = msg_seq;
62
nlh->nlmsg_type = msg_type;
63
nlh->nlmsg_flags = msg_flags;
65
memcpy(NLMSG_DATA(nlh), emsg, payload_len);
66
rc = sendto(nl_ctx->socket_fd, nlh, nlh->nlmsg_len, 0,
67
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
70
syslog(LOG_ERR, "Failed to send eCryptfs netlink "
79
int ecryptfs_recv_netlink(struct ecryptfs_nl_ctx *nl_ctx,
80
struct ecryptfs_message **emsg,
81
int *msg_seq, uint8_t *msg_type)
83
struct nlmsghdr *nlh = NULL;
84
struct sockaddr_nl nladdr;
85
socklen_t nladdr_len = sizeof(nladdr);
87
int buf_len = sizeof(*nlh);
92
nlh = (struct nlmsghdr *)realloc(nlh, buf_len);
95
syslog(LOG_ERR, "Failed to allocate memory for "
96
"netlink message: %m\n");
99
rc = recvfrom(nl_ctx->socket_fd, nlh, buf_len, flags,
100
(struct sockaddr*)&nladdr, &nladdr_len);
103
syslog(LOG_ERR, "Failed to receive netlink header; errno = "
104
"[%d]; errno msg = [%m]\n", errno);
107
if (flags & MSG_PEEK) {
108
buf_len = nlh->nlmsg_len;
112
if (nladdr_len != sizeof(nladdr)) {
114
syslog(LOG_ERR, "Received invalid netlink message\n");
119
syslog(LOG_WARNING, "Received netlink packet from a "
120
"userspace application; pid [%d] may be trying "
121
"to spoof eCryptfs netlink packets\n",
125
pl_len = NLMSG_PAYLOAD(nlh, 0);
127
*emsg = malloc(pl_len);
130
syslog(LOG_ERR, "Failed to allocate memory "
131
"for eCryptfs netlink message: %m\n");
134
memcpy(*emsg, NLMSG_DATA(nlh), pl_len);
136
*msg_seq = nlh->nlmsg_seq;
137
*msg_type = nlh->nlmsg_type;
144
int ecryptfs_init_netlink(struct ecryptfs_nl_ctx *nl_ctx)
146
struct sockaddr_nl src_addr;
149
nl_ctx->socket_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ECRYPTFS);
150
if (nl_ctx->socket_fd == -1) {
152
syslog(LOG_ERR, "Failed to create the eCryptfs "
153
"netlink socket: [%m]\n");
156
memset(&src_addr, 0, sizeof(src_addr));
157
src_addr.nl_family = AF_NETLINK;
158
src_addr.nl_pid = getpid();
159
src_addr.nl_groups = 0;
160
rc = bind(nl_ctx->socket_fd, (struct sockaddr *)&src_addr,
164
syslog(LOG_ERR, "Failed to bind the eCryptfs netlink "
168
syslog(LOG_DEBUG, "eCryptfs netlink socket was successfully "
174
void ecryptfs_release_netlink(struct ecryptfs_nl_ctx *nl_ctx)
176
if (nl_ctx->socket_fd)
177
close(nl_ctx->socket_fd);
180
int ecryptfs_run_netlink_daemon(struct ecryptfs_nl_ctx *nl_ctx)
182
struct ecryptfs_message *emsg = NULL;
183
struct ecryptfs_ctx ctx;
189
memset(&ctx, 0, sizeof(struct ecryptfs_ctx));
190
if ((rc = ecryptfs_register_key_modules(&ctx))) {
191
syslog(LOG_ERR, "Failed to register key modules; rc = [%d]\n",
196
rc = ecryptfs_recv_netlink(nl_ctx, &emsg, &msg_seq, &msg_type);
198
syslog(LOG_ERR, "Error while receiving eCryptfs netlink "
199
"message; errno = [%d]; errno msg = [%m]\n", errno);
201
if (error_count > ECRYPTFS_NETLINK_ERROR_COUNT_THRESHOLD) {
202
syslog(LOG_ERR, "Netlink error threshold exceeded "
203
"maximum of [%d]; terminating daemon\n",
204
ECRYPTFS_NETLINK_ERROR_COUNT_THRESHOLD);
208
} else if (msg_type == ECRYPTFS_MSG_HELO) {
209
syslog(LOG_DEBUG, "Received eCryptfs netlink HELO "
210
"message from the kernel\n");
212
} else if (msg_type == ECRYPTFS_MSG_QUIT) {
213
syslog(LOG_DEBUG, "Received eCryptfs netlink QUIT "
214
"message from the kernel\n");
218
} else if (msg_type == ECRYPTFS_MSG_REQUEST) {
219
struct ecryptfs_message *reply = NULL;
221
rc = parse_packet(&ctx, emsg, &reply);
223
syslog(LOG_ERR, "Failed to process "
228
reply->index = emsg->index;
229
rc = ecryptfs_send_netlink(nl_ctx, reply,
230
ECRYPTFS_MSG_RESPONSE, 0,
233
syslog(LOG_ERR, "Failed to send netlink "
234
"message in response to kernel "
240
syslog(LOG_DEBUG, "Received unrecognized netlink "
241
"message type [%d]\n", msg_type);
246
ecryptfs_free_key_mod_list(&ctx);