1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71#include <linux/kernel.h>
72#include <linux/string.h>
73#include <linux/socket.h>
74#include <linux/un.h>
75#include <linux/net.h>
76#include <linux/fs.h>
77#include <linux/skbuff.h>
78#include <linux/netdevice.h>
79#include <linux/file.h>
80#include <linux/proc_fs.h>
81#include <linux/mutex.h>
82#include <linux/wait.h>
83
84#include <net/sock.h>
85#include <net/af_unix.h>
86#include <net/scm.h>
87#include <net/tcp_states.h>
88
89
90
91static LIST_HEAD(gc_inflight_list);
92static LIST_HEAD(gc_candidates);
93static DEFINE_SPINLOCK(unix_gc_lock);
94static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
95
96unsigned int unix_tot_inflight;
97
98
99struct sock *unix_get_socket(struct file *filp)
100{
101 struct sock *u_sock = NULL;
102 struct inode *inode = filp->f_path.dentry->d_inode;
103
104
105
106
107 if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) {
108 struct socket *sock = SOCKET_I(inode);
109 struct sock *s = sock->sk;
110
111
112
113
114 if (s && sock->ops && sock->ops->family == PF_UNIX)
115 u_sock = s;
116 }
117 return u_sock;
118}
119
120
121
122
123
124
125void unix_inflight(struct file *fp)
126{
127 struct sock *s = unix_get_socket(fp);
128 if (s) {
129 struct unix_sock *u = unix_sk(s);
130 spin_lock(&unix_gc_lock);
131 if (atomic_long_inc_return(&u->inflight) == 1) {
132 BUG_ON(!list_empty(&u->link));
133 list_add_tail(&u->link, &gc_inflight_list);
134 } else {
135 BUG_ON(list_empty(&u->link));
136 }
137 unix_tot_inflight++;
138 spin_unlock(&unix_gc_lock);
139 }
140}
141
142void unix_notinflight(struct file *fp)
143{
144 struct sock *s = unix_get_socket(fp);
145 if (s) {
146 struct unix_sock *u = unix_sk(s);
147 spin_lock(&unix_gc_lock);
148 BUG_ON(list_empty(&u->link));
149 if (atomic_long_dec_and_test(&u->inflight))
150 list_del_init(&u->link);
151 unix_tot_inflight--;
152 spin_unlock(&unix_gc_lock);
153 }
154}
155
156static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
157 struct sk_buff_head *hitlist)
158{
159 struct sk_buff *skb;
160 struct sk_buff *next;
161
162 spin_lock(&x->sk_receive_queue.lock);
163 skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
164
165
166
167 if (UNIXCB(skb).fp) {
168 bool hit = false;
169
170
171
172 int nfd = UNIXCB(skb).fp->count;
173 struct file **fp = UNIXCB(skb).fp->fp;
174 while (nfd--) {
175
176
177
178
179 struct sock *sk = unix_get_socket(*fp++);
180 if (sk) {
181 struct unix_sock *u = unix_sk(sk);
182
183
184
185
186
187
188 if (u->gc_candidate) {
189 hit = true;
190 func(u);
191 }
192 }
193 }
194 if (hit && hitlist != NULL) {
195 __skb_unlink(skb, &x->sk_receive_queue);
196 __skb_queue_tail(hitlist, skb);
197 }
198 }
199 }
200 spin_unlock(&x->sk_receive_queue.lock);
201}
202
203static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
204 struct sk_buff_head *hitlist)
205{
206 if (x->sk_state != TCP_LISTEN)
207 scan_inflight(x, func, hitlist);
208 else {
209 struct sk_buff *skb;
210 struct sk_buff *next;
211 struct unix_sock *u;
212 LIST_HEAD(embryos);
213
214
215
216
217
218 spin_lock(&x->sk_receive_queue.lock);
219 skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
220 u = unix_sk(skb->sk);
221
222
223
224
225
226 BUG_ON(!list_empty(&u->link));
227 list_add_tail(&u->link, &embryos);
228 }
229 spin_unlock(&x->sk_receive_queue.lock);
230
231 while (!list_empty(&embryos)) {
232 u = list_entry(embryos.next, struct unix_sock, link);
233 scan_inflight(&u->sk, func, hitlist);
234 list_del_init(&u->link);
235 }
236 }
237}
238
239static void dec_inflight(struct unix_sock *usk)
240{
241 atomic_long_dec(&usk->inflight);
242}
243
244static void inc_inflight(struct unix_sock *usk)
245{
246 atomic_long_inc(&usk->inflight);
247}
248
249static void inc_inflight_move_tail(struct unix_sock *u)
250{
251 atomic_long_inc(&u->inflight);
252
253
254
255
256
257 if (u->gc_maybe_cycle)
258 list_move_tail(&u->link, &gc_candidates);
259}
260
261static bool gc_in_progress = false;
262#define UNIX_INFLIGHT_TRIGGER_GC 16000
263
264void wait_for_unix_gc(void)
265{
266
267
268
269
270 if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
271 unix_gc();
272 wait_event(unix_gc_wait, gc_in_progress == false);
273}
274
275
276void unix_gc(void)
277{
278 struct unix_sock *u;
279 struct unix_sock *next;
280 struct sk_buff_head hitlist;
281 struct list_head cursor;
282 LIST_HEAD(not_cycle_list);
283
284 spin_lock(&unix_gc_lock);
285
286
287 if (gc_in_progress)
288 goto out;
289
290 gc_in_progress = true;
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
308 long total_refs;
309 long inflight_refs;
310
311 total_refs = file_count(u->sk.sk_socket->file);
312 inflight_refs = atomic_long_read(&u->inflight);
313
314 BUG_ON(inflight_refs < 1);
315 BUG_ON(total_refs < inflight_refs);
316 if (total_refs == inflight_refs) {
317 list_move_tail(&u->link, &gc_candidates);
318 u->gc_candidate = 1;
319 u->gc_maybe_cycle = 1;
320 }
321 }
322
323
324
325
326
327 list_for_each_entry(u, &gc_candidates, link)
328 scan_children(&u->sk, dec_inflight, NULL);
329
330
331
332
333
334
335
336
337
338 list_add(&cursor, &gc_candidates);
339 while (cursor.next != &gc_candidates) {
340 u = list_entry(cursor.next, struct unix_sock, link);
341
342
343 list_move(&cursor, &u->link);
344
345 if (atomic_long_read(&u->inflight) > 0) {
346 list_move_tail(&u->link, ¬_cycle_list);
347 u->gc_maybe_cycle = 0;
348 scan_children(&u->sk, inc_inflight_move_tail, NULL);
349 }
350 }
351 list_del(&cursor);
352
353
354
355
356
357 while (!list_empty(¬_cycle_list)) {
358 u = list_entry(not_cycle_list.next, struct unix_sock, link);
359 u->gc_candidate = 0;
360 list_move_tail(&u->link, &gc_inflight_list);
361 }
362
363
364
365
366
367
368 skb_queue_head_init(&hitlist);
369 list_for_each_entry(u, &gc_candidates, link)
370 scan_children(&u->sk, inc_inflight, &hitlist);
371
372 spin_unlock(&unix_gc_lock);
373
374
375 __skb_queue_purge(&hitlist);
376
377 spin_lock(&unix_gc_lock);
378
379
380 BUG_ON(!list_empty(&gc_candidates));
381 gc_in_progress = false;
382 wake_up(&unix_gc_wait);
383
384 out:
385 spin_unlock(&unix_gc_lock);
386}
387