]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - security/selinux/netlabel.c
UBUNTU: Ubuntu-5.15.0-39.42
[mirror_ubuntu-jammy-kernel.git] / security / selinux / netlabel.c
CommitLineData
1ccea77e 1// SPDX-License-Identifier: GPL-2.0-or-later
5778eabd
PM
2/*
3 * SELinux NetLabel Support
4 *
5 * This file provides the necessary glue to tie NetLabel into the SELinux
6 * subsystem.
7 *
82c21bfa 8 * Author: Paul Moore <paul@paul-moore.com>
5778eabd
PM
9 */
10
11/*
948bf85c 12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
5778eabd
PM
13 */
14
15#include <linux/spinlock.h>
16#include <linux/rcupdate.h>
5a0e3ad6 17#include <linux/gfp.h>
014ab19a
PM
18#include <linux/ip.h>
19#include <linux/ipv6.h>
12ddb08a 20#include <linux/lsm_hooks.h>
5778eabd
PM
21#include <net/sock.h>
22#include <net/netlabel.h>
014ab19a
PM
23#include <net/ip.h>
24#include <net/ipv6.h>
5778eabd
PM
25
26#include "objsec.h"
27#include "security.h"
d4ee4231 28#include "netlabel.h"
5778eabd 29
5dbe1eb0
PM
30/**
31 * selinux_netlbl_sidlookup_cached - Cache a SID lookup
32 * @skb: the packet
33 * @secattr: the NetLabel security attributes
34 * @sid: the SID
35 *
36 * Description:
37 * Query the SELinux security server to lookup the correct SID for the given
38 * security attributes. If the query is successful, cache the result to speed
39 * up future lookups. Returns zero on success, negative values on failure.
40 *
41 */
42static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
4fee5242 43 u16 family,
5dbe1eb0
PM
44 struct netlbl_lsm_secattr *secattr,
45 u32 *sid)
46{
47 int rc;
48
aa8e712c 49 rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
5dbe1eb0
PM
50 if (rc == 0 &&
51 (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
52 (secattr->flags & NETLBL_SECATTR_CACHE))
4fee5242 53 netlbl_cache_add(skb, family, secattr);
5dbe1eb0
PM
54
55 return rc;
56}
57
6c5b3fc0
PM
58/**
59 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
60 * @sk: the socket
61 *
62 * Description:
63 * Generate the NetLabel security attributes for a socket, making full use of
64 * the socket's attribute cache. Returns a pointer to the security attributes
65 * on success, NULL on failure.
66 *
67 */
68static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
69{
70 int rc;
12ddb08a 71 struct sk_security_struct *sksec = selinux_sock(sk);
6c5b3fc0
PM
72 struct netlbl_lsm_secattr *secattr;
73
74 if (sksec->nlbl_secattr != NULL)
75 return sksec->nlbl_secattr;
76
77 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
78 if (secattr == NULL)
79 return NULL;
aa8e712c
SS
80 rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
81 secattr);
6c5b3fc0
PM
82 if (rc != 0) {
83 netlbl_secattr_free(secattr);
84 return NULL;
85 }
86 sksec->nlbl_secattr = secattr;
87
88 return secattr;
89}
90
050d032b
PM
91/**
92 * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
93 * @sk: the socket
94 * @sid: the SID
95 *
96 * Query the socket's cached secattr and if the SID matches the cached value
97 * return the cache, otherwise return NULL.
98 *
99 */
100static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
101 const struct sock *sk,
102 u32 sid)
103{
12ddb08a 104 struct sk_security_struct *sksec = selinux_sock(sk);
050d032b
PM
105 struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
106
107 if (secattr == NULL)
108 return NULL;
109
110 if ((secattr->flags & NETLBL_SECATTR_SECID) &&
fc6eae24 111 (secattr->attr.lsmblob.secid[selinux_lsmid.slot] == sid))
050d032b
PM
112 return secattr;
113
114 return NULL;
115}
116
5778eabd
PM
117/**
118 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
119 *
120 * Description:
121 * Invalidate the NetLabel security attribute mapping cache.
122 *
123 */
124void selinux_netlbl_cache_invalidate(void)
125{
126 netlbl_cache_invalidate();
127}
128
dfaebe98
PM
129/**
130 * selinux_netlbl_err - Handle a NetLabel packet error
131 * @skb: the packet
132 * @error: the error code
133 * @gateway: true if host is acting as a gateway, false otherwise
134 *
135 * Description:
136 * When a packet is dropped due to a call to avc_has_perm() pass the error
137 * code to the NetLabel subsystem so any protocol specific processing can be
138 * done. This is safe to call even if you are unsure if NetLabel labeling is
139 * present on the packet, NetLabel is smart enough to only act when it should.
140 *
141 */
a04e71f6 142void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
dfaebe98 143{
a04e71f6 144 netlbl_skbuff_err(skb, family, error, gateway);
dfaebe98
PM
145}
146
6c5b3fc0
PM
147/**
148 * selinux_netlbl_sk_security_free - Free the NetLabel fields
dd3e7836 149 * @sksec: the sk_security_struct
6c5b3fc0
PM
150 *
151 * Description:
152 * Free all of the memory in the NetLabel fields of a sk_security_struct.
153 *
154 */
dd3e7836 155void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
6c5b3fc0 156{
dd3e7836
EP
157 if (sksec->nlbl_secattr != NULL)
158 netlbl_secattr_free(sksec->nlbl_secattr);
6c5b3fc0
PM
159}
160
5778eabd
PM
161/**
162 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
dd3e7836 163 * @sksec: the sk_security_struct
5778eabd
PM
164 * @family: the socket family
165 *
166 * Description:
167 * Called when the NetLabel state of a sk_security_struct needs to be reset.
25985edc 168 * The caller is responsible for all the NetLabel sk_security_struct locking.
5778eabd
PM
169 *
170 */
dd3e7836 171void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec)
5778eabd 172{
dd3e7836 173 sksec->nlbl_state = NLBL_UNSET;
5778eabd
PM
174}
175
5778eabd
PM
176/**
177 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
178 * @skb: the packet
75e22910 179 * @family: protocol family
220deb96 180 * @type: NetLabel labeling protocol type
5778eabd
PM
181 * @sid: the SID
182 *
183 * Description:
184 * Call the NetLabel mechanism to get the security attributes of the given
185 * packet and use those attributes to determine the correct context/SID to
186 * assign to the packet. Returns zero on success, negative values on failure.
187 *
188 */
75e22910
PM
189int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
190 u16 family,
220deb96 191 u32 *type,
75e22910 192 u32 *sid)
5778eabd
PM
193{
194 int rc;
195 struct netlbl_lsm_secattr secattr;
196
23bcdc1a
PM
197 if (!netlbl_enabled()) {
198 *sid = SECSID_NULL;
199 return 0;
200 }
201
5778eabd 202 netlbl_secattr_init(&secattr);
75e22910 203 rc = netlbl_skbuff_getattr(skb, family, &secattr);
5dbe1eb0 204 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
4fee5242
HD
205 rc = selinux_netlbl_sidlookup_cached(skb, family,
206 &secattr, sid);
5dbe1eb0 207 else
5778eabd 208 *sid = SECSID_NULL;
220deb96 209 *type = secattr.type;
5778eabd
PM
210 netlbl_secattr_destroy(&secattr);
211
212 return rc;
213}
214
948bf85c
PM
215/**
216 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
217 * @skb: the packet
218 * @family: protocol family
219 * @sid: the SID
220 *
221 * Description
222 * Call the NetLabel mechanism to set the label of a packet using @sid.
af901ca1 223 * Returns zero on success, negative values on failure.
948bf85c
PM
224 *
225 */
226int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
227 u16 family,
228 u32 sid)
229{
230 int rc;
6c5b3fc0
PM
231 struct netlbl_lsm_secattr secattr_storage;
232 struct netlbl_lsm_secattr *secattr = NULL;
948bf85c
PM
233 struct sock *sk;
234
235 /* if this is a locally generated packet check to see if it is already
236 * being labeled by it's parent socket, if it is just exit */
54abc686 237 sk = skb_to_full_sk(skb);
948bf85c 238 if (sk != NULL) {
12ddb08a 239 struct sk_security_struct *sksec = selinux_sock(sk);
d452930f 240
948bf85c
PM
241 if (sksec->nlbl_state != NLBL_REQSKB)
242 return 0;
050d032b 243 secattr = selinux_netlbl_sock_getattr(sk, sid);
6c5b3fc0
PM
244 }
245 if (secattr == NULL) {
246 secattr = &secattr_storage;
247 netlbl_secattr_init(secattr);
aa8e712c
SS
248 rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
249 secattr);
6c5b3fc0
PM
250 if (rc != 0)
251 goto skbuff_setsid_return;
948bf85c
PM
252 }
253
6c5b3fc0 254 rc = netlbl_skbuff_setattr(skb, family, secattr);
948bf85c
PM
255
256skbuff_setsid_return:
6c5b3fc0
PM
257 if (secattr == &secattr_storage)
258 netlbl_secattr_destroy(secattr);
948bf85c
PM
259 return rc;
260}
261
d452930f
RH
262/**
263 * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association.
264 * @ep: incoming association endpoint.
265 * @skb: the packet.
266 *
267 * Description:
268 * A new incoming connection is represented by @ep, ......
269 * Returns zero on success, negative values on failure.
270 *
271 */
272int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
273 struct sk_buff *skb)
274{
275 int rc;
276 struct netlbl_lsm_secattr secattr;
12ddb08a 277 struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
d452930f 278 struct sockaddr_in addr4;
d452930f 279 struct sockaddr_in6 addr6;
d452930f
RH
280
281 if (ep->base.sk->sk_family != PF_INET &&
282 ep->base.sk->sk_family != PF_INET6)
283 return 0;
284
285 netlbl_secattr_init(&secattr);
aa8e712c
SS
286 rc = security_netlbl_sid_to_secattr(&selinux_state,
287 ep->secid, &secattr);
d452930f
RH
288 if (rc != 0)
289 goto assoc_request_return;
290
291 /* Move skb hdr address info to a struct sockaddr and then call
292 * netlbl_conn_setattr().
293 */
294 if (ip_hdr(skb)->version == 4) {
295 addr4.sin_family = AF_INET;
296 addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
98bbbb76
AB
297 rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr4, &secattr);
298 } else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) {
d452930f
RH
299 addr6.sin6_family = AF_INET6;
300 addr6.sin6_addr = ipv6_hdr(skb)->saddr;
98bbbb76
AB
301 rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr6, &secattr);
302 } else {
303 rc = -EAFNOSUPPORT;
d452930f
RH
304 }
305
d452930f
RH
306 if (rc == 0)
307 sksec->nlbl_state = NLBL_LABELED;
308
309assoc_request_return:
310 netlbl_secattr_destroy(&secattr);
311 return rc;
312}
313
5778eabd 314/**
389fb800
PM
315 * selinux_netlbl_inet_conn_request - Label an incoming stream connection
316 * @req: incoming connection request socket
5778eabd
PM
317 *
318 * Description:
389fb800
PM
319 * A new incoming connection request is represented by @req, we need to label
320 * the new request_sock here and the stack will ensure the on-the-wire label
321 * will get preserved when a full sock is created once the connection handshake
322 * is complete. Returns zero on success, negative values on failure.
5778eabd
PM
323 *
324 */
389fb800 325int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
5778eabd 326{
014ab19a 327 int rc;
389fb800 328 struct netlbl_lsm_secattr secattr;
014ab19a 329
e1adea92 330 if (family != PF_INET && family != PF_INET6)
389fb800 331 return 0;
014ab19a 332
389fb800 333 netlbl_secattr_init(&secattr);
aa8e712c
SS
334 rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
335 &secattr);
389fb800
PM
336 if (rc != 0)
337 goto inet_conn_request_return;
338 rc = netlbl_req_setattr(req, &secattr);
339inet_conn_request_return:
340 netlbl_secattr_destroy(&secattr);
341 return rc;
5778eabd
PM
342}
343
344/**
389fb800
PM
345 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
346 * @sk: the new sock
5778eabd
PM
347 *
348 * Description:
389fb800
PM
349 * A new connection has been established using @sk, we've already labeled the
350 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
351 * we need to set the NetLabel state here since we now have a sock structure.
5778eabd
PM
352 *
353 */
389fb800 354void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
5778eabd 355{
12ddb08a 356 struct sk_security_struct *sksec = selinux_sock(sk);
389fb800
PM
357
358 if (family == PF_INET)
359 sksec->nlbl_state = NLBL_LABELED;
360 else
361 sksec->nlbl_state = NLBL_UNSET;
5778eabd
PM
362}
363
d452930f
RH
364/**
365 * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock
366 * @sk: current sock
367 * @newsk: the new sock
368 *
369 * Description:
370 * Called whenever a new socket is created by accept(2) or sctp_peeloff(3).
371 */
372void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
373{
12ddb08a
CS
374 struct sk_security_struct *sksec = selinux_sock(sk);
375 struct sk_security_struct *newsksec = selinux_sock(newsk);
d452930f
RH
376
377 newsksec->nlbl_state = sksec->nlbl_state;
378}
379
5778eabd 380/**
389fb800
PM
381 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
382 * @sock: the socket to label
383 * @family: protocol family
5778eabd
PM
384 *
385 * Description:
389fb800
PM
386 * Attempt to label a socket using the NetLabel mechanism using the given
387 * SID. Returns zero values on success, negative values on failure.
5778eabd
PM
388 *
389 */
389fb800 390int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
5778eabd
PM
391{
392 int rc;
12ddb08a 393 struct sk_security_struct *sksec = selinux_sock(sk);
389fb800 394 struct netlbl_lsm_secattr *secattr;
5778eabd 395
ceba1832 396 if (family != PF_INET && family != PF_INET6)
5778eabd 397 return 0;
f74af6e8 398
389fb800
PM
399 secattr = selinux_netlbl_sock_genattr(sk);
400 if (secattr == NULL)
401 return -ENOMEM;
402 rc = netlbl_sock_setattr(sk, family, secattr);
403 switch (rc) {
404 case 0:
405 sksec->nlbl_state = NLBL_LABELED;
406 break;
407 case -EDESTADDRREQ:
408 sksec->nlbl_state = NLBL_REQSKB;
f74af6e8 409 rc = 0;
389fb800
PM
410 break;
411 }
5778eabd
PM
412
413 return rc;
414}
415
416/**
417 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
418 * @sksec: the sock's sk_security_struct
419 * @skb: the packet
75e22910 420 * @family: protocol family
5778eabd
PM
421 * @ad: the audit data
422 *
423 * Description:
424 * Fetch the NetLabel security attributes from @skb and perform an access check
425 * against the receiving socket. Returns zero on success, negative values on
426 * error.
427 *
428 */
429int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
430 struct sk_buff *skb,
75e22910 431 u16 family,
2bf49690 432 struct common_audit_data *ad)
5778eabd
PM
433{
434 int rc;
f36158c4
PM
435 u32 nlbl_sid;
436 u32 perm;
437 struct netlbl_lsm_secattr secattr;
5778eabd 438
23bcdc1a
PM
439 if (!netlbl_enabled())
440 return 0;
441
f36158c4 442 netlbl_secattr_init(&secattr);
75e22910 443 rc = netlbl_skbuff_getattr(skb, family, &secattr);
5dbe1eb0 444 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
4fee5242
HD
445 rc = selinux_netlbl_sidlookup_cached(skb, family,
446 &secattr, &nlbl_sid);
5dbe1eb0 447 else
f36158c4
PM
448 nlbl_sid = SECINITSID_UNLABELED;
449 netlbl_secattr_destroy(&secattr);
5778eabd
PM
450 if (rc != 0)
451 return rc;
8d9107e8 452
5778eabd
PM
453 switch (sksec->sclass) {
454 case SECCLASS_UDP_SOCKET:
f36158c4 455 perm = UDP_SOCKET__RECVFROM;
5778eabd
PM
456 break;
457 case SECCLASS_TCP_SOCKET:
f36158c4 458 perm = TCP_SOCKET__RECVFROM;
5778eabd
PM
459 break;
460 default:
f36158c4 461 perm = RAWIP_SOCKET__RECVFROM;
5778eabd
PM
462 }
463
6b6bc620
SS
464 rc = avc_has_perm(&selinux_state,
465 sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
5778eabd
PM
466 if (rc == 0)
467 return 0;
468
f36158c4 469 if (nlbl_sid != SECINITSID_UNLABELED)
a04e71f6 470 netlbl_skbuff_err(skb, family, rc, 0);
5778eabd
PM
471 return rc;
472}
473
1f440c99
HD
474/**
475 * selinux_netlbl_option - Is this a NetLabel option
476 * @level: the socket level or protocol
477 * @optname: the socket option name
478 *
479 * Description:
480 * Returns true if @level and @optname refer to a NetLabel option.
481 * Helper for selinux_netlbl_socket_setsockopt().
482 */
483static inline int selinux_netlbl_option(int level, int optname)
484{
485 return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
486 (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
487}
488
5778eabd
PM
489/**
490 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
491 * @sock: the socket
492 * @level: the socket level or protocol
493 * @optname: the socket option name
494 *
495 * Description:
496 * Check the setsockopt() call and if the user is trying to replace the IP
497 * options on a socket and a NetLabel is in place for the socket deny the
498 * access; otherwise allow the access. Returns zero when the access is
499 * allowed, -EACCES when denied, and other negative values on error.
500 *
501 */
502int selinux_netlbl_socket_setsockopt(struct socket *sock,
503 int level,
504 int optname)
505{
506 int rc = 0;
ba6ff9f2 507 struct sock *sk = sock->sk;
12ddb08a 508 struct sk_security_struct *sksec = selinux_sock(sk);
5778eabd
PM
509 struct netlbl_lsm_secattr secattr;
510
1f440c99 511 if (selinux_netlbl_option(level, optname) &&
014ab19a
PM
512 (sksec->nlbl_state == NLBL_LABELED ||
513 sksec->nlbl_state == NLBL_CONNLABELED)) {
5778eabd 514 netlbl_secattr_init(&secattr);
ba6ff9f2 515 lock_sock(sk);
050d032b
PM
516 /* call the netlabel function directly as we want to see the
517 * on-the-wire label that is assigned via the socket's options
518 * and not the cached netlabel/lsm attributes */
ba6ff9f2
PM
519 rc = netlbl_sock_getattr(sk, &secattr);
520 release_sock(sk);
09c50b4a 521 if (rc == 0)
5778eabd 522 rc = -EACCES;
09c50b4a
PM
523 else if (rc == -ENOMSG)
524 rc = 0;
5778eabd
PM
525 netlbl_secattr_destroy(&secattr);
526 }
5778eabd
PM
527
528 return rc;
529}
014ab19a
PM
530
531/**
d452930f
RH
532 * selinux_netlbl_socket_connect_helper - Help label a client-side socket on
533 * connect
014ab19a
PM
534 * @sk: the socket to label
535 * @addr: the destination address
536 *
537 * Description:
538 * Attempt to label a connected socket with NetLabel using the given address.
539 * Returns zero values on success, negative values on failure.
540 *
541 */
d452930f
RH
542static int selinux_netlbl_socket_connect_helper(struct sock *sk,
543 struct sockaddr *addr)
014ab19a
PM
544{
545 int rc;
12ddb08a 546 struct sk_security_struct *sksec = selinux_sock(sk);
6c5b3fc0 547 struct netlbl_lsm_secattr *secattr;
014ab19a 548
014ab19a
PM
549 /* connected sockets are allowed to disconnect when the address family
550 * is set to AF_UNSPEC, if that is what is happening we want to reset
551 * the socket */
552 if (addr->sa_family == AF_UNSPEC) {
553 netlbl_sock_delattr(sk);
554 sksec->nlbl_state = NLBL_REQSKB;
555 rc = 0;
d452930f 556 return rc;
014ab19a 557 }
6c5b3fc0
PM
558 secattr = selinux_netlbl_sock_genattr(sk);
559 if (secattr == NULL) {
560 rc = -ENOMEM;
d452930f 561 return rc;
6c5b3fc0
PM
562 }
563 rc = netlbl_conn_setattr(sk, addr, secattr);
564 if (rc == 0)
565 sksec->nlbl_state = NLBL_CONNLABELED;
014ab19a 566
d452930f
RH
567 return rc;
568}
569
570/**
571 * selinux_netlbl_socket_connect_locked - Label a client-side socket on
572 * connect
573 * @sk: the socket to label
574 * @addr: the destination address
575 *
576 * Description:
577 * Attempt to label a connected socket that already has the socket locked
578 * with NetLabel using the given address.
579 * Returns zero values on success, negative values on failure.
580 *
581 */
582int selinux_netlbl_socket_connect_locked(struct sock *sk,
583 struct sockaddr *addr)
584{
12ddb08a 585 struct sk_security_struct *sksec = selinux_sock(sk);
d452930f
RH
586
587 if (sksec->nlbl_state != NLBL_REQSKB &&
588 sksec->nlbl_state != NLBL_CONNLABELED)
589 return 0;
590
591 return selinux_netlbl_socket_connect_helper(sk, addr);
592}
593
594/**
595 * selinux_netlbl_socket_connect - Label a client-side socket on connect
596 * @sk: the socket to label
597 * @addr: the destination address
598 *
599 * Description:
600 * Attempt to label a connected socket with NetLabel using the given address.
601 * Returns zero values on success, negative values on failure.
602 *
603 */
604int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
605{
606 int rc;
607
608 lock_sock(sk);
609 rc = selinux_netlbl_socket_connect_locked(sk, addr);
42d64e1a 610 release_sock(sk);
d452930f 611
014ab19a
PM
612 return rc;
613}