Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <linux/netlink.h>
3 : : #include <linux/rtnetlink.h>
4 : : #include <poll.h>
5 : :
6 : : #include "fdset.h"
7 : : #include "files.h"
8 : : #include "sockets.h"
9 : : #include "util.h"
10 : :
11 : : #include "protobuf.h"
12 : : #include "protobuf/sk-netlink.pb-c.h"
13 : : #include "netlink_diag.h"
14 : : #include "libnetlink.h"
15 : :
16 : : struct netlink_sk_desc {
17 : : struct socket_desc sd;
18 : : u32 portid;
19 : : u32 *groups;
20 : : u32 gsize;
21 : : u32 dst_portid;
22 : : u32 dst_group;
23 : : u8 state;
24 : : u8 protocol;
25 : : };
26 : :
27 : 17652 : int netlink_receive_one(struct nlmsghdr *hdr, void *arg)
28 : : {
29 : : struct rtattr *tb[NETLINK_DIAG_MAX+1];
30 : : struct netlink_diag_msg *m;
31 : : struct netlink_sk_desc *sd;
32 : : unsigned long *groups;
33 : :
34 : : m = NLMSG_DATA(hdr);
35 : 17652 : pr_info("Collect netlink sock 0x%x\n", m->ndiag_ino);
36 : :
37 [ - + ]: 17652 : sd = xmalloc(sizeof(*sd));
38 [ + - ]: 17652 : if (!sd)
39 : : return -1;
40 : :
41 : 17652 : sd->protocol = m->ndiag_protocol;
42 : 17652 : sd->portid = m->ndiag_portid;
43 : 17652 : sd->dst_portid = m->ndiag_dst_portid;
44 : 17652 : sd->dst_group = m->ndiag_dst_group;
45 : 17652 : sd->state = m->ndiag_state;
46 : :
47 : 17652 : parse_rtattr(tb, NETLINK_DIAG_MAX, (struct rtattr *)(m + 1),
48 : 17652 : hdr->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
49 : :
50 [ + + ]: 17652 : if (tb[NETLINK_DIAG_GROUPS]) {
51 : 12984 : sd->gsize = RTA_PAYLOAD(tb[NETLINK_DIAG_GROUPS]);
52 : 12984 : groups = RTA_DATA(tb[NETLINK_DIAG_GROUPS]);
53 : :
54 [ - + ]: 12984 : sd->groups = xmalloc(sd->gsize);
55 [ - + ]: 12984 : if (!sd->groups) {
56 [ # # ]: 0 : xfree(sd);
57 : : return -1;
58 : : }
59 : 12984 : memcpy(sd->groups, groups, sd->gsize);
60 : : } else {
61 : 4668 : sd->groups = NULL;
62 : 4668 : sd->gsize = 0;
63 : : }
64 : :
65 : 17652 : return sk_collect_one(m->ndiag_ino, PF_NETLINK, &sd->sd);
66 : : }
67 : :
68 : 16 : static bool can_dump_netlink_sk(int lfd)
69 : : {
70 : 16 : struct pollfd pfd = {lfd, POLLIN, 0};
71 : : int ret;
72 : :
73 : : ret = poll(&pfd, 1, 0);
74 [ - + ]: 16 : if (ret < 0) {
75 : 0 : pr_perror("poll() failed");
76 [ - + ]: 16 : } else if (ret == 1)
77 : 0 : pr_err("The socket has data to read\n");
78 : :
79 : 16 : return ret == 0;
80 : : }
81 : :
82 : 16 : static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p)
83 : : {
84 : : struct netlink_sk_desc *sk;
85 : 16 : NetlinkSkEntry ne = NETLINK_SK_ENTRY__INIT;
86 : 16 : SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
87 : :
88 : 16 : sk = (struct netlink_sk_desc *)lookup_socket(p->stat.st_ino, PF_NETLINK, 0);
89 [ + - ]: 16 : if (IS_ERR(sk))
90 : : goto err;
91 : :
92 : 16 : ne.id = id;
93 : 16 : ne.ino = p->stat.st_ino;
94 : :
95 [ + - ]: 16 : if (!can_dump_netlink_sk(lfd))
96 : : goto err;
97 : :
98 [ + + ]: 16 : if (sk) {
99 [ - + ]: 12 : BUG_ON(sk->sd.already_dumped);
100 : :
101 : 12 : ne.protocol = sk->protocol;
102 : 12 : ne.portid = sk->portid;
103 : 12 : ne.groups = sk->groups;
104 : :
105 : :
106 : 12 : ne.n_groups = sk->gsize / sizeof(ne.groups[0]);
107 : : /*
108 : : * On 64-bit sk->gsize is multiple to 8 bytes (sizeof(long)),
109 : : * so remove the last 4 bytes if they are empty.
110 : : */
111 [ + + ][ + - ]: 12 : if (ne.n_groups && sk->groups[ne.n_groups - 1] == 0)
112 : 4 : ne.n_groups -= 1;
113 : :
114 [ - + ]: 12 : if (ne.n_groups > 1) {
115 : 0 : pr_err("%d %x\n", sk->gsize, sk->groups[1]);
116 : 0 : pr_err("The netlink socket 0x%x has more than 32 groups\n", ne.ino);
117 : 0 : return -1;
118 : : }
119 [ + + ][ - + ]: 12 : if (sk->groups && !sk->portid) {
120 : 0 : pr_err("The netlink socket 0x%x is bound to groups but not to portid\n", ne.ino);
121 : 0 : return -1;
122 : : }
123 : 12 : ne.state = sk->state;
124 : 12 : ne.dst_portid = sk->dst_portid;
125 : 12 : ne.dst_group = sk->dst_group;
126 : : } else { /* unconnected and unbound socket */
127 : : int val;
128 : 4 : socklen_t aux = sizeof(val);
129 : :
130 [ - + ]: 4 : if (getsockopt(lfd, SOL_SOCKET, SO_PROTOCOL, &val, &aux) < 0) {
131 : 0 : pr_perror("Unable to get protocol for netlink socket");
132 : 0 : goto err;
133 : : }
134 : :
135 : 4 : ne.protocol = val;
136 : : }
137 : :
138 : 16 : ne.fown = (FownEntry *)&p->fown;
139 : 16 : ne.opts = &skopts;
140 : :
141 [ + - ]: 16 : if (dump_socket_opts(lfd, &skopts))
142 : : goto err;
143 : :
144 [ - + ]: 16 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_NETLINK_SK), &ne, PB_NETLINK_SK))
145 : : goto err;
146 : :
147 : : return 0;
148 : : err:
149 : : return -1;
150 : : }
151 : :
152 : : const struct fdtype_ops netlink_dump_ops = {
153 : : .type = FD_TYPES__NETLINKSK,
154 : : .dump = dump_one_netlink_fd,
155 : : };
156 : :
157 : : struct netlink_sock_info {
158 : : NetlinkSkEntry *nse;
159 : : struct file_desc d;
160 : : };
161 : :
162 : 8 : static int open_netlink_sk(struct file_desc *d)
163 : : {
164 : : struct netlink_sock_info *nsi;
165 : : NetlinkSkEntry *nse;
166 : : struct sockaddr_nl addr;
167 : : int sk = -1;
168 : :
169 : : nsi = container_of(d, struct netlink_sock_info, d);
170 : 8 : nse = nsi->nse;
171 : :
172 : 8 : pr_info("Opening netlink socket id %#x\n", nse->id);
173 : :
174 : 8 : sk = socket(PF_NETLINK, SOCK_RAW, nse->protocol);
175 [ - + ]: 8 : if (sk < 0) {
176 : 0 : pr_perror("Can't create netlink sock");
177 : 0 : goto err;
178 : : }
179 : :
180 [ + + ]: 8 : if (nse->portid) {
181 : : memset(&addr, 0, sizeof(addr));
182 : 6 : addr.nl_family = AF_NETLINK;
183 [ - + ]: 6 : if (nse->n_groups > 1) {
184 : 0 : pr_err("Groups above 32 are not supported yet\n");
185 : 0 : goto err;
186 : : }
187 [ + + ]: 6 : if (nse->n_groups)
188 : 2 : addr.nl_groups = nse->groups[0];
189 : 6 : addr.nl_pid = nse->portid;
190 : :
191 [ - + ]: 6 : if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
192 : 0 : pr_perror("Can't bind netlink socket");
193 : 0 : goto err;
194 : : }
195 : : }
196 : :
197 [ + + ]: 8 : if (nse->state == NETLINK_CONNECTED) {
198 : 2 : addr.nl_family = AF_NETLINK;
199 : 2 : addr.nl_groups = 1 << (nse->dst_group - 1);
200 : 2 : addr.nl_pid = nse->dst_portid;
201 [ - + ]: 2 : if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
202 : 0 : pr_perror("Can't connect netlink socket");
203 : 0 : goto err;
204 : : }
205 : : }
206 : :
207 [ + - ]: 8 : if (rst_file_params(sk, nse->fown, nse->flags))
208 : : goto err;
209 : :
210 [ - + ]: 8 : if (restore_socket_opts(sk, nse->opts))
211 : : goto err;
212 : :
213 : : return sk;
214 : : err:
215 : 0 : close(sk);
216 : 0 : return -1;
217 : : }
218 : :
219 : : static struct file_desc_ops netlink_sock_desc_ops = {
220 : : .type = FD_TYPES__NETLINKSK,
221 : : .open = open_netlink_sk,
222 : : };
223 : :
224 : 8 : static int collect_one_netlink_sk(void *o, ProtobufCMessage *base)
225 : : {
226 : : struct netlink_sock_info *si = o;
227 : :
228 : 8 : si->nse = pb_msg(base, NetlinkSkEntry);
229 : 8 : return file_desc_add(&si->d, si->nse->id, &netlink_sock_desc_ops);
230 : : }
231 : :
232 : : struct collect_image_info netlink_sk_cinfo = {
233 : : .fd_type = CR_FD_NETLINK_SK,
234 : : .pb_type = PB_NETLINK_SK,
235 : : .priv_size = sizeof(struct netlink_sock_info),
236 : : .collect = collect_one_netlink_sk,
237 : : .flags = COLLECT_OPTIONAL,
238 : : };
|