From f8cd54884e675dfaf0c86cc7c088adb6ca9d7638 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:15:11 -0800 Subject: [IPSEC]: Sync series - core changes This patch provides the core functionality needed for sync events for ipsec. Derived work of Krisztian KOVACS Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7de17559249a..6f643e58e044 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -28,7 +28,7 @@ #include #include -static struct sock *xfrm_nl; +struct sock *xfrm_nl; static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) { @@ -1618,3 +1618,5 @@ module_init(xfrm_user_init); module_exit(xfrm_user_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); +EXPORT_SYMBOL(xfrm_nl); + -- cgit v1.2.3 From d51d081d65048a7a6f9956a7809c3bb504f3b95d Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:16:12 -0800 Subject: [IPSEC]: Sync series - user Add xfrm as the user of the core changes Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/key/af_key.c | 2 + net/xfrm/xfrm_user.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 230 insertions(+), 10 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/key/af_key.c b/net/key/af_key.c index b2d4d1dd2116..520fe70d0993 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2651,6 +2651,8 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) return key_notify_sa(x, c); case XFRM_MSG_FLUSHSA: return key_notify_sa_flush(c); + case XFRM_MSG_NEWAE: /* not yet supported */ + break; default: printk("pfkey: Unknown SA event %d\n", c->event); break; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6f643e58e044..e230ba5328d3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -276,6 +276,56 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * x->props.flags = p->flags; } +/* + * someday when pfkey also has support, we could have the code + * somehow made shareable and move it to xfrm_state.c - JHS + * +*/ +static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma) +{ + int err = - EINVAL; + struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1]; + struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1]; + struct rtattr *et = xfrma[XFRMA_ETIMER_THRESH-1]; + struct rtattr *rt = xfrma[XFRMA_REPLAY_THRESH-1]; + + if (rp) { + struct xfrm_replay_state *replay; + if (RTA_PAYLOAD(rp) < sizeof(*replay)) + goto error; + replay = RTA_DATA(rp); + memcpy(&x->replay, replay, sizeof(*replay)); + memcpy(&x->preplay, replay, sizeof(*replay)); + } + + if (lt) { + struct xfrm_lifetime_cur *ltime; + if (RTA_PAYLOAD(lt) < sizeof(*ltime)) + goto error; + ltime = RTA_DATA(lt); + x->curlft.bytes = ltime->bytes; + x->curlft.packets = ltime->packets; + x->curlft.add_time = ltime->add_time; + x->curlft.use_time = ltime->use_time; + } + + if (et) { + if (RTA_PAYLOAD(et) < sizeof(u32)) + goto error; + x->replay_maxage = *(u32*)RTA_DATA(et); + } + + if (rt) { + if (RTA_PAYLOAD(rt) < sizeof(u32)) + goto error; + x->replay_maxdiff = *(u32*)RTA_DATA(rt); + } + + return 0; +error: + return err; +} + static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, struct rtattr **xfrma, int *errp) @@ -311,6 +361,18 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, goto error; x->km.seq = p->seq; + x->replay_maxdiff = sysctl_xfrm_aevent_rseqth; + /* sysctl_xfrm_aevent_etime is in 100ms units */ + x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M; + x->preplay.bitmap = 0; + x->preplay.seq = x->replay.seq+x->replay_maxdiff; + x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; + + /* override default values from above */ + + err = xfrm_update_ae_params(x, (struct rtattr **)xfrma); + if (err < 0) + goto error; return x; @@ -1025,6 +1087,139 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma return 0; } + +static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) +{ + struct xfrm_aevent_id *id; + struct nlmsghdr *nlh; + struct xfrm_lifetime_cur ltime; + unsigned char *b = skb->tail; + + nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id)); + id = NLMSG_DATA(nlh); + nlh->nlmsg_flags = 0; + + id->sa_id.daddr = x->id.daddr; + id->sa_id.spi = x->id.spi; + id->sa_id.family = x->props.family; + id->sa_id.proto = x->id.proto; + id->flags = c->data.aevent; + + RTA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); + + ltime.bytes = x->curlft.bytes; + ltime.packets = x->curlft.packets; + ltime.add_time = x->curlft.add_time; + ltime.use_time = x->curlft.use_time; + + RTA_PUT(skb, XFRMA_LTIME_VAL, sizeof(struct xfrm_lifetime_cur), <ime); + + if (id->flags&XFRM_AE_RTHR) { + RTA_PUT(skb,XFRMA_REPLAY_THRESH,sizeof(u32),&x->replay_maxdiff); + } + + if (id->flags&XFRM_AE_ETHR) { + u32 etimer = x->replay_maxage*10/HZ; + RTA_PUT(skb,XFRMA_ETIMER_THRESH,sizeof(u32),&etimer); + } + + nlh->nlmsg_len = skb->tail - b; + return skb->len; + +rtattr_failure: +nlmsg_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_state *x; + struct sk_buff *r_skb; + int err; + struct km_event c; + struct xfrm_aevent_id *p = NLMSG_DATA(nlh); + int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); + struct xfrm_usersa_id *id = &p->sa_id; + + len += RTA_SPACE(sizeof(struct xfrm_replay_state)); + len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur)); + + if (p->flags&XFRM_AE_RTHR) + len+=RTA_SPACE(sizeof(u32)); + + if (p->flags&XFRM_AE_ETHR) + len+=RTA_SPACE(sizeof(u32)); + + r_skb = alloc_skb(len, GFP_ATOMIC); + if (r_skb == NULL) + return -ENOMEM; + + x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family); + if (x == NULL) { + kfree(r_skb); + return -ESRCH; + } + + /* + * XXX: is this lock really needed - none of the other + * gets lock (the concern is things getting updated + * while we are still reading) - jhs + */ + spin_lock_bh(&x->lock); + c.data.aevent = p->flags; + c.seq = nlh->nlmsg_seq; + c.pid = nlh->nlmsg_pid; + + if (build_aevent(r_skb, x, &c) < 0) + BUG(); + err = netlink_unicast(xfrm_nl, r_skb, + NETLINK_CB(skb).pid, MSG_DONTWAIT); + spin_unlock_bh(&x->lock); + xfrm_state_put(x); + return err; +} + +static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_state *x; + struct km_event c; + int err = - EINVAL; + struct xfrm_aevent_id *p = NLMSG_DATA(nlh); + struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1]; + struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1]; + + if (!lt && !rp) + return err; + + /* pedantic mode - thou shalt sayeth replaceth */ + if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) + return err; + + x = xfrm_state_lookup(&p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); + if (x == NULL) + return -ESRCH; + + if (x->km.state != XFRM_STATE_VALID) + goto out; + + spin_lock_bh(&x->lock); + err = xfrm_update_ae_params(x,(struct rtattr **)xfrma); + spin_unlock_bh(&x->lock); + if (err < 0) + goto out; + + c.event = nlh->nlmsg_type; + c.seq = nlh->nlmsg_seq; + c.pid = nlh->nlmsg_pid; + c.data.aevent = XFRM_AE_CU; + km_state_notify(x, &c); + err = 0; +out: + xfrm_state_put(x); + return err; +} + static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct km_event c; @@ -1037,6 +1232,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } + #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { @@ -1047,13 +1243,12 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), - [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), - [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), - [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), + [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), + [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), }; #undef XMSGSIZE @@ -1075,6 +1270,8 @@ static struct xfrm_link { [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, + [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, + [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, }; static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) @@ -1163,19 +1360,19 @@ static void xfrm_netlink_rcv(struct sock *sk, int len) } while (qlen); } -static int build_expire(struct sk_buff *skb, struct xfrm_state *x, int hard) +static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) { struct xfrm_user_expire *ue; struct nlmsghdr *nlh; unsigned char *b = skb->tail; - nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_EXPIRE, + nlh = NLMSG_PUT(skb, c->pid, 0, XFRM_MSG_EXPIRE, sizeof(*ue)); ue = NLMSG_DATA(nlh); nlh->nlmsg_flags = 0; copy_to_user_state(x, &ue->state); - ue->hard = (hard != 0) ? 1 : 0; + ue->hard = (c->data.hard != 0) ? 1 : 0; nlh->nlmsg_len = skb->tail - b; return skb->len; @@ -1194,13 +1391,31 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) if (skb == NULL) return -ENOMEM; - if (build_expire(skb, x, c->data.hard) < 0) + if (build_expire(skb, x, c) < 0) BUG(); NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); } +static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) +{ + struct sk_buff *skb; + int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); + + len += RTA_SPACE(sizeof(struct xfrm_replay_state)); + len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur)); + skb = alloc_skb(len, GFP_ATOMIC); + if (skb == NULL) + return -ENOMEM; + + if (build_aevent(skb, x, c) < 0) + BUG(); + + NETLINK_CB(skb).dst_group = XFRMNLGRP_AEVENTS; + return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); +} + static int xfrm_notify_sa_flush(struct km_event *c) { struct xfrm_usersa_flush *p; @@ -1313,6 +1528,8 @@ static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c) switch (c->event) { case XFRM_MSG_EXPIRE: return xfrm_exp_state_notify(x, c); + case XFRM_MSG_NEWAE: + return xfrm_aevent_state_notify(x, c); case XFRM_MSG_DELSA: case XFRM_MSG_UPDSA: case XFRM_MSG_NEWSA: @@ -1443,13 +1660,14 @@ static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt, } static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, - int dir, int hard) + int dir, struct km_event *c) { struct xfrm_user_polexpire *upe; struct nlmsghdr *nlh; + int hard = c->data.hard; unsigned char *b = skb->tail; - nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe)); + nlh = NLMSG_PUT(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe)); upe = NLMSG_DATA(nlh); nlh->nlmsg_flags = 0; @@ -1480,7 +1698,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve if (skb == NULL) return -ENOMEM; - if (build_polexpire(skb, xp, dir, c->data.hard) < 0) + if (build_polexpire(skb, xp, dir, c) < 0) BUG(); NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; -- cgit v1.2.3 From 980ebd25794f0f87ac32844e2c73e9e81f0a72ba Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:16:40 -0800 Subject: [IPSEC]: Sync series - acquire insert This introduces a feature similar to the one described in RFC 2367: " ... the application needing an SA sends a PF_KEY SADB_ACQUIRE message down to the Key Engine, which then either returns an error or sends a similar SADB_ACQUIRE message up to one or more key management applications capable of creating such SAs. ... ... The third is where an application-layer consumer of security associations (e.g. an OSPFv2 or RIPv2 daemon) needs a security association. Send an SADB_ACQUIRE message from a user process to the kernel. The kernel returns an SADB_ACQUIRE message to registered sockets. The user-level consumer waits for an SADB_UPDATE or SADB_ADD message for its particular type, and then can use that association by using SADB_GET messages. " An app such as OSPF could then use ipsec KM to get keys Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/xfrm/xfrm_state.c | 5 +++-- net/xfrm/xfrm_user.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index bc005e62e434..30a940b147b0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -214,10 +214,10 @@ extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c); extern void km_state_notify(struct xfrm_state *x, struct km_event *c); - #define XFRM_ACQ_EXPIRES 30 struct xfrm_tmpl; +extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); struct xfrm_state_afinfo { unsigned short family; rwlock_t lock; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 8eaee499cad5..a613b5c7d409 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -57,7 +57,7 @@ static int __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); -static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); static void km_state_expired(struct xfrm_state *x, int hard); static void xfrm_state_gc_destroy(struct xfrm_state *x) @@ -925,7 +925,7 @@ void km_state_expired(struct xfrm_state *x, int hard) * We send to all registered managers regardless of failure * We are happy with one success */ -static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) { int err = -EINVAL, acqret; struct xfrm_mgr *km; @@ -939,6 +939,7 @@ static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_polic read_unlock(&xfrm_km_lock); return err; } +EXPORT_SYMBOL(km_query); int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e230ba5328d3..d6e6527fd8d7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1232,6 +1232,58 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_policy *xp; + struct xfrm_user_tmpl *ut; + int i; + struct rtattr *rt = xfrma[XFRMA_TMPL-1]; + + struct xfrm_user_acquire *ua = NLMSG_DATA(nlh); + struct xfrm_state *x = xfrm_state_alloc(); + int err = -ENOMEM; + + if (!x) + return err; + + err = verify_newpolicy_info(&ua->policy); + if (err) { + printk("BAD policy passed\n"); + kfree(x); + return err; + } + + /* build an XP */ + xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err); if (!xp) { + kfree(x); + return err; + } + + memcpy(&x->id, &ua->id, sizeof(ua->id)); + memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); + memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); + + ut = RTA_DATA(rt); + /* extract the templates and for each call km_key */ + for (i = 0; i < xp->xfrm_nr; i++, ut++) { + struct xfrm_tmpl *t = &xp->xfrm_vec[i]; + memcpy(&x->id, &t->id, sizeof(x->id)); + x->props.mode = t->mode; + x->props.reqid = t->reqid; + x->props.family = ut->family; + t->aalgos = ua->aalgos; + t->ealgos = ua->ealgos; + t->calgos = ua->calgos; + err = km_query(x, t, xp); + + } + + kfree(x); + kfree(xp); + + return 0; +} + #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) @@ -1243,6 +1295,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), + [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), @@ -1266,6 +1319,7 @@ static struct xfrm_link { [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, .dump = xfrm_dump_policy }, [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, + [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, -- cgit v1.2.3 From 53bc6b4d29c07664f3abe029b7e6878a1067899a Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:17:03 -0800 Subject: [IPSEC]: Sync series - SA expires This patch allows a user to insert SA expires. This is useful to do on an HA backup for the case of byte counts but may not be very useful for the case of time based expiry. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 3 +++ net/xfrm/xfrm_state.c | 17 ++++++++++------- net/xfrm/xfrm_user.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 30a940b147b0..d409c9d5e293 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -218,6 +218,9 @@ extern void km_state_notify(struct xfrm_state *x, struct km_event *c); struct xfrm_tmpl; extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid); +extern int __xfrm_state_delete(struct xfrm_state *x); + struct xfrm_state_afinfo { unsigned short family; rwlock_t lock; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a613b5c7d409..7784adbb3362 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -52,13 +52,13 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock); static int xfrm_state_gc_flush_bundles; -static int __xfrm_state_delete(struct xfrm_state *x); +int __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); -static void km_state_expired(struct xfrm_state *x, int hard); +void km_state_expired(struct xfrm_state *x, int hard, u32 pid); static void xfrm_state_gc_destroy(struct xfrm_state *x) { @@ -157,7 +157,7 @@ static void xfrm_timer_handler(unsigned long data) x->km.dying = warn; if (warn) - km_state_expired(x, 0); + km_state_expired(x, 0, 0); resched: if (next != LONG_MAX && !mod_timer(&x->timer, jiffies + make_jiffies(next))) @@ -172,7 +172,7 @@ expired: goto resched; } if (!__xfrm_state_delete(x) && x->id.spi) - km_state_expired(x, 1); + km_state_expired(x, 1, 0); out: spin_unlock(&x->lock); @@ -221,7 +221,7 @@ void __xfrm_state_destroy(struct xfrm_state *x) } EXPORT_SYMBOL(__xfrm_state_destroy); -static int __xfrm_state_delete(struct xfrm_state *x) +int __xfrm_state_delete(struct xfrm_state *x) { int err = -ESRCH; @@ -260,6 +260,7 @@ static int __xfrm_state_delete(struct xfrm_state *x) return err; } +EXPORT_SYMBOL(__xfrm_state_delete); int xfrm_state_delete(struct xfrm_state *x) { @@ -595,7 +596,7 @@ int xfrm_state_check_expire(struct xfrm_state *x) (x->curlft.bytes >= x->lft.soft_byte_limit || x->curlft.packets >= x->lft.soft_packet_limit)) { x->km.dying = 1; - km_state_expired(x, 0); + km_state_expired(x, 0, 0); } return 0; } @@ -909,11 +910,12 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c) EXPORT_SYMBOL(km_policy_notify); EXPORT_SYMBOL(km_state_notify); -void km_state_expired(struct xfrm_state *x, int hard) +void km_state_expired(struct xfrm_state *x, int hard, u32 pid) { struct km_event c; c.data.hard = hard; + c.pid = pid; c.event = XFRM_MSG_EXPIRE; km_state_notify(x, &c); @@ -921,6 +923,7 @@ void km_state_expired(struct xfrm_state *x, int hard) wake_up(&km_waitq); } +EXPORT_SYMBOL(km_state_expired); /* * We send to all registered managers regardless of failure * We are happy with one success diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d6e6527fd8d7..2dc1e69b2cb7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1232,6 +1232,34 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_state *x; + int err; + struct xfrm_user_expire *ue = NLMSG_DATA(nlh); + struct xfrm_usersa_info *p = &ue->state; + + x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family); + err = -ENOENT; + + if (x == NULL) + return err; + + err = -EINVAL; + + spin_lock_bh(&x->lock); + if (x->km.state != XFRM_STATE_VALID) + goto out; + km_state_expired(x, ue->hard, current->pid); + + if (ue->hard) + __xfrm_state_delete(x); +out: + spin_unlock_bh(&x->lock); + xfrm_state_put(x); + return err; +} + static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct xfrm_policy *xp; @@ -1296,6 +1324,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), + [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), @@ -1320,6 +1349,7 @@ static struct xfrm_link { .dump = xfrm_dump_policy }, [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, + [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, -- cgit v1.2.3 From 6c5c8ca7ff20523e427b955aa84cef407934710f Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:17:25 -0800 Subject: [IPSEC]: Sync series - policy expires This is similar to the SA expire insertion patch - only it inserts expires for SP. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/xfrm/xfrm_policy.c | 4 ++-- net/xfrm/xfrm_state.c | 3 ++- net/xfrm/xfrm_user.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 5 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d409c9d5e293..156f52ef8a91 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -957,7 +957,7 @@ extern void xfrm_init_pmtu(struct dst_entry *dst); extern wait_queue_head_t km_waitq; extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); -extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard); +extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); extern void xfrm_input_init(void); extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ae62054a9fc4..453551ec87a1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -203,7 +203,7 @@ static void xfrm_policy_timer(unsigned long data) } if (warn) - km_policy_expired(xp, dir, 0); + km_policy_expired(xp, dir, 0, 0); if (next != LONG_MAX && !mod_timer(&xp->timer, jiffies + make_jiffies(next))) xfrm_pol_hold(xp); @@ -216,7 +216,7 @@ out: expired: read_unlock(&xp->lock); if (!xfrm_policy_delete(xp, dir)) - km_policy_expired(xp, dir, 1); + km_policy_expired(xp, dir, 1, 0); xfrm_pol_put(xp); } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7784adbb3362..8df547d7d61c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -961,11 +961,12 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) } EXPORT_SYMBOL(km_new_mapping); -void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) +void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) { struct km_event c; c.data.hard = hard; + c.pid = pid; c.event = XFRM_MSG_POLEXPIRE; km_policy_notify(pol, dir, &c); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2dc1e69b2cb7..b46ee7d4dae7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1222,7 +1222,7 @@ out: static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { - struct km_event c; +struct km_event c; xfrm_policy_flush(); c.event = nlh->nlmsg_type; @@ -1232,6 +1232,58 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_policy *xp; + struct xfrm_user_polexpire *up = NLMSG_DATA(nlh); + struct xfrm_userpolicy_info *p = &up->pol; + int err = -ENOENT; + + if (p->index) + xp = xfrm_policy_byid(p->dir, p->index, 0); + else { + struct rtattr **rtattrs = (struct rtattr **)xfrma; + struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; + struct xfrm_policy tmp; + + err = verify_sec_ctx_len(rtattrs); + if (err) + return err; + + 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; + } + xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, 0); + security_xfrm_policy_free(&tmp); + } + + if (xp == NULL) + return err; + read_lock(&xp->lock); + if (xp->dead) { + read_unlock(&xp->lock); + goto out; + } + + read_unlock(&xp->lock); + err = 0; + if (up->hard) { + xfrm_policy_delete(xp, p->dir); + } else { + // reset the timers here? + printk("Dont know what to do with soft policy expire\n"); + } + km_policy_expired(xp, p->dir, up->hard, current->pid); + +out: + xfrm_pol_put(xp); + return err; +} + static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct xfrm_state *x; @@ -1327,6 +1379,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), + [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), @@ -1352,6 +1405,7 @@ static struct xfrm_link { [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, + [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire}, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, -- cgit v1.2.3 From ee857a7d672859cf4eb735d32bce22c8b7ad0bd2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Mar 2006 19:18:37 -0800 Subject: [XFRM]: Move xfrm_nl to xfrm_state.c from xfrm_user.c xfrm_user could be modular, and since generic code uses this symbol now... Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 3 +++ net/xfrm/xfrm_user.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index cd1d5e11ee74..037bc8e4d667 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -20,6 +20,9 @@ #include #include +struct sock *xfrm_nl; +EXPORT_SYMBOL(xfrm_nl); + u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME; u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE; /* Each xfrm_state may be linked to two tables: diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b46ee7d4dae7..07b71680cde0 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -28,8 +28,6 @@ #include #include -struct sock *xfrm_nl; - static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) { struct rtattr *rt = xfrma[type - 1]; @@ -1974,5 +1972,4 @@ module_init(xfrm_user_init); module_exit(xfrm_user_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); -EXPORT_SYMBOL(xfrm_nl); -- cgit v1.2.3 From 253aa11578c1b89757282430891bb66ae5300092 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Mar 2006 22:23:35 -0800 Subject: [IPSEC] xfrm_user: Kill PAGE_SIZE check in verify_sec_ctx_len() First, it warns when PAGE_SIZE >= 64K because the ctx_len field is 16-bits. Secondly, if there are any real length limitations it can be verified by the security layer security_xfrm_state_alloc() call. Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 07b71680cde0..7b1acd995168 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -101,9 +101,6 @@ static inline int verify_sec_ctx_len(struct rtattr **xfrma) uctx = RTA_DATA(rt); - if (uctx->ctx_len > PAGE_SIZE) - return -EINVAL; - len += sizeof(struct xfrm_user_sec_ctx); len += uctx->ctx_len; -- cgit v1.2.3 From 4a3e2f711a00a1feb72ae12fdc749da10179d185 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 20 Mar 2006 22:33:17 -0800 Subject: [NET] sem2mutex: net/ Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/net/xfrm.h | 3 ++- net/atm/ioctl.c | 15 ++++++++------- net/bluetooth/rfcomm/core.c | 8 +++++--- net/core/dev.c | 7 ++++--- net/core/flow.c | 7 ++++--- net/ipv4/ipcomp.c | 17 +++++++++-------- net/ipv4/netfilter/ip_queue.c | 11 ++++++----- net/ipv4/xfrm4_tunnel.c | 11 ++++++----- net/ipv6/ipcomp6.c | 15 ++++++++------- net/ipv6/netfilter/ip6_queue.c | 11 ++++++----- net/ipv6/xfrm6_tunnel.c | 11 ++++++----- net/key/af_key.c | 4 ++-- net/netfilter/nf_sockopt.c | 25 +++++++++++++------------ net/socket.c | 31 ++++++++++++++++--------------- net/sunrpc/cache.c | 17 +++++++++-------- net/sunrpc/sched.c | 11 ++++++----- net/unix/garbage.c | 7 ++++--- net/xfrm/xfrm_policy.c | 4 ++-- net/xfrm/xfrm_user.c | 4 ++-- 19 files changed, 118 insertions(+), 101 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 156f52ef8a91..786371365f2b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -24,7 +25,7 @@ extern struct sock *xfrm_nl; extern u32 sysctl_xfrm_aevent_etime; extern u32 sysctl_xfrm_aevent_rseqth; -extern struct semaphore xfrm_cfg_sem; +extern struct mutex xfrm_cfg_mutex; /* Organization of SPD aka "XFRM rules" ------------------------------------ diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index eb109af7eb4a..851cfa6312af 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "resources.h" @@ -25,22 +26,22 @@ #include "common.h" -static DECLARE_MUTEX(ioctl_mutex); +static DEFINE_MUTEX(ioctl_mutex); static LIST_HEAD(ioctl_list); void register_atm_ioctl(struct atm_ioctl *ioctl) { - down(&ioctl_mutex); + mutex_lock(&ioctl_mutex); list_add_tail(&ioctl->list, &ioctl_list); - up(&ioctl_mutex); + mutex_unlock(&ioctl_mutex); } void deregister_atm_ioctl(struct atm_ioctl *ioctl) { - down(&ioctl_mutex); + mutex_lock(&ioctl_mutex); list_del(&ioctl->list); - up(&ioctl_mutex); + mutex_unlock(&ioctl_mutex); } EXPORT_SYMBOL(register_atm_ioctl); @@ -137,7 +138,7 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) error = -ENOIOCTLCMD; - down(&ioctl_mutex); + mutex_lock(&ioctl_mutex); list_for_each(pos, &ioctl_list) { struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); if (try_module_get(ic->owner)) { @@ -147,7 +148,7 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; } } - up(&ioctl_mutex); + mutex_unlock(&ioctl_mutex); if (error != -ENOIOCTLCMD) goto done; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5b4253c61f62..e99010ce8bb2 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -37,6 +37,8 @@ #include #include #include +#include + #include #include #include @@ -57,9 +59,9 @@ static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; static struct task_struct *rfcomm_thread; -static DECLARE_MUTEX(rfcomm_sem); -#define rfcomm_lock() down(&rfcomm_sem); -#define rfcomm_unlock() up(&rfcomm_sem); +static DEFINE_MUTEX(rfcomm_mutex); +#define rfcomm_lock() mutex_lock(&rfcomm_mutex) +#define rfcomm_unlock() mutex_unlock(&rfcomm_mutex) static unsigned long rfcomm_event; diff --git a/net/core/dev.c b/net/core/dev.c index ee044097f7f2..08dec6eb922b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -2931,7 +2932,7 @@ static void netdev_wait_allrefs(struct net_device *dev) * 2) Since we run with the RTNL semaphore not held, we can sleep * safely in order to wait for the netdev refcnt to drop to zero. */ -static DECLARE_MUTEX(net_todo_run_mutex); +static DEFINE_MUTEX(net_todo_run_mutex); void netdev_run_todo(void) { struct list_head list = LIST_HEAD_INIT(list); @@ -2939,7 +2940,7 @@ void netdev_run_todo(void) /* Need to guard against multiple cpu's getting out of order. */ - down(&net_todo_run_mutex); + mutex_lock(&net_todo_run_mutex); /* Not safe to do outside the semaphore. We must not return * until all unregister events invoked by the local processor @@ -2996,7 +2997,7 @@ void netdev_run_todo(void) } out: - up(&net_todo_run_mutex); + mutex_unlock(&net_todo_run_mutex); } /** diff --git a/net/core/flow.c b/net/core/flow.c index c4f25385029f..55789f832eda 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -287,11 +288,11 @@ static void flow_cache_flush_per_cpu(void *data) void flow_cache_flush(void) { struct flow_flush_info info; - static DECLARE_MUTEX(flow_flush_sem); + static DEFINE_MUTEX(flow_flush_sem); /* Don't want cpus going down or up during this. */ lock_cpu_hotplug(); - down(&flow_flush_sem); + mutex_lock(&flow_flush_sem); atomic_set(&info.cpuleft, num_online_cpus()); init_completion(&info.completion); @@ -301,7 +302,7 @@ void flow_cache_flush(void) local_bh_enable(); wait_for_completion(&info.completion); - up(&flow_flush_sem); + mutex_unlock(&flow_flush_sem); unlock_cpu_hotplug(); } diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index d64e2ec8da7b..c95020f7c81e 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,7 @@ struct ipcomp_tfms { int users; }; -static DECLARE_MUTEX(ipcomp_resource_sem); +static DEFINE_MUTEX(ipcomp_resource_mutex); static void **ipcomp_scratches; static int ipcomp_scratch_users; static LIST_HEAD(ipcomp_tfms_list); @@ -253,7 +254,7 @@ error: } /* - * Must be protected by xfrm_cfg_sem. State and tunnel user references are + * Must be protected by xfrm_cfg_mutex. State and tunnel user references are * always incremented on success. */ static int ipcomp_tunnel_attach(struct xfrm_state *x) @@ -411,9 +412,9 @@ static void ipcomp_destroy(struct xfrm_state *x) if (!ipcd) return; xfrm_state_delete_tunnel(x); - down(&ipcomp_resource_sem); + mutex_lock(&ipcomp_resource_mutex); ipcomp_free_data(ipcd); - up(&ipcomp_resource_sem); + mutex_unlock(&ipcomp_resource_mutex); kfree(ipcd); } @@ -440,14 +441,14 @@ static int ipcomp_init_state(struct xfrm_state *x) if (x->props.mode) x->props.header_len += sizeof(struct iphdr); - down(&ipcomp_resource_sem); + mutex_lock(&ipcomp_resource_mutex); if (!ipcomp_alloc_scratches()) goto error; ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name); if (!ipcd->tfms) goto error; - up(&ipcomp_resource_sem); + mutex_unlock(&ipcomp_resource_mutex); if (x->props.mode) { err = ipcomp_tunnel_attach(x); @@ -464,10 +465,10 @@ out: return err; error_tunnel: - down(&ipcomp_resource_sem); + mutex_lock(&ipcomp_resource_mutex); error: ipcomp_free_data(ipcd); - up(&ipcomp_resource_sem); + mutex_unlock(&ipcomp_resource_mutex); kfree(ipcd); goto out; } diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 08f80e2ea2aa..1655866c55b9 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,7 @@ static unsigned int queue_dropped = 0; static unsigned int queue_user_dropped = 0; static struct sock *ipqnl; static LIST_HEAD(queue_list); -static DECLARE_MUTEX(ipqnl_sem); +static DEFINE_MUTEX(ipqnl_mutex); static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) @@ -539,7 +540,7 @@ ipq_rcv_sk(struct sock *sk, int len) struct sk_buff *skb; unsigned int qlen; - down(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { skb = skb_dequeue(&sk->sk_receive_queue); @@ -547,7 +548,7 @@ ipq_rcv_sk(struct sock *sk, int len) kfree_skb(skb); } - up(&ipqnl_sem); + mutex_unlock(&ipqnl_mutex); } static int @@ -708,8 +709,8 @@ cleanup_sysctl: cleanup_ipqnl: sock_release(ipqnl->sk_socket); - down(&ipqnl_sem); - up(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); + mutex_unlock(&ipqnl_mutex); cleanup_netlink_notifier: netlink_unregister_notifier(&ipq_nl_notifier); diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index afbb0d4cc305..b08d56b117f8 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -26,19 +27,19 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, s } static struct xfrm_tunnel *ipip_handler; -static DECLARE_MUTEX(xfrm4_tunnel_sem); +static DEFINE_MUTEX(xfrm4_tunnel_mutex); int xfrm4_tunnel_register(struct xfrm_tunnel *handler) { int ret; - down(&xfrm4_tunnel_sem); + mutex_lock(&xfrm4_tunnel_mutex); ret = 0; if (ipip_handler != NULL) ret = -EINVAL; if (!ret) ipip_handler = handler; - up(&xfrm4_tunnel_sem); + mutex_unlock(&xfrm4_tunnel_mutex); return ret; } @@ -49,13 +50,13 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) { int ret; - down(&xfrm4_tunnel_sem); + mutex_lock(&xfrm4_tunnel_mutex); ret = 0; if (ipip_handler != handler) ret = -EINVAL; if (!ret) ipip_handler = NULL; - up(&xfrm4_tunnel_sem); + mutex_unlock(&xfrm4_tunnel_mutex); synchronize_net(); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 6107592fbd8c..3c7b324cd20c 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -50,6 +50,7 @@ #include #include #include +#include struct ipcomp6_tfms { struct list_head list; @@ -57,7 +58,7 @@ struct ipcomp6_tfms { int users; }; -static DECLARE_MUTEX(ipcomp6_resource_sem); +static DEFINE_MUTEX(ipcomp6_resource_mutex); static void **ipcomp6_scratches; static int ipcomp6_scratch_users; static LIST_HEAD(ipcomp6_tfms_list); @@ -405,9 +406,9 @@ static void ipcomp6_destroy(struct xfrm_state *x) if (!ipcd) return; xfrm_state_delete_tunnel(x); - down(&ipcomp6_resource_sem); + mutex_lock(&ipcomp6_resource_mutex); ipcomp6_free_data(ipcd); - up(&ipcomp6_resource_sem); + mutex_unlock(&ipcomp6_resource_mutex); kfree(ipcd); xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); @@ -436,14 +437,14 @@ static int ipcomp6_init_state(struct xfrm_state *x) if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); - down(&ipcomp6_resource_sem); + mutex_lock(&ipcomp6_resource_mutex); if (!ipcomp6_alloc_scratches()) goto error; ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name); if (!ipcd->tfms) goto error; - up(&ipcomp6_resource_sem); + mutex_unlock(&ipcomp6_resource_mutex); if (x->props.mode) { err = ipcomp6_tunnel_attach(x); @@ -459,10 +460,10 @@ static int ipcomp6_init_state(struct xfrm_state *x) out: return err; error_tunnel: - down(&ipcomp6_resource_sem); + mutex_lock(&ipcomp6_resource_mutex); error: ipcomp6_free_data(ipcd); - up(&ipcomp6_resource_sem); + mutex_unlock(&ipcomp6_resource_mutex); kfree(ipcd); goto out; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index af0635084df8..344eab3b5da8 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,7 @@ static unsigned int queue_dropped = 0; static unsigned int queue_user_dropped = 0; static struct sock *ipqnl; static LIST_HEAD(queue_list); -static DECLARE_MUTEX(ipqnl_sem); +static DEFINE_MUTEX(ipqnl_mutex); static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) @@ -537,7 +538,7 @@ ipq_rcv_sk(struct sock *sk, int len) struct sk_buff *skb; unsigned int qlen; - down(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { skb = skb_dequeue(&sk->sk_receive_queue); @@ -545,7 +546,7 @@ ipq_rcv_sk(struct sock *sk, int len) kfree_skb(skb); } - up(&ipqnl_sem); + mutex_unlock(&ipqnl_mutex); } static int @@ -704,8 +705,8 @@ cleanup_sysctl: cleanup_ipqnl: sock_release(ipqnl->sk_socket); - down(&ipqnl_sem); - up(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); + mutex_unlock(&ipqnl_mutex); cleanup_netlink_notifier: netlink_unregister_notifier(&ipq_nl_notifier); diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 8cfc58b96fc2..08f9abbdf1d7 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG # define X6TDEBUG 3 @@ -357,19 +358,19 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec } static struct xfrm6_tunnel *xfrm6_tunnel_handler; -static DECLARE_MUTEX(xfrm6_tunnel_sem); +static DEFINE_MUTEX(xfrm6_tunnel_mutex); int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) { int ret; - down(&xfrm6_tunnel_sem); + mutex_lock(&xfrm6_tunnel_mutex); ret = 0; if (xfrm6_tunnel_handler != NULL) ret = -EINVAL; if (!ret) xfrm6_tunnel_handler = handler; - up(&xfrm6_tunnel_sem); + mutex_unlock(&xfrm6_tunnel_mutex); return ret; } @@ -380,13 +381,13 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) { int ret; - down(&xfrm6_tunnel_sem); + mutex_lock(&xfrm6_tunnel_mutex); ret = 0; if (xfrm6_tunnel_handler != handler) ret = -EINVAL; if (!ret) xfrm6_tunnel_handler = NULL; - up(&xfrm6_tunnel_sem); + mutex_unlock(&xfrm6_tunnel_mutex); synchronize_net(); diff --git a/net/key/af_key.c b/net/key/af_key.c index 520fe70d0993..859582275cab 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3080,9 +3080,9 @@ static int pfkey_sendmsg(struct kiocb *kiocb, if (!hdr) goto out; - down(&xfrm_cfg_sem); + mutex_lock(&xfrm_cfg_mutex); err = pfkey_process(sk, skb, hdr); - up(&xfrm_cfg_sem); + mutex_unlock(&xfrm_cfg_mutex); out: if (err && hdr && pfkey_error(hdr, err, sk) == 0) diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index 61a833a9caa6..0e5c5e204799 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "nf_internals.h" @@ -11,7 +12,7 @@ /* Sockopts only registered and called from user context, so net locking would be overkill. Also, [gs]etsockopt calls may sleep. */ -static DECLARE_MUTEX(nf_sockopt_mutex); +static DEFINE_MUTEX(nf_sockopt_mutex); static LIST_HEAD(nf_sockopts); /* Do exclusive ranges overlap? */ @@ -26,7 +27,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg) struct list_head *i; int ret = 0; - if (down_interruptible(&nf_sockopt_mutex) != 0) + if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; list_for_each(i, &nf_sockopts) { @@ -48,7 +49,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg) list_add(®->list, &nf_sockopts); out: - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); return ret; } EXPORT_SYMBOL(nf_register_sockopt); @@ -57,18 +58,18 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg) { /* No point being interruptible: we're probably in cleanup_module() */ restart: - down(&nf_sockopt_mutex); + mutex_lock(&nf_sockopt_mutex); if (reg->use != 0) { /* To be woken by nf_sockopt call... */ /* FIXME: Stuart Young's name appears gratuitously. */ set_current_state(TASK_UNINTERRUPTIBLE); reg->cleanup_task = current; - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); schedule(); goto restart; } list_del(®->list); - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); } EXPORT_SYMBOL(nf_unregister_sockopt); @@ -80,7 +81,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val, struct nf_sockopt_ops *ops; int ret; - if (down_interruptible(&nf_sockopt_mutex) != 0) + if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; list_for_each(i, &nf_sockopts) { @@ -90,7 +91,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val, if (val >= ops->get_optmin && val < ops->get_optmax) { ops->use++; - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); ret = ops->get(sk, val, opt, len); goto out; } @@ -98,22 +99,22 @@ static int nf_sockopt(struct sock *sk, int pf, int val, if (val >= ops->set_optmin && val < ops->set_optmax) { ops->use++; - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); ret = ops->set(sk, val, opt, *len); goto out; } } } } - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); return -ENOPROTOOPT; out: - down(&nf_sockopt_mutex); + mutex_lock(&nf_sockopt_mutex); ops->use--; if (ops->cleanup_task) wake_up_process(ops->cleanup_task); - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); return ret; } diff --git a/net/socket.c b/net/socket.c index 510ae18d220a..e3c21d5ec288 100644 --- a/net/socket.c +++ b/net/socket.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -826,36 +827,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, * with module unload. */ -static DECLARE_MUTEX(br_ioctl_mutex); +static DEFINE_MUTEX(br_ioctl_mutex); static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; void brioctl_set(int (*hook)(unsigned int, void __user *)) { - down(&br_ioctl_mutex); + mutex_lock(&br_ioctl_mutex); br_ioctl_hook = hook; - up(&br_ioctl_mutex); + mutex_unlock(&br_ioctl_mutex); } EXPORT_SYMBOL(brioctl_set); -static DECLARE_MUTEX(vlan_ioctl_mutex); +static DEFINE_MUTEX(vlan_ioctl_mutex); static int (*vlan_ioctl_hook)(void __user *arg); void vlan_ioctl_set(int (*hook)(void __user *)) { - down(&vlan_ioctl_mutex); + mutex_lock(&vlan_ioctl_mutex); vlan_ioctl_hook = hook; - up(&vlan_ioctl_mutex); + mutex_unlock(&vlan_ioctl_mutex); } EXPORT_SYMBOL(vlan_ioctl_set); -static DECLARE_MUTEX(dlci_ioctl_mutex); +static DEFINE_MUTEX(dlci_ioctl_mutex); static int (*dlci_ioctl_hook)(unsigned int, void __user *); void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) { - down(&dlci_ioctl_mutex); + mutex_lock(&dlci_ioctl_mutex); dlci_ioctl_hook = hook; - up(&dlci_ioctl_mutex); + mutex_unlock(&dlci_ioctl_mutex); } EXPORT_SYMBOL(dlci_ioctl_set); @@ -899,10 +900,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (!br_ioctl_hook) request_module("bridge"); - down(&br_ioctl_mutex); + mutex_lock(&br_ioctl_mutex); if (br_ioctl_hook) err = br_ioctl_hook(cmd, argp); - up(&br_ioctl_mutex); + mutex_unlock(&br_ioctl_mutex); break; case SIOCGIFVLAN: case SIOCSIFVLAN: @@ -910,10 +911,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (!vlan_ioctl_hook) request_module("8021q"); - down(&vlan_ioctl_mutex); + mutex_lock(&vlan_ioctl_mutex); if (vlan_ioctl_hook) err = vlan_ioctl_hook(argp); - up(&vlan_ioctl_mutex); + mutex_unlock(&vlan_ioctl_mutex); break; case SIOCGIFDIVERT: case SIOCSIFDIVERT: @@ -927,9 +928,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) request_module("dlci"); if (dlci_ioctl_hook) { - down(&dlci_ioctl_mutex); + mutex_lock(&dlci_ioctl_mutex); err = dlci_ioctl_hook(cmd, argp); - up(&dlci_ioctl_mutex); + mutex_unlock(&dlci_ioctl_mutex); } break; default: diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index dcaa0c4453ff..0acccfeeb284 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -532,7 +533,7 @@ void cache_clean_deferred(void *owner) */ static DEFINE_SPINLOCK(queue_lock); -static DECLARE_MUTEX(queue_io_sem); +static DEFINE_MUTEX(queue_io_mutex); struct cache_queue { struct list_head list; @@ -561,7 +562,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) if (count == 0) return 0; - down(&queue_io_sem); /* protect against multiple concurrent + mutex_lock(&queue_io_mutex); /* protect against multiple concurrent * readers on this file */ again: spin_lock(&queue_lock); @@ -574,7 +575,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) } if (rp->q.list.next == &cd->queue) { spin_unlock(&queue_lock); - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); BUG_ON(rp->offset); return 0; } @@ -621,11 +622,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) } if (err == -EAGAIN) goto again; - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); return err ? err : count; } -static char write_buf[8192]; /* protected by queue_io_sem */ +static char write_buf[8192]; /* protected by queue_io_mutex */ static ssize_t cache_write(struct file *filp, const char __user *buf, size_t count, @@ -639,10 +640,10 @@ cache_write(struct file *filp, const char __user *buf, size_t count, if (count >= sizeof(write_buf)) return -EINVAL; - down(&queue_io_sem); + mutex_lock(&queue_io_mutex); if (copy_from_user(write_buf, buf, count)) { - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); return -EFAULT; } write_buf[count] = '\0'; @@ -651,7 +652,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count, else err = -EINVAL; - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); return err ? err : count; } diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index e838d042f7f5..dff07795bd16 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,7 @@ static LIST_HEAD(all_tasks); /* * rpciod-related stuff */ -static DECLARE_MUTEX(rpciod_sema); +static DEFINE_MUTEX(rpciod_mutex); static unsigned int rpciod_users; static struct workqueue_struct *rpciod_workqueue; @@ -1047,7 +1048,7 @@ rpciod_up(void) struct workqueue_struct *wq; int error = 0; - down(&rpciod_sema); + mutex_lock(&rpciod_mutex); dprintk("rpciod_up: users %d\n", rpciod_users); rpciod_users++; if (rpciod_workqueue) @@ -1070,14 +1071,14 @@ rpciod_up(void) rpciod_workqueue = wq; error = 0; out: - up(&rpciod_sema); + mutex_unlock(&rpciod_mutex); return error; } void rpciod_down(void) { - down(&rpciod_sema); + mutex_lock(&rpciod_mutex); dprintk("rpciod_down sema %d\n", rpciod_users); if (rpciod_users) { if (--rpciod_users) @@ -1094,7 +1095,7 @@ rpciod_down(void) destroy_workqueue(rpciod_workqueue); rpciod_workqueue = NULL; out: - up(&rpciod_sema); + mutex_unlock(&rpciod_mutex); } #ifdef RPC_DEBUG diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 411802bd4d37..746c2f4a5fa6 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -169,7 +170,7 @@ static void maybe_unmark_and_push(struct sock *x) void unix_gc(void) { - static DECLARE_MUTEX(unix_gc_sem); + static DEFINE_MUTEX(unix_gc_sem); int i; struct sock *s; struct sk_buff_head hitlist; @@ -179,7 +180,7 @@ void unix_gc(void) * Avoid a recursive GC. */ - if (down_trylock(&unix_gc_sem)) + if (!mutex_trylock(&unix_gc_sem)) return; spin_lock(&unix_table_lock); @@ -308,5 +309,5 @@ void unix_gc(void) */ __skb_queue_purge(&hitlist); - up(&unix_gc_sem); + mutex_unlock(&unix_gc_sem); } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b46079263e8b..f5eae9febd26 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -26,8 +26,8 @@ #include #include -DECLARE_MUTEX(xfrm_cfg_sem); -EXPORT_SYMBOL(xfrm_cfg_sem); +DEFINE_MUTEX(xfrm_cfg_mutex); +EXPORT_SYMBOL(xfrm_cfg_mutex); static DEFINE_RWLOCK(xfrm_policy_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7b1acd995168..4a7120a7e10f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1486,9 +1486,9 @@ static void xfrm_netlink_rcv(struct sock *sk, int len) unsigned int qlen = 0; do { - down(&xfrm_cfg_sem); + mutex_lock(&xfrm_cfg_mutex); netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg); - up(&xfrm_cfg_sem); + mutex_unlock(&xfrm_cfg_mutex); } while (qlen); } -- cgit v1.2.3 From be33690d8fcf40377f16193c463681170eb6b295 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 22:40:54 -0800 Subject: [XFRM]: Fix aevent related crash When xfrm_user isn't loaded xfrm_nl is NULL, which makes IPsec crash because xfrm_aevent_is_on passes the NULL pointer to netlink_has_listeners as socket. A second problem is that the xfrm_nl pointer is not cleared when the socket is releases at module unload time. Protect references of xfrm_nl from outside of xfrm_user by RCU, check that the socket is present in xfrm_aevent_is_on and set it to NULL when unloading xfrm_user. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/xfrm.h | 10 +++++++++- net/xfrm/xfrm_user.c | 15 +++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 786371365f2b..61b7504fc2ba 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1001,7 +1001,15 @@ static inline int xfrm_policy_id2dir(u32 index) static inline int xfrm_aevent_is_on(void) { - return netlink_has_listeners(xfrm_nl,XFRMNLGRP_AEVENTS); + struct sock *nlsk; + int ret = 0; + + rcu_read_lock(); + nlsk = rcu_dereference(xfrm_nl); + if (nlsk) + ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS); + rcu_read_unlock(); + return ret; } static inline void xfrm_aevent_doreplay(struct xfrm_state *x) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4a7120a7e10f..81d1005830f4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1947,12 +1947,15 @@ static struct xfrm_mgr netlink_mgr = { static int __init xfrm_user_init(void) { + struct sock *nlsk; + printk(KERN_INFO "Initializing IPsec netlink socket\n"); - xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, - xfrm_netlink_rcv, THIS_MODULE); - if (xfrm_nl == NULL) + nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, + xfrm_netlink_rcv, THIS_MODULE); + if (nlsk == NULL) return -ENOMEM; + rcu_assign_pointer(xfrm_nl, nlsk); xfrm_register_km(&netlink_mgr); @@ -1961,8 +1964,12 @@ static int __init xfrm_user_init(void) static void __exit xfrm_user_exit(void) { + struct sock *nlsk = xfrm_nl; + xfrm_unregister_km(&netlink_mgr); - sock_release(xfrm_nl->sk_socket); + rcu_assign_pointer(xfrm_nl, NULL); + synchronize_rcu(); + sock_release(nlsk->sk_socket); } module_init(xfrm_user_init); -- cgit v1.2.3