1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/string.h>
5 #include <linux/socket.h>
8 #include <net/af_unix.h>
10 #include <linux/init.h>
11 #include <linux/io_uring.h>
15 unsigned int unix_tot_inflight
;
16 EXPORT_SYMBOL(unix_tot_inflight
);
18 LIST_HEAD(gc_inflight_list
);
19 EXPORT_SYMBOL(gc_inflight_list
);
21 DEFINE_SPINLOCK(unix_gc_lock
);
22 EXPORT_SYMBOL(unix_gc_lock
);
24 struct sock
*unix_get_socket(struct file
*filp
)
26 struct sock
*u_sock
= NULL
;
27 struct inode
*inode
= file_inode(filp
);
30 if (S_ISSOCK(inode
->i_mode
) && !(filp
->f_mode
& FMODE_PATH
)) {
31 struct socket
*sock
= SOCKET_I(inode
);
32 struct sock
*s
= sock
->sk
;
35 if (s
&& sock
->ops
&& sock
->ops
->family
== PF_UNIX
)
38 /* Could be an io_uring instance */
39 u_sock
= io_uring_get_socket(filp
);
43 EXPORT_SYMBOL(unix_get_socket
);
45 /* Keep the number of times in flight count for the file
46 * descriptor if it is for an AF_UNIX socket.
48 void unix_inflight(struct user_struct
*user
, struct file
*fp
)
50 struct sock
*s
= unix_get_socket(fp
);
52 spin_lock(&unix_gc_lock
);
55 struct unix_sock
*u
= unix_sk(s
);
57 if (atomic_long_inc_return(&u
->inflight
) == 1) {
58 BUG_ON(!list_empty(&u
->link
));
59 list_add_tail(&u
->link
, &gc_inflight_list
);
61 BUG_ON(list_empty(&u
->link
));
65 user
->unix_inflight
++;
66 spin_unlock(&unix_gc_lock
);
69 void unix_notinflight(struct user_struct
*user
, struct file
*fp
)
71 struct sock
*s
= unix_get_socket(fp
);
73 spin_lock(&unix_gc_lock
);
76 struct unix_sock
*u
= unix_sk(s
);
78 BUG_ON(!atomic_long_read(&u
->inflight
));
79 BUG_ON(list_empty(&u
->link
));
81 if (atomic_long_dec_and_test(&u
->inflight
))
82 list_del_init(&u
->link
);
85 user
->unix_inflight
--;
86 spin_unlock(&unix_gc_lock
);
90 * The "user->unix_inflight" variable is protected by the garbage
91 * collection lock, and we just read it locklessly here. If you go
92 * over the limit, there might be a tiny race in actually noticing
93 * it across threads. Tough.
95 static inline bool too_many_unix_fds(struct task_struct
*p
)
97 struct user_struct
*user
= current_user();
99 if (unlikely(user
->unix_inflight
> task_rlimit(p
, RLIMIT_NOFILE
)))
100 return !capable(CAP_SYS_RESOURCE
) && !capable(CAP_SYS_ADMIN
);
104 int unix_attach_fds(struct scm_cookie
*scm
, struct sk_buff
*skb
)
108 if (too_many_unix_fds(current
))
109 return -ETOOMANYREFS
;
112 * Need to duplicate file references for the sake of garbage
113 * collection. Otherwise a socket in the fps might become a
114 * candidate for GC while the skb is not yet queued.
116 UNIXCB(skb
).fp
= scm_fp_dup(scm
->fp
);
120 for (i
= scm
->fp
->count
- 1; i
>= 0; i
--)
121 unix_inflight(scm
->fp
->user
, scm
->fp
->fp
[i
]);
124 EXPORT_SYMBOL(unix_attach_fds
);
126 void unix_detach_fds(struct scm_cookie
*scm
, struct sk_buff
*skb
)
130 scm
->fp
= UNIXCB(skb
).fp
;
131 UNIXCB(skb
).fp
= NULL
;
133 for (i
= scm
->fp
->count
-1; i
>= 0; i
--)
134 unix_notinflight(scm
->fp
->user
, scm
->fp
->fp
[i
]);
136 EXPORT_SYMBOL(unix_detach_fds
);
138 void unix_destruct_scm(struct sk_buff
*skb
)
140 struct scm_cookie scm
;
142 memset(&scm
, 0, sizeof(scm
));
143 scm
.pid
= UNIXCB(skb
).pid
;
145 unix_detach_fds(&scm
, skb
);
147 /* Alas, it calls VFS */
148 /* So fscking what? fput() had been SMP-safe since the last Summer */
152 EXPORT_SYMBOL(unix_destruct_scm
);