mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
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>
This commit is contained in:
parent
3041bbbeb4
commit
38b95d588f
|
|
@ -102,123 +102,10 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
|
|||
return __scm_send(sock, msg, scm);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_NETWORK
|
||||
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
||||
{
|
||||
struct lsm_context ctx;
|
||||
int err;
|
||||
|
||||
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
|
||||
err = security_secid_to_secctx(scm->secid, &ctx);
|
||||
|
||||
if (err >= 0) {
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
|
||||
ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool scm_has_secdata(struct socket *sock)
|
||||
{
|
||||
return test_bit(SOCK_PASSSEC, &sock->flags);
|
||||
}
|
||||
#else
|
||||
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
||||
{ }
|
||||
|
||||
static inline bool scm_has_secdata(struct socket *sock)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_SECURITY_NETWORK */
|
||||
|
||||
static __inline__ void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
|
||||
{
|
||||
struct file *pidfd_file = NULL;
|
||||
int len, pidfd;
|
||||
|
||||
/* put_cmsg() doesn't return an error if CMSG is truncated,
|
||||
* that's why we need to opencode these checks here.
|
||||
*/
|
||||
if (msg->msg_flags & MSG_CMSG_COMPAT)
|
||||
len = sizeof(struct compat_cmsghdr) + sizeof(int);
|
||||
else
|
||||
len = sizeof(struct cmsghdr) + sizeof(int);
|
||||
|
||||
if (msg->msg_controllen < len) {
|
||||
msg->msg_flags |= MSG_CTRUNC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scm->pid)
|
||||
return;
|
||||
|
||||
pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
|
||||
|
||||
if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
|
||||
if (pidfd_file) {
|
||||
put_unused_fd(pidfd);
|
||||
fput(pidfd_file);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pidfd_file)
|
||||
fd_install(pidfd, pidfd_file);
|
||||
}
|
||||
|
||||
static inline bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags)
|
||||
{
|
||||
if (!msg->msg_control) {
|
||||
if (test_bit(SOCK_PASSCRED, &sock->flags) ||
|
||||
test_bit(SOCK_PASSPIDFD, &sock->flags) ||
|
||||
scm->fp || scm_has_secdata(sock))
|
||||
msg->msg_flags |= MSG_CTRUNC;
|
||||
scm_destroy(scm);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (test_bit(SOCK_PASSCRED, &sock->flags)) {
|
||||
struct user_namespace *current_ns = current_user_ns();
|
||||
struct ucred ucreds = {
|
||||
.pid = scm->creds.pid,
|
||||
.uid = from_kuid_munged(current_ns, scm->creds.uid),
|
||||
.gid = from_kgid_munged(current_ns, scm->creds.gid),
|
||||
};
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
|
||||
}
|
||||
|
||||
scm_passec(sock, msg, scm);
|
||||
|
||||
if (scm->fp)
|
||||
scm_detach_fds(msg, scm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void scm_recv(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags)
|
||||
{
|
||||
if (!__scm_recv_common(sock, msg, scm, flags))
|
||||
return;
|
||||
|
||||
scm_destroy_cred(scm);
|
||||
}
|
||||
|
||||
static inline void scm_recv_unix(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags)
|
||||
{
|
||||
if (!__scm_recv_common(sock, msg, scm, flags))
|
||||
return;
|
||||
|
||||
if (test_bit(SOCK_PASSPIDFD, &sock->flags))
|
||||
scm_pidfd_recv(msg, scm);
|
||||
|
||||
scm_destroy_cred(scm);
|
||||
}
|
||||
void scm_recv(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags);
|
||||
void scm_recv_unix(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags);
|
||||
|
||||
static inline int scm_recv_one_fd(struct file *f, int __user *ufd,
|
||||
unsigned int flags)
|
||||
|
|
|
|||
123
net/core/scm.c
123
net/core/scm.c
|
|
@ -404,3 +404,126 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
|
|||
return new_fpl;
|
||||
}
|
||||
EXPORT_SYMBOL(scm_fp_dup);
|
||||
|
||||
#ifdef CONFIG_SECURITY_NETWORK
|
||||
static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
||||
{
|
||||
struct lsm_context ctx;
|
||||
int err;
|
||||
|
||||
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
|
||||
err = security_secid_to_secctx(scm->secid, &ctx);
|
||||
|
||||
if (err >= 0) {
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
|
||||
ctx.context);
|
||||
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool scm_has_secdata(struct socket *sock)
|
||||
{
|
||||
return test_bit(SOCK_PASSSEC, &sock->flags);
|
||||
}
|
||||
#else
|
||||
static void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
||||
{
|
||||
}
|
||||
|
||||
static bool scm_has_secdata(struct socket *sock)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
|
||||
{
|
||||
struct file *pidfd_file = NULL;
|
||||
int len, pidfd;
|
||||
|
||||
/* put_cmsg() doesn't return an error if CMSG is truncated,
|
||||
* that's why we need to opencode these checks here.
|
||||
*/
|
||||
if (msg->msg_flags & MSG_CMSG_COMPAT)
|
||||
len = sizeof(struct compat_cmsghdr) + sizeof(int);
|
||||
else
|
||||
len = sizeof(struct cmsghdr) + sizeof(int);
|
||||
|
||||
if (msg->msg_controllen < len) {
|
||||
msg->msg_flags |= MSG_CTRUNC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scm->pid)
|
||||
return;
|
||||
|
||||
pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
|
||||
|
||||
if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
|
||||
if (pidfd_file) {
|
||||
put_unused_fd(pidfd);
|
||||
fput(pidfd_file);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pidfd_file)
|
||||
fd_install(pidfd, pidfd_file);
|
||||
}
|
||||
|
||||
static bool __scm_recv_common(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags)
|
||||
{
|
||||
if (!msg->msg_control) {
|
||||
if (test_bit(SOCK_PASSCRED, &sock->flags) ||
|
||||
test_bit(SOCK_PASSPIDFD, &sock->flags) ||
|
||||
scm->fp || scm_has_secdata(sock))
|
||||
msg->msg_flags |= MSG_CTRUNC;
|
||||
|
||||
scm_destroy(scm);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (test_bit(SOCK_PASSCRED, &sock->flags)) {
|
||||
struct user_namespace *current_ns = current_user_ns();
|
||||
struct ucred ucreds = {
|
||||
.pid = scm->creds.pid,
|
||||
.uid = from_kuid_munged(current_ns, scm->creds.uid),
|
||||
.gid = from_kgid_munged(current_ns, scm->creds.gid),
|
||||
};
|
||||
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
|
||||
}
|
||||
|
||||
scm_passec(sock, msg, scm);
|
||||
|
||||
if (scm->fp)
|
||||
scm_detach_fds(msg, scm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void scm_recv(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags)
|
||||
{
|
||||
if (!__scm_recv_common(sock, msg, scm, flags))
|
||||
return;
|
||||
|
||||
scm_destroy_cred(scm);
|
||||
}
|
||||
EXPORT_SYMBOL(scm_recv);
|
||||
|
||||
void scm_recv_unix(struct socket *sock, struct msghdr *msg,
|
||||
struct scm_cookie *scm, int flags)
|
||||
{
|
||||
if (!__scm_recv_common(sock, msg, scm, flags))
|
||||
return;
|
||||
|
||||
if (test_bit(SOCK_PASSPIDFD, &sock->flags))
|
||||
scm_pidfd_recv(msg, scm);
|
||||
|
||||
scm_destroy_cred(scm);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user