1 /**
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define _GNU_SOURCE
17 #define ARRAY_SIZE(__a) (sizeof(__a) / sizeof((__a)[0]))
18 #include <errno.h>
19 #include <linux/filter.h>
20 #include <linux/netlink.h>
21 #include <stdlib.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26
27 static struct sock_filter nlattr[] = {
28 { 0000, 0, 0, 0x87654321 },
29 { 0x01, 0, 0, 0x0000002a },
30 { 0x20, 0, 0, 0xfffff00c },
31 { 0x16, 0, 0, 0000000000 },
32 };
33
34 static struct sock_fprog bpf_nlattr = {
35 .len = ARRAY_SIZE(nlattr),
36 .filter = nlattr,
37 };
38
39 static struct sock_filter nlattr_nest[] = {
40 { 0000, 0, 0, 0x87654321 },
41 { 0x01, 0, 0, 0x0000002a },
42 { 0x20, 0, 0, 0xfffff010 },
43 { 0x16, 0, 0, 0000000000 },
44 };
45
46 static struct sock_fprog bpf_nlattr_nest = {
47 .len = ARRAY_SIZE(nlattr_nest),
48 .filter = nlattr_nest,
49 };
50
51 static struct sock_filter nest_rem[] = {
52 { 0000, 0, 0, 0000000000 },
53 { 0x01, 0, 0, 0x0000002a },
54 { 0x20, 0, 0, 0xfffff010 },
55 { 0x16, 0, 0, 0000000000 },
56 };
57
58 static struct sock_fprog bpf_nest_rem = {
59 .len = ARRAY_SIZE(nest_rem),
60 .filter = nest_rem,
61 };
62
send_receive_packet(int s[2],const void * pkt,int len)63 static int send_receive_packet(int s[2], const void* pkt, int len)
64 {
65 char tmp[1024];
66 ssize_t ret;
67
68 ret = send(s[1], pkt, len, 0);
69 if (ret != len) {
70 return -1;
71 }
72
73 ret = recv(s[0], tmp, len, MSG_DONTWAIT);
74 if (ret < 0 && errno == EAGAIN)
75 return 0;
76
77 return 1;
78 }
79
main()80 int main()
81 {
82 struct nlattr chkrem[2] = {
83 [0] = {
84 .nla_len = 0xfff0,
85 .nla_type = 0,
86 },
87 [1] = {
88 .nla_len = sizeof(struct nlattr),
89 .nla_type = 42,
90 },
91 };
92 __u16 chksz = 0xfefe;
93 int s[2], ret;
94
95 ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, s);
96 if (ret) {
97 return -1;
98 }
99
100 ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
101 &bpf_nlattr, sizeof(bpf_nlattr));
102 if (ret < 0) {
103 return -1;
104 }
105
106 ret = send_receive_packet(s, &chksz, sizeof(chksz));
107 if (ret) {
108 ret = 113;
109 goto out;
110 }
111
112 ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
113 &bpf_nlattr_nest, sizeof(bpf_nlattr_nest));
114 if (ret < 0) {
115 return -1;
116 }
117
118 ret = send_receive_packet(s, &chksz, sizeof(chksz));
119 if (ret) {
120 ret = 113;
121 goto out;
122 }
123
124 ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
125 &bpf_nest_rem, sizeof(bpf_nest_rem));
126 if (ret < 0) {
127 return -1;
128 }
129
130 ret = send_receive_packet(s, chkrem, sizeof(chkrem));
131 if(ret){
132 ret = 113;
133 }
134
135 out:
136 return ret;
137 }
138