mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
fs: Add receive_fd() wrapper for __receive_fd()
For both pidfd and seccomp, the __user pointer is not used. Update __receive_fd() to make writing to ufd optional via a NULL check. However, for the receive_fd_user() wrapper, ufd is NULL checked so an -EFAULT can be returned to avoid changing the SCM_RIGHTS interface behavior. Add new wrapper receive_fd() for pidfd and seccomp that does not use the ufd argument. For the new helper, the allocated fd needs to be returned on success. Update the existing callers to handle it. Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: linux-fsdevel@vger.kernel.org Reviewed-by: Sargun Dhillon <sargun@sargun.me> Acked-by: Christian Brauner <christian.brauner@ubuntu.com> Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
17
fs/file.c
17
fs/file.c
@@ -944,12 +944,13 @@ out_unlock:
|
|||||||
* @o_flags: the O_* flags to apply to the new fd entry
|
* @o_flags: the O_* flags to apply to the new fd entry
|
||||||
*
|
*
|
||||||
* Installs a received file into the file descriptor table, with appropriate
|
* Installs a received file into the file descriptor table, with appropriate
|
||||||
* checks and count updates. Writes the fd number to userspace.
|
* checks and count updates. Optionally writes the fd number to userspace, if
|
||||||
|
* @ufd is non-NULL.
|
||||||
*
|
*
|
||||||
* This helper handles its own reference counting of the incoming
|
* This helper handles its own reference counting of the incoming
|
||||||
* struct file.
|
* struct file.
|
||||||
*
|
*
|
||||||
* Returns -ve on error.
|
* Returns newly install fd or -ve on error.
|
||||||
*/
|
*/
|
||||||
int __receive_fd(struct file *file, int __user *ufd, unsigned int o_flags)
|
int __receive_fd(struct file *file, int __user *ufd, unsigned int o_flags)
|
||||||
{
|
{
|
||||||
@@ -964,16 +965,18 @@ int __receive_fd(struct file *file, int __user *ufd, unsigned int o_flags)
|
|||||||
if (new_fd < 0)
|
if (new_fd < 0)
|
||||||
return new_fd;
|
return new_fd;
|
||||||
|
|
||||||
error = put_user(new_fd, ufd);
|
if (ufd) {
|
||||||
if (error) {
|
error = put_user(new_fd, ufd);
|
||||||
put_unused_fd(new_fd);
|
if (error) {
|
||||||
return error;
|
put_unused_fd(new_fd);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bump the sock usage counts, if any. */
|
/* Bump the sock usage counts, if any. */
|
||||||
__receive_sock(file);
|
__receive_sock(file);
|
||||||
fd_install(new_fd, get_file(file));
|
fd_install(new_fd, get_file(file));
|
||||||
return 0;
|
return new_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ksys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
|
static int ksys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/posix_types.h>
|
#include <linux/posix_types.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
|
||||||
struct file;
|
struct file;
|
||||||
|
|
||||||
@@ -96,8 +97,14 @@ extern int __receive_fd(struct file *file, int __user *ufd,
|
|||||||
static inline int receive_fd_user(struct file *file, int __user *ufd,
|
static inline int receive_fd_user(struct file *file, int __user *ufd,
|
||||||
unsigned int o_flags)
|
unsigned int o_flags)
|
||||||
{
|
{
|
||||||
|
if (ufd == NULL)
|
||||||
|
return -EFAULT;
|
||||||
return __receive_fd(file, ufd, o_flags);
|
return __receive_fd(file, ufd, o_flags);
|
||||||
}
|
}
|
||||||
|
static inline int receive_fd(struct file *file, unsigned int o_flags)
|
||||||
|
{
|
||||||
|
return __receive_fd(file, NULL, o_flags);
|
||||||
|
}
|
||||||
|
|
||||||
extern void flush_delayed_fput(void);
|
extern void flush_delayed_fput(void);
|
||||||
extern void __fput_sync(struct file *);
|
extern void __fput_sync(struct file *);
|
||||||
|
@@ -299,7 +299,7 @@ void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm)
|
|||||||
|
|
||||||
for (i = 0; i < fdmax; i++) {
|
for (i = 0; i < fdmax; i++) {
|
||||||
err = receive_fd_user(scm->fp->fp[i], cmsg_data + i, o_flags);
|
err = receive_fd_user(scm->fp->fp[i], cmsg_data + i, o_flags);
|
||||||
if (err)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -307,7 +307,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
|
|||||||
|
|
||||||
for (i = 0; i < fdmax; i++) {
|
for (i = 0; i < fdmax; i++) {
|
||||||
err = receive_fd_user(scm->fp->fp[i], cmsg_data + i, o_flags);
|
err = receive_fd_user(scm->fp->fp[i], cmsg_data + i, o_flags);
|
||||||
if (err)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user