Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: sandbox/linux/bpf_dsl/bpf_dsl.cc

Issue 1892783002: bpf_dsl: replace scoped_refptr with std::shared_ptr (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix asan build Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl.h ('k') | sandbox/linux/bpf_dsl/bpf_dsl_forward.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" 5 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" 14 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
16 #include "sandbox/linux/bpf_dsl/errorcode.h" 15 #include "sandbox/linux/bpf_dsl/errorcode.h"
17 #include "sandbox/linux/bpf_dsl/policy_compiler.h" 16 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
18 #include "sandbox/linux/system_headers/linux_seccomp.h" 17 #include "sandbox/linux/system_headers/linux_seccomp.h"
19 18
20 namespace sandbox { 19 namespace sandbox {
21 namespace bpf_dsl { 20 namespace bpf_dsl {
22 namespace { 21 namespace {
23 22
24 class ReturnResultExprImpl : public internal::ResultExprImpl { 23 class ReturnResultExprImpl : public internal::ResultExprImpl {
25 public: 24 public:
26 explicit ReturnResultExprImpl(uint32_t ret) : ret_(ret) {} 25 explicit ReturnResultExprImpl(uint32_t ret) : ret_(ret) {}
26 ~ReturnResultExprImpl() override {}
27 27
28 CodeGen::Node Compile(PolicyCompiler* pc) const override { 28 CodeGen::Node Compile(PolicyCompiler* pc) const override {
29 return pc->Return(ret_); 29 return pc->Return(ret_);
30 } 30 }
31 31
32 bool IsAllow() const override { return IsAction(SECCOMP_RET_ALLOW); } 32 bool IsAllow() const override { return IsAction(SECCOMP_RET_ALLOW); }
33 33
34 bool IsDeny() const override { 34 bool IsDeny() const override {
35 return IsAction(SECCOMP_RET_ERRNO) || IsAction(SECCOMP_RET_KILL); 35 return IsAction(SECCOMP_RET_ERRNO) || IsAction(SECCOMP_RET_KILL);
36 } 36 }
37 37
38 private: 38 private:
39 ~ReturnResultExprImpl() override {}
40
41 bool IsAction(uint32_t action) const { 39 bool IsAction(uint32_t action) const {
42 return (ret_ & SECCOMP_RET_ACTION) == action; 40 return (ret_ & SECCOMP_RET_ACTION) == action;
43 } 41 }
44 42
45 uint32_t ret_; 43 uint32_t ret_;
46 44
47 DISALLOW_COPY_AND_ASSIGN(ReturnResultExprImpl); 45 DISALLOW_COPY_AND_ASSIGN(ReturnResultExprImpl);
48 }; 46 };
49 47
50 class TrapResultExprImpl : public internal::ResultExprImpl { 48 class TrapResultExprImpl : public internal::ResultExprImpl {
51 public: 49 public:
52 TrapResultExprImpl(TrapRegistry::TrapFnc func, const void* arg, bool safe) 50 TrapResultExprImpl(TrapRegistry::TrapFnc func, const void* arg, bool safe)
53 : func_(func), arg_(arg), safe_(safe) { 51 : func_(func), arg_(arg), safe_(safe) {
54 DCHECK(func_); 52 DCHECK(func_);
55 } 53 }
54 ~TrapResultExprImpl() override {}
56 55
57 CodeGen::Node Compile(PolicyCompiler* pc) const override { 56 CodeGen::Node Compile(PolicyCompiler* pc) const override {
58 return pc->Trap(func_, arg_, safe_); 57 return pc->Trap(func_, arg_, safe_);
59 } 58 }
60 59
61 bool HasUnsafeTraps() const override { return safe_ == false; } 60 bool HasUnsafeTraps() const override { return safe_ == false; }
62 61
63 bool IsDeny() const override { return true; } 62 bool IsDeny() const override { return true; }
64 63
65 private: 64 private:
66 ~TrapResultExprImpl() override {}
67
68 TrapRegistry::TrapFnc func_; 65 TrapRegistry::TrapFnc func_;
69 const void* arg_; 66 const void* arg_;
70 bool safe_; 67 bool safe_;
71 68
72 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl); 69 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
73 }; 70 };
74 71
75 class IfThenResultExprImpl : public internal::ResultExprImpl { 72 class IfThenResultExprImpl : public internal::ResultExprImpl {
76 public: 73 public:
77 IfThenResultExprImpl(const BoolExpr& cond, 74 IfThenResultExprImpl(BoolExpr cond,
78 const ResultExpr& then_result, 75 ResultExpr then_result,
79 const ResultExpr& else_result) 76 ResultExpr else_result)
80 : cond_(cond), then_result_(then_result), else_result_(else_result) {} 77 : cond_(std::move(cond)),
78 then_result_(std::move(then_result)),
79 else_result_(std::move(else_result)) {}
80 ~IfThenResultExprImpl() override {}
81 81
82 CodeGen::Node Compile(PolicyCompiler* pc) const override { 82 CodeGen::Node Compile(PolicyCompiler* pc) const override {
83 // We compile the "then" and "else" expressions in separate statements so 83 // We compile the "then" and "else" expressions in separate statements so
84 // they have a defined sequencing. See https://crbug.com/529480. 84 // they have a defined sequencing. See https://crbug.com/529480.
85 CodeGen::Node then_node = then_result_->Compile(pc); 85 CodeGen::Node then_node = then_result_->Compile(pc);
86 CodeGen::Node else_node = else_result_->Compile(pc); 86 CodeGen::Node else_node = else_result_->Compile(pc);
87 return cond_->Compile(pc, then_node, else_node); 87 return cond_->Compile(pc, then_node, else_node);
88 } 88 }
89 89
90 bool HasUnsafeTraps() const override { 90 bool HasUnsafeTraps() const override {
91 return then_result_->HasUnsafeTraps() || else_result_->HasUnsafeTraps(); 91 return then_result_->HasUnsafeTraps() || else_result_->HasUnsafeTraps();
92 } 92 }
93 93
94 private: 94 private:
95 ~IfThenResultExprImpl() override {}
96
97 BoolExpr cond_; 95 BoolExpr cond_;
98 ResultExpr then_result_; 96 ResultExpr then_result_;
99 ResultExpr else_result_; 97 ResultExpr else_result_;
100 98
101 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl); 99 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
102 }; 100 };
103 101
104 class ConstBoolExprImpl : public internal::BoolExprImpl { 102 class ConstBoolExprImpl : public internal::BoolExprImpl {
105 public: 103 public:
106 ConstBoolExprImpl(bool value) : value_(value) {} 104 ConstBoolExprImpl(bool value) : value_(value) {}
105 ~ConstBoolExprImpl() override {}
107 106
108 CodeGen::Node Compile(PolicyCompiler* pc, 107 CodeGen::Node Compile(PolicyCompiler* pc,
109 CodeGen::Node then_node, 108 CodeGen::Node then_node,
110 CodeGen::Node else_node) const override { 109 CodeGen::Node else_node) const override {
111 return value_ ? then_node : else_node; 110 return value_ ? then_node : else_node;
112 } 111 }
113 112
114 private: 113 private:
115 ~ConstBoolExprImpl() override {}
116
117 bool value_; 114 bool value_;
118 115
119 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl); 116 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl);
120 }; 117 };
121 118
122 class MaskedEqualBoolExprImpl : public internal::BoolExprImpl { 119 class MaskedEqualBoolExprImpl : public internal::BoolExprImpl {
123 public: 120 public:
124 MaskedEqualBoolExprImpl(int argno, 121 MaskedEqualBoolExprImpl(int argno,
125 size_t width, 122 size_t width,
126 uint64_t mask, 123 uint64_t mask,
127 uint64_t value) 124 uint64_t value)
128 : argno_(argno), width_(width), mask_(mask), value_(value) {} 125 : argno_(argno), width_(width), mask_(mask), value_(value) {}
126 ~MaskedEqualBoolExprImpl() override {}
129 127
130 CodeGen::Node Compile(PolicyCompiler* pc, 128 CodeGen::Node Compile(PolicyCompiler* pc,
131 CodeGen::Node then_node, 129 CodeGen::Node then_node,
132 CodeGen::Node else_node) const override { 130 CodeGen::Node else_node) const override {
133 return pc->MaskedEqual(argno_, width_, mask_, value_, then_node, else_node); 131 return pc->MaskedEqual(argno_, width_, mask_, value_, then_node, else_node);
134 } 132 }
135 133
136 private: 134 private:
137 ~MaskedEqualBoolExprImpl() override {}
138
139 int argno_; 135 int argno_;
140 size_t width_; 136 size_t width_;
141 uint64_t mask_; 137 uint64_t mask_;
142 uint64_t value_; 138 uint64_t value_;
143 139
144 DISALLOW_COPY_AND_ASSIGN(MaskedEqualBoolExprImpl); 140 DISALLOW_COPY_AND_ASSIGN(MaskedEqualBoolExprImpl);
145 }; 141 };
146 142
147 class NegateBoolExprImpl : public internal::BoolExprImpl { 143 class NegateBoolExprImpl : public internal::BoolExprImpl {
148 public: 144 public:
149 explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {} 145 explicit NegateBoolExprImpl(BoolExpr cond) : cond_(std::move(cond)) {}
146 ~NegateBoolExprImpl() override {}
150 147
151 CodeGen::Node Compile(PolicyCompiler* pc, 148 CodeGen::Node Compile(PolicyCompiler* pc,
152 CodeGen::Node then_node, 149 CodeGen::Node then_node,
153 CodeGen::Node else_node) const override { 150 CodeGen::Node else_node) const override {
154 return cond_->Compile(pc, else_node, then_node); 151 return cond_->Compile(pc, else_node, then_node);
155 } 152 }
156 153
157 private: 154 private:
158 ~NegateBoolExprImpl() override {}
159
160 BoolExpr cond_; 155 BoolExpr cond_;
161 156
162 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl); 157 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
163 }; 158 };
164 159
165 class AndBoolExprImpl : public internal::BoolExprImpl { 160 class AndBoolExprImpl : public internal::BoolExprImpl {
166 public: 161 public:
167 AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs) 162 AndBoolExprImpl(BoolExpr lhs, BoolExpr rhs)
168 : lhs_(lhs), rhs_(rhs) {} 163 : lhs_(std::move(lhs)), rhs_(std::move(rhs)) {}
164 ~AndBoolExprImpl() override {}
169 165
170 CodeGen::Node Compile(PolicyCompiler* pc, 166 CodeGen::Node Compile(PolicyCompiler* pc,
171 CodeGen::Node then_node, 167 CodeGen::Node then_node,
172 CodeGen::Node else_node) const override { 168 CodeGen::Node else_node) const override {
173 return lhs_->Compile(pc, rhs_->Compile(pc, then_node, else_node), 169 return lhs_->Compile(pc, rhs_->Compile(pc, then_node, else_node),
174 else_node); 170 else_node);
175 } 171 }
176 172
177 private: 173 private:
178 ~AndBoolExprImpl() override {}
179
180 BoolExpr lhs_; 174 BoolExpr lhs_;
181 BoolExpr rhs_; 175 BoolExpr rhs_;
182 176
183 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl); 177 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
184 }; 178 };
185 179
186 class OrBoolExprImpl : public internal::BoolExprImpl { 180 class OrBoolExprImpl : public internal::BoolExprImpl {
187 public: 181 public:
188 OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs) 182 OrBoolExprImpl(BoolExpr lhs, BoolExpr rhs)
189 : lhs_(lhs), rhs_(rhs) {} 183 : lhs_(std::move(lhs)), rhs_(std::move(rhs)) {}
184 ~OrBoolExprImpl() override {}
190 185
191 CodeGen::Node Compile(PolicyCompiler* pc, 186 CodeGen::Node Compile(PolicyCompiler* pc,
192 CodeGen::Node then_node, 187 CodeGen::Node then_node,
193 CodeGen::Node else_node) const override { 188 CodeGen::Node else_node) const override {
194 return lhs_->Compile(pc, then_node, 189 return lhs_->Compile(pc, then_node,
195 rhs_->Compile(pc, then_node, else_node)); 190 rhs_->Compile(pc, then_node, else_node));
196 } 191 }
197 192
198 private: 193 private:
199 ~OrBoolExprImpl() override {}
200
201 BoolExpr lhs_; 194 BoolExpr lhs_;
202 BoolExpr rhs_; 195 BoolExpr rhs_;
203 196
204 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl); 197 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
205 }; 198 };
206 199
207 } // namespace 200 } // namespace
208 201
209 namespace internal { 202 namespace internal {
210 203
(...skipping 19 matching lines...) Expand all
230 CHECK(false) << "Unimplemented DefaultMask case"; 223 CHECK(false) << "Unimplemented DefaultMask case";
231 return 0; 224 return 0;
232 } 225 }
233 } 226 }
234 227
235 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) { 228 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
236 // If this is changed, update Arg<T>::EqualTo's static_cast rules 229 // If this is changed, update Arg<T>::EqualTo's static_cast rules
237 // accordingly. 230 // accordingly.
238 CHECK(size == 4 || size == 8); 231 CHECK(size == 4 || size == 8);
239 232
240 return BoolExpr(new const MaskedEqualBoolExprImpl(num, size, mask, val)); 233 return std::make_shared<MaskedEqualBoolExprImpl>(num, size, mask, val);
241 } 234 }
242 235
243 } // namespace internal 236 } // namespace internal
244 237
245 ResultExpr Allow() { 238 ResultExpr Allow() {
246 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_ALLOW)); 239 return std::make_shared<ReturnResultExprImpl>(SECCOMP_RET_ALLOW);
247 } 240 }
248 241
249 ResultExpr Error(int err) { 242 ResultExpr Error(int err) {
250 CHECK(err >= ErrorCode::ERR_MIN_ERRNO && err <= ErrorCode::ERR_MAX_ERRNO); 243 CHECK(err >= ErrorCode::ERR_MIN_ERRNO && err <= ErrorCode::ERR_MAX_ERRNO);
251 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_ERRNO + err)); 244 return std::make_shared<ReturnResultExprImpl>(SECCOMP_RET_ERRNO + err);
252 } 245 }
253 246
254 ResultExpr Kill() { 247 ResultExpr Kill() {
255 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_KILL)); 248 return std::make_shared<ReturnResultExprImpl>(SECCOMP_RET_KILL);
256 } 249 }
257 250
258 ResultExpr Trace(uint16_t aux) { 251 ResultExpr Trace(uint16_t aux) {
259 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_TRACE + aux)); 252 return std::make_shared<ReturnResultExprImpl>(SECCOMP_RET_TRACE + aux);
260 } 253 }
261 254
262 ResultExpr Trap(TrapRegistry::TrapFnc trap_func, const void* aux) { 255 ResultExpr Trap(TrapRegistry::TrapFnc trap_func, const void* aux) {
263 return ResultExpr( 256 return std::make_shared<TrapResultExprImpl>(trap_func, aux, true /* safe */);
264 new const TrapResultExprImpl(trap_func, aux, true /* safe */));
265 } 257 }
266 258
267 ResultExpr UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux) { 259 ResultExpr UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux) {
268 return ResultExpr( 260 return std::make_shared<TrapResultExprImpl>(trap_func, aux,
269 new const TrapResultExprImpl(trap_func, aux, false /* unsafe */)); 261 false /* unsafe */);
270 } 262 }
271 263
272 BoolExpr BoolConst(bool value) { 264 BoolExpr BoolConst(bool value) {
273 return BoolExpr(new const ConstBoolExprImpl(value)); 265 return std::make_shared<ConstBoolExprImpl>(value);
274 } 266 }
275 267
276 BoolExpr Not(const BoolExpr& cond) { 268 BoolExpr Not(BoolExpr cond) {
277 return BoolExpr(new const NegateBoolExprImpl(cond)); 269 return std::make_shared<NegateBoolExprImpl>(std::move(cond));
278 } 270 }
279 271
280 BoolExpr AllOf() { 272 BoolExpr AllOf() {
281 return BoolConst(true); 273 return BoolConst(true);
282 } 274 }
283 275
284 BoolExpr AllOf(const BoolExpr& lhs, const BoolExpr& rhs) { 276 BoolExpr AllOf(BoolExpr lhs, BoolExpr rhs) {
285 return BoolExpr(new const AndBoolExprImpl(lhs, rhs)); 277 return std::make_shared<AndBoolExprImpl>(std::move(lhs), std::move(rhs));
286 } 278 }
287 279
288 BoolExpr AnyOf() { 280 BoolExpr AnyOf() {
289 return BoolConst(false); 281 return BoolConst(false);
290 } 282 }
291 283
292 BoolExpr AnyOf(const BoolExpr& lhs, const BoolExpr& rhs) { 284 BoolExpr AnyOf(BoolExpr lhs, BoolExpr rhs) {
293 return BoolExpr(new const OrBoolExprImpl(lhs, rhs)); 285 return std::make_shared<OrBoolExprImpl>(std::move(lhs), std::move(rhs));
294 } 286 }
295 287
296 Elser If(const BoolExpr& cond, const ResultExpr& then_result) { 288 Elser If(BoolExpr cond, ResultExpr then_result) {
297 return Elser(nullptr).ElseIf(cond, then_result); 289 return Elser(nullptr).ElseIf(std::move(cond), std::move(then_result));
298 } 290 }
299 291
300 Elser::Elser(cons::List<Clause> clause_list) : clause_list_(clause_list) { 292 Elser::Elser(cons::List<Clause> clause_list) : clause_list_(clause_list) {
301 } 293 }
302 294
303 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) { 295 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
304 } 296 }
305 297
306 Elser::~Elser() { 298 Elser::~Elser() {
307 } 299 }
308 300
309 Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const { 301 Elser Elser::ElseIf(BoolExpr cond, ResultExpr then_result) const {
310 return Elser(Cons(std::make_pair(cond, then_result), clause_list_)); 302 return Elser(Cons(std::make_pair(std::move(cond), std::move(then_result)),
303 clause_list_));
311 } 304 }
312 305
313 ResultExpr Elser::Else(const ResultExpr& else_result) const { 306 ResultExpr Elser::Else(ResultExpr else_result) const {
314 // We finally have the default result expression for this 307 // We finally have the default result expression for this
315 // if/then/else sequence. Also, we've already accumulated all 308 // if/then/else sequence. Also, we've already accumulated all
316 // if/then pairs into a list of reverse order (i.e., lower priority 309 // if/then pairs into a list of reverse order (i.e., lower priority
317 // conditions are listed before higher priority ones). E.g., an 310 // conditions are listed before higher priority ones). E.g., an
318 // expression like 311 // expression like
319 // 312 //
320 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4) 313 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
321 // 314 //
322 // will have built up a list like 315 // will have built up a list like
323 // 316 //
324 // [(b3, e3), (b2, e2), (b1, e1)]. 317 // [(b3, e3), (b2, e2), (b1, e1)].
325 // 318 //
326 // Now that we have e4, we can walk the list and create a ResultExpr 319 // Now that we have e4, we can walk the list and create a ResultExpr
327 // tree like: 320 // tree like:
328 // 321 //
329 // expr = e4 322 // expr = e4
330 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4) 323 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
331 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4)) 324 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
332 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4))) 325 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
333 // 326 //
334 // and end up with an appropriately chained tree. 327 // and end up with an appropriately chained tree.
335 328
336 ResultExpr expr = else_result; 329 ResultExpr expr = std::move(else_result);
337 for (const Clause& clause : clause_list_) { 330 for (const Clause& clause : clause_list_) {
338 expr = ResultExpr( 331 expr = std::make_shared<IfThenResultExprImpl>(clause.first, clause.second,
339 new const IfThenResultExprImpl(clause.first, clause.second, expr)); 332 std::move(expr));
340 } 333 }
341 return expr; 334 return expr;
342 } 335 }
343 336
344 } // namespace bpf_dsl 337 } // namespace bpf_dsl
345 } // namespace sandbox 338 } // namespace sandbox
346 339
347 template class scoped_refptr<const sandbox::bpf_dsl::internal::BoolExprImpl>; 340 namespace std {
348 template class scoped_refptr<const sandbox::bpf_dsl::internal::ResultExprImpl>; 341 template class shared_ptr<const sandbox::bpf_dsl::internal::BoolExprImpl>;
342 template class shared_ptr<const sandbox::bpf_dsl::internal::ResultExprImpl>;
343 } // namespace std
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl.h ('k') | sandbox/linux/bpf_dsl/bpf_dsl_forward.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698