Hi Trent: Thanks for your good work. Here are the comments for your first patch. I won't comment on the second patch since others have already looked through it and I don't know enough about SELINUX to be of much help.
On Thu, Aug 11, 2005 at 02:21:15PM -0400, jaegert wrote: > > +static inline struct xfrm_sec_ctx *xfrm_policy_security(struct xfrm_policy > *xp) > +{ > + return xp->security; > +} > + > +static inline struct xfrm_sec_ctx *xfrm_state_security(struct xfrm_state *x) > +{ > + return x->security; > +} Any reason why we can't use xp->security and x->security directly? > @@ -2027,6 +2150,21 @@ static int pfkey_spdadd(struct sock *sk, > if (xp->selector.dport) > xp->selector.dport_mask = ~0; > > + sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; > + if (sec_ctx != NULL) { > + struct xfrm_user_sec_ctx *uctx = > pfkey_sadb2xfrm_user_ctx(sec_ctx); > + > + if (!uctx) > + goto out; Please set err. > @@ -2703,10 +2858,25 @@ static struct xfrm_policy *pfkey_compile > (*dir = parse_ipsecrequests(xp, pol)) < 0) > goto out; > > + /* security context too */ > + if (len >= (pol->sadb_x_policy_len*8 + > + sizeof(struct sadb_x_sec_ctx))) { > + char *p = (char *) pol; > + > + p += pol->sadb_x_policy_len*8; > + if (verify_sec_ctx_len(p)) > + goto out; I think this might be insufficient. When verify_sec_ctx_len is called by parse_exthdr the caller has already verified that sadb_x_sec_len is within the packet. So you should explicitly check sadb_x_sec_len here. > + sec_ctx = (struct sadb_x_sec_ctx *) p; BTW, please remove all the spaces between cast operators and their operand. > + if (security_xfrm_policy_alloc( > + xp, (struct xfrm_user_sec_ctx *)sec_ctx)) You need to do the sadb->xfrm conversion here just like spddelete. You should also stored the returned error value in *dir. > diff -puN net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks net/xfrm/xfrm_policy.c > @@ -491,23 +494,25 @@ EXPORT_SYMBOL(xfrm_policy_walk); > > /* Find policy to apply to this flow. */ > > -static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, > +static void xfrm_policy_lookup(struct flowi *fl, struct sock *sk, u16 > family, u8 dir, > void **objp, atomic_t **obj_refp) > { > struct xfrm_policy *pol; > > read_lock_bh(&xfrm_policy_lock); > for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) { > - struct xfrm_selector *sel = &pol->selector; > int match; > > if (pol->family != family) > continue; > > - match = xfrm_selector_match(sel, fl, family); > + match = xfrm_selector_match(&pol->selector, fl, family); > + This looks like a left-over from previous changes. Please preserve the existing code. } > @@ -383,6 +386,13 @@ xfrm_state_find(xfrm_address_t *daddr, x > xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); > > if (km_query(x, tmpl, pol) == 0) { > + if (!xfrm_sec_ctx_match(xfrm_policy_security(pol), > xfrm_state_security(x))) { > + x->km.state = XFRM_STATE_DEAD; ??? At this point we've only sent a message to user-space so x is not going to have any security context. > diff -puN net/xfrm/xfrm_user.c~lsm-xfrm-nethooks net/xfrm/xfrm_user.c > @@ -88,6 +88,31 @@ static int verify_encap_tmpl(struct rtat > return 0; > } > > + > +static inline int verify_sec_ctx_len(struct rtattr **xfrma) > +{ > + struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1]; > + struct xfrm_user_sec_ctx *uctx; > + int len = 0; > + > + if (!rt) > + return 0; > + > + uctx = RTA_DATA(rt); > + > + if (uctx->ctx_len > PAGE_SIZE) > + return -EINVAL; You need to verify that rta_len isn't less than sizeof(*uctx) first. > + > + len += sizeof(struct xfrm_user_sec_ctx); > + len += uctx->ctx_len; > + > + if (uctx->len != len) > + return -EINVAL; error: structure has no member named `len' :) > @@ -390,6 +471,21 @@ static int dump_one_state(struct xfrm_st > if (x->encap) > RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); > > + if ((xfrm_ctx = xfrm_state_security(x))) { > + int ctx_size = sizeof(struct xfrm_user_sec_ctx) + > + xfrm_ctx->ctx_len; > + struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL); > + int err; > + > + if (!uctx) > + goto rtattr_failure; I feel uneasy about this. Netlink dumping isn't used to these sort of error conditions. Perhaps you could just dump it straight from x->security and avoid the kmalloc altogether. > +static int copy_sec_ctx(struct xfrm_policy *pol, struct xfrm_user_sec_ctx > *uctx) > +{ > + int err = 0; > + > + if (uctx) { > + err = security_xfrm_policy_alloc(pol, uctx); > + } > + > + return err; > +} Do we really need this function? > +static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct rtattr > **xfrma) > +{ > + struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1]; > + struct xfrm_user_sec_ctx *uctx; > + > + if (!rt) > + return 0; > + > + uctx = RTA_DATA(rt); > + return copy_sec_ctx(pol, uctx); > +} Certainly not here since uctx can't be NULL. As there is only one other user you might as well get rid of it. > +static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb, > int src) src is unused. > +{ > + int err = 0; > + struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp); > + > + if (xfrm_ctx) { > + int ctx_size = sizeof(struct xfrm_user_sec_ctx) + > + xfrm_ctx->ctx_len; > + struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_ATOMIC); > + > + if (!uctx) > + return -ENOMEM; > + > + err = dump_one_sec_ctx(xfrm_ctx, uctx, skb, > + ctx_size); Same comment as dump_one_state. It'd be better to just dump the context directly onto the skb and avoid the kmalloc. > @@ -852,8 +1000,21 @@ static int xfrm_get_policy(struct sk_buf > > if (p->index) > xp = xfrm_policy_byid(p->dir, p->index, delete); > - else > - xp = xfrm_policy_bysel(p->dir, &p->sel, delete); > + else { > + struct rtattr **rtattrs = (struct rtattr **) xfrma; > + struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; > + struct xfrm_policy tmp; > + > + memset(&tmp, 0, sizeof(struct xfrm_policy)); > + if (rt) { > + struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); > + > + if ((err = security_xfrm_policy_alloc(&tmp, uctx))) > + return err; You need to verify the validity of uctx. > @@ -1346,9 +1511,26 @@ static struct xfrm_policy *xfrm_compile_ > verify_newpolicy_info(p)) > return NULL; > > + if (len > (sizeof(*p) + (XFRM_MAX_DEPTH * > + sizeof(struct xfrm_user_tmpl)))) { Sorry, this isn't going to fly. This stops us from ever increasing XFRM_MAX_DEPTH. You'll need to think of some other way to do this. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html