aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/xfrm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/xfrm.c')
-rw-r--r--security/selinux/xfrm.c453
1 files changed, 202 insertions, 251 deletions
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index d03081886214..a91d205ec0c6 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -56,7 +56,7 @@
56atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0); 56atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
57 57
58/* 58/*
59 * Returns true if an LSM/SELinux context 59 * Returns true if the context is an LSM/SELinux context.
60 */ 60 */
61static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx) 61static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
62{ 62{
@@ -66,7 +66,7 @@ static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
66} 66}
67 67
68/* 68/*
69 * Returns true if the xfrm contains a security blob for SELinux 69 * Returns true if the xfrm contains a security blob for SELinux.
70 */ 70 */
71static inline int selinux_authorizable_xfrm(struct xfrm_state *x) 71static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
72{ 72{
@@ -74,48 +74,111 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
74} 74}
75 75
76/* 76/*
77 * LSM hook implementation that authorizes that a flow can use 77 * Allocates a xfrm_sec_state and populates it using the supplied security
78 * a xfrm policy rule. 78 * xfrm_user_sec_ctx context.
79 */ 79 */
80int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) 80static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
81 struct xfrm_user_sec_ctx *uctx)
81{ 82{
82 int rc; 83 int rc;
83 u32 sel_sid; 84 const struct task_security_struct *tsec = current_security();
85 struct xfrm_sec_ctx *ctx = NULL;
86 u32 str_len;
84 87
85 /* Context sid is either set to label or ANY_ASSOC */ 88 if (ctxp == NULL || uctx == NULL ||
86 if (ctx) { 89 uctx->ctx_doi != XFRM_SC_DOI_LSM ||
87 if (!selinux_authorizable_ctx(ctx)) 90 uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
88 return -EINVAL; 91 return -EINVAL;
89
90 sel_sid = ctx->ctx_sid;
91 } else
92 /*
93 * All flows should be treated as polmatch'ing an
94 * otherwise applicable "non-labeled" policy. This
95 * would prevent inadvertent "leaks".
96 */
97 return 0;
98 92
99 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, 93 str_len = uctx->ctx_len;
100 ASSOCIATION__POLMATCH, 94 if (str_len >= PAGE_SIZE)
101 NULL); 95 return -ENOMEM;
102 96
103 if (rc == -EACCES) 97 ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
104 return -ESRCH; 98 if (!ctx)
99 return -ENOMEM;
105 100
101 ctx->ctx_doi = XFRM_SC_DOI_LSM;
102 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
103 ctx->ctx_len = str_len;
104 memcpy(ctx->ctx_str, &uctx[1], str_len);
105 ctx->ctx_str[str_len] = '\0';
106 rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
107 if (rc)
108 goto err;
109
110 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
111 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
112 if (rc)
113 goto err;
114
115 *ctxp = ctx;
116 atomic_inc(&selinux_xfrm_refcount);
117 return 0;
118
119err:
120 kfree(ctx);
106 return rc; 121 return rc;
107} 122}
108 123
109/* 124/*
125 * Free the xfrm_sec_ctx structure.
126 */
127static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
128{
129 if (!ctx)
130 return;
131
132 atomic_dec(&selinux_xfrm_refcount);
133 kfree(ctx);
134}
135
136/*
137 * Authorize the deletion of a labeled SA or policy rule.
138 */
139static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
140{
141 const struct task_security_struct *tsec = current_security();
142
143 if (!ctx)
144 return 0;
145
146 return avc_has_perm(tsec->sid, ctx->ctx_sid,
147 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
148 NULL);
149}
150
151/*
152 * LSM hook implementation that authorizes that a flow can use a xfrm policy
153 * rule.
154 */
155int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
156{
157 int rc;
158
159 /* All flows should be treated as polmatch'ing an otherwise applicable
160 * "non-labeled" policy. This would prevent inadvertent "leaks". */
161 if (!ctx)
162 return 0;
163
164 /* Context sid is either set to label or ANY_ASSOC */
165 if (!selinux_authorizable_ctx(ctx))
166 return -EINVAL;
167
168 rc = avc_has_perm(fl_secid, ctx->ctx_sid,
169 SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
170 return (rc == -EACCES ? -ESRCH : rc);
171}
172
173/*
110 * LSM hook implementation that authorizes that a state matches 174 * LSM hook implementation that authorizes that a state matches
111 * the given policy, flow combo. 175 * the given policy, flow combo.
112 */ 176 */
113 177int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
114int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, 178 struct xfrm_policy *xp,
115 const struct flowi *fl) 179 const struct flowi *fl)
116{ 180{
117 u32 state_sid; 181 u32 state_sid;
118 int rc;
119 182
120 if (!xp->security) 183 if (!xp->security)
121 if (x->security) 184 if (x->security)
@@ -138,187 +201,80 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
138 if (fl->flowi_secid != state_sid) 201 if (fl->flowi_secid != state_sid)
139 return 0; 202 return 0;
140 203
141 rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION, 204 /* We don't need a separate SA Vs. policy polmatch check since the SA
142 ASSOCIATION__SENDTO, 205 * is now of the same label as the flow and a flow Vs. policy polmatch
143 NULL)? 0:1; 206 * check had already happened in selinux_xfrm_policy_lookup() above. */
144 207 return (avc_has_perm(fl->flowi_secid, state_sid,
145 /* 208 SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
146 * We don't need a separate SA Vs. policy polmatch check 209 NULL) ? 0 : 1);
147 * since the SA is now of the same label as the flow and
148 * a flow Vs. policy polmatch check had already happened
149 * in selinux_xfrm_policy_lookup() above.
150 */
151
152 return rc;
153} 210}
154 211
155/* 212/*
156 * LSM hook implementation that checks and/or returns the xfrm sid for the 213 * LSM hook implementation that checks and/or returns the xfrm sid for the
157 * incoming packet. 214 * incoming packet.
158 */ 215 */
159
160int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 216int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
161{ 217{
218 u32 sid_session = SECSID_NULL;
162 struct sec_path *sp; 219 struct sec_path *sp;
163 220
164 *sid = SECSID_NULL;
165
166 if (skb == NULL) 221 if (skb == NULL)
167 return 0; 222 goto out;
168 223
169 sp = skb->sp; 224 sp = skb->sp;
170 if (sp) { 225 if (sp) {
171 int i, sid_set = 0; 226 int i;
172 227
173 for (i = sp->len-1; i >= 0; i--) { 228 for (i = sp->len - 1; i >= 0; i--) {
174 struct xfrm_state *x = sp->xvec[i]; 229 struct xfrm_state *x = sp->xvec[i];
175 if (selinux_authorizable_xfrm(x)) { 230 if (selinux_authorizable_xfrm(x)) {
176 struct xfrm_sec_ctx *ctx = x->security; 231 struct xfrm_sec_ctx *ctx = x->security;
177 232
178 if (!sid_set) { 233 if (sid_session == SECSID_NULL) {
179 *sid = ctx->ctx_sid; 234 sid_session = ctx->ctx_sid;
180 sid_set = 1;
181
182 if (!ckall) 235 if (!ckall)
183 break; 236 goto out;
184 } else if (*sid != ctx->ctx_sid) 237 } else if (sid_session != ctx->ctx_sid) {
238 *sid = SECSID_NULL;
185 return -EINVAL; 239 return -EINVAL;
240 }
186 } 241 }
187 } 242 }
188 } 243 }
189 244
190 return 0;
191}
192
193/*
194 * Security blob allocation for xfrm_policy and xfrm_state
195 * CTX does not have a meaningful value on input
196 */
197static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
198 struct xfrm_user_sec_ctx *uctx, u32 sid)
199{
200 int rc = 0;
201 const struct task_security_struct *tsec = current_security();
202 struct xfrm_sec_ctx *ctx = NULL;
203 char *ctx_str = NULL;
204 u32 str_len;
205
206 BUG_ON(uctx && sid);
207
208 if (!uctx)
209 goto not_from_user;
210
211 if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
212 return -EINVAL;
213
214 str_len = uctx->ctx_len;
215 if (str_len >= PAGE_SIZE)
216 return -ENOMEM;
217
218 *ctxp = ctx = kmalloc(sizeof(*ctx) +
219 str_len + 1,
220 GFP_KERNEL);
221
222 if (!ctx)
223 return -ENOMEM;
224
225 ctx->ctx_doi = uctx->ctx_doi;
226 ctx->ctx_len = str_len;
227 ctx->ctx_alg = uctx->ctx_alg;
228
229 memcpy(ctx->ctx_str,
230 uctx+1,
231 str_len);
232 ctx->ctx_str[str_len] = 0;
233 rc = security_context_to_sid(ctx->ctx_str,
234 str_len,
235 &ctx->ctx_sid);
236
237 if (rc)
238 goto out;
239
240 /*
241 * Does the subject have permission to set security context?
242 */
243 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
244 SECCLASS_ASSOCIATION,
245 ASSOCIATION__SETCONTEXT, NULL);
246 if (rc)
247 goto out;
248
249 return rc;
250
251not_from_user:
252 rc = security_sid_to_context(sid, &ctx_str, &str_len);
253 if (rc)
254 goto out;
255
256 *ctxp = ctx = kmalloc(sizeof(*ctx) +
257 str_len,
258 GFP_ATOMIC);
259
260 if (!ctx) {
261 rc = -ENOMEM;
262 goto out;
263 }
264
265 ctx->ctx_doi = XFRM_SC_DOI_LSM;
266 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
267 ctx->ctx_sid = sid;
268 ctx->ctx_len = str_len;
269 memcpy(ctx->ctx_str,
270 ctx_str,
271 str_len);
272
273 goto out2;
274
275out: 245out:
276 *ctxp = NULL; 246 *sid = sid_session;
277 kfree(ctx); 247 return 0;
278out2:
279 kfree(ctx_str);
280 return rc;
281} 248}
282 249
283/* 250/*
284 * LSM hook implementation that allocs and transfers uctx spec to 251 * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
285 * xfrm_policy.
286 */ 252 */
287int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, 253int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
288 struct xfrm_user_sec_ctx *uctx) 254 struct xfrm_user_sec_ctx *uctx)
289{ 255{
290 int err; 256 return selinux_xfrm_alloc_user(ctxp, uctx);
291
292 BUG_ON(!uctx);
293
294 err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
295 if (err == 0)
296 atomic_inc(&selinux_xfrm_refcount);
297
298 return err;
299} 257}
300 258
301
302/* 259/*
303 * LSM hook implementation that copies security data structure from old to 260 * LSM hook implementation that copies security data structure from old to new
304 * new for policy cloning. 261 * for policy cloning.
305 */ 262 */
306int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, 263int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
307 struct xfrm_sec_ctx **new_ctxp) 264 struct xfrm_sec_ctx **new_ctxp)
308{ 265{
309 struct xfrm_sec_ctx *new_ctx; 266 struct xfrm_sec_ctx *new_ctx;
310 267
311 if (old_ctx) { 268 if (!old_ctx)
312 new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, 269 return 0;
313 GFP_ATOMIC); 270
314 if (!new_ctx) 271 new_ctx = kmemdup(old_ctx, sizeof(*old_ctx) + old_ctx->ctx_len,
315 return -ENOMEM; 272 GFP_ATOMIC);
273 if (!new_ctx)
274 return -ENOMEM;
275 atomic_inc(&selinux_xfrm_refcount);
276 *new_ctxp = new_ctx;
316 277
317 memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
318 memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
319 atomic_inc(&selinux_xfrm_refcount);
320 *new_ctxp = new_ctx;
321 }
322 return 0; 278 return 0;
323} 279}
324 280
@@ -327,8 +283,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
327 */ 283 */
328void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx) 284void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
329{ 285{
330 atomic_dec(&selinux_xfrm_refcount); 286 selinux_xfrm_free(ctx);
331 kfree(ctx);
332} 287}
333 288
334/* 289/*
@@ -336,31 +291,55 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
336 */ 291 */
337int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) 292int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
338{ 293{
339 const struct task_security_struct *tsec = current_security(); 294 return selinux_xfrm_delete(ctx);
340 295}
341 if (!ctx)
342 return 0;
343 296
344 return avc_has_perm(tsec->sid, ctx->ctx_sid, 297/*
345 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, 298 * LSM hook implementation that allocates a xfrm_sec_state, populates it using
346 NULL); 299 * the supplied security context, and assigns it to the xfrm_state.
300 */
301int selinux_xfrm_state_alloc(struct xfrm_state *x,
302 struct xfrm_user_sec_ctx *uctx)
303{
304 return selinux_xfrm_alloc_user(&x->security, uctx);
347} 305}
348 306
349/* 307/*
350 * LSM hook implementation that allocs and transfers sec_ctx spec to 308 * LSM hook implementation that allocates a xfrm_sec_state and populates based
351 * xfrm_state. 309 * on a secid.
352 */ 310 */
353int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, 311int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
354 u32 secid) 312 struct xfrm_sec_ctx *polsec, u32 secid)
355{ 313{
356 int err; 314 int rc;
315 struct xfrm_sec_ctx *ctx;
316 char *ctx_str = NULL;
317 int str_len;
318
319 if (!polsec)
320 return 0;
357 321
358 BUG_ON(!x); 322 if (secid == 0)
323 return -EINVAL;
359 324
360 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); 325 rc = security_sid_to_context(secid, &ctx_str, &str_len);
361 if (err == 0) 326 if (rc)
362 atomic_inc(&selinux_xfrm_refcount); 327 return rc;
363 return err; 328
329 ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
330 if (!ctx)
331 return -ENOMEM;
332
333 ctx->ctx_doi = XFRM_SC_DOI_LSM;
334 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
335 ctx->ctx_sid = secid;
336 ctx->ctx_len = str_len;
337 memcpy(ctx->ctx_str, ctx_str, str_len);
338 kfree(ctx_str);
339
340 x->security = ctx;
341 atomic_inc(&selinux_xfrm_refcount);
342 return 0;
364} 343}
365 344
366/* 345/*
@@ -368,24 +347,15 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
368 */ 347 */
369void selinux_xfrm_state_free(struct xfrm_state *x) 348void selinux_xfrm_state_free(struct xfrm_state *x)
370{ 349{
371 atomic_dec(&selinux_xfrm_refcount); 350 selinux_xfrm_free(x->security);
372 kfree(x->security);
373} 351}
374 352
375 /* 353/*
376 * LSM hook implementation that authorizes deletion of labeled SAs. 354 * LSM hook implementation that authorizes deletion of labeled SAs.
377 */ 355 */
378int selinux_xfrm_state_delete(struct xfrm_state *x) 356int selinux_xfrm_state_delete(struct xfrm_state *x)
379{ 357{
380 const struct task_security_struct *tsec = current_security(); 358 return selinux_xfrm_delete(x->security);
381 struct xfrm_sec_ctx *ctx = x->security;
382
383 if (!ctx)
384 return 0;
385
386 return avc_has_perm(tsec->sid, ctx->ctx_sid,
387 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
388 NULL);
389} 359}
390 360
391/* 361/*
@@ -395,14 +365,12 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
395 * we need to check for unlabelled access since this may not have 365 * we need to check for unlabelled access since this may not have
396 * gone thru the IPSec process. 366 * gone thru the IPSec process.
397 */ 367 */
398int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 368int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
399 struct common_audit_data *ad) 369 struct common_audit_data *ad)
400{ 370{
401 int i, rc = 0; 371 int i;
402 struct sec_path *sp; 372 struct sec_path *sp = skb->sp;
403 u32 sel_sid = SECINITSID_UNLABELED; 373 u32 peer_sid = SECINITSID_UNLABELED;
404
405 sp = skb->sp;
406 374
407 if (sp) { 375 if (sp) {
408 for (i = 0; i < sp->len; i++) { 376 for (i = 0; i < sp->len; i++) {
@@ -410,23 +378,17 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
410 378
411 if (x && selinux_authorizable_xfrm(x)) { 379 if (x && selinux_authorizable_xfrm(x)) {
412 struct xfrm_sec_ctx *ctx = x->security; 380 struct xfrm_sec_ctx *ctx = x->security;
413 sel_sid = ctx->ctx_sid; 381 peer_sid = ctx->ctx_sid;
414 break; 382 break;
415 } 383 }
416 } 384 }
417 } 385 }
418 386
419 /* 387 /* This check even when there's no association involved is intended,
420 * This check even when there's no association involved is 388 * according to Trent Jaeger, to make sure a process can't engage in
421 * intended, according to Trent Jaeger, to make sure a 389 * non-IPsec communication unless explicitly allowed by policy. */
422 * process can't engage in non-ipsec communication unless 390 return avc_has_perm(sk_sid, peer_sid,
423 * explicitly allowed by policy. 391 SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
424 */
425
426 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
427 ASSOCIATION__RECVFROM, ad);
428
429 return rc;
430} 392}
431 393
432/* 394/*
@@ -436,49 +398,38 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
436 * If we do have a authorizable security association, then it has already been 398 * If we do have a authorizable security association, then it has already been
437 * checked in the selinux_xfrm_state_pol_flow_match hook above. 399 * checked in the selinux_xfrm_state_pol_flow_match hook above.
438 */ 400 */
439int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 401int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
440 struct common_audit_data *ad, u8 proto) 402 struct common_audit_data *ad, u8 proto)
441{ 403{
442 struct dst_entry *dst; 404 struct dst_entry *dst;
443 int rc = 0;
444
445 dst = skb_dst(skb);
446
447 if (dst) {
448 struct dst_entry *dst_test;
449
450 for (dst_test = dst; dst_test != NULL;
451 dst_test = dst_test->child) {
452 struct xfrm_state *x = dst_test->xfrm;
453
454 if (x && selinux_authorizable_xfrm(x))
455 goto out;
456 }
457 }
458 405
459 switch (proto) { 406 switch (proto) {
460 case IPPROTO_AH: 407 case IPPROTO_AH:
461 case IPPROTO_ESP: 408 case IPPROTO_ESP:
462 case IPPROTO_COMP: 409 case IPPROTO_COMP:
463 /* 410 /* We should have already seen this packet once before it
464 * We should have already seen this packet once before 411 * underwent xfrm(s). No need to subject it to the unlabeled
465 * it underwent xfrm(s). No need to subject it to the 412 * check. */
466 * unlabeled check. 413 return 0;
467 */
468 goto out;
469 default: 414 default:
470 break; 415 break;
471 } 416 }
472 417
473 /* 418 dst = skb_dst(skb);
474 * This check even when there's no association involved is 419 if (dst) {
475 * intended, according to Trent Jaeger, to make sure a 420 struct dst_entry *iter;
476 * process can't engage in non-ipsec communication unless
477 * explicitly allowed by policy.
478 */
479 421
480 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 422 for (iter = dst; iter != NULL; iter = iter->child) {
481 ASSOCIATION__SENDTO, ad); 423 struct xfrm_state *x = iter->xfrm;
482out: 424
483 return rc; 425 if (x && selinux_authorizable_xfrm(x))
426 return 0;
427 }
428 }
429
430 /* This check even when there's no association involved is intended,
431 * according to Trent Jaeger, to make sure a process can't engage in
432 * non-IPsec communication unless explicitly allowed by policy. */
433 return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
434 SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
484} 435}