net/compat: Add missing sock updates for SCM_RIGHTS

Add missed sock updates to compat path via a new helper, which will be
used more in coming patches. (The net/core/scm.c code is left as-is here
to assist with -stable backports for the compat path.)

Cc: Christoph Hellwig <hch@lst.de>
Cc: Sargun Dhillon <sargun@sargun.me>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: stable@vger.kernel.org
Fixes: 48a87cc26c ("net: netprio: fd passed in SCM_RIGHTS datagram not set correctly")
Fixes: d84295067f ("net: net_cls: fd passed in SCM_RIGHTS datagram not set correctly")
Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
Kees Cook 2020-06-09 16:11:29 -07:00
parent 11eb004ef7
commit d9539752d2
3 changed files with 26 additions and 0 deletions

View File

@ -890,6 +890,8 @@ static inline int sk_memalloc_socks(void)
{ {
return static_branch_unlikely(&memalloc_socks_key); return static_branch_unlikely(&memalloc_socks_key);
} }
void __receive_sock(struct file *file);
#else #else
static inline int sk_memalloc_socks(void) static inline int sk_memalloc_socks(void)
@ -897,6 +899,8 @@ static inline int sk_memalloc_socks(void)
return 0; return 0;
} }
static inline void __receive_sock(struct file *file)
{ }
#endif #endif
static inline gfp_t sk_gfp_mask(const struct sock *sk, gfp_t gfp_mask) static inline gfp_t sk_gfp_mask(const struct sock *sk, gfp_t gfp_mask)

View File

@ -309,6 +309,7 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
break; break;
} }
/* Bump the usage count and install the file. */ /* Bump the usage count and install the file. */
__receive_sock(fp[i]);
fd_install(new_fd, get_file(fp[i])); fd_install(new_fd, get_file(fp[i]));
} }

View File

@ -2840,6 +2840,27 @@ int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *
} }
EXPORT_SYMBOL(sock_no_mmap); EXPORT_SYMBOL(sock_no_mmap);
/*
* When a file is received (via SCM_RIGHTS, etc), we must bump the
* various sock-based usage counts.
*/
void __receive_sock(struct file *file)
{
struct socket *sock;
int error;
/*
* The resulting value of "error" is ignored here since we only
* need to take action when the file is a socket and testing
* "sock" for NULL is sufficient.
*/
sock = sock_from_file(file, &error);
if (sock) {
sock_update_netprioidx(&sock->sk->sk_cgrp_data);
sock_update_classid(&sock->sk->sk_cgrp_data);
}
}
ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags)
{ {
ssize_t res; ssize_t res;