~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/libecryptfs/netlink.c

  • Committer: Tyler Hicks
  • Date: 2012-11-02 14:31:32 UTC
  • Revision ID: tyhicks@canonical.com-20121102143132-uvlq4qqogmdouny0
* src/daemon/main.c, src/include/ecryptfs.h,
  src/libecryptfs/{Makefile.am,messaging.c,miscdev.c,netlink.c,sysfs.c},
  doc/manpage/ecryptfsd.8, doc/design_doc/ecryptfs_design_doc_v0_2.tex:
  - Remove netlink messaging interface support
  - Netlink messaging support was superceded by the miscdev interface
    (/dev/ecryptfs) in upstream kernel version 2.6.26 in July, 2008
  - Netlink messaging support was completely removed from the upstream
    kernel starting with version 2.6.32 in December, 2009

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * Userspace side of netlink communications with eCryptfs kernel
3
 
 * module.
4
 
 *
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>
8
 
 *
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.
13
 
 *
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.
18
 
 *
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
22
 
 * 02111-1307, USA.
23
 
 */
24
 
 
25
 
#include <errno.h>
26
 
#include <fcntl.h>
27
 
#include <signal.h>
28
 
#ifndef S_SPLINT_S
29
 
#include <stdio.h>
30
 
#include <syslog.h>
31
 
#endif
32
 
#include <stdlib.h>
33
 
#include <string.h>
34
 
#include <sys/socket.h>
35
 
#include "config.h"
36
 
#include "../include/ecryptfs.h"
37
 
 
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)
41
 
{
42
 
        struct nlmsghdr *nlh = NULL;
43
 
        struct sockaddr_nl dst_addr;
44
 
        int payload_len;
45
 
        int rc;
46
 
 
47
 
        payload_len = emsg ? sizeof(*emsg) + emsg->data_len : 0;
48
 
        nlh = malloc(NLMSG_SPACE(payload_len));
49
 
        if (!nlh) {
50
 
                ecryptfs_syslog(LOG_ERR, "Failed to allocate memory for "
51
 
                                "netlink header: %m\n");
52
 
                rc = -ENOMEM;
53
 
                goto out;
54
 
        }
55
 
        memset(&dst_addr, 0, sizeof(dst_addr));
56
 
        dst_addr.nl_family = AF_NETLINK;
57
 
        dst_addr.nl_pid = 0;
58
 
        dst_addr.nl_groups = 0;
59
 
        nlh->nlmsg_len = NLMSG_LENGTH(payload_len);
60
 
        nlh->nlmsg_seq = msg_seq;
61
 
        nlh->nlmsg_pid = 0;
62
 
        nlh->nlmsg_type = msg_type;
63
 
        nlh->nlmsg_flags = msg_flags;
64
 
        if (payload_len)
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));
68
 
        if (rc < 0) {
69
 
                rc = -errno;
70
 
                syslog(LOG_ERR, "Failed to send eCryptfs netlink "
71
 
                       "message: %m\n");
72
 
                goto out;
73
 
        }
74
 
out:
75
 
        free(nlh);
76
 
        return rc;
77
 
}
78
 
 
79
 
int ecryptfs_recv_netlink(struct ecryptfs_nl_ctx *nl_ctx,
80
 
                          struct ecryptfs_message **emsg,
81
 
                          int *msg_seq, uint8_t *msg_type)
82
 
{
83
 
        struct nlmsghdr *nlh = NULL;
84
 
        struct sockaddr_nl nladdr;
85
 
        socklen_t nladdr_len = sizeof(nladdr);
86
 
        int flags = MSG_PEEK;
87
 
        int buf_len = sizeof(*nlh);
88
 
        int pl_len;
89
 
        int rc;
90
 
 
91
 
receive:
92
 
        nlh = (struct nlmsghdr *)realloc(nlh, buf_len);
93
 
        if (!nlh) {
94
 
                rc = -errno;
95
 
                syslog(LOG_ERR, "Failed to allocate memory for "
96
 
                       "netlink message: %m\n");
97
 
                goto out;
98
 
        }
99
 
        rc = recvfrom(nl_ctx->socket_fd, nlh, buf_len, flags,
100
 
                      (struct sockaddr*)&nladdr, &nladdr_len);
101
 
        if (rc < 0) {
102
 
                rc = -errno;
103
 
                syslog(LOG_ERR, "Failed to receive netlink header; errno = "
104
 
                       "[%d]; errno msg = [%m]\n", errno);
105
 
                goto free_out;
106
 
        }
107
 
        if (flags & MSG_PEEK) {
108
 
                buf_len = nlh->nlmsg_len;
109
 
                flags &= ~MSG_PEEK;
110
 
                goto receive;
111
 
        }
112
 
        if (nladdr_len != sizeof(nladdr)) {
113
 
                rc = -EPROTO;
114
 
                syslog(LOG_ERR, "Received invalid netlink message\n");
115
 
                goto free_out;
116
 
        }
117
 
        if (nladdr.nl_pid) {
118
 
                rc = -ENOMSG;
119
 
                syslog(LOG_WARNING, "Received netlink packet from a "
120
 
                                "userspace application; pid [%d] may be trying "
121
 
                                "to spoof eCryptfs netlink packets\n",
122
 
                                nladdr.nl_pid);
123
 
                goto out;
124
 
        }
125
 
        pl_len = NLMSG_PAYLOAD(nlh, 0);
126
 
        if (pl_len) {
127
 
                *emsg = malloc(pl_len);
128
 
                if (!*emsg) {
129
 
                        rc = -errno;
130
 
                        syslog(LOG_ERR, "Failed to allocate memory "
131
 
                                        "for eCryptfs netlink message: %m\n");
132
 
                        goto free_out;
133
 
                }
134
 
                memcpy(*emsg, NLMSG_DATA(nlh), pl_len);
135
 
        }
136
 
        *msg_seq = nlh->nlmsg_seq;
137
 
        *msg_type = nlh->nlmsg_type;
138
 
free_out:
139
 
        free(nlh);
140
 
out:
141
 
        return rc;
142
 
}
143
 
 
144
 
int ecryptfs_init_netlink(struct ecryptfs_nl_ctx *nl_ctx)
145
 
{
146
 
        struct sockaddr_nl src_addr;
147
 
        int rc;
148
 
 
149
 
        nl_ctx->socket_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ECRYPTFS);
150
 
        if (nl_ctx->socket_fd == -1) {
151
 
                rc = -errno;
152
 
                syslog(LOG_ERR, "Failed to create the eCryptfs "
153
 
                       "netlink socket: [%m]\n");
154
 
                goto out;
155
 
        }
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,
161
 
                  sizeof(src_addr));
162
 
        if (rc) {
163
 
                rc = -errno;
164
 
                syslog(LOG_ERR, "Failed to bind the eCryptfs netlink "
165
 
                       "socket: %m\n");
166
 
                goto out;
167
 
        }
168
 
        syslog(LOG_DEBUG, "eCryptfs netlink socket was successfully "
169
 
               "initialized\n");
170
 
out:
171
 
        return rc;
172
 
}
173
 
 
174
 
void ecryptfs_release_netlink(struct ecryptfs_nl_ctx *nl_ctx)
175
 
{
176
 
        if (nl_ctx->socket_fd)
177
 
                close(nl_ctx->socket_fd);
178
 
}
179
 
 
180
 
int ecryptfs_run_netlink_daemon(struct ecryptfs_nl_ctx *nl_ctx)
181
 
{
182
 
        struct ecryptfs_message *emsg = NULL;
183
 
        struct ecryptfs_ctx ctx;
184
 
        int msg_seq;
185
 
        uint8_t msg_type;
186
 
        int error_count = 0;
187
 
        int rc;
188
 
 
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",
192
 
                       rc);
193
 
                goto out;
194
 
        }
195
 
receive:
196
 
        rc = ecryptfs_recv_netlink(nl_ctx, &emsg, &msg_seq, &msg_type);
197
 
        if (rc < 0) {
198
 
                syslog(LOG_ERR, "Error while receiving eCryptfs netlink "
199
 
                       "message; errno = [%d]; errno msg = [%m]\n", errno);
200
 
                error_count++;
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);
205
 
                        rc = -EIO;
206
 
                        goto out;
207
 
                }
208
 
        } else if (msg_type == ECRYPTFS_MSG_HELO) {
209
 
                syslog(LOG_DEBUG, "Received eCryptfs netlink HELO "
210
 
                       "message from the kernel\n");
211
 
                error_count = 0;
212
 
        } else if (msg_type == ECRYPTFS_MSG_QUIT) {
213
 
                syslog(LOG_DEBUG, "Received eCryptfs netlink QUIT "
214
 
                       "message from the kernel\n");
215
 
                free(emsg);
216
 
                rc = 0;
217
 
                goto out;
218
 
        } else if (msg_type == ECRYPTFS_MSG_REQUEST) {
219
 
                struct ecryptfs_message *reply = NULL;
220
 
 
221
 
                rc = parse_packet(&ctx, emsg, &reply);
222
 
                if (rc) {
223
 
                        syslog(LOG_ERR, "Failed to process "
224
 
                               "netlink packet\n");
225
 
                        free(reply);
226
 
                        goto free_emsg;
227
 
                }
228
 
                reply->index = emsg->index;
229
 
                rc = ecryptfs_send_netlink(nl_ctx, reply,
230
 
                                           ECRYPTFS_MSG_RESPONSE, 0,
231
 
                                           msg_seq);
232
 
                if (rc < 0) {
233
 
                        syslog(LOG_ERR, "Failed to send netlink "
234
 
                               "message in response to kernel "
235
 
                               "request\n");
236
 
                }
237
 
                free(reply);
238
 
                error_count = 0;
239
 
        } else
240
 
                syslog(LOG_DEBUG, "Received unrecognized netlink "
241
 
                       "message type [%d]\n", msg_type);
242
 
free_emsg:
243
 
        free(emsg);
244
 
        goto receive;
245
 
out:
246
 
        ecryptfs_free_key_mod_list(&ctx);
247
 
        return rc;
248
 
}