On Thu, 2007-03-22 at 20:56 -0400, James Morris wrote:
>On Thu, 22 Mar 2007, Joy Latten wrote:
>> > Perhaps a better semantic would be to fail the entire flush operation if 
>> > one of the security checks failed.  e.g. loop through for permissions 
>> > first, then if all ok, loop through for deletion.
>> > 
>> Ok, will code this up and test it if there are no objections.
>
>I'd suggest making the permission loop a noop if CONFIG_SECURITY=n, via a 
>static inline function.

Reworked patch with improved semantics as suggested.
I used CONFIG_SECURITY_NETWORK_XFRM instead
of CONFIG_SECURITY since this can be considered part of the
labeled networking semantics. Let me know if my assumption 
sounds incorrect.

Also, I have built and tested with and without CONFIG_SECURITY_NETWORK_XFRM.

Regards,
Joy

Signed-off-by: Joy Latten<[EMAIL PROTECTED]>


diff -urpN linux-2.6.20.orig/include/net/xfrm.h 
linux-2.6.20.patch/include/net/xfrm.h
--- linux-2.6.20.orig/include/net/xfrm.h        2007-03-23 11:01:48.000000000 
-0500
+++ linux-2.6.20.patch/include/net/xfrm.h       2007-03-25 21:36:05.000000000 
-0500
@@ -937,7 +937,7 @@ static inline int xfrm_state_sort(struct
 #endif
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
-extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
+extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
 extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
@@ -991,13 +991,13 @@ struct xfrm_policy *xfrm_policy_bysel_ct
                                          struct xfrm_sec_ctx *ctx, int delete,
                                          int *err);
 struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int 
*err);
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 u32 xfrm_get_acqseq(void);
 void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
                                  xfrm_address_t *daddr, xfrm_address_t *saddr,
                                  int create, unsigned short family);
-extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+extern int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy 
*pol);
 extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
                          struct flowi *fl, int family, int strict);
diff -urpN linux-2.6.20.orig/net/key/af_key.c 
linux-2.6.20.patch/net/key/af_key.c
--- linux-2.6.20.orig/net/key/af_key.c  2007-03-23 11:02:49.000000000 -0500
+++ linux-2.6.20.patch/net/key/af_key.c 2007-03-25 21:34:35.000000000 -0500
@@ -1645,6 +1645,7 @@ static int pfkey_flush(struct sock *sk, 
        unsigned proto;
        struct km_event c;
        struct xfrm_audit audit_info;
+       int err;
 
        proto = pfkey_satype2proto(hdr->sadb_msg_satype);
        if (proto == 0)
@@ -1652,7 +1653,9 @@ static int pfkey_flush(struct sock *sk, 
 
        audit_info.loginuid = audit_get_loginuid(current->audit_context);
        audit_info.secid = 0;
-       xfrm_state_flush(proto, &audit_info);
+       err = xfrm_state_flush(proto, &audit_info);
+       if (err)
+               return err;
        c.data.proto = proto;
        c.seq = hdr->sadb_msg_seq;
        c.pid = hdr->sadb_msg_pid;
@@ -2628,10 +2631,13 @@ static int pfkey_spdflush(struct sock *s
 {
        struct km_event c;
        struct xfrm_audit audit_info;
+       int err;
 
        audit_info.loginuid = audit_get_loginuid(current->audit_context);
        audit_info.secid = 0;
-       xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+       err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+       if (err)
+               return err;
        c.data.type = XFRM_POLICY_TYPE_MAIN;
        c.event = XFRM_MSG_FLUSHPOLICY;
        c.pid = hdr->sadb_msg_pid;
diff -urpN linux-2.6.20.orig/net/xfrm/xfrm_policy.c 
linux-2.6.20.patch/net/xfrm/xfrm_policy.c
--- linux-2.6.20.orig/net/xfrm/xfrm_policy.c    2007-03-23 11:02:46.000000000 
-0500
+++ linux-2.6.20.patch/net/xfrm/xfrm_policy.c   2007-03-25 21:32:51.000000000 
-0500
@@ -813,11 +813,65 @@ struct xfrm_policy *xfrm_policy_byid(u8 
 }
 EXPORT_SYMBOL(xfrm_policy_byid);
 
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
 {
-       int dir;
+       int dir, err = 0;
+
+       for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
+               struct xfrm_policy *pol;
+               struct hlist_node *entry;
+               int i;
+
+               hlist_for_each_entry(pol, entry,
+                                    &xfrm_policy_inexact[dir], bydst) {
+                       if (pol->type != type)
+                               continue;
+                       if ((err = security_xfrm_policy_delete(pol)) != 0) {
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSPD,
+                                              err ? 0 : 1, pol, NULL);
+                               return err;
+                       }
+                }
+               for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
+                       hlist_for_each_entry(pol, entry,
+                                            xfrm_policy_bydst[dir].table + i,
+                                            bydst) {
+                               if (pol->type != type)
+                                       continue;
+                               if ((err = security_xfrm_policy_delete(pol)) != 
0) {
+                                       xfrm_audit_log(audit_info->loginuid,
+                                                      audit_info->secid,
+                                                      AUDIT_MAC_IPSEC_DELSPD,
+                                                      err ? 0 : 1, pol, NULL);
+                                       return err;
+                               }
+                       }
+               }
+       }
+       return err;
+}
+#else
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+{
+       return 0;
+}
+#endif
+
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+{
+       int dir, err = 0;
 
        write_lock_bh(&xfrm_policy_lock);
+
+       err = xfrm_policy_flush_secctx_check(type, audit_info);
+       if (err)
+               goto out;
+
        for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
                struct xfrm_policy *pol;
                struct hlist_node *entry;
@@ -870,7 +924,9 @@ void xfrm_policy_flush(u8 type, struct x
                xfrm_policy_count[dir] -= killed;
        }
        atomic_inc(&flow_cache_genid);
+out:
        write_unlock_bh(&xfrm_policy_lock);
+       return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
 
@@ -2485,4 +2541,3 @@ restore_state:
 }
 EXPORT_SYMBOL(xfrm_migrate);
 #endif
-
diff -urpN linux-2.6.20.orig/net/xfrm/xfrm_state.c 
linux-2.6.20.patch/net/xfrm/xfrm_state.c
--- linux-2.6.20.orig/net/xfrm/xfrm_state.c     2007-03-23 11:02:46.000000000 
-0500
+++ linux-2.6.20.patch/net/xfrm/xfrm_state.c    2007-03-25 21:33:02.000000000 
-0500
@@ -388,12 +388,48 @@ int xfrm_state_delete(struct xfrm_state 
 }
 EXPORT_SYMBOL(xfrm_state_delete);
 
-void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) 
 {
-       int i;
-       int err = 0;
+       int i, err = 0;
+
+       for (i = 0; i <= xfrm_state_hmask; i++) {
+               struct hlist_node *entry;
+               struct xfrm_state *x;
+
+               hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+                       if (xfrm_id_proto_match(x->id.proto, proto) &&
+                          (err = security_xfrm_state_delete(x)) != 0) {
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSA, 
+                                               err ? 0 : 1, NULL, x);
+
+                               return err;
+                       }
+               }
+       }
+
+       return err;
+}
+#else
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+{
+       return 0;
+}
+#endif
+
+int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+{
+       int i, err = 0;
 
        spin_lock_bh(&xfrm_state_lock);
+       err = xfrm_state_flush_secctx_check(proto, audit_info);
+       if (err)
+               goto out;
+               
        for (i = 0; i <= xfrm_state_hmask; i++) {
                struct hlist_node *entry;
                struct xfrm_state *x;
@@ -416,8 +452,12 @@ restart:
                        }
                }
        }
+       err = 0;
+
+out:
        spin_unlock_bh(&xfrm_state_lock);
        wake_up(&km_waitq);
+       return err;
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
diff -urpN linux-2.6.20.orig/net/xfrm/xfrm_user.c 
linux-2.6.20.patch/net/xfrm/xfrm_user.c
--- linux-2.6.20.orig/net/xfrm/xfrm_user.c      2007-03-23 11:02:46.000000000 
-0500
+++ linux-2.6.20.patch/net/xfrm/xfrm_user.c     2007-03-25 21:33:52.000000000 
-0500
@@ -1312,10 +1312,13 @@ static int xfrm_flush_sa(struct sk_buff 
        struct km_event c;
        struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
        struct xfrm_audit audit_info;
+       int err;
 
        audit_info.loginuid = NETLINK_CB(skb).loginuid;
        audit_info.secid = NETLINK_CB(skb).sid;
-       xfrm_state_flush(p->proto, &audit_info);
+       err = xfrm_state_flush(p->proto, &audit_info);
+       if (err)
+               return err;
        c.data.proto = p->proto;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1476,7 +1479,9 @@ static int xfrm_flush_policy(struct sk_b
 
        audit_info.loginuid = NETLINK_CB(skb).loginuid;
        audit_info.secid = NETLINK_CB(skb).sid;
-       xfrm_policy_flush(type, &audit_info);
+       err = xfrm_policy_flush(type, &audit_info);
+       if (err)
+               return err;
        c.data.type = type;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
-
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