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

Reply via email to