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>
14 unsigned int unix_tot_inflight
;
15 EXPORT_SYMBOL(unix_tot_inflight
);
17 LIST_HEAD(gc_inflight_list
);
18 EXPORT_SYMBOL(gc_inflight_list
);
20 DEFINE_SPINLOCK(unix_gc_lock
);
21 EXPORT_SYMBOL(unix_gc_lock
);
23 struct sock
*unix_get_socket(struct file
*filp
)
25 struct sock
*u_sock
= NULL
;
26 struct inode
*inode
= file_inode(filp
);
29 if (S_ISSOCK(inode
->i_mode
) && !(filp
->f_mode
& FMODE_PATH
)) {
30 struct socket
*sock
= SOCKET_I(inode
);
31 struct sock
*s
= sock
->sk
;
34 if (s
&& sock
->ops
&& sock
->ops
->family
== PF_UNIX
)
37 /* Could be an io_uring instance */
38 u_sock
= io_uring_get_socket(filp
);
42 EXPORT_SYMBOL(unix_get_socket
);
44 /* Keep the number of times in flight count for the file
45 * descriptor if it is for an AF_UNIX socket.
47 void unix_inflight(struct user_struct
*user
, struct file
*fp
)
49 struct sock
*s
= unix_get_socket(fp
);
51 spin_lock(&unix_gc_lock
);
54 struct unix_sock
*u
= unix_sk(s
);
56 if (atomic_long_inc_return(&u
->inflight
) == 1) {
57 BUG_ON(!list_empty(&u
->link
));
58 list_add_tail(&u
->link
, &gc_inflight_list
);
60 BUG_ON(list_empty(&u
->link
));
64 user
->unix_inflight
++;
65 spin_unlock(&unix_gc_lock
);
68 void unix_notinflight(struct user_struct
*user
, struct file
*fp
)
70 struct sock
*s
= unix_get_socket(fp
);
72 spin_lock(&unix_gc_lock
);
75 struct unix_sock
*u
= unix_sk(s
);
77 BUG_ON(!atomic_long_read(&u
->inflight
));
78 BUG_ON(list_empty(&u
->link
));
80 if (atomic_long_dec_and_test(&u
->inflight
))
81 list_del_init(&u
->link
);
84 user
->unix_inflight
--;
85 spin_unlock(&unix_gc_lock
);
89 * The "user->unix_inflight" variable is protected by the garbage
90 * collection lock, and we just read it locklessly here. If you go
91 * over the limit, there might be a tiny race in actually noticing
92 * it across threads. Tough.
94 static inline bool too_many_unix_fds(struct task_struct
*p
)
96 struct user_struct
*user
= current_user();
98 if (unlikely(user
->unix_inflight
> task_rlimit(p
, RLIMIT_NOFILE
)))
99 return !capable(CAP_SYS_RESOURCE
) && !capable(CAP_SYS_ADMIN
);
103 int unix_attach_fds(struct scm_cookie
*scm
, struct sk_buff
*skb
)
107 if (too_many_unix_fds(current
))
108 return -ETOOMANYREFS
;
111 * Need to duplicate file references for the sake of garbage
112 * collection. Otherwise a socket in the fps might become a
113 * candidate for GC while the skb is not yet queued.
115 UNIXCB(skb
).fp
= scm_fp_dup(scm
->fp
);
119 for (i
= scm
->fp
->count
- 1; i
>= 0; i
--)
120 unix_inflight(scm
->fp
->user
, scm
->fp
->fp
[i
]);
123 EXPORT_SYMBOL(unix_attach_fds
);
125 void unix_detach_fds(struct scm_cookie
*scm
, struct sk_buff
*skb
)
129 scm
->fp
= UNIXCB(skb
).fp
;
130 UNIXCB(skb
).fp
= NULL
;
132 for (i
= scm
->fp
->count
-1; i
>= 0; i
--)
133 unix_notinflight(scm
->fp
->user
, scm
->fp
->fp
[i
]);
135 EXPORT_SYMBOL(unix_detach_fds
);
137 void unix_destruct_scm(struct sk_buff
*skb
)
139 struct scm_cookie scm
;
141 memset(&scm
, 0, sizeof(scm
));
142 scm
.pid
= UNIXCB(skb
).pid
;
144 unix_detach_fds(&scm
, skb
);
146 /* Alas, it calls VFS */
147 /* So fscking what? fput() had been SMP-safe since the last Summer */
151 EXPORT_SYMBOL(unix_destruct_scm
);