diff options
43 files changed, 411 insertions, 219 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 9b5fea81f55e..b200b9856f32 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -882,7 +882,8 @@ struct request_sock; | |||
882 | * Check permission when a flow selects a xfrm_policy for processing | 882 | * Check permission when a flow selects a xfrm_policy for processing |
883 | * XFRMs on a packet. The hook is called when selecting either a | 883 | * XFRMs on a packet. The hook is called when selecting either a |
884 | * per-socket policy or a generic xfrm policy. | 884 | * per-socket policy or a generic xfrm policy. |
885 | * Return 0 if permission is granted. | 885 | * Return 0 if permission is granted, -ESRCH otherwise, or -errno |
886 | * on other errors. | ||
886 | * @xfrm_state_pol_flow_match: | 887 | * @xfrm_state_pol_flow_match: |
887 | * @x contains the state to match. | 888 | * @x contains the state to match. |
888 | * @xp contains the policy to check for a match. | 889 | * @xp contains the policy to check for a match. |
@@ -891,6 +892,7 @@ struct request_sock; | |||
891 | * @xfrm_flow_state_match: | 892 | * @xfrm_flow_state_match: |
892 | * @fl contains the flow key to match. | 893 | * @fl contains the flow key to match. |
893 | * @xfrm points to the xfrm_state to match. | 894 | * @xfrm points to the xfrm_state to match. |
895 | * @xp points to the xfrm_policy to match. | ||
894 | * Return 1 if there is a match. | 896 | * Return 1 if there is a match. |
895 | * @xfrm_decode_session: | 897 | * @xfrm_decode_session: |
896 | * @skb points to skb to decode. | 898 | * @skb points to skb to decode. |
@@ -1388,7 +1390,8 @@ struct security_operations { | |||
1388 | int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); | 1390 | int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); |
1389 | int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, | 1391 | int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, |
1390 | struct xfrm_policy *xp, struct flowi *fl); | 1392 | struct xfrm_policy *xp, struct flowi *fl); |
1391 | int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm); | 1393 | int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm, |
1394 | struct xfrm_policy *xp); | ||
1392 | int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); | 1395 | int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); |
1393 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 1396 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
1394 | 1397 | ||
@@ -3120,11 +3123,6 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm | |||
3120 | return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL); | 3123 | return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL); |
3121 | } | 3124 | } |
3122 | 3125 | ||
3123 | static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk) | ||
3124 | { | ||
3125 | return security_ops->xfrm_policy_alloc_security(xp, NULL, sk); | ||
3126 | } | ||
3127 | |||
3128 | static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) | 3126 | static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) |
3129 | { | 3127 | { |
3130 | return security_ops->xfrm_policy_clone_security(old, new); | 3128 | return security_ops->xfrm_policy_clone_security(old, new); |
@@ -3175,9 +3173,10 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | |||
3175 | return security_ops->xfrm_state_pol_flow_match(x, xp, fl); | 3173 | return security_ops->xfrm_state_pol_flow_match(x, xp, fl); |
3176 | } | 3174 | } |
3177 | 3175 | ||
3178 | static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) | 3176 | static inline int security_xfrm_flow_state_match(struct flowi *fl, |
3177 | struct xfrm_state *xfrm, struct xfrm_policy *xp) | ||
3179 | { | 3178 | { |
3180 | return security_ops->xfrm_flow_state_match(fl, xfrm); | 3179 | return security_ops->xfrm_flow_state_match(fl, xfrm, xp); |
3181 | } | 3180 | } |
3182 | 3181 | ||
3183 | static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) | 3182 | static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) |
@@ -3197,11 +3196,6 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm | |||
3197 | return 0; | 3196 | return 0; |
3198 | } | 3197 | } |
3199 | 3198 | ||
3200 | static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk) | ||
3201 | { | ||
3202 | return 0; | ||
3203 | } | ||
3204 | |||
3205 | static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) | 3199 | static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) |
3206 | { | 3200 | { |
3207 | return 0; | 3201 | return 0; |
@@ -3249,7 +3243,7 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, | |||
3249 | } | 3243 | } |
3250 | 3244 | ||
3251 | static inline int security_xfrm_flow_state_match(struct flowi *fl, | 3245 | static inline int security_xfrm_flow_state_match(struct flowi *fl, |
3252 | struct xfrm_state *xfrm) | 3246 | struct xfrm_state *xfrm, struct xfrm_policy *xp) |
3253 | { | 3247 | { |
3254 | return 1; | 3248 | return 1; |
3255 | } | 3249 | } |
diff --git a/include/net/flow.h b/include/net/flow.h index ddf5f3ca1720..3b44d72b27d3 100644 --- a/include/net/flow.h +++ b/include/net/flow.h | |||
@@ -97,7 +97,7 @@ struct flowi { | |||
97 | #define FLOW_DIR_FWD 2 | 97 | #define FLOW_DIR_FWD 2 |
98 | 98 | ||
99 | struct sock; | 99 | struct sock; |
100 | typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir, | 100 | typedef int (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir, |
101 | void **objp, atomic_t **obj_refp); | 101 | void **objp, atomic_t **obj_refp); |
102 | 102 | ||
103 | extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, | 103 | extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, |
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 6d14c22a00c5..5f48748fe017 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h | |||
@@ -196,6 +196,7 @@ static inline void inet_twsk_put(struct inet_timewait_sock *tw) | |||
196 | { | 196 | { |
197 | if (atomic_dec_and_test(&tw->tw_refcnt)) { | 197 | if (atomic_dec_and_test(&tw->tw_refcnt)) { |
198 | struct module *owner = tw->tw_prot->owner; | 198 | struct module *owner = tw->tw_prot->owner; |
199 | twsk_destructor((struct sock *)tw); | ||
199 | #ifdef SOCK_REFCNT_DEBUG | 200 | #ifdef SOCK_REFCNT_DEBUG |
200 | printk(KERN_DEBUG "%s timewait_sock %p released\n", | 201 | printk(KERN_DEBUG "%s timewait_sock %p released\n", |
201 | tw->tw_prot->name, tw); | 202 | tw->tw_prot->name, tw); |
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index c63a58058e21..113337c27955 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/net.h> | 34 | #include <linux/net.h> |
35 | #include <linux/skbuff.h> | 35 | #include <linux/skbuff.h> |
36 | #include <net/netlink.h> | 36 | #include <net/netlink.h> |
37 | #include <asm/atomic.h> | ||
37 | 38 | ||
38 | /* | 39 | /* |
39 | * NetLabel - A management interface for maintaining network packet label | 40 | * NetLabel - A management interface for maintaining network packet label |
@@ -106,6 +107,7 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); | |||
106 | 107 | ||
107 | /* LSM security attributes */ | 108 | /* LSM security attributes */ |
108 | struct netlbl_lsm_cache { | 109 | struct netlbl_lsm_cache { |
110 | atomic_t refcount; | ||
109 | void (*free) (const void *data); | 111 | void (*free) (const void *data); |
110 | void *data; | 112 | void *data; |
111 | }; | 113 | }; |
@@ -117,7 +119,7 @@ struct netlbl_lsm_secattr { | |||
117 | unsigned char *mls_cat; | 119 | unsigned char *mls_cat; |
118 | size_t mls_cat_len; | 120 | size_t mls_cat_len; |
119 | 121 | ||
120 | struct netlbl_lsm_cache cache; | 122 | struct netlbl_lsm_cache *cache; |
121 | }; | 123 | }; |
122 | 124 | ||
123 | /* | 125 | /* |
@@ -126,6 +128,43 @@ struct netlbl_lsm_secattr { | |||
126 | 128 | ||
127 | 129 | ||
128 | /** | 130 | /** |
131 | * netlbl_secattr_cache_alloc - Allocate and initialize a secattr cache | ||
132 | * @flags: the memory allocation flags | ||
133 | * | ||
134 | * Description: | ||
135 | * Allocate and initialize a netlbl_lsm_cache structure. Returns a pointer | ||
136 | * on success, NULL on failure. | ||
137 | * | ||
138 | */ | ||
139 | static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(int flags) | ||
140 | { | ||
141 | struct netlbl_lsm_cache *cache; | ||
142 | |||
143 | cache = kzalloc(sizeof(*cache), flags); | ||
144 | if (cache) | ||
145 | atomic_set(&cache->refcount, 1); | ||
146 | return cache; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * netlbl_secattr_cache_free - Frees a netlbl_lsm_cache struct | ||
151 | * @cache: the struct to free | ||
152 | * | ||
153 | * Description: | ||
154 | * Frees @secattr including all of the internal buffers. | ||
155 | * | ||
156 | */ | ||
157 | static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache) | ||
158 | { | ||
159 | if (!atomic_dec_and_test(&cache->refcount)) | ||
160 | return; | ||
161 | |||
162 | if (cache->free) | ||
163 | cache->free(cache->data); | ||
164 | kfree(cache); | ||
165 | } | ||
166 | |||
167 | /** | ||
129 | * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct | 168 | * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct |
130 | * @secattr: the struct to initialize | 169 | * @secattr: the struct to initialize |
131 | * | 170 | * |
@@ -143,20 +182,16 @@ static inline int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr) | |||
143 | /** | 182 | /** |
144 | * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct | 183 | * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct |
145 | * @secattr: the struct to clear | 184 | * @secattr: the struct to clear |
146 | * @clear_cache: cache clear flag | ||
147 | * | 185 | * |
148 | * Description: | 186 | * Description: |
149 | * Destroys the @secattr struct, including freeing all of the internal buffers. | 187 | * Destroys the @secattr struct, including freeing all of the internal buffers. |
150 | * If @clear_cache is true then free the cache fields, otherwise leave them | 188 | * The struct must be reset with a call to netlbl_secattr_init() before reuse. |
151 | * intact. The struct must be reset with a call to netlbl_secattr_init() | ||
152 | * before reuse. | ||
153 | * | 189 | * |
154 | */ | 190 | */ |
155 | static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr, | 191 | static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr) |
156 | u32 clear_cache) | ||
157 | { | 192 | { |
158 | if (clear_cache && secattr->cache.data != NULL && secattr->cache.free) | 193 | if (secattr->cache) |
159 | secattr->cache.free(secattr->cache.data); | 194 | netlbl_secattr_cache_free(secattr->cache); |
160 | kfree(secattr->domain); | 195 | kfree(secattr->domain); |
161 | kfree(secattr->mls_cat); | 196 | kfree(secattr->mls_cat); |
162 | } | 197 | } |
@@ -178,17 +213,14 @@ static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(int flags) | |||
178 | /** | 213 | /** |
179 | * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct | 214 | * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct |
180 | * @secattr: the struct to free | 215 | * @secattr: the struct to free |
181 | * @clear_cache: cache clear flag | ||
182 | * | 216 | * |
183 | * Description: | 217 | * Description: |
184 | * Frees @secattr including all of the internal buffers. If @clear_cache is | 218 | * Frees @secattr including all of the internal buffers. |
185 | * true then free the cache fields, otherwise leave them intact. | ||
186 | * | 219 | * |
187 | */ | 220 | */ |
188 | static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr, | 221 | static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr) |
189 | u32 clear_cache) | ||
190 | { | 222 | { |
191 | netlbl_secattr_destroy(secattr, clear_cache); | 223 | netlbl_secattr_destroy(secattr); |
192 | kfree(secattr); | 224 | kfree(secattr); |
193 | } | 225 | } |
194 | 226 | ||
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index ee68a3124076..764e3af5be93 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -139,6 +139,7 @@ int sctp_inet_listen(struct socket *sock, int backlog); | |||
139 | void sctp_write_space(struct sock *sk); | 139 | void sctp_write_space(struct sock *sk); |
140 | unsigned int sctp_poll(struct file *file, struct socket *sock, | 140 | unsigned int sctp_poll(struct file *file, struct socket *sock, |
141 | poll_table *wait); | 141 | poll_table *wait); |
142 | void sctp_sock_rfree(struct sk_buff *skb); | ||
142 | 143 | ||
143 | /* | 144 | /* |
144 | * sctp/primitive.c | 145 | * sctp/primitive.c |
@@ -444,6 +445,19 @@ static inline struct list_head *sctp_list_dequeue(struct list_head *list) | |||
444 | return result; | 445 | return result; |
445 | } | 446 | } |
446 | 447 | ||
448 | /* SCTP version of skb_set_owner_r. We need this one because | ||
449 | * of the way we have to do receive buffer accounting on bundled | ||
450 | * chunks. | ||
451 | */ | ||
452 | static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) | ||
453 | { | ||
454 | struct sctp_ulpevent *event = sctp_skb2event(skb); | ||
455 | |||
456 | skb->sk = sk; | ||
457 | skb->destructor = sctp_sock_rfree; | ||
458 | atomic_add(event->rmem_len, &sk->sk_rmem_alloc); | ||
459 | } | ||
460 | |||
447 | /* Tests if the list has one and only one entry. */ | 461 | /* Tests if the list has one and only one entry. */ |
448 | static inline int sctp_list_single_entry(struct list_head *head) | 462 | static inline int sctp_list_single_entry(struct list_head *head) |
449 | { | 463 | { |
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 6c40cfc4832d..1a4ddc1ec7d2 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h | |||
@@ -63,6 +63,7 @@ struct sctp_ulpevent { | |||
63 | __u32 cumtsn; | 63 | __u32 cumtsn; |
64 | int msg_flags; | 64 | int msg_flags; |
65 | int iif; | 65 | int iif; |
66 | unsigned int rmem_len; | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | /* Retrieve the skb this event sits inside of. */ | 69 | /* Retrieve the skb this event sits inside of. */ |
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h index 2544281e1d5e..be293d795e38 100644 --- a/include/net/timewait_sock.h +++ b/include/net/timewait_sock.h | |||
@@ -19,6 +19,7 @@ struct timewait_sock_ops { | |||
19 | unsigned int twsk_obj_size; | 19 | unsigned int twsk_obj_size; |
20 | int (*twsk_unique)(struct sock *sk, | 20 | int (*twsk_unique)(struct sock *sk, |
21 | struct sock *sktw, void *twp); | 21 | struct sock *sktw, void *twp); |
22 | void (*twsk_destructor)(struct sock *sk); | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp) | 25 | static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp) |
@@ -28,4 +29,10 @@ static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp) | |||
28 | return 0; | 29 | return 0; |
29 | } | 30 | } |
30 | 31 | ||
32 | static inline void twsk_destructor(struct sock *sk) | ||
33 | { | ||
34 | if (sk->sk_prot->twsk_prot->twsk_destructor != NULL) | ||
35 | sk->sk_prot->twsk_prot->twsk_destructor(sk); | ||
36 | } | ||
37 | |||
31 | #endif /* _TIMEWAIT_SOCK_H */ | 38 | #endif /* _TIMEWAIT_SOCK_H */ |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 1e2a4ddec96e..737fdb2ee8a4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -995,7 +995,8 @@ struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | |||
995 | int create, unsigned short family); | 995 | int create, unsigned short family); |
996 | extern void xfrm_policy_flush(u8 type); | 996 | extern void xfrm_policy_flush(u8 type); |
997 | extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); | 997 | extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); |
998 | extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict); | 998 | extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, |
999 | struct flowi *fl, int family, int strict); | ||
999 | extern void xfrm_init_pmtu(struct dst_entry *dst); | 1000 | extern void xfrm_init_pmtu(struct dst_entry *dst); |
1000 | 1001 | ||
1001 | extern wait_queue_head_t km_waitq; | 1002 | extern wait_queue_head_t km_waitq; |
diff --git a/net/compat.c b/net/compat.c index d5d69fa15d07..52d32f1bc728 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -285,8 +285,7 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) | |||
285 | 285 | ||
286 | if (i > 0) { | 286 | if (i > 0) { |
287 | int cmlen = CMSG_COMPAT_LEN(i * sizeof(int)); | 287 | int cmlen = CMSG_COMPAT_LEN(i * sizeof(int)); |
288 | if (!err) | 288 | err = put_user(SOL_SOCKET, &cm->cmsg_level); |
289 | err = put_user(SOL_SOCKET, &cm->cmsg_level); | ||
290 | if (!err) | 289 | if (!err) |
291 | err = put_user(SCM_RIGHTS, &cm->cmsg_type); | 290 | err = put_user(SCM_RIGHTS, &cm->cmsg_type); |
292 | if (!err) | 291 | if (!err) |
diff --git a/net/core/flow.c b/net/core/flow.c index f23e7e386543..b16d31ae5e54 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
@@ -85,6 +85,14 @@ static void flow_cache_new_hashrnd(unsigned long arg) | |||
85 | add_timer(&flow_hash_rnd_timer); | 85 | add_timer(&flow_hash_rnd_timer); |
86 | } | 86 | } |
87 | 87 | ||
88 | static void flow_entry_kill(int cpu, struct flow_cache_entry *fle) | ||
89 | { | ||
90 | if (fle->object) | ||
91 | atomic_dec(fle->object_ref); | ||
92 | kmem_cache_free(flow_cachep, fle); | ||
93 | flow_count(cpu)--; | ||
94 | } | ||
95 | |||
88 | static void __flow_cache_shrink(int cpu, int shrink_to) | 96 | static void __flow_cache_shrink(int cpu, int shrink_to) |
89 | { | 97 | { |
90 | struct flow_cache_entry *fle, **flp; | 98 | struct flow_cache_entry *fle, **flp; |
@@ -100,10 +108,7 @@ static void __flow_cache_shrink(int cpu, int shrink_to) | |||
100 | } | 108 | } |
101 | while ((fle = *flp) != NULL) { | 109 | while ((fle = *flp) != NULL) { |
102 | *flp = fle->next; | 110 | *flp = fle->next; |
103 | if (fle->object) | 111 | flow_entry_kill(cpu, fle); |
104 | atomic_dec(fle->object_ref); | ||
105 | kmem_cache_free(flow_cachep, fle); | ||
106 | flow_count(cpu)--; | ||
107 | } | 112 | } |
108 | } | 113 | } |
109 | } | 114 | } |
@@ -220,24 +225,33 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, | |||
220 | 225 | ||
221 | nocache: | 226 | nocache: |
222 | { | 227 | { |
228 | int err; | ||
223 | void *obj; | 229 | void *obj; |
224 | atomic_t *obj_ref; | 230 | atomic_t *obj_ref; |
225 | 231 | ||
226 | resolver(key, family, dir, &obj, &obj_ref); | 232 | err = resolver(key, family, dir, &obj, &obj_ref); |
227 | 233 | ||
228 | if (fle) { | 234 | if (fle) { |
229 | fle->genid = atomic_read(&flow_cache_genid); | 235 | if (err) { |
230 | 236 | /* Force security policy check on next lookup */ | |
231 | if (fle->object) | 237 | *head = fle->next; |
232 | atomic_dec(fle->object_ref); | 238 | flow_entry_kill(cpu, fle); |
233 | 239 | } else { | |
234 | fle->object = obj; | 240 | fle->genid = atomic_read(&flow_cache_genid); |
235 | fle->object_ref = obj_ref; | 241 | |
236 | if (obj) | 242 | if (fle->object) |
237 | atomic_inc(fle->object_ref); | 243 | atomic_dec(fle->object_ref); |
244 | |||
245 | fle->object = obj; | ||
246 | fle->object_ref = obj_ref; | ||
247 | if (obj) | ||
248 | atomic_inc(fle->object_ref); | ||
249 | } | ||
238 | } | 250 | } |
239 | local_bh_enable(); | 251 | local_bh_enable(); |
240 | 252 | ||
253 | if (err) | ||
254 | obj = ERR_PTR(err); | ||
241 | return obj; | 255 | return obj; |
242 | } | 256 | } |
243 | } | 257 | } |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 221e4038216b..02f3c7947898 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -602,7 +602,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
602 | goto errout; | 602 | goto errout; |
603 | } | 603 | } |
604 | 604 | ||
605 | err = rtnl_unicast(skb, NETLINK_CB(skb).pid); | 605 | err = rtnl_unicast(nskb, NETLINK_CB(skb).pid); |
606 | errout: | 606 | errout: |
607 | kfree(iw_buf); | 607 | kfree(iw_buf); |
608 | dev_put(dev); | 608 | dev_put(dev); |
diff --git a/net/core/scm.c b/net/core/scm.c index 649d01ef35b6..271cf060ef8c 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -245,8 +245,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
245 | if (i > 0) | 245 | if (i > 0) |
246 | { | 246 | { |
247 | int cmlen = CMSG_LEN(i*sizeof(int)); | 247 | int cmlen = CMSG_LEN(i*sizeof(int)); |
248 | if (!err) | 248 | err = put_user(SOL_SOCKET, &cm->cmsg_level); |
249 | err = put_user(SOL_SOCKET, &cm->cmsg_level); | ||
250 | if (!err) | 249 | if (!err) |
251 | err = put_user(SCM_RIGHTS, &cm->cmsg_type); | 250 | err = put_user(SCM_RIGHTS, &cm->cmsg_type); |
252 | if (!err) | 251 | if (!err) |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index bf692c1c116f..7e746c4c1688 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -311,7 +311,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) | |||
311 | } | 311 | } |
312 | 312 | ||
313 | if (sk->sk_state == DCCP_TIME_WAIT) { | 313 | if (sk->sk_state == DCCP_TIME_WAIT) { |
314 | inet_twsk_put((struct inet_timewait_sock *)sk); | 314 | inet_twsk_put(inet_twsk(sk)); |
315 | return; | 315 | return; |
316 | } | 316 | } |
317 | 317 | ||
@@ -614,7 +614,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
614 | bh_lock_sock(nsk); | 614 | bh_lock_sock(nsk); |
615 | return nsk; | 615 | return nsk; |
616 | } | 616 | } |
617 | inet_twsk_put((struct inet_timewait_sock *)nsk); | 617 | inet_twsk_put(inet_twsk(nsk)); |
618 | return NULL; | 618 | return NULL; |
619 | } | 619 | } |
620 | 620 | ||
@@ -980,7 +980,7 @@ discard_and_relse: | |||
980 | goto discard_it; | 980 | goto discard_it; |
981 | 981 | ||
982 | do_time_wait: | 982 | do_time_wait: |
983 | inet_twsk_put((struct inet_timewait_sock *)sk); | 983 | inet_twsk_put(inet_twsk(sk)); |
984 | goto no_dccp_socket; | 984 | goto no_dccp_socket; |
985 | } | 985 | } |
986 | 986 | ||
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 7a47399cf31f..7171a78671aa 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -285,7 +285,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
285 | } | 285 | } |
286 | 286 | ||
287 | if (sk->sk_state == DCCP_TIME_WAIT) { | 287 | if (sk->sk_state == DCCP_TIME_WAIT) { |
288 | inet_twsk_put((struct inet_timewait_sock *)sk); | 288 | inet_twsk_put(inet_twsk(sk)); |
289 | return; | 289 | return; |
290 | } | 290 | } |
291 | 291 | ||
@@ -663,7 +663,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
663 | bh_lock_sock(nsk); | 663 | bh_lock_sock(nsk); |
664 | return nsk; | 664 | return nsk; |
665 | } | 665 | } |
666 | inet_twsk_put((struct inet_timewait_sock *)nsk); | 666 | inet_twsk_put(inet_twsk(nsk)); |
667 | return NULL; | 667 | return NULL; |
668 | } | 668 | } |
669 | 669 | ||
@@ -1109,7 +1109,7 @@ discard_and_relse: | |||
1109 | goto discard_it; | 1109 | goto discard_it; |
1110 | 1110 | ||
1111 | do_time_wait: | 1111 | do_time_wait: |
1112 | inet_twsk_put((struct inet_timewait_sock *)sk); | 1112 | inet_twsk_put(inet_twsk(sk)); |
1113 | goto no_dccp_socket; | 1113 | goto no_dccp_socket; |
1114 | } | 1114 | } |
1115 | 1115 | ||
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 70e027375682..3456cd331835 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -1178,8 +1178,10 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len | |||
1178 | if (peer) { | 1178 | if (peer) { |
1179 | if ((sock->state != SS_CONNECTED && | 1179 | if ((sock->state != SS_CONNECTED && |
1180 | sock->state != SS_CONNECTING) && | 1180 | sock->state != SS_CONNECTING) && |
1181 | scp->accept_mode == ACC_IMMED) | 1181 | scp->accept_mode == ACC_IMMED) { |
1182 | release_sock(sk); | ||
1182 | return -ENOTCONN; | 1183 | return -ENOTCONN; |
1184 | } | ||
1183 | 1185 | ||
1184 | memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn)); | 1186 | memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn)); |
1185 | } else { | 1187 | } else { |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index dd0761e3d280..a2a43d8d93fe 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -267,9 +267,14 @@ static void dn_dst_link_failure(struct sk_buff *skb) | |||
267 | 267 | ||
268 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | 268 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) |
269 | { | 269 | { |
270 | return memcmp(&fl1->nl_u.dn_u, &fl2->nl_u.dn_u, sizeof(fl1->nl_u.dn_u)) == 0 && | 270 | return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | |
271 | fl1->oif == fl2->oif && | 271 | (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | |
272 | fl1->iif == fl2->iif; | 272 | #ifdef CONFIG_IP_ROUTE_FWMARK |
273 | (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) | | ||
274 | #endif | ||
275 | (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | | ||
276 | (fl1->oif ^ fl2->oif) | | ||
277 | (fl1->iif ^ fl2->iif)) == 0; | ||
273 | } | 278 | } |
274 | 279 | ||
275 | static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) | 280 | static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index a8e2e879a647..bde8ccaa1531 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <net/tcp.h> | 43 | #include <net/tcp.h> |
44 | #include <net/netlabel.h> | 44 | #include <net/netlabel.h> |
45 | #include <net/cipso_ipv4.h> | 45 | #include <net/cipso_ipv4.h> |
46 | #include <asm/atomic.h> | ||
46 | #include <asm/bug.h> | 47 | #include <asm/bug.h> |
47 | 48 | ||
48 | struct cipso_v4_domhsh_entry { | 49 | struct cipso_v4_domhsh_entry { |
@@ -79,7 +80,7 @@ struct cipso_v4_map_cache_entry { | |||
79 | unsigned char *key; | 80 | unsigned char *key; |
80 | size_t key_len; | 81 | size_t key_len; |
81 | 82 | ||
82 | struct netlbl_lsm_cache lsm_data; | 83 | struct netlbl_lsm_cache *lsm_data; |
83 | 84 | ||
84 | u32 activity; | 85 | u32 activity; |
85 | struct list_head list; | 86 | struct list_head list; |
@@ -188,13 +189,14 @@ static void cipso_v4_doi_domhsh_free(struct rcu_head *entry) | |||
188 | * @entry: the entry to free | 189 | * @entry: the entry to free |
189 | * | 190 | * |
190 | * Description: | 191 | * Description: |
191 | * This function frees the memory associated with a cache entry. | 192 | * This function frees the memory associated with a cache entry including the |
193 | * LSM cache data if there are no longer any users, i.e. reference count == 0. | ||
192 | * | 194 | * |
193 | */ | 195 | */ |
194 | static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) | 196 | static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) |
195 | { | 197 | { |
196 | if (entry->lsm_data.free) | 198 | if (entry->lsm_data) |
197 | entry->lsm_data.free(entry->lsm_data.data); | 199 | netlbl_secattr_cache_free(entry->lsm_data); |
198 | kfree(entry->key); | 200 | kfree(entry->key); |
199 | kfree(entry); | 201 | kfree(entry); |
200 | } | 202 | } |
@@ -315,8 +317,8 @@ static int cipso_v4_cache_check(const unsigned char *key, | |||
315 | entry->key_len == key_len && | 317 | entry->key_len == key_len && |
316 | memcmp(entry->key, key, key_len) == 0) { | 318 | memcmp(entry->key, key, key_len) == 0) { |
317 | entry->activity += 1; | 319 | entry->activity += 1; |
318 | secattr->cache.free = entry->lsm_data.free; | 320 | atomic_inc(&entry->lsm_data->refcount); |
319 | secattr->cache.data = entry->lsm_data.data; | 321 | secattr->cache = entry->lsm_data; |
320 | if (prev_entry == NULL) { | 322 | if (prev_entry == NULL) { |
321 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); | 323 | spin_unlock_bh(&cipso_v4_cache[bkt].lock); |
322 | return 0; | 324 | return 0; |
@@ -383,8 +385,8 @@ int cipso_v4_cache_add(const struct sk_buff *skb, | |||
383 | memcpy(entry->key, cipso_ptr, cipso_ptr_len); | 385 | memcpy(entry->key, cipso_ptr, cipso_ptr_len); |
384 | entry->key_len = cipso_ptr_len; | 386 | entry->key_len = cipso_ptr_len; |
385 | entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); | 387 | entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); |
386 | entry->lsm_data.free = secattr->cache.free; | 388 | atomic_inc(&secattr->cache->refcount); |
387 | entry->lsm_data.data = secattr->cache.data; | 389 | entry->lsm_data = secattr->cache; |
388 | 390 | ||
389 | bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); | 391 | bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); |
390 | spin_lock_bh(&cipso_v4_cache[bkt].lock); | 392 | spin_lock_bh(&cipso_v4_cache[bkt].lock); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index f5fba051df3d..d5b5dec075b8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -611,8 +611,8 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
611 | * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header | 611 | * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header |
612 | */ | 612 | */ |
613 | if (flags == 0 && | 613 | if (flags == 0 && |
614 | skb->protocol == __constant_htons(ETH_P_WCCP)) { | 614 | skb->protocol == htons(ETH_P_WCCP)) { |
615 | skb->protocol = __constant_htons(ETH_P_IP); | 615 | skb->protocol = htons(ETH_P_IP); |
616 | if ((*(h + offset) & 0xF0) != 0x40) | 616 | if ((*(h + offset) & 0xF0) != 0x40) |
617 | offset += 4; | 617 | offset += 4; |
618 | } | 618 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c41ddba02e9d..925ee4dfc32c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -566,9 +566,15 @@ static inline u32 rt_score(struct rtable *rt) | |||
566 | 566 | ||
567 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | 567 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) |
568 | { | 568 | { |
569 | return memcmp(&fl1->nl_u.ip4_u, &fl2->nl_u.ip4_u, sizeof(fl1->nl_u.ip4_u)) == 0 && | 569 | return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | |
570 | fl1->oif == fl2->oif && | 570 | (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | |
571 | fl1->iif == fl2->iif; | 571 | #ifdef CONFIG_IP_ROUTE_FWMARK |
572 | (fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) | | ||
573 | #endif | ||
574 | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ | ||
575 | *(u16 *)&fl2->nl_u.ip4_u.tos) | | ||
576 | (fl1->oif ^ fl2->oif) | | ||
577 | (fl1->iif ^ fl2->iif)) == 0; | ||
572 | } | 578 | } |
573 | 579 | ||
574 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | 580 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c83938b8fcb1..6bbd98575172 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -355,7 +355,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) | |||
355 | return; | 355 | return; |
356 | } | 356 | } |
357 | if (sk->sk_state == TCP_TIME_WAIT) { | 357 | if (sk->sk_state == TCP_TIME_WAIT) { |
358 | inet_twsk_put((struct inet_timewait_sock *)sk); | 358 | inet_twsk_put(inet_twsk(sk)); |
359 | return; | 359 | return; |
360 | } | 360 | } |
361 | 361 | ||
@@ -578,7 +578,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
578 | struct tcphdr *th = skb->h.th; | 578 | struct tcphdr *th = skb->h.th; |
579 | struct { | 579 | struct { |
580 | struct tcphdr th; | 580 | struct tcphdr th; |
581 | u32 tsopt[3]; | 581 | u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2]; |
582 | } rep; | 582 | } rep; |
583 | struct ip_reply_arg arg; | 583 | struct ip_reply_arg arg; |
584 | 584 | ||
@@ -960,7 +960,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
960 | bh_lock_sock(nsk); | 960 | bh_lock_sock(nsk); |
961 | return nsk; | 961 | return nsk; |
962 | } | 962 | } |
963 | inet_twsk_put((struct inet_timewait_sock *)nsk); | 963 | inet_twsk_put(inet_twsk(nsk)); |
964 | return NULL; | 964 | return NULL; |
965 | } | 965 | } |
966 | 966 | ||
@@ -1154,26 +1154,24 @@ discard_and_relse: | |||
1154 | 1154 | ||
1155 | do_time_wait: | 1155 | do_time_wait: |
1156 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 1156 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
1157 | inet_twsk_put((struct inet_timewait_sock *) sk); | 1157 | inet_twsk_put(inet_twsk(sk)); |
1158 | goto discard_it; | 1158 | goto discard_it; |
1159 | } | 1159 | } |
1160 | 1160 | ||
1161 | if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { | 1161 | if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) { |
1162 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1162 | TCP_INC_STATS_BH(TCP_MIB_INERRS); |
1163 | inet_twsk_put((struct inet_timewait_sock *) sk); | 1163 | inet_twsk_put(inet_twsk(sk)); |
1164 | goto discard_it; | 1164 | goto discard_it; |
1165 | } | 1165 | } |
1166 | switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk, | 1166 | switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { |
1167 | skb, th)) { | ||
1168 | case TCP_TW_SYN: { | 1167 | case TCP_TW_SYN: { |
1169 | struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo, | 1168 | struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo, |
1170 | skb->nh.iph->daddr, | 1169 | skb->nh.iph->daddr, |
1171 | th->dest, | 1170 | th->dest, |
1172 | inet_iif(skb)); | 1171 | inet_iif(skb)); |
1173 | if (sk2) { | 1172 | if (sk2) { |
1174 | inet_twsk_deschedule((struct inet_timewait_sock *)sk, | 1173 | inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row); |
1175 | &tcp_death_row); | 1174 | inet_twsk_put(inet_twsk(sk)); |
1176 | inet_twsk_put((struct inet_timewait_sock *)sk); | ||
1177 | sk = sk2; | 1175 | sk = sk2; |
1178 | goto process; | 1176 | goto process; |
1179 | } | 1177 | } |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9a253faefc81..f22536e32cb1 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -273,10 +273,10 @@ static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, | |||
273 | __u32 tstamp) | 273 | __u32 tstamp) |
274 | { | 274 | { |
275 | if (tp->rx_opt.tstamp_ok) { | 275 | if (tp->rx_opt.tstamp_ok) { |
276 | *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | | 276 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
277 | (TCPOPT_NOP << 16) | | 277 | (TCPOPT_NOP << 16) | |
278 | (TCPOPT_TIMESTAMP << 8) | | 278 | (TCPOPT_TIMESTAMP << 8) | |
279 | TCPOLEN_TIMESTAMP); | 279 | TCPOLEN_TIMESTAMP); |
280 | *ptr++ = htonl(tstamp); | 280 | *ptr++ = htonl(tstamp); |
281 | *ptr++ = htonl(tp->rx_opt.ts_recent); | 281 | *ptr++ = htonl(tp->rx_opt.ts_recent); |
282 | } | 282 | } |
@@ -325,18 +325,27 @@ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack, | |||
325 | *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss); | 325 | *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss); |
326 | if (ts) { | 326 | if (ts) { |
327 | if(sack) | 327 | if(sack) |
328 | *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) | | 328 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | |
329 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); | 329 | (TCPOLEN_SACK_PERM << 16) | |
330 | (TCPOPT_TIMESTAMP << 8) | | ||
331 | TCPOLEN_TIMESTAMP); | ||
330 | else | 332 | else |
331 | *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 333 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
332 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); | 334 | (TCPOPT_NOP << 16) | |
335 | (TCPOPT_TIMESTAMP << 8) | | ||
336 | TCPOLEN_TIMESTAMP); | ||
333 | *ptr++ = htonl(tstamp); /* TSVAL */ | 337 | *ptr++ = htonl(tstamp); /* TSVAL */ |
334 | *ptr++ = htonl(ts_recent); /* TSECR */ | 338 | *ptr++ = htonl(ts_recent); /* TSECR */ |
335 | } else if(sack) | 339 | } else if(sack) |
336 | *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 340 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
337 | (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM); | 341 | (TCPOPT_NOP << 16) | |
342 | (TCPOPT_SACK_PERM << 8) | | ||
343 | TCPOLEN_SACK_PERM); | ||
338 | if (offer_wscale) | 344 | if (offer_wscale) |
339 | *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale)); | 345 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
346 | (TCPOPT_WINDOW << 16) | | ||
347 | (TCPOLEN_WINDOW << 8) | | ||
348 | (wscale)); | ||
340 | } | 349 | } |
341 | 350 | ||
342 | /* This routine actually transmits TCP packets queued in by | 351 | /* This routine actually transmits TCP packets queued in by |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 7a7a00147e55..1bed0cdf53e3 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -52,7 +52,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | |||
52 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && | 52 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && |
53 | xdst->u.rt.fl.fl4_src == fl->fl4_src && | 53 | xdst->u.rt.fl.fl4_src == fl->fl4_src && |
54 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && | 54 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && |
55 | xfrm_bundle_ok(xdst, fl, AF_INET, 0)) { | 55 | xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) { |
56 | dst_clone(dst); | 56 | dst_clone(dst); |
57 | break; | 57 | break; |
58 | } | 58 | } |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index a460e8132b4d..ef5eaad44851 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -153,6 +153,19 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION | |||
153 | ---help--- | 153 | ---help--- |
154 | Support for MIPv6 route optimization mode. | 154 | Support for MIPv6 route optimization mode. |
155 | 155 | ||
156 | config IPV6_SIT | ||
157 | tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)" | ||
158 | depends on IPV6 | ||
159 | default y | ||
160 | ---help--- | ||
161 | Tunneling means encapsulating data of one protocol type within | ||
162 | another protocol and sending it over a channel that understands the | ||
163 | encapsulating protocol. This driver implements encapsulation of IPv6 | ||
164 | into IPv4 packets. This is useful if you want to connect two IPv6 | ||
165 | networks over an IPv4-only path. | ||
166 | |||
167 | Saying M here will produce a module called sit.ko. If unsure, say Y. | ||
168 | |||
156 | config IPV6_TUNNEL | 169 | config IPV6_TUNNEL |
157 | tristate "IPv6: IPv6-in-IPv6 tunnel" | 170 | tristate "IPv6: IPv6-in-IPv6 tunnel" |
158 | select INET6_TUNNEL | 171 | select INET6_TUNNEL |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 87274e47fe32..addcc011bc01 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_IPV6) += ipv6.o | 5 | obj-$(CONFIG_IPV6) += ipv6.o |
6 | 6 | ||
7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ | 7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ |
8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ | 8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ |
9 | protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ | 9 | protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ |
10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ | 10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ |
@@ -29,6 +29,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o | |||
29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | 29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o |
30 | obj-$(CONFIG_NETFILTER) += netfilter/ | 30 | obj-$(CONFIG_NETFILTER) += netfilter/ |
31 | 31 | ||
32 | obj-$(CONFIG_IPV6_SIT) += sit.o | ||
32 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 33 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
33 | 34 | ||
34 | obj-y += exthdrs_core.o | 35 | obj-y += exthdrs_core.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e03c33b2465b..b312a5f7a759 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -396,8 +396,10 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
396 | ndev->regen_timer.data = (unsigned long) ndev; | 396 | ndev->regen_timer.data = (unsigned long) ndev; |
397 | if ((dev->flags&IFF_LOOPBACK) || | 397 | if ((dev->flags&IFF_LOOPBACK) || |
398 | dev->type == ARPHRD_TUNNEL || | 398 | dev->type == ARPHRD_TUNNEL || |
399 | dev->type == ARPHRD_NONE || | 399 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
400 | dev->type == ARPHRD_SIT) { | 400 | dev->type == ARPHRD_SIT || |
401 | #endif | ||
402 | dev->type == ARPHRD_NONE) { | ||
401 | printk(KERN_INFO | 403 | printk(KERN_INFO |
402 | "%s: Disabled Privacy Extensions\n", | 404 | "%s: Disabled Privacy Extensions\n", |
403 | dev->name); | 405 | dev->name); |
@@ -1546,8 +1548,10 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
1546 | This thing is done here expecting that the whole | 1548 | This thing is done here expecting that the whole |
1547 | class of non-broadcast devices need not cloning. | 1549 | class of non-broadcast devices need not cloning. |
1548 | */ | 1550 | */ |
1551 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | ||
1549 | if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT)) | 1552 | if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT)) |
1550 | cfg.fc_flags |= RTF_NONEXTHOP; | 1553 | cfg.fc_flags |= RTF_NONEXTHOP; |
1554 | #endif | ||
1551 | 1555 | ||
1552 | ip6_route_add(&cfg); | 1556 | ip6_route_add(&cfg); |
1553 | } | 1557 | } |
@@ -1569,6 +1573,7 @@ static void addrconf_add_mroute(struct net_device *dev) | |||
1569 | ip6_route_add(&cfg); | 1573 | ip6_route_add(&cfg); |
1570 | } | 1574 | } |
1571 | 1575 | ||
1576 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | ||
1572 | static void sit_route_add(struct net_device *dev) | 1577 | static void sit_route_add(struct net_device *dev) |
1573 | { | 1578 | { |
1574 | struct fib6_config cfg = { | 1579 | struct fib6_config cfg = { |
@@ -1582,6 +1587,7 @@ static void sit_route_add(struct net_device *dev) | |||
1582 | /* prefix length - 96 bits "::d.d.d.d" */ | 1587 | /* prefix length - 96 bits "::d.d.d.d" */ |
1583 | ip6_route_add(&cfg); | 1588 | ip6_route_add(&cfg); |
1584 | } | 1589 | } |
1590 | #endif | ||
1585 | 1591 | ||
1586 | static void addrconf_add_lroute(struct net_device *dev) | 1592 | static void addrconf_add_lroute(struct net_device *dev) |
1587 | { | 1593 | { |
@@ -1852,6 +1858,7 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1852 | if (dev == NULL) | 1858 | if (dev == NULL) |
1853 | goto err_exit; | 1859 | goto err_exit; |
1854 | 1860 | ||
1861 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | ||
1855 | if (dev->type == ARPHRD_SIT) { | 1862 | if (dev->type == ARPHRD_SIT) { |
1856 | struct ifreq ifr; | 1863 | struct ifreq ifr; |
1857 | mm_segment_t oldfs; | 1864 | mm_segment_t oldfs; |
@@ -1881,6 +1888,7 @@ int addrconf_set_dstaddr(void __user *arg) | |||
1881 | err = dev_open(dev); | 1888 | err = dev_open(dev); |
1882 | } | 1889 | } |
1883 | } | 1890 | } |
1891 | #endif | ||
1884 | 1892 | ||
1885 | err_exit: | 1893 | err_exit: |
1886 | rtnl_unlock(); | 1894 | rtnl_unlock(); |
@@ -2010,6 +2018,7 @@ int addrconf_del_ifaddr(void __user *arg) | |||
2010 | return err; | 2018 | return err; |
2011 | } | 2019 | } |
2012 | 2020 | ||
2021 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | ||
2013 | static void sit_add_v4_addrs(struct inet6_dev *idev) | 2022 | static void sit_add_v4_addrs(struct inet6_dev *idev) |
2014 | { | 2023 | { |
2015 | struct inet6_ifaddr * ifp; | 2024 | struct inet6_ifaddr * ifp; |
@@ -2078,6 +2087,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2078 | } | 2087 | } |
2079 | } | 2088 | } |
2080 | } | 2089 | } |
2090 | #endif | ||
2081 | 2091 | ||
2082 | static void init_loopback(struct net_device *dev) | 2092 | static void init_loopback(struct net_device *dev) |
2083 | { | 2093 | { |
@@ -2141,6 +2151,7 @@ static void addrconf_dev_config(struct net_device *dev) | |||
2141 | addrconf_add_linklocal(idev, &addr); | 2151 | addrconf_add_linklocal(idev, &addr); |
2142 | } | 2152 | } |
2143 | 2153 | ||
2154 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | ||
2144 | static void addrconf_sit_config(struct net_device *dev) | 2155 | static void addrconf_sit_config(struct net_device *dev) |
2145 | { | 2156 | { |
2146 | struct inet6_dev *idev; | 2157 | struct inet6_dev *idev; |
@@ -2166,6 +2177,7 @@ static void addrconf_sit_config(struct net_device *dev) | |||
2166 | } else | 2177 | } else |
2167 | sit_route_add(dev); | 2178 | sit_route_add(dev); |
2168 | } | 2179 | } |
2180 | #endif | ||
2169 | 2181 | ||
2170 | static inline int | 2182 | static inline int |
2171 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | 2183 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) |
@@ -2260,9 +2272,11 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2260 | } | 2272 | } |
2261 | 2273 | ||
2262 | switch(dev->type) { | 2274 | switch(dev->type) { |
2275 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | ||
2263 | case ARPHRD_SIT: | 2276 | case ARPHRD_SIT: |
2264 | addrconf_sit_config(dev); | 2277 | addrconf_sit_config(dev); |
2265 | break; | 2278 | break; |
2279 | #endif | ||
2266 | case ARPHRD_TUNNEL6: | 2280 | case ARPHRD_TUNNEL6: |
2267 | addrconf_ip6_tnl_config(dev); | 2281 | addrconf_ip6_tnl_config(dev); |
2268 | break; | 2282 | break; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e94eccb99707..858cae29581c 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -850,7 +850,6 @@ static int __init inet6_init(void) | |||
850 | err = addrconf_init(); | 850 | err = addrconf_init(); |
851 | if (err) | 851 | if (err) |
852 | goto addrconf_fail; | 852 | goto addrconf_fail; |
853 | sit_init(); | ||
854 | 853 | ||
855 | /* Init v6 extension headers. */ | 854 | /* Init v6 extension headers. */ |
856 | ipv6_rthdr_init(); | 855 | ipv6_rthdr_init(); |
@@ -927,7 +926,6 @@ static void __exit inet6_exit(void) | |||
927 | mip6_fini(); | 926 | mip6_fini(); |
928 | #endif | 927 | #endif |
929 | /* Cleanup code parts. */ | 928 | /* Cleanup code parts. */ |
930 | sit_cleanup(); | ||
931 | ip6_flowlabel_cleanup(); | 929 | ip6_flowlabel_cleanup(); |
932 | addrconf_cleanup(); | 930 | addrconf_cleanup(); |
933 | ip6_route_cleanup(); | 931 | ip6_route_cleanup(); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 836eecd7e62b..dc5765b62b87 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -850,3 +850,6 @@ int __init sit_init(void) | |||
850 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); | 850 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); |
851 | goto out; | 851 | goto out; |
852 | } | 852 | } |
853 | |||
854 | module_init(sit_init); | ||
855 | module_exit(sit_cleanup); | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3b6575478fcc..4c2a7c0cafef 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -329,7 +329,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
329 | } | 329 | } |
330 | 330 | ||
331 | if (sk->sk_state == TCP_TIME_WAIT) { | 331 | if (sk->sk_state == TCP_TIME_WAIT) { |
332 | inet_twsk_put((struct inet_timewait_sock *)sk); | 332 | inet_twsk_put(inet_twsk(sk)); |
333 | return; | 333 | return; |
334 | } | 334 | } |
335 | 335 | ||
@@ -653,7 +653,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
653 | int tot_len = sizeof(struct tcphdr); | 653 | int tot_len = sizeof(struct tcphdr); |
654 | 654 | ||
655 | if (ts) | 655 | if (ts) |
656 | tot_len += 3*4; | 656 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
657 | 657 | ||
658 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, | 658 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, |
659 | GFP_ATOMIC); | 659 | GFP_ATOMIC); |
@@ -749,7 +749,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
749 | bh_lock_sock(nsk); | 749 | bh_lock_sock(nsk); |
750 | return nsk; | 750 | return nsk; |
751 | } | 751 | } |
752 | inet_twsk_put((struct inet_timewait_sock *)nsk); | 752 | inet_twsk_put(inet_twsk(nsk)); |
753 | return NULL; | 753 | return NULL; |
754 | } | 754 | } |
755 | 755 | ||
@@ -1283,18 +1283,17 @@ discard_and_relse: | |||
1283 | 1283 | ||
1284 | do_time_wait: | 1284 | do_time_wait: |
1285 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 1285 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
1286 | inet_twsk_put((struct inet_timewait_sock *)sk); | 1286 | inet_twsk_put(inet_twsk(sk)); |
1287 | goto discard_it; | 1287 | goto discard_it; |
1288 | } | 1288 | } |
1289 | 1289 | ||
1290 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1290 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
1291 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1291 | TCP_INC_STATS_BH(TCP_MIB_INERRS); |
1292 | inet_twsk_put((struct inet_timewait_sock *)sk); | 1292 | inet_twsk_put(inet_twsk(sk)); |
1293 | goto discard_it; | 1293 | goto discard_it; |
1294 | } | 1294 | } |
1295 | 1295 | ||
1296 | switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk, | 1296 | switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { |
1297 | skb, th)) { | ||
1298 | case TCP_TW_SYN: | 1297 | case TCP_TW_SYN: |
1299 | { | 1298 | { |
1300 | struct sock *sk2; | 1299 | struct sock *sk2; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 6a252e2134d1..73cee2ec07e8 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -73,7 +73,7 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | |||
73 | xdst->u.rt6.rt6i_src.plen); | 73 | xdst->u.rt6.rt6i_src.plen); |
74 | if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && | 74 | if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && |
75 | ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && | 75 | ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && |
76 | xfrm_bundle_ok(xdst, fl, AF_INET6, | 76 | xfrm_bundle_ok(policy, xdst, fl, AF_INET6, |
77 | (xdst->u.rt6.rt6i_dst.plen != 128 || | 77 | (xdst->u.rt6.rt6i_dst.plen != 128 || |
78 | xdst->u.rt6.rt6i_src.plen != 128))) { | 78 | xdst->u.rt6.rt6i_src.plen != 128))) { |
79 | dst_clone(dst); | 79 | dst_clone(dst); |
diff --git a/net/key/af_key.c b/net/key/af_key.c index ff98e70b0931..20ff7cca1d07 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -2928,11 +2928,6 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, | |||
2928 | if (*dir) | 2928 | if (*dir) |
2929 | goto out; | 2929 | goto out; |
2930 | } | 2930 | } |
2931 | else { | ||
2932 | *dir = security_xfrm_sock_policy_alloc(xp, sk); | ||
2933 | if (*dir) | ||
2934 | goto out; | ||
2935 | } | ||
2936 | 2931 | ||
2937 | *dir = pol->sadb_x_policy_dir-1; | 2932 | *dir = pol->sadb_x_policy_dir-1; |
2938 | return xp; | 2933 | return xp; |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 54fb7de3c2b1..ff971103fd0c 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -200,7 +200,7 @@ void netlbl_cache_invalidate(void) | |||
200 | int netlbl_cache_add(const struct sk_buff *skb, | 200 | int netlbl_cache_add(const struct sk_buff *skb, |
201 | const struct netlbl_lsm_secattr *secattr) | 201 | const struct netlbl_lsm_secattr *secattr) |
202 | { | 202 | { |
203 | if (secattr->cache.data == NULL) | 203 | if (secattr->cache == NULL) |
204 | return -ENOMSG; | 204 | return -ENOMSG; |
205 | 205 | ||
206 | if (CIPSO_V4_OPTEXIST(skb)) | 206 | if (CIPSO_V4_OPTEXIST(skb)) |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index bb3ddd4784b1..9b9c555c713f 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -786,11 +786,10 @@ static long htb_do_events(struct htb_sched *q, int level) | |||
786 | for (i = 0; i < 500; i++) { | 786 | for (i = 0; i < 500; i++) { |
787 | struct htb_class *cl; | 787 | struct htb_class *cl; |
788 | long diff; | 788 | long diff; |
789 | struct rb_node *p = q->wait_pq[level].rb_node; | 789 | struct rb_node *p = rb_first(&q->wait_pq[level]); |
790 | |||
790 | if (!p) | 791 | if (!p) |
791 | return 0; | 792 | return 0; |
792 | while (p->rb_left) | ||
793 | p = p->rb_left; | ||
794 | 793 | ||
795 | cl = rb_entry(p, struct htb_class, pq_node); | 794 | cl = rb_entry(p, struct htb_class, pq_node); |
796 | if (time_after(cl->pq_key, q->jiffies)) { | 795 | if (time_after(cl->pq_key, q->jiffies)) { |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index a356d8d310a9..7f49e769080e 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -344,7 +344,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
344 | assoc, sk, sctp_sk(sk)->type, sk->sk_state, | 344 | assoc, sk, sctp_sk(sk)->type, sk->sk_state, |
345 | assoc->state, hash, assoc->assoc_id, | 345 | assoc->state, hash, assoc->assoc_id, |
346 | assoc->sndbuf_used, | 346 | assoc->sndbuf_used, |
347 | (sk->sk_rcvbuf - assoc->rwnd), | 347 | atomic_read(&assoc->rmem_alloc), |
348 | sock_i_uid(sk), sock_i_ino(sk), | 348 | sock_i_uid(sk), sock_i_ino(sk), |
349 | epb->bind_addr.port, | 349 | epb->bind_addr.port, |
350 | assoc->peer.port); | 350 | assoc->peer.port); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3fe906d65069..9deec4391187 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5362,6 +5362,20 @@ static void sctp_wfree(struct sk_buff *skb) | |||
5362 | sctp_association_put(asoc); | 5362 | sctp_association_put(asoc); |
5363 | } | 5363 | } |
5364 | 5364 | ||
5365 | /* Do accounting for the receive space on the socket. | ||
5366 | * Accounting for the association is done in ulpevent.c | ||
5367 | * We set this as a destructor for the cloned data skbs so that | ||
5368 | * accounting is done at the correct time. | ||
5369 | */ | ||
5370 | void sctp_sock_rfree(struct sk_buff *skb) | ||
5371 | { | ||
5372 | struct sock *sk = skb->sk; | ||
5373 | struct sctp_ulpevent *event = sctp_skb2event(skb); | ||
5374 | |||
5375 | atomic_sub(event->rmem_len, &sk->sk_rmem_alloc); | ||
5376 | } | ||
5377 | |||
5378 | |||
5365 | /* Helper function to wait for space in the sndbuf. */ | 5379 | /* Helper function to wait for space in the sndbuf. */ |
5366 | static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, | 5380 | static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, |
5367 | size_t msg_len) | 5381 | size_t msg_len) |
@@ -5634,10 +5648,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5634 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { | 5648 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { |
5635 | event = sctp_skb2event(skb); | 5649 | event = sctp_skb2event(skb); |
5636 | if (event->asoc == assoc) { | 5650 | if (event->asoc == assoc) { |
5637 | sock_rfree(skb); | 5651 | sctp_sock_rfree(skb); |
5638 | __skb_unlink(skb, &oldsk->sk_receive_queue); | 5652 | __skb_unlink(skb, &oldsk->sk_receive_queue); |
5639 | __skb_queue_tail(&newsk->sk_receive_queue, skb); | 5653 | __skb_queue_tail(&newsk->sk_receive_queue, skb); |
5640 | skb_set_owner_r(skb, newsk); | 5654 | sctp_skb_set_owner_r(skb, newsk); |
5641 | } | 5655 | } |
5642 | } | 5656 | } |
5643 | 5657 | ||
@@ -5665,10 +5679,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5665 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { | 5679 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { |
5666 | event = sctp_skb2event(skb); | 5680 | event = sctp_skb2event(skb); |
5667 | if (event->asoc == assoc) { | 5681 | if (event->asoc == assoc) { |
5668 | sock_rfree(skb); | 5682 | sctp_sock_rfree(skb); |
5669 | __skb_unlink(skb, &oldsp->pd_lobby); | 5683 | __skb_unlink(skb, &oldsp->pd_lobby); |
5670 | __skb_queue_tail(queue, skb); | 5684 | __skb_queue_tail(queue, skb); |
5671 | skb_set_owner_r(skb, newsk); | 5685 | sctp_skb_set_owner_r(skb, newsk); |
5672 | } | 5686 | } |
5673 | } | 5687 | } |
5674 | 5688 | ||
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index ee236784a6bb..a015283a9087 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -55,10 +55,13 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event); | |||
55 | 55 | ||
56 | 56 | ||
57 | /* Initialize an ULP event from an given skb. */ | 57 | /* Initialize an ULP event from an given skb. */ |
58 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) | 58 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, |
59 | int msg_flags, | ||
60 | unsigned int len) | ||
59 | { | 61 | { |
60 | memset(event, 0, sizeof(struct sctp_ulpevent)); | 62 | memset(event, 0, sizeof(struct sctp_ulpevent)); |
61 | event->msg_flags = msg_flags; | 63 | event->msg_flags = msg_flags; |
64 | event->rmem_len = len; | ||
62 | } | 65 | } |
63 | 66 | ||
64 | /* Create a new sctp_ulpevent. */ | 67 | /* Create a new sctp_ulpevent. */ |
@@ -73,7 +76,7 @@ SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, | |||
73 | goto fail; | 76 | goto fail; |
74 | 77 | ||
75 | event = sctp_skb2event(skb); | 78 | event = sctp_skb2event(skb); |
76 | sctp_ulpevent_init(event, msg_flags); | 79 | sctp_ulpevent_init(event, msg_flags, skb->truesize); |
77 | 80 | ||
78 | return event; | 81 | return event; |
79 | 82 | ||
@@ -101,17 +104,16 @@ static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, | |||
101 | sctp_association_hold((struct sctp_association *)asoc); | 104 | sctp_association_hold((struct sctp_association *)asoc); |
102 | skb = sctp_event2skb(event); | 105 | skb = sctp_event2skb(event); |
103 | event->asoc = (struct sctp_association *)asoc; | 106 | event->asoc = (struct sctp_association *)asoc; |
104 | atomic_add(skb->truesize, &event->asoc->rmem_alloc); | 107 | atomic_add(event->rmem_len, &event->asoc->rmem_alloc); |
105 | skb_set_owner_r(skb, asoc->base.sk); | 108 | sctp_skb_set_owner_r(skb, asoc->base.sk); |
106 | } | 109 | } |
107 | 110 | ||
108 | /* A simple destructor to give up the reference to the association. */ | 111 | /* A simple destructor to give up the reference to the association. */ |
109 | static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) | 112 | static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) |
110 | { | 113 | { |
111 | struct sctp_association *asoc = event->asoc; | 114 | struct sctp_association *asoc = event->asoc; |
112 | struct sk_buff *skb = sctp_event2skb(event); | ||
113 | 115 | ||
114 | atomic_sub(skb->truesize, &asoc->rmem_alloc); | 116 | atomic_sub(event->rmem_len, &asoc->rmem_alloc); |
115 | sctp_association_put(asoc); | 117 | sctp_association_put(asoc); |
116 | } | 118 | } |
117 | 119 | ||
@@ -372,7 +374,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error( | |||
372 | 374 | ||
373 | /* Embed the event fields inside the cloned skb. */ | 375 | /* Embed the event fields inside the cloned skb. */ |
374 | event = sctp_skb2event(skb); | 376 | event = sctp_skb2event(skb); |
375 | sctp_ulpevent_init(event, MSG_NOTIFICATION); | 377 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); |
376 | 378 | ||
377 | sre = (struct sctp_remote_error *) | 379 | sre = (struct sctp_remote_error *) |
378 | skb_push(skb, sizeof(struct sctp_remote_error)); | 380 | skb_push(skb, sizeof(struct sctp_remote_error)); |
@@ -464,7 +466,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed( | |||
464 | 466 | ||
465 | /* Embed the event fields inside the cloned skb. */ | 467 | /* Embed the event fields inside the cloned skb. */ |
466 | event = sctp_skb2event(skb); | 468 | event = sctp_skb2event(skb); |
467 | sctp_ulpevent_init(event, MSG_NOTIFICATION); | 469 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); |
468 | 470 | ||
469 | ssf = (struct sctp_send_failed *) | 471 | ssf = (struct sctp_send_failed *) |
470 | skb_push(skb, sizeof(struct sctp_send_failed)); | 472 | skb_push(skb, sizeof(struct sctp_send_failed)); |
@@ -682,8 +684,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, | |||
682 | /* Embed the event fields inside the cloned skb. */ | 684 | /* Embed the event fields inside the cloned skb. */ |
683 | event = sctp_skb2event(skb); | 685 | event = sctp_skb2event(skb); |
684 | 686 | ||
685 | /* Initialize event with flags 0. */ | 687 | /* Initialize event with flags 0 and correct length |
686 | sctp_ulpevent_init(event, 0); | 688 | * Since this is a clone of the original skb, only account for |
689 | * the data of this chunk as other chunks will be accounted separately. | ||
690 | */ | ||
691 | sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff)); | ||
687 | 692 | ||
688 | sctp_ulpevent_receive_data(event, asoc); | 693 | sctp_ulpevent_receive_data(event, asoc); |
689 | 694 | ||
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 575e556aeb3e..e1d144275f97 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -309,7 +309,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu | |||
309 | if (!new) | 309 | if (!new) |
310 | return NULL; /* try again later */ | 310 | return NULL; /* try again later */ |
311 | 311 | ||
312 | new->sk = f_frag->sk; | 312 | sctp_skb_set_owner_r(new, f_frag->sk); |
313 | 313 | ||
314 | skb_shinfo(new)->frag_list = pos; | 314 | skb_shinfo(new)->frag_list = pos; |
315 | } else | 315 | } else |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2a7861661f14..7736b23c3f03 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -883,30 +883,32 @@ out: | |||
883 | } | 883 | } |
884 | EXPORT_SYMBOL(xfrm_policy_walk); | 884 | EXPORT_SYMBOL(xfrm_policy_walk); |
885 | 885 | ||
886 | /* Find policy to apply to this flow. */ | 886 | /* |
887 | 887 | * Find policy to apply to this flow. | |
888 | * | ||
889 | * Returns 0 if policy found, else an -errno. | ||
890 | */ | ||
888 | static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, | 891 | static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, |
889 | u8 type, u16 family, int dir) | 892 | u8 type, u16 family, int dir) |
890 | { | 893 | { |
891 | struct xfrm_selector *sel = &pol->selector; | 894 | struct xfrm_selector *sel = &pol->selector; |
892 | int match; | 895 | int match, ret = -ESRCH; |
893 | 896 | ||
894 | if (pol->family != family || | 897 | if (pol->family != family || |
895 | pol->type != type) | 898 | pol->type != type) |
896 | return 0; | 899 | return ret; |
897 | 900 | ||
898 | match = xfrm_selector_match(sel, fl, family); | 901 | match = xfrm_selector_match(sel, fl, family); |
899 | if (match) { | 902 | if (match) |
900 | if (!security_xfrm_policy_lookup(pol, fl->secid, dir)) | 903 | ret = security_xfrm_policy_lookup(pol, fl->secid, dir); |
901 | return 1; | ||
902 | } | ||
903 | 904 | ||
904 | return 0; | 905 | return ret; |
905 | } | 906 | } |
906 | 907 | ||
907 | static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | 908 | static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, |
908 | u16 family, u8 dir) | 909 | u16 family, u8 dir) |
909 | { | 910 | { |
911 | int err; | ||
910 | struct xfrm_policy *pol, *ret; | 912 | struct xfrm_policy *pol, *ret; |
911 | xfrm_address_t *daddr, *saddr; | 913 | xfrm_address_t *daddr, *saddr; |
912 | struct hlist_node *entry; | 914 | struct hlist_node *entry; |
@@ -922,7 +924,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | |||
922 | chain = policy_hash_direct(daddr, saddr, family, dir); | 924 | chain = policy_hash_direct(daddr, saddr, family, dir); |
923 | ret = NULL; | 925 | ret = NULL; |
924 | hlist_for_each_entry(pol, entry, chain, bydst) { | 926 | hlist_for_each_entry(pol, entry, chain, bydst) { |
925 | if (xfrm_policy_match(pol, fl, type, family, dir)) { | 927 | err = xfrm_policy_match(pol, fl, type, family, dir); |
928 | if (err) { | ||
929 | if (err == -ESRCH) | ||
930 | continue; | ||
931 | else { | ||
932 | ret = ERR_PTR(err); | ||
933 | goto fail; | ||
934 | } | ||
935 | } else { | ||
926 | ret = pol; | 936 | ret = pol; |
927 | priority = ret->priority; | 937 | priority = ret->priority; |
928 | break; | 938 | break; |
@@ -930,36 +940,53 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | |||
930 | } | 940 | } |
931 | chain = &xfrm_policy_inexact[dir]; | 941 | chain = &xfrm_policy_inexact[dir]; |
932 | hlist_for_each_entry(pol, entry, chain, bydst) { | 942 | hlist_for_each_entry(pol, entry, chain, bydst) { |
933 | if (xfrm_policy_match(pol, fl, type, family, dir) && | 943 | err = xfrm_policy_match(pol, fl, type, family, dir); |
934 | pol->priority < priority) { | 944 | if (err) { |
945 | if (err == -ESRCH) | ||
946 | continue; | ||
947 | else { | ||
948 | ret = ERR_PTR(err); | ||
949 | goto fail; | ||
950 | } | ||
951 | } else if (pol->priority < priority) { | ||
935 | ret = pol; | 952 | ret = pol; |
936 | break; | 953 | break; |
937 | } | 954 | } |
938 | } | 955 | } |
939 | if (ret) | 956 | if (ret) |
940 | xfrm_pol_hold(ret); | 957 | xfrm_pol_hold(ret); |
958 | fail: | ||
941 | read_unlock_bh(&xfrm_policy_lock); | 959 | read_unlock_bh(&xfrm_policy_lock); |
942 | 960 | ||
943 | return ret; | 961 | return ret; |
944 | } | 962 | } |
945 | 963 | ||
946 | static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, | 964 | static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, |
947 | void **objp, atomic_t **obj_refp) | 965 | void **objp, atomic_t **obj_refp) |
948 | { | 966 | { |
949 | struct xfrm_policy *pol; | 967 | struct xfrm_policy *pol; |
968 | int err = 0; | ||
950 | 969 | ||
951 | #ifdef CONFIG_XFRM_SUB_POLICY | 970 | #ifdef CONFIG_XFRM_SUB_POLICY |
952 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir); | 971 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir); |
953 | if (pol) | 972 | if (IS_ERR(pol)) { |
973 | err = PTR_ERR(pol); | ||
974 | pol = NULL; | ||
975 | } | ||
976 | if (pol || err) | ||
954 | goto end; | 977 | goto end; |
955 | #endif | 978 | #endif |
956 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir); | 979 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir); |
957 | 980 | if (IS_ERR(pol)) { | |
981 | err = PTR_ERR(pol); | ||
982 | pol = NULL; | ||
983 | } | ||
958 | #ifdef CONFIG_XFRM_SUB_POLICY | 984 | #ifdef CONFIG_XFRM_SUB_POLICY |
959 | end: | 985 | end: |
960 | #endif | 986 | #endif |
961 | if ((*objp = (void *) pol) != NULL) | 987 | if ((*objp = (void *) pol) != NULL) |
962 | *obj_refp = &pol->refcnt; | 988 | *obj_refp = &pol->refcnt; |
989 | return err; | ||
963 | } | 990 | } |
964 | 991 | ||
965 | static inline int policy_to_flow_dir(int dir) | 992 | static inline int policy_to_flow_dir(int dir) |
@@ -989,12 +1016,16 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc | |||
989 | sk->sk_family); | 1016 | sk->sk_family); |
990 | int err = 0; | 1017 | int err = 0; |
991 | 1018 | ||
992 | if (match) | 1019 | if (match) { |
993 | err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir)); | 1020 | err = security_xfrm_policy_lookup(pol, fl->secid, |
994 | 1021 | policy_to_flow_dir(dir)); | |
995 | if (match && !err) | 1022 | if (!err) |
996 | xfrm_pol_hold(pol); | 1023 | xfrm_pol_hold(pol); |
997 | else | 1024 | else if (err == -ESRCH) |
1025 | pol = NULL; | ||
1026 | else | ||
1027 | pol = ERR_PTR(err); | ||
1028 | } else | ||
998 | pol = NULL; | 1029 | pol = NULL; |
999 | } | 1030 | } |
1000 | read_unlock_bh(&xfrm_policy_lock); | 1031 | read_unlock_bh(&xfrm_policy_lock); |
@@ -1286,8 +1317,11 @@ restart: | |||
1286 | pol_dead = 0; | 1317 | pol_dead = 0; |
1287 | xfrm_nr = 0; | 1318 | xfrm_nr = 0; |
1288 | 1319 | ||
1289 | if (sk && sk->sk_policy[1]) | 1320 | if (sk && sk->sk_policy[1]) { |
1290 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); | 1321 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); |
1322 | if (IS_ERR(policy)) | ||
1323 | return PTR_ERR(policy); | ||
1324 | } | ||
1291 | 1325 | ||
1292 | if (!policy) { | 1326 | if (!policy) { |
1293 | /* To accelerate a bit... */ | 1327 | /* To accelerate a bit... */ |
@@ -1297,6 +1331,8 @@ restart: | |||
1297 | 1331 | ||
1298 | policy = flow_cache_lookup(fl, dst_orig->ops->family, | 1332 | policy = flow_cache_lookup(fl, dst_orig->ops->family, |
1299 | dir, xfrm_policy_lookup); | 1333 | dir, xfrm_policy_lookup); |
1334 | if (IS_ERR(policy)) | ||
1335 | return PTR_ERR(policy); | ||
1300 | } | 1336 | } |
1301 | 1337 | ||
1302 | if (!policy) | 1338 | if (!policy) |
@@ -1343,6 +1379,10 @@ restart: | |||
1343 | fl, family, | 1379 | fl, family, |
1344 | XFRM_POLICY_OUT); | 1380 | XFRM_POLICY_OUT); |
1345 | if (pols[1]) { | 1381 | if (pols[1]) { |
1382 | if (IS_ERR(pols[1])) { | ||
1383 | err = PTR_ERR(pols[1]); | ||
1384 | goto error; | ||
1385 | } | ||
1346 | if (pols[1]->action == XFRM_POLICY_BLOCK) { | 1386 | if (pols[1]->action == XFRM_POLICY_BLOCK) { |
1347 | err = -EPERM; | 1387 | err = -EPERM; |
1348 | goto error; | 1388 | goto error; |
@@ -1574,13 +1614,19 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1574 | } | 1614 | } |
1575 | 1615 | ||
1576 | pol = NULL; | 1616 | pol = NULL; |
1577 | if (sk && sk->sk_policy[dir]) | 1617 | if (sk && sk->sk_policy[dir]) { |
1578 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); | 1618 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); |
1619 | if (IS_ERR(pol)) | ||
1620 | return 0; | ||
1621 | } | ||
1579 | 1622 | ||
1580 | if (!pol) | 1623 | if (!pol) |
1581 | pol = flow_cache_lookup(&fl, family, fl_dir, | 1624 | pol = flow_cache_lookup(&fl, family, fl_dir, |
1582 | xfrm_policy_lookup); | 1625 | xfrm_policy_lookup); |
1583 | 1626 | ||
1627 | if (IS_ERR(pol)) | ||
1628 | return 0; | ||
1629 | |||
1584 | if (!pol) { | 1630 | if (!pol) { |
1585 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { | 1631 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { |
1586 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 1632 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
@@ -1599,6 +1645,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1599 | &fl, family, | 1645 | &fl, family, |
1600 | XFRM_POLICY_IN); | 1646 | XFRM_POLICY_IN); |
1601 | if (pols[1]) { | 1647 | if (pols[1]) { |
1648 | if (IS_ERR(pols[1])) | ||
1649 | return 0; | ||
1602 | pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec; | 1650 | pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec; |
1603 | npols ++; | 1651 | npols ++; |
1604 | } | 1652 | } |
@@ -1706,7 +1754,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | |||
1706 | 1754 | ||
1707 | static int stale_bundle(struct dst_entry *dst) | 1755 | static int stale_bundle(struct dst_entry *dst) |
1708 | { | 1756 | { |
1709 | return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0); | 1757 | return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0); |
1710 | } | 1758 | } |
1711 | 1759 | ||
1712 | void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) | 1760 | void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) |
@@ -1828,7 +1876,8 @@ EXPORT_SYMBOL(xfrm_init_pmtu); | |||
1828 | * still valid. | 1876 | * still valid. |
1829 | */ | 1877 | */ |
1830 | 1878 | ||
1831 | int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict) | 1879 | int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, |
1880 | struct flowi *fl, int family, int strict) | ||
1832 | { | 1881 | { |
1833 | struct dst_entry *dst = &first->u.dst; | 1882 | struct dst_entry *dst = &first->u.dst; |
1834 | struct xfrm_dst *last; | 1883 | struct xfrm_dst *last; |
@@ -1845,7 +1894,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int str | |||
1845 | 1894 | ||
1846 | if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) | 1895 | if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) |
1847 | return 0; | 1896 | return 0; |
1848 | if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm)) | 1897 | if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol)) |
1849 | return 0; | 1898 | return 0; |
1850 | if (dst->xfrm->km.state != XFRM_STATE_VALID) | 1899 | if (dst->xfrm->km.state != XFRM_STATE_VALID) |
1851 | return 0; | 1900 | return 0; |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d54b3a70d5df..2b2e59d8ffbc 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1992,15 +1992,6 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, | |||
1992 | xp->type = XFRM_POLICY_TYPE_MAIN; | 1992 | xp->type = XFRM_POLICY_TYPE_MAIN; |
1993 | copy_templates(xp, ut, nr); | 1993 | copy_templates(xp, ut, nr); |
1994 | 1994 | ||
1995 | if (!xp->security) { | ||
1996 | int err = security_xfrm_sock_policy_alloc(xp, sk); | ||
1997 | if (err) { | ||
1998 | kfree(xp); | ||
1999 | *dir = err; | ||
2000 | return NULL; | ||
2001 | } | ||
2002 | } | ||
2003 | |||
2004 | *dir = p->dir; | 1995 | *dir = p->dir; |
2005 | 1996 | ||
2006 | return xp; | 1997 | return xp; |
diff --git a/security/dummy.c b/security/dummy.c index aeee70565509..43874c1e6e23 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -881,7 +881,8 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x, | |||
881 | return 1; | 881 | return 1; |
882 | } | 882 | } |
883 | 883 | ||
884 | static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) | 884 | static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, |
885 | struct xfrm_policy *xp) | ||
885 | { | 886 | { |
886 | return 1; | 887 | return 1; |
887 | } | 888 | } |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 81eb59890162..526b28019aca 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -19,7 +19,8 @@ int selinux_xfrm_state_delete(struct xfrm_state *x); | |||
19 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); | 19 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); |
20 | int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | 20 | int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, |
21 | struct xfrm_policy *xp, struct flowi *fl); | 21 | struct xfrm_policy *xp, struct flowi *fl); |
22 | int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm); | 22 | int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, |
23 | struct xfrm_policy *xp); | ||
23 | 24 | ||
24 | 25 | ||
25 | /* | 26 | /* |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index b18895302555..ba48961f9d05 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -618,6 +618,7 @@ void policydb_destroy(struct policydb *p) | |||
618 | c = c->next; | 618 | c = c->next; |
619 | ocontext_destroy(ctmp,i); | 619 | ocontext_destroy(ctmp,i); |
620 | } | 620 | } |
621 | p->ocontexts[i] = NULL; | ||
621 | } | 622 | } |
622 | 623 | ||
623 | g = p->genfs; | 624 | g = p->genfs; |
@@ -633,6 +634,7 @@ void policydb_destroy(struct policydb *p) | |||
633 | g = g->next; | 634 | g = g->next; |
634 | kfree(gtmp); | 635 | kfree(gtmp); |
635 | } | 636 | } |
637 | p->genfs = NULL; | ||
636 | 638 | ||
637 | cond_policydb_destroy(p); | 639 | cond_policydb_destroy(p); |
638 | 640 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 0c219a1b3243..18274b005090 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -2172,7 +2172,12 @@ struct netlbl_cache { | |||
2172 | */ | 2172 | */ |
2173 | static void selinux_netlbl_cache_free(const void *data) | 2173 | static void selinux_netlbl_cache_free(const void *data) |
2174 | { | 2174 | { |
2175 | struct netlbl_cache *cache = NETLBL_CACHE(data); | 2175 | struct netlbl_cache *cache; |
2176 | |||
2177 | if (data == NULL) | ||
2178 | return; | ||
2179 | |||
2180 | cache = NETLBL_CACHE(data); | ||
2176 | switch (cache->type) { | 2181 | switch (cache->type) { |
2177 | case NETLBL_CACHE_T_MLS: | 2182 | case NETLBL_CACHE_T_MLS: |
2178 | ebitmap_destroy(&cache->data.mls_label.level[0].cat); | 2183 | ebitmap_destroy(&cache->data.mls_label.level[0].cat); |
@@ -2197,17 +2202,20 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) | |||
2197 | struct netlbl_lsm_secattr secattr; | 2202 | struct netlbl_lsm_secattr secattr; |
2198 | 2203 | ||
2199 | netlbl_secattr_init(&secattr); | 2204 | netlbl_secattr_init(&secattr); |
2205 | secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); | ||
2206 | if (secattr.cache == NULL) | ||
2207 | goto netlbl_cache_add_return; | ||
2200 | 2208 | ||
2201 | cache = kzalloc(sizeof(*cache), GFP_ATOMIC); | 2209 | cache = kzalloc(sizeof(*cache), GFP_ATOMIC); |
2202 | if (cache == NULL) | 2210 | if (cache == NULL) |
2203 | goto netlbl_cache_add_failure; | 2211 | goto netlbl_cache_add_return; |
2204 | secattr.cache.free = selinux_netlbl_cache_free; | 2212 | secattr.cache->free = selinux_netlbl_cache_free; |
2205 | secattr.cache.data = (void *)cache; | 2213 | secattr.cache->data = (void *)cache; |
2206 | 2214 | ||
2207 | cache->type = NETLBL_CACHE_T_MLS; | 2215 | cache->type = NETLBL_CACHE_T_MLS; |
2208 | if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, | 2216 | if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, |
2209 | &ctx->range.level[0].cat) != 0) | 2217 | &ctx->range.level[0].cat) != 0) |
2210 | goto netlbl_cache_add_failure; | 2218 | goto netlbl_cache_add_return; |
2211 | cache->data.mls_label.level[1].cat.highbit = | 2219 | cache->data.mls_label.level[1].cat.highbit = |
2212 | cache->data.mls_label.level[0].cat.highbit; | 2220 | cache->data.mls_label.level[0].cat.highbit; |
2213 | cache->data.mls_label.level[1].cat.node = | 2221 | cache->data.mls_label.level[1].cat.node = |
@@ -2215,13 +2223,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) | |||
2215 | cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; | 2223 | cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; |
2216 | cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; | 2224 | cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; |
2217 | 2225 | ||
2218 | if (netlbl_cache_add(skb, &secattr) != 0) | 2226 | netlbl_cache_add(skb, &secattr); |
2219 | goto netlbl_cache_add_failure; | ||
2220 | 2227 | ||
2221 | return; | 2228 | netlbl_cache_add_return: |
2222 | 2229 | netlbl_secattr_destroy(&secattr); | |
2223 | netlbl_cache_add_failure: | ||
2224 | netlbl_secattr_destroy(&secattr, 1); | ||
2225 | } | 2230 | } |
2226 | 2231 | ||
2227 | /** | 2232 | /** |
@@ -2263,8 +2268,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, | |||
2263 | 2268 | ||
2264 | POLICY_RDLOCK; | 2269 | POLICY_RDLOCK; |
2265 | 2270 | ||
2266 | if (secattr->cache.data) { | 2271 | if (secattr->cache) { |
2267 | cache = NETLBL_CACHE(secattr->cache.data); | 2272 | cache = NETLBL_CACHE(secattr->cache->data); |
2268 | switch (cache->type) { | 2273 | switch (cache->type) { |
2269 | case NETLBL_CACHE_T_SID: | 2274 | case NETLBL_CACHE_T_SID: |
2270 | *sid = cache->data.sid; | 2275 | *sid = cache->data.sid; |
@@ -2331,7 +2336,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, | |||
2331 | selinux_netlbl_cache_add(skb, &ctx_new); | 2336 | selinux_netlbl_cache_add(skb, &ctx_new); |
2332 | ebitmap_destroy(&ctx_new.range.level[0].cat); | 2337 | ebitmap_destroy(&ctx_new.range.level[0].cat); |
2333 | } else { | 2338 | } else { |
2334 | *sid = SECINITSID_UNLABELED; | 2339 | *sid = SECSID_NULL; |
2335 | rc = 0; | 2340 | rc = 0; |
2336 | } | 2341 | } |
2337 | 2342 | ||
@@ -2369,7 +2374,7 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | |||
2369 | &secattr, | 2374 | &secattr, |
2370 | base_sid, | 2375 | base_sid, |
2371 | sid); | 2376 | sid); |
2372 | netlbl_secattr_destroy(&secattr, 0); | 2377 | netlbl_secattr_destroy(&secattr); |
2373 | 2378 | ||
2374 | return rc; | 2379 | return rc; |
2375 | } | 2380 | } |
@@ -2415,7 +2420,7 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) | |||
2415 | if (rc == 0) | 2420 | if (rc == 0) |
2416 | sksec->nlbl_state = NLBL_LABELED; | 2421 | sksec->nlbl_state = NLBL_LABELED; |
2417 | 2422 | ||
2418 | netlbl_secattr_destroy(&secattr, 0); | 2423 | netlbl_secattr_destroy(&secattr); |
2419 | 2424 | ||
2420 | netlbl_socket_setsid_return: | 2425 | netlbl_socket_setsid_return: |
2421 | POLICY_RDUNLOCK; | 2426 | POLICY_RDUNLOCK; |
@@ -2514,10 +2519,10 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | |||
2514 | if (netlbl_sock_getattr(sk, &secattr) == 0 && | 2519 | if (netlbl_sock_getattr(sk, &secattr) == 0 && |
2515 | selinux_netlbl_secattr_to_sid(NULL, | 2520 | selinux_netlbl_secattr_to_sid(NULL, |
2516 | &secattr, | 2521 | &secattr, |
2517 | sksec->sid, | 2522 | SECINITSID_UNLABELED, |
2518 | &nlbl_peer_sid) == 0) | 2523 | &nlbl_peer_sid) == 0) |
2519 | sksec->peer_sid = nlbl_peer_sid; | 2524 | sksec->peer_sid = nlbl_peer_sid; |
2520 | netlbl_secattr_destroy(&secattr, 0); | 2525 | netlbl_secattr_destroy(&secattr); |
2521 | 2526 | ||
2522 | sksec->nlbl_state = NLBL_REQUIRE; | 2527 | sksec->nlbl_state = NLBL_REQUIRE; |
2523 | 2528 | ||
@@ -2547,9 +2552,6 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid) | |||
2547 | if (rc != 0) | 2552 | if (rc != 0) |
2548 | return SECSID_NULL; | 2553 | return SECSID_NULL; |
2549 | 2554 | ||
2550 | if (peer_sid == SECINITSID_UNLABELED) | ||
2551 | return SECSID_NULL; | ||
2552 | |||
2553 | return peer_sid; | 2555 | return peer_sid; |
2554 | } | 2556 | } |
2555 | 2557 | ||
@@ -2611,11 +2613,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
2611 | u32 netlbl_sid; | 2613 | u32 netlbl_sid; |
2612 | u32 recv_perm; | 2614 | u32 recv_perm; |
2613 | 2615 | ||
2614 | rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid); | 2616 | rc = selinux_netlbl_skbuff_getsid(skb, |
2617 | SECINITSID_UNLABELED, | ||
2618 | &netlbl_sid); | ||
2615 | if (rc != 0) | 2619 | if (rc != 0) |
2616 | return rc; | 2620 | return rc; |
2617 | 2621 | ||
2618 | if (netlbl_sid == SECINITSID_UNLABELED) | 2622 | if (netlbl_sid == SECSID_NULL) |
2619 | return 0; | 2623 | return 0; |
2620 | 2624 | ||
2621 | switch (sksec->sclass) { | 2625 | switch (sksec->sclass) { |
@@ -2653,10 +2657,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
2653 | u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | 2657 | u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) |
2654 | { | 2658 | { |
2655 | struct sk_security_struct *sksec = sock->sk->sk_security; | 2659 | struct sk_security_struct *sksec = sock->sk->sk_security; |
2656 | |||
2657 | if (sksec->peer_sid == SECINITSID_UNLABELED) | ||
2658 | return SECSID_NULL; | ||
2659 | |||
2660 | return sksec->peer_sid; | 2660 | return sksec->peer_sid; |
2661 | } | 2661 | } |
2662 | 2662 | ||
@@ -2672,16 +2672,10 @@ u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | |||
2672 | u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) | 2672 | u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) |
2673 | { | 2673 | { |
2674 | int peer_sid; | 2674 | int peer_sid; |
2675 | struct sock *sk = skb->sk; | ||
2676 | struct inode_security_struct *isec; | ||
2677 | 2675 | ||
2678 | if (sk == NULL || sk->sk_socket == NULL) | 2676 | if (selinux_netlbl_skbuff_getsid(skb, |
2679 | return SECSID_NULL; | 2677 | SECINITSID_UNLABELED, |
2680 | 2678 | &peer_sid) != 0) | |
2681 | isec = SOCK_INODE(sk->sk_socket)->i_security; | ||
2682 | if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0) | ||
2683 | return SECSID_NULL; | ||
2684 | if (peer_sid == SECINITSID_UNLABELED) | ||
2685 | return SECSID_NULL; | 2679 | return SECSID_NULL; |
2686 | 2680 | ||
2687 | return peer_sid; | 2681 | return peer_sid; |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 3e742b850af6..675b995a67c3 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -77,8 +77,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x) | |||
77 | */ | 77 | */ |
78 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) | 78 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) |
79 | { | 79 | { |
80 | int rc = 0; | 80 | int rc; |
81 | u32 sel_sid = SECINITSID_UNLABELED; | 81 | u32 sel_sid; |
82 | struct xfrm_sec_ctx *ctx; | 82 | struct xfrm_sec_ctx *ctx; |
83 | 83 | ||
84 | /* Context sid is either set to label or ANY_ASSOC */ | 84 | /* Context sid is either set to label or ANY_ASSOC */ |
@@ -88,11 +88,21 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) | |||
88 | 88 | ||
89 | sel_sid = ctx->ctx_sid; | 89 | sel_sid = ctx->ctx_sid; |
90 | } | 90 | } |
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; | ||
91 | 98 | ||
92 | rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, | 99 | rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, |
93 | ASSOCIATION__POLMATCH, | 100 | ASSOCIATION__POLMATCH, |
94 | NULL); | 101 | NULL); |
95 | 102 | ||
103 | if (rc == -EACCES) | ||
104 | rc = -ESRCH; | ||
105 | |||
96 | return rc; | 106 | return rc; |
97 | } | 107 | } |
98 | 108 | ||
@@ -108,15 +118,20 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy * | |||
108 | u32 pol_sid; | 118 | u32 pol_sid; |
109 | int err; | 119 | int err; |
110 | 120 | ||
111 | if (x->security) | 121 | if (xp->security) { |
112 | state_sid = x->security->ctx_sid; | 122 | if (!x->security) |
113 | else | 123 | /* unlabeled SA and labeled policy can't match */ |
114 | state_sid = SECINITSID_UNLABELED; | 124 | return 0; |
115 | 125 | else | |
116 | if (xp->security) | 126 | state_sid = x->security->ctx_sid; |
117 | pol_sid = xp->security->ctx_sid; | 127 | pol_sid = xp->security->ctx_sid; |
118 | else | 128 | } else |
119 | pol_sid = SECINITSID_UNLABELED; | 129 | if (x->security) |
130 | /* unlabeled policy and labeled SA can't match */ | ||
131 | return 0; | ||
132 | else | ||
133 | /* unlabeled policy and unlabeled SA match all flows */ | ||
134 | return 1; | ||
120 | 135 | ||
121 | err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION, | 136 | err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION, |
122 | ASSOCIATION__POLMATCH, | 137 | ASSOCIATION__POLMATCH, |
@@ -125,7 +140,11 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy * | |||
125 | if (err) | 140 | if (err) |
126 | return 0; | 141 | return 0; |
127 | 142 | ||
128 | return selinux_xfrm_flow_state_match(fl, x); | 143 | err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION, |
144 | ASSOCIATION__SENDTO, | ||
145 | NULL)? 0:1; | ||
146 | |||
147 | return err; | ||
129 | } | 148 | } |
130 | 149 | ||
131 | /* | 150 | /* |
@@ -133,12 +152,22 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy * | |||
133 | * can use a given security association. | 152 | * can use a given security association. |
134 | */ | 153 | */ |
135 | 154 | ||
136 | int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) | 155 | int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, |
156 | struct xfrm_policy *xp) | ||
137 | { | 157 | { |
138 | int rc = 0; | 158 | int rc = 0; |
139 | u32 sel_sid = SECINITSID_UNLABELED; | 159 | u32 sel_sid = SECINITSID_UNLABELED; |
140 | struct xfrm_sec_ctx *ctx; | 160 | struct xfrm_sec_ctx *ctx; |
141 | 161 | ||
162 | if (!xp->security) | ||
163 | if (!xfrm->security) | ||
164 | return 1; | ||
165 | else | ||
166 | return 0; | ||
167 | else | ||
168 | if (!xfrm->security) | ||
169 | return 0; | ||
170 | |||
142 | /* Context sid is either set to label or ANY_ASSOC */ | 171 | /* Context sid is either set to label or ANY_ASSOC */ |
143 | if ((ctx = xfrm->security)) { | 172 | if ((ctx = xfrm->security)) { |
144 | if (!selinux_authorizable_ctx(ctx)) | 173 | if (!selinux_authorizable_ctx(ctx)) |