Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scm: Move scm_recv() from scm.h to scm.c.

scm_recv() has been placed in scm.h since the pre-git era for no
particular reason (I think), which makes the file really fragile.

For example, when you move SOCK_PASSCRED from include/linux/net.h to
enum sock_flags in include/net/sock.h, you will see weird build failure
due to terrible dependency.

To avoid the build failure in the future, let's move scm_recv(_unix())?
and its callees to scm.c.

Note that only scm_recv() needs to be exported for Bluetooth.

scm_send() should be moved to scm.c too, but I'll revisit later.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Kuniyuki Iwashima and committed by
David S. Miller
38b95d58 3041bbbe

+127 -117
+4 -117
include/net/scm.h
··· 102 102 return __scm_send(sock, msg, scm); 103 103 } 104 104 105 - #ifdef CONFIG_SECURITY_NETWORK 106 - static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 107 - { 108 - struct lsm_context ctx; 109 - int err; 110 - 111 - if (test_bit(SOCK_PASSSEC, &sock->flags)) { 112 - err = security_secid_to_secctx(scm->secid, &ctx); 113 - 114 - if (err >= 0) { 115 - put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len, 116 - ctx.context); 117 - security_release_secctx(&ctx); 118 - } 119 - } 120 - } 121 - 122 - static inline bool scm_has_secdata(struct socket *sock) 123 - { 124 - return test_bit(SOCK_PASSSEC, &sock->flags); 125 - } 126 - #else 127 - static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 128 - { } 129 - 130 - static inline bool scm_has_secdata(struct socket *sock) 131 - { 132 - return false; 133 - } 134 - #endif /* CONFIG_SECURITY_NETWORK */ 135 - 136 - static __inline__ void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm) 137 - { 138 - struct file *pidfd_file = NULL; 139 - int len, pidfd; 140 - 141 - /* put_cmsg() doesn't return an error if CMSG is truncated, 142 - * that's why we need to opencode these checks here. 143 - */ 144 - if (msg->msg_flags & MSG_CMSG_COMPAT) 145 - len = sizeof(struct compat_cmsghdr) + sizeof(int); 146 - else 147 - len = sizeof(struct cmsghdr) + sizeof(int); 148 - 149 - if (msg->msg_controllen < len) { 150 - msg->msg_flags |= MSG_CTRUNC; 151 - return; 152 - } 153 - 154 - if (!scm->pid) 155 - return; 156 - 157 - pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file); 158 - 159 - if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) { 160 - if (pidfd_file) { 161 - put_unused_fd(pidfd); 162 - fput(pidfd_file); 163 - } 164 - 165 - return; 166 - } 167 - 168 - if (pidfd_file) 169 - fd_install(pidfd, pidfd_file); 170 - } 171 - 172 - static inline bool __scm_recv_common(struct socket *sock, struct msghdr *msg, 173 - struct scm_cookie *scm, int flags) 174 - { 175 - if (!msg->msg_control) { 176 - if (test_bit(SOCK_PASSCRED, &sock->flags) || 177 - test_bit(SOCK_PASSPIDFD, &sock->flags) || 178 - scm->fp || scm_has_secdata(sock)) 179 - msg->msg_flags |= MSG_CTRUNC; 180 - scm_destroy(scm); 181 - return false; 182 - } 183 - 184 - if (test_bit(SOCK_PASSCRED, &sock->flags)) { 185 - struct user_namespace *current_ns = current_user_ns(); 186 - struct ucred ucreds = { 187 - .pid = scm->creds.pid, 188 - .uid = from_kuid_munged(current_ns, scm->creds.uid), 189 - .gid = from_kgid_munged(current_ns, scm->creds.gid), 190 - }; 191 - put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds); 192 - } 193 - 194 - scm_passec(sock, msg, scm); 195 - 196 - if (scm->fp) 197 - scm_detach_fds(msg, scm); 198 - 199 - return true; 200 - } 201 - 202 - static inline void scm_recv(struct socket *sock, struct msghdr *msg, 203 - struct scm_cookie *scm, int flags) 204 - { 205 - if (!__scm_recv_common(sock, msg, scm, flags)) 206 - return; 207 - 208 - scm_destroy_cred(scm); 209 - } 210 - 211 - static inline void scm_recv_unix(struct socket *sock, struct msghdr *msg, 212 - struct scm_cookie *scm, int flags) 213 - { 214 - if (!__scm_recv_common(sock, msg, scm, flags)) 215 - return; 216 - 217 - if (test_bit(SOCK_PASSPIDFD, &sock->flags)) 218 - scm_pidfd_recv(msg, scm); 219 - 220 - scm_destroy_cred(scm); 221 - } 105 + void scm_recv(struct socket *sock, struct msghdr *msg, 106 + struct scm_cookie *scm, int flags); 107 + void scm_recv_unix(struct socket *sock, struct msghdr *msg, 108 + struct scm_cookie *scm, int flags); 222 109 223 110 static inline int scm_recv_one_fd(struct file *f, int __user *ufd, 224 111 unsigned int flags)
+123
net/core/scm.c
··· 404 404 return new_fpl; 405 405 } 406 406 EXPORT_SYMBOL(scm_fp_dup); 407 + 408 + #ifdef CONFIG_SECURITY_NETWORK 409 + static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 410 + { 411 + struct lsm_context ctx; 412 + int err; 413 + 414 + if (test_bit(SOCK_PASSSEC, &sock->flags)) { 415 + err = security_secid_to_secctx(scm->secid, &ctx); 416 + 417 + if (err >= 0) { 418 + put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len, 419 + ctx.context); 420 + 421 + security_release_secctx(&ctx); 422 + } 423 + } 424 + } 425 + 426 + static bool scm_has_secdata(struct socket *sock) 427 + { 428 + return test_bit(SOCK_PASSSEC, &sock->flags); 429 + } 430 + #else 431 + static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 432 + { 433 + } 434 + 435 + static bool scm_has_secdata(struct socket *sock) 436 + { 437 + return false; 438 + } 439 + #endif 440 + 441 + static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm) 442 + { 443 + struct file *pidfd_file = NULL; 444 + int len, pidfd; 445 + 446 + /* put_cmsg() doesn't return an error if CMSG is truncated, 447 + * that's why we need to opencode these checks here. 448 + */ 449 + if (msg->msg_flags & MSG_CMSG_COMPAT) 450 + len = sizeof(struct compat_cmsghdr) + sizeof(int); 451 + else 452 + len = sizeof(struct cmsghdr) + sizeof(int); 453 + 454 + if (msg->msg_controllen < len) { 455 + msg->msg_flags |= MSG_CTRUNC; 456 + return; 457 + } 458 + 459 + if (!scm->pid) 460 + return; 461 + 462 + pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file); 463 + 464 + if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) { 465 + if (pidfd_file) { 466 + put_unused_fd(pidfd); 467 + fput(pidfd_file); 468 + } 469 + 470 + return; 471 + } 472 + 473 + if (pidfd_file) 474 + fd_install(pidfd, pidfd_file); 475 + } 476 + 477 + static bool __scm_recv_common(struct socket *sock, struct msghdr *msg, 478 + struct scm_cookie *scm, int flags) 479 + { 480 + if (!msg->msg_control) { 481 + if (test_bit(SOCK_PASSCRED, &sock->flags) || 482 + test_bit(SOCK_PASSPIDFD, &sock->flags) || 483 + scm->fp || scm_has_secdata(sock)) 484 + msg->msg_flags |= MSG_CTRUNC; 485 + 486 + scm_destroy(scm); 487 + return false; 488 + } 489 + 490 + if (test_bit(SOCK_PASSCRED, &sock->flags)) { 491 + struct user_namespace *current_ns = current_user_ns(); 492 + struct ucred ucreds = { 493 + .pid = scm->creds.pid, 494 + .uid = from_kuid_munged(current_ns, scm->creds.uid), 495 + .gid = from_kgid_munged(current_ns, scm->creds.gid), 496 + }; 497 + 498 + put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds); 499 + } 500 + 501 + scm_passec(sock, msg, scm); 502 + 503 + if (scm->fp) 504 + scm_detach_fds(msg, scm); 505 + 506 + return true; 507 + } 508 + 509 + void scm_recv(struct socket *sock, struct msghdr *msg, 510 + struct scm_cookie *scm, int flags) 511 + { 512 + if (!__scm_recv_common(sock, msg, scm, flags)) 513 + return; 514 + 515 + scm_destroy_cred(scm); 516 + } 517 + EXPORT_SYMBOL(scm_recv); 518 + 519 + void scm_recv_unix(struct socket *sock, struct msghdr *msg, 520 + struct scm_cookie *scm, int flags) 521 + { 522 + if (!__scm_recv_common(sock, msg, scm, flags)) 523 + return; 524 + 525 + if (test_bit(SOCK_PASSPIDFD, &sock->flags)) 526 + scm_pidfd_recv(msg, scm); 527 + 528 + scm_destroy_cred(scm); 529 + }